blob: 5e785ae6c6c4afd88f408eaa807303d7dde167e2 [file] [log] [blame]
package com.savoirfairelinux.sflphone.model;
import java.util.ArrayList;
import android.graphics.PointF;
import android.util.Log;
public class BubbleModel
{
private static final String TAG = BubbleModel.class.getSimpleName();
public long lastUpdate = 0;
public int width, height;
public ArrayList<Bubble> listBubbles = new ArrayList<Bubble>();
public ArrayList<Attractor> attractors = new ArrayList<Attractor>();
private static final float ATTRACTOR_DIST_SUCK = 20.f;
private static final double BUBBLE_RETURN_TIME_HALF_LIFE = .25;
private static final double BUBBLE_RETURN_TIME_LAMBDA = Math.log(2)/BUBBLE_RETURN_TIME_HALF_LIFE;
/*private static final float FRICTION_VISCOUS = .5f; // Viscous friction factor
private static final float BUBBLE_MAX_SPEED = 2500.f; // Max target speed in px/sec
private static final float ATTRACTOR_SMOOTH_DIST = 100.f;// Size of the "gravity hole" around the attractor
private static final float ATTRACTOR_STALL_DIST = 15.f; // Size of the "gravity hole" flat bottom
private static final float ATTRACTOR_ACCEL = 10.f; // Acceleration factor towards target speed
*/
public void update()
{
long now = System.nanoTime();
// Do nothing if lastUpdate is in the future.
if (lastUpdate > now)
return;
double ddt = Math.min((now - lastUpdate) / 1000000000.0, .2);
lastUpdate = now;
float dt = (float)ddt;
//Log.w(TAG, "update dt="+dt);
int attr_n = attractors.size();
// Iterators should not be used in frequently called methods
// to avoid garbage collection glitches caused by iterator objects.
for(int i=0, n=listBubbles.size(); i<n; i++) {
Bubble b = listBubbles.get(i);
//Log.w(TAG, "update b");
if(!b.dragged) {
float bx=b.getPosX(), by=b.getPosY();
Attractor attractor = null;
PointF attractor_pos = b.attractor;
float attractor_dist = (attractor_pos.x-bx)*(attractor_pos.x-bx) + (attractor_pos.y-by)*(attractor_pos.x-by);
for(Attractor t : attractors) {
float dx = t.pos.x-bx, dy = t.pos.y-by;
float adist = dx*dx + dy*dy;
if(adist < attractor_dist) {
attractor = t;
attractor_pos = t.pos;
attractor_dist = adist;
}
}
double edt = -Math.expm1(-BUBBLE_RETURN_TIME_LAMBDA*dt);
double dx = (attractor_pos.x - bx) * edt;
double dy = (attractor_pos.y - by) * edt;
// Log.w(TAG, "update dx="+dt+" dy="+dy);
b.setPos((float)(bx+dx), (float)(by+dy));
if(attractor != null && attractor_dist < ATTRACTOR_DIST_SUCK*ATTRACTOR_DIST_SUCK) {
attractor.callback.onBubbleSucked(b);
listBubbles.remove(b);
n--;
}
/* float bx=b.getPosX(), by=b.getPosY();
/// Apply viscous friction
float friction_coef = 1.f-FRICTION_VISCOUS*dt;
float tdx = b.attractor.x - bx, tdy = b.attractor.y - by;
float dist = (float) Math.sqrt(tdx*tdx + tdy*tdy);
float speed = (float)Math.sqrt(b.speed.x*b.speed.x + b.speed.y*b.speed.y);
b.speed.x *= friction_coef;
b.speed.y *= friction_coef;
if(speed > 10.f || dist > ATTRACTOR_STALL_DIST) {
dist = Math.max(1.f, dist); // Avoid division by 0
b.speed.x *= friction_coef;
b.speed.y *= friction_coef;
// Target speed (defines the "gravity hole")
float target_speed;
if(dist > ATTRACTOR_SMOOTH_DIST)
target_speed = BUBBLE_MAX_SPEED;
else if(dist < ATTRACTOR_STALL_DIST)
target_speed = 0;
else
target_speed = BUBBLE_MAX_SPEED/(ATTRACTOR_SMOOTH_DIST-ATTRACTOR_STALL_DIST)*(dist-ATTRACTOR_STALL_DIST);
float target_speed_x = target_speed*tdx/dist;
float target_speed_y = target_speed*tdy/dist;
// Acceleration
float ax = (target_speed_x-b.speed.x) * ATTRACTOR_ACCEL;// + 2*(b.last_speed.x-b.speed.x)*(1-FRICTION_VISCOUS)/FRICTION_VISCOUS*60.f;
float ay = (target_speed_y-b.speed.y) * ATTRACTOR_ACCEL;// + 2*(b.last_speed.y-b.speed.y)*(1-FRICTION_VISCOUS)/FRICTION_VISCOUS*60.f;
// Speed update
b.speed.x += ax*dt;
b.speed.y += ay*dt;
b.last_speed.set(b.speed);
Log.w(TAG, "dist " + dist + " speed " + Math.sqrt(b.speed.x*b.speed.x + b.speed.y*b.speed.y) + " target speed "+target_speed);
// Position update
float dx = b.speed.x * dt;
float dy = b.speed.y * dt;
b.setPos(bx+dx, by+dy);
}
// Prevent speed higher than BUBBLE_MAX_SPEED
float ds = (target_speed-speed)*dt;
// Set motion direction and speed
float nsr = (speed>BUBBLE_MAX_SPEED ? BUBBLE_MAX_SPEED : speed+ds)/(dist < 1.f ? 1.f : dist);
b.speed.x = tdx * nsr;
b.speed.y = tdy * nsr;*/
}
}
}
}