import java.awt.*; import java.util.*; public class avoiding extends BufferedApplet { int N = 6, w = 0, h, n = -1; Thing thing[] = new Thing[N]; Random rand = new Random(); public void render(Graphics g) { // INITIALIZE FIRST TIME if (w == 0) { w = bounds().width; h = bounds().height; for (int i = 0 ; i < N ; i++) { thing[i] = new Thing(); thing[i].id = i; thing[i].x = w/2 + (rand.nextInt() % (w/2)); thing[i].y = h/2 + (rand.nextInt() % (h/2)); thing[i].angle = rand.nextDouble() * 2*Math.PI; thing[i].R = w / 20; } } // CLEAR SCREEN g.setColor(Thing.RedBg); g.fillRect(0,0,w/3+1,h); g.setColor(Thing.GrnBg); g.fillRect(w/3,0,w/3+1,h); g.setColor(Thing.BluBg); g.fillRect(2*w/3,0,w/3+1,h); // DRAW THE VEHICLES for (int i = 0 ; i < N ; i++) { Thing T = thing[i]; if (T.stopped) { T.draw(g); continue; } double angle = T.angle; double cos = Math.cos(angle), sin = -Math.sin(angle); // TURN AWAY FROM WALLS if (T.x < 3*T.R) T.angle += swerve(-cos, sin); if (T.x > w-3*T.R) T.angle += swerve( cos,-sin); if (T.y < 3*T.R) T.angle += swerve(-sin,-cos); if (T.y > h-3*T.R) T.angle += swerve( sin, cos); // TURN AWAY FROM OTHER VEHICLES for (int j = 0 ; j < N ; j++) if (j != i) { Thing S = thing[j]; double dx = S.x - T.x, dy = S.y - T.y; double r = Math.sqrt(dx*dx + dy*dy); dx /= r; dy /= r; double t = 1 - r / (2 * (T.R + S.R)); if (t > 0) T.angle += 4 * t * swerve(dx*cos + dy*sin, dy*cos - dx*sin); } // MOVE FORWARD double fwd = 3; if (T.highlight = 3 * mx / w == i) fwd *= 2 - 2. * my / h; T.x += (int)(fwd * cos); T.y += (int)(fwd * sin); // HARD CONSTRAINT: STAY WITHIN ROOM T.x = Math.min(T.x, w-T.R); T.y = Math.min(T.y, h-T.R); T.x = Math.max(T.x, T.R); T.y = Math.max(T.y, T.R); // HARD CONSTRAINT: DON'T RUN INTO OTHER VEHICLES for (int j = 0 ; j < N ; j++) if (j != i) { Thing S = thing[j]; double dx = T.x - S.x, dy = T.y - S.y; double dist = Math.sqrt(dx * dx + dy * dy); double R = T.R + S.R; if (dist < R) { double f = (R - dist) / R; double t = .5; if (i == n || T.stopped) t = 0; if (j == n || S.stopped) t = 1; T.x += t * dx * f; T.y += t * dy * f; S.x -= (1-t) * dx * f; S.y -= (1-t) * dy * f; } } T.draw(g); } // OUTLINE THE WINDOW g.setColor(Color.black); g.drawRect(0,0,w-1,h-1); animating = true; // FORCE CONTINUAL REFRESH } double swerve(double u, double v) { return .1 * (1 + u) * v; } int mx, my; public boolean mouseMove(Event e, int x, int y) { mx = x; my = y; return true; } boolean dragged = false; public boolean mouseDown(Event e, int x, int y) { dragged = false; n = -1; for (int i = N-1 ; i >= 0 ; i--) { int dx = x - thing[i].x; int dy = y - thing[i].y; int r = (int)Math.sqrt(dx * dx + dy * dy); if (r < thing[i].R) { thing[i].x = x; thing[i].y = y; for (int j = 0 ; j < N ; j++) thing[j].inDisk = i==j; n = i; break; } } damage = true; return true; } public boolean mouseDrag(Event e, int x, int y) { dragged = true; if (n >= 0) { thing[n].x = x; thing[n].y = y; } damage = true; return true; } public boolean mouseUp(Event e, int x, int y) { if (n >= 0) { thing[n].inDisk = thing[n].onEdge = false; if (! dragged) thing[n].stopped = ! thing[n].stopped; } damage = true; return true; } public boolean keyUp(Event e, int key) { switch (key) { case 'c': damage = true; } return true; } } class Thing { static double dx[] = {.6, -.35, -.35}; static double dy[] = { 0, -.35, .35}; static Color Red = new Color(255,128,128); static Color Grn = new Color(128,255,128); static Color Blu = new Color(128,128,255); static Color RedBg = new Color(240,200,200); static Color GrnBg = new Color(200,240,200); static Color BluBg = new Color(200,200,240); int X[] = {0,0,0}, Y[] = {0,0,0}; int id, x, y, R; double angle = 0; boolean stopped = false, inDisk, onEdge, highlight = false; void draw(Graphics g) { switch (id) { case 0 : g.setColor(Red); break; case 1 : g.setColor(Grn); break; case 2 : g.setColor(Blu); break; default: g.setColor(Color.white); } g.fillOval(x - R, y - R, 2*R, 2*R); if (onEdge) { g.setColor(Color.red); for (int i = -2 ; i <= 2 ; i++) { int r = R + i; g.drawOval(x - r, y - r, 2*r, 2*r); } } else { g.setColor(Color.black); g.drawOval(x - R, y - R, 2*R, 2*R); } double c = Math.cos(angle), s = Math.sin(angle), r = highlight ? 1.4*R : R; for (int i = 0 ; i < X.length ; i++) { X[i] = (int)(x + r * ( dx[i] * c + dy[i] * s)); Y[i] = (int)(y + r * (-dx[i] * s + dy[i] * c)); } g.setColor(Color.black); g.fillPolygon(X,Y,X.length); } int type() { return id / 3; } }