public void draw(Graphics g) { animate(); g.setColor(Color.black); g.fillRect(0, 0, dim.width, dim.height); g.setColor(Color.white); numpaint++; DebugPrinter dbg = new DebugPrinter(g, 50, 60); dbg.print( "Spring-mass demo by yigal irani, drag balls or create new ones by clicking inside box"); dbg.print("frame", numpaint); dbg.print("fps", 1 / timer.time_diff); Point top_left = point_by_vec(new Vec(-1, 1)); g.draw3DRect(top_left.x, top_left.y, screen_dist(2), screen_dist(2), true); for (int i = 0; i < springs.size(); i++) { Spring spring = springs.get2(i); Point p1 = point_by_vec(balls.get2(spring.start).pos); Point p2 = point_by_vec(balls.get2(spring.end).pos); g.drawLine(p1.x, p1.y, p2.x, p2.y); } for (int i = 0; i < balls.size(); i++) { Ball ball = balls.get2(i); Point p = point_by_vec(ball.pos); int screen_radius = screen_dist(RADIUS); g.setColor(Color.blue); g.fillOval(p.x - screen_radius, p.y - screen_radius, screen_radius * 2, screen_radius * 2); g.setColor(Color.white); g.drawOval(p.x - screen_radius, p.y - screen_radius, screen_radius * 2, screen_radius * 2); g.drawString("" + i, p.x, p.y); } }
void the_derive(double time, double y[], double dy[]) { int i; BallVector balls = decode_balls(y); // new BallVector();//Ball[num_balls]; BallVector dballs = new BallVector(); // new Ball[num_balls]; for (i = 0; i < num_balls; i++) { Ball p = balls.get2(i); Ball d = new Ball(); d.pos = p.speed; d.speed = wall_power(p); d.speed.y -= 1; // gravity dballs.add(d); } for (i = 0; i < num_balls; i++) for (int j = i + 1; j < num_balls; j++) { Ball p1 = balls.get2(i); Ball p2 = balls.get2(j); if (far_away_fast_calc(p1.pos, p2.pos, radius * 2)) continue; double dist = p1.pos.calc_dist(p2.pos); // if (dist>radius*2) // continue; Vec collide_power = calc_collide_power(p1, p2, dist); dballs.get2(i).speed.add_to(collide_power); dballs.get2(j).speed.sub_to(collide_power); } for (i = 0; i < springs.size(); i++) { Spring s = springs.get2(i); Vec collide_power = calc_spring_power(balls.get2(s.start), balls.get2(s.end)); dballs.get2(s.start).speed.add_to(collide_power); dballs.get2(s.end).speed.sub_to(collide_power); } encode_balls(dballs, dy); };
BallVector decode_balls(double y[]) { BallVector ans = new BallVector(); for (int i = 0; i < num_balls; i++) { Ball p = new Ball(); p.pos.x = y[i * 4 + 1]; p.pos.y = y[i * 4 + 2]; p.speed.x = y[i * 4 + 3]; p.speed.y = y[i * 4 + 4]; ans.addElement(p); } return ans; }
int find_ball(Vec v) { int num_balls = balls.size(); for (int i = 0; i < num_balls; i++) { Ball p = balls.get2(i); double dist = v.calc_dist(p.pos); if (dist < RADIUS) { // printf("found ball %d\n",i); find_offset = p.pos.sub(dragged_vec); // last_dragged_vec=v; return i; } } return -1; }
void encode_balls(BallVector balls, double y[]) { for (int i = 0; i < num_balls; i++) { Ball p = balls.get2(i); y[i * 4 + 1] = p.pos.x; y[i * 4 + 2] = p.pos.y; y[i * 4 + 3] = p.speed.x; y[i * 4 + 4] = p.speed.y; } }
void animate() { dim = getSize(); size = (int) (Math.min(dim.height, dim.width) / 2.2); timer.tell_time(); if (timer.time_diff == 0) return; // not enought time has passed, dont animate-crach fix dragged_speed = dragged_vec.sub(last_dragged_vec).div(timer.time_diff); last_dragged_vec = dragged_vec; if (dragged_ball != -1) { balls.get2(dragged_ball).pos = dragged_vec.add(find_offset).trim(-1, 1); balls.get2(dragged_ball).speed = dragged_speed; } balls = new WorldAnimate().calc_new_frame(balls, springs, RADIUS, timer); }
public BallVector calc_new_frame( BallVector _balls, SpringVector _springs, double _radius, Timer timer) { // return the the balls of the next frame balls = _balls; springs = _springs; radius = _radius; num_balls = balls.size(); int i; for (i = 0; i < NUM_STEPS; i++) call_rk4(timer.cur_time, timer.time_diff / NUM_STEPS); // too: acum the time? return balls; }
void call_rk4(double cur_time, double time_diff) { num_balls = balls.size(); double[] y = new_vector(num_balls * 4); // double[num_balls*4]; double[] dy = new_vector(num_balls * 4); encode_balls(balls, y); the_derive( cur_time, y, dy); // the current implementation of derive does not uses the time, but can envision an // implementation that might (gravity is off every second, perhaps?) rk4(y, dy, num_balls * 4, cur_time, time_diff, y); // balls=new BallVector(); balls = decode_balls(y); // free_vector(y,1,num_balls*4); // free_vector(dy,1,num_balls*4); }
void init_world() { springs = new SpringVector(); // [num_springs]; add_spring(0, 1); add_spring(1, 2); add_spring(2, 0); add_spring(3, 4); add_spring(4, 5); add_spring(5, 3); add_spring(0, 4); balls = new BallVector(); // [num_balls]; for (int i = 0; i < NUM_POINTS; i++) { Ball p = new Ball(); init_rand(p); balls.addElement(p); } }
void new_ball(Vec vec) { Ball b = new Ball(); b.pos = vec; balls.add(b); }