// Collision detection test // // Author Matthew Caryl // Created 26.5.97 package Test; import java.awt.*; import java.applet.*; import ADT.*; public final class StaticTest extends Applet implements Runnable { // // Private interface // private Thread animation; private Graphics graphics; private Random random = new Random(0); // // Public world interface // public void init() { setBackground(Color.black); // save graphics context for later // note: this seems to reduce garbage collection problems graphics = this.getGraphics(); } public void destroy() { if (animation != null && animation.isAlive()) animation.stop(); if (graphics != null) graphics.dispose(); super.destroy(); } public void start() { if (animation == null) { animation = new Thread(this); animation.start(); } else animation.resume(); } public void stop() { if (animation != null && animation.isAlive()) animation.suspend(); } public void run() { int width = size().width; // create 2 by 2 buckets in width by width playing area Bucket[] buckets = staticCreateBuckets(2, 2, width); // create 16 bots of radius 16 with positions in ([0..width-1], [0..width-1) Bot[] bots = staticCreateBots(buckets, 2, 2, 16, 16, width); while (true) { long ticks = System.currentTimeMillis(); erase(bots); staticTick(bots, width, buckets, 2, 2); staticCollision(bots); display(bots, Color.white); try { animation.sleep(Math.max(100, 100 - (System.currentTimeMillis() - ticks))); } catch (InterruptedException e) { // do nothing } } } public void erase(Bot[] bots) { graphics.setColor(Color.black); for (int i = bots.length - 1; i >= 0; i--) { Bot b = bots[i]; if (b.collision) graphics.fillOval(b.x - b.r / 2, b.y - b.r / 2, 2 * b.r, 2 * b.r); else graphics.drawOval(b.x - b.r / 2, b.y - b.r / 2, 2 * b.r, 2 * b.r); b.collision = false; } } public void display(Bot[] bots, Color color) { graphics.setColor(color); for (int i = bots.length - 1; i >= 0; i--) { Bot b = bots[i]; if (b.collision) graphics.fillOval(b.x - b.r / 2, b.y - b.r / 2, 2 * b.r, 2 * b.r); else graphics.drawOval(b.x - b.r / 2, b.y - b.r / 2, 2 * b.r, 2 * b.r); } } public Bucket[] staticCreateBuckets(int width, int height, int range) { Bucket[] buckets = new Bucket[width * height]; for (int y = height - 1; y >= 0; y--) for (int x = width - 1; x >= 0; x--) buckets[y * width + x] = new Bucket(); for (int y = height - 1; y >= 0; y--) for (int x = width - 1; x >= 0; x--) { Bucket b = buckets[y * width + x]; b.bots = new Bot(); b.bots.next = b.bots; b.bots.prev = b.bots; // neighbouring buckets b.north = (y > 0) ? buckets[(y - 1) * width + x] : null; b.east = (x < width - 1) ? buckets[y * width + (x + 1)] : null; b.south = (y < height - 1) ? buckets[(y + 1) * width + x] : null; b.west = (x > 0) ? buckets[y * width + (x - 1)] : null; // bucket range b.top = range * y / height; b.left = range * x / width; b.bottom = range * (y + 1) / height - 1; b.right = range * (x + 1) / width - 1; } return buckets; } public Bot[] staticCreateBots(Bucket[] buckets, int width, int height, int number, int radius, int range) { Bot[] bots = new Bot[number]; for (int i = bots.length - 1; i >= 0; i--) { Bot b = new Bot(); b.x = random.range(range); b.y = random.range(range); b.r = radius; b.dx = random.range(15) - 7; b.dy = random.range(15) - 7; b.add(buckets[(b.y * width / range) * width + (b.x * width / range)]); bots[i] = b; } return bots; } public void staticTick(Bot[] bots, int range, Bucket[] buckets, int width, int height) { for (int i = bots.length - 1; i >= 0; i--) { Bot b = bots[i]; b.x = (b.x + b.dx) & (range - 1); b.y = (b.y + b.dy) & (range - 1); if (b.outside()) { // move bot to another bucket b.sub(); b.add(buckets[(b.y * width / range) * width + (b.x * width / range)]); } } } public void staticCollision(Bucket home, Bot bot) { for (Bot b = home.bots.next; b != home.bots; b = b.next) { int dx = (bot.x - b.x); int dy = (bot.y - b.y); int dr = (bot.r + b.r); if (dx * dx + dy * dy <= dr * dr) { bot.collision = true; b.collision = true; } } } public void staticCollision(Bot[] bots) { for (int i = bots.length - 1; i >= 0; i--) { Bot b = bots[i]; Bucket home = b.home; b.sub(); staticCollision(home, b); if (home.north != null && home.top > b.y - b.r) staticCollision(home.north, b); if (home.west != null && home.left > b.x - b.r) staticCollision(home.west, b); if (home.south != null && home.bottom < b.y + b.r) staticCollision(home.south, b); if (home.east != null && home.right < b.x + b.r) staticCollision(home.east, b); b.add(home); } } }