/* built with Studio Sketchpad: * https://sketchpad.cc * * observe the evolution of this sketch: * https://studio.sketchpad.cc/sp/pad/view/ro.HV8ZiiSv0MT/rev.49 * * authors: * GoToLoop * license (unless otherwise specified): * creative commons attribution-share alike 3.0 license. * https://creativecommons.org/licenses/by-sa/3.0/ */ /** * Asteroids Vs. Bullets Sim (v3.21) * by GoToLoop (2014/Mar) * * forum.processing.org/two/discussion/3980/check-asteroid-death-help * forum.processing.org/two/discussion/3890/collision-problem * * studio.processingtogether.com/sp/pad/export/ro.9K-kjhuONcJDZ/latest */ static final int ASTEROIDS = 30, BULLETS = 100, NUM = 10, FPS = 60; static final color BG = 0; static final boolean ONLINE = 1/2 == 1/2.; final ArrayList<Asteroid> asteroids; final ArrayList<Bullet> bullets; { asteroids = ONLINE? new ArrayList() : new ArrayList(ASTEROIDS); bullets = ONLINE? new ArrayList() : new ArrayList(BULLETS); } int score; boolean isPaused; void setup() { size(900, 750, JAVA2D); frameRate(FPS); smooth(4); ellipseMode(CENTER); rectMode(Asteroid.RECT_MODE); strokeWeight(Bullet.DIAM); fill(Asteroid.COLOUR); instantiateSprites(); } void draw() { background(BG); displaySprites(); checkDeath(); checkVictory(); } void mousePressed() { keyPressed(); } void keyPressed() { if (isPaused ^= true) noLoop(); else loop(); } void restart() { instantiateSprites(); score = 0; } void instantiateSprites() { asteroids.clear(); //bullets.clear(); for ( int i = 0; i++ != ASTEROIDS; asteroids.add(new Asteroid()) ); for ( int i = 0; i++ != BULLETS; bullets.add(new Bullet( random(width), random(height), random(TWO_PI))) ); } void displaySprites() { noStroke(); for (int a = asteroids.size(), len = a; a-- != 0;) if (asteroids.get(a).script()) { asteroids.set(a, asteroids.get(--len)); asteroids.remove(len); println("An asteroid has flown too far away!"); } stroke(Bullet.COLOUR); for (int b = bullets.size(), len = b; b-- != 0;) if (bullets.get(b).script()) { bullets.set(b, bullets.get(--len)); bullets.remove(len); println("A bullet has strayed too far from view!"); } } void checkDeath() { for (int lenB = bullets.size(), b = lenB; b-- != 0;) { final Bullet u = bullets.get(b); for (int lenA = asteroids.size(), a = lenA; a-- != 0;) if (u.checkHit(asteroids.get(a))) { //java.util.Collections.swap(asteroids, a, --lenA); //java.util.Collections.swap(bullets, b, --lenB); asteroids.set(a, asteroids.get(--lenA)); bullets.set(b, bullets.get(--lenB)); asteroids.remove(lenA); bullets.remove(lenB); score += NUM; println("An asteroid has been pulverized!"); break; } } } void checkVictory() { final int a = asteroids.size(), b = bullets.size(); if (!ONLINE) frame.setTitle("Score: #" + score + "\t\tFPS: #" + round(frameRate)); if (b == 0) { println("\nAsteroids left: #" + a + "\tFinal score: #" + score); isPaused = true; noLoop(); restart(); } } class Asteroid { static final boolean IS_CIRCLE = false; static final int RECT_MODE = CORNER; // Either CORNER or CENTER. static final color COLOUR = #00A0F0; static final float SPD = 1.5; static final int DIAM = 25, RAD = DIAM>>1, RAD_SQ = RAD*RAD; static final int DIM_X = 20, RAD_X = DIM_X>>1; static final int DIM_Y = 30, RAD_Y = DIM_Y>>1; float x = IS_CIRCLE ? random(DIAM, width - DIAM) : random(DIM_X, width - DIM_X); float y = IS_CIRCLE ? random(DIAM, height - DIAM) : random(DIM_Y, height - DIM_Y); final float vx, vy; Asteroid() // Fix for JS { final float dir = random(TWO_PI); vx = cos(dir)*SPD; vy = sin(dir)*SPD; } boolean script() { update(); display(); return isOuttaBounds(); } void update() { x += vx; y += vy; } void display() { if (IS_CIRCLE) ellipse(x, y, DIAM, DIAM); else rect(x, y, DIM_X, DIM_Y); } boolean isOuttaBounds() { return IS_CIRCLE ? x < -RAD | x >= width+RAD | y < -RAD | y >= height+RAD : RECT_MODE == CORNER ? x < 0 | x >= width+DIM_X | y < 0 | y >= height+DIM_Y : x < -RAD_X | x >= width+RAD_X | y < -RAD_Y | y >= height+RAD_Y; } } class Bullet { static final color COLOUR = #C86400; static final int DIAM = 4; static final float SPD = 4.0; float x, y; final float vx, vy; Bullet(float xx, float yy, float dir) { x = xx; y = yy; vx = cos(dir)*SPD; vy = sin(dir)*SPD; } boolean script() { update(); display(); return isOuttaBounds(); } void update() { x += vx; y += vy; } void display() { point(x, y); } boolean isOuttaBounds() { return x < -DIAM | x > width+DIAM | y < -DIAM | y > height+DIAM; } boolean checkHit(Asteroid a) { return Asteroid.IS_CIRCLE ? sq(a.x - x) + sq(a.y - y) < Asteroid.RAD_SQ : Asteroid.RECT_MODE == CORNER ? x >= a.x & x < a.x+Asteroid.DIM_X & y >= a.y & y < a.y+Asteroid.DIM_Y : x >= a.x-Asteroid.RAD_X & x < a.x+Asteroid.RAD_X & y >= a.y-Asteroid.RAD_Y & y < a.y+Asteroid.RAD_Y; } }