/* 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;
}
}