import java.util.*; import net.phys2d.math.*; import net.phys2d.raw.*; import net.phys2d.raw.shapes.*; import net.phys2d.raw.strategies.*; public World world; ArrayList boxes; final int SCREEN_WIDTH = 800; final int SCREEN_HEIGHT = 400; final int DROP_FREQUENCY = 2; final float BOX_SIZE_MIN = 30.0f; final float BOX_SIZE_MAX = 70.0f; final float OBJECT_X_MIN = 100.0f; final float OBJECT_X_MAX = SCREEN_WIDTH - 100.0f; final float OBJECT_Y = -100.0f; final float BOX_DEPTH = 50.0f; final float FLOOR_DEPTH = 400.0f; final float HALF_FLOOR_DEPTH = FLOOR_DEPTH / 2; final float FRICTION = 0.3f; final float MIN_FORCE_X = -10.0f; final float MAX_FORCE_X = 10.0f; final float ANGULAR_VELOCITY_MIN = -3.0f; final float ANGULAR_VELOCITY_MAX = 3.0f; final float GROUND_FILL = 250; final float GROUND_X = SCREEN_WIDTH / 2; final float GROUND_Y = SCREEN_HEIGHT - 10; final color BOX_FILL = color(192, 156, 118); final float EXPLOSION_FORCE = 1500000.0f; final float MAX_BOUNDS_X = SCREEN_WIDTH + 100; final float MIN_BOUNDS_X = -100; final float MAX_BOUNDS_Y = SCREEN_HEIGHT + 100; Body ground; final float BOX_COLOUR_R = 180.0f; final float BOX_COLOUR_G = 140.0f; final float BOX_COLOUR_B = 100.0f; final float BOX_COLOUR_DEVIATION = 0.2f; int ticks = 0; void setup() { // Setup window size(SCREEN_WIDTH, SCREEN_HEIGHT, P3D); frameRate(24); boxes = new ArrayList(); initialiseWorld(); rectMode(CENTER); camera( SCREEN_WIDTH / 2, SCREEN_HEIGHT - 150, 270, SCREEN_WIDTH / 2, SCREEN_HEIGHT - 130, 0, 0, 1.0, 0 ); //noLoop(); } void initialiseWorld() { // Initialise physics world = new World(new Vector2f(0.0f, 20.0f), 20, new QuadSpaceStrategy(20, 5)); // Add ground ground = new StaticBody("Ground", new Box(width + 400, 10.0f)); ground.setPosition(GROUND_X, GROUND_Y); ground.setFriction(0.7f); world.add(ground); } void draw() { background(255); stroke(100); ticks++; if (ticks < 200 && ticks % DROP_FREQUENCY == 0) { addBox(); } else if (ticks == 200) { explode(); } removeOutOfBoundsBoxes(); world.step(); world.step(); world.step(); world.step(); drawGround(); Iterator boxIterator = boxes.iterator(); while (boxIterator.hasNext()) { PhysicalBox pbox = (PhysicalBox)boxIterator.next(); pbox.render(); } if (ticks == 600) { reset(); } } void addBox() { float boxWidth = random(BOX_SIZE_MIN, BOX_SIZE_MAX); float boxHeight = random(BOX_SIZE_MIN, BOX_SIZE_MAX); float colourDeviation = random(-BOX_COLOUR_DEVIATION, BOX_COLOUR_DEVIATION); color boxColour = color( (int)(BOX_COLOUR_R + BOX_COLOUR_R * colourDeviation), (int)(BOX_COLOUR_G + BOX_COLOUR_G * colourDeviation), (int)(BOX_COLOUR_B + BOX_COLOUR_B * colourDeviation) ); PhysicalBox pbox = new PhysicalBox(boxWidth, boxHeight, BOX_DEPTH, boxColour); pbox.setPosition(random(OBJECT_X_MIN, OBJECT_X_MAX), OBJECT_Y); pbox.setRotation(random(0, TWO_PI)); pbox.setForce(random(MIN_FORCE_X, MAX_FORCE_X), 20); pbox.setFriction(FRICTION); pbox.adjustAngularVelocity(random(ANGULAR_VELOCITY_MIN, ANGULAR_VELOCITY_MAX)); boxes.add((Object)pbox); world.add(pbox); } void removeOutOfBoundsBoxes() { Iterator boxIterator = boxes.iterator(); while (boxIterator.hasNext()) { PhysicalBox pbox = (PhysicalBox)boxIterator.next(); ROVector2f p = pbox.getPosition(); if (p.getX() > MAX_BOUNDS_X || p.getX() < MIN_BOUNDS_X || p.getY() > MAX_BOUNDS_Y) { world.remove(pbox); boxIterator.remove(); } } } void explode() { Vector2f detonationPoint = new Vector2f(GROUND_X, GROUND_Y); Iterator boxIterator = boxes.iterator(); while (boxIterator.hasNext()) { PhysicalBox pbox = (PhysicalBox)boxIterator.next(); pbox.explode(detonationPoint, EXPLOSION_FORCE); } } void reset() { Iterator boxIterator = boxes.iterator(); while (boxIterator.hasNext()) { PhysicalBox pbox = (PhysicalBox)boxIterator.next(); world.remove(pbox); boxIterator.remove(); } ticks = 0; } void drawGround() { fill(GROUND_FILL); Box b = (Box)ground.getShape(); ROVector2f groundSize = b.getSize(); ROVector2f p = ground.getPosition(); float r = ground.getRotation(); pushMatrix(); translate(p.getX(), p.getY(), 0.0f); rotateZ(r); box(groundSize.getX(), groundSize.getY(), FLOOR_DEPTH); popMatrix(); } class PhysicalBox extends Body { private float boxWidth, boxHeight, boxDepth; private color c; PhysicalBox(float w, float h, float d, color c) { super(new Box(w, h), w * h); this.boxWidth = w; this.boxHeight = h; this.boxDepth = d; this.c = c; } public color getColor() { return this.c; } public void setColor(color c) { this.c = c; } public void explode(Vector2f detonationPoint, float magnitude) { ROVector2f p = this.getPosition(); Vector2f explosionVector = MathUtil.sub(p, detonationPoint); magnitude /= explosionVector.lengthSquared(); explosionVector = MathUtil.scale(explosionVector, magnitude * this.getMass()); this.addForce(explosionVector); } public void render() { Box b = (Box)this.getShape(); ROVector2f boxSize = b.getSize(); ROVector2f p = this.getPosition(); float r = this.getRotation(); pushMatrix(); fill(this.c); translate(p.getX(), p.getY(), 0.0f); rotateZ(r); box(boxSize.getX(), boxSize.getY(), boxDepth); popMatrix(); } }