/* built with Studio Sketchpad:
* https://sketchpad.cc
*
* observe the evolution of this sketch:
* https://studio.sketchpad.cc/sp/pad/view/ro.-qMtDtWYW7q/rev.1714
*
* authors:
*
* Zach Denton
* license (unless otherwise specified):
* creative commons attribution-share alike 3.0 license.
* https://creativecommons.org/licenses/by-sa/3.0/
*/
ArrayList things, beams;
Blaster blaster;
int lastTime = 0;
float thingIncidence;
void setup() {
size(600, 400);
smooth();
things = new ArrayList();
thingIncidence = 1;
beams = new ArrayList();
blaster = new Blaster(new PVector(width / 2, 3 * height / 4), 30);
}
void draw() {
background(0);
blaster.draw();
for (int i = 0; i < things.size(); i++) {
Thing thing = (Thing) things.get(i);
thing.draw();
}
for (int i = 0; i < beams.size(); i++) {
ParticleBeam beam = (ParticleBeam) beams.get(i);
beam.draw();
}
int currentTime = millis();
if (currentTime > lastTime + 30) {
update();
lastTime = currentTime;
}
}
void update() {
blaster.update();
if (random(1) <= thingIncidence) {
things.add(new Thing(new PVector(int(random(20, width-20)), -30)));
}
for (int i = 0; i < things.size(); i++) {
Thing thing = (Thing) things.get(i);
if (!thing.targeted) {
blaster.shoot(thing);
}
if (thing.alive) {
thing.update();
} else {
things.remove(i);
}
}
for (int i = 0; i < beams.size(); i++) {
ParticleBeam beam = (ParticleBeam) beams.get(i);
if (beam.alive) {
beam.update();
} else {
beams.remove(i);
}
}
}
class Thing {
PVector position, velocity, v1, v2, v3;
int w = 8;
int h = 38;
boolean alive = true;
boolean targeted = false;
Thing(PVector p) {
position = p;
velocity = new PVector(0, 3 + random(-thingIncidence, thingIncidence));
v1 = new PVector(position.x - w/2, position.y - h/2);
v2 = new PVector(position.x + w/2, position.y - h/2);
v3 = new PVector(position.x, position.y + h/2);
}
void update() {
position.add(velocity);
v1.set(position.x - w/2, position.y - h/2, 0);
v2.set(position.x + w/2, position.y - h/2, 0);
v3.set(position.x, position.y + h/2, 0);
if ((position.y - h/2) >= height) {
alive = false;
}
}
void draw() {
if (alive) {
triangle(v1.x, v1.y, v2.x, v2.y, v3.x, v3.y);
}
}
}
class Blaster {
PVector position;
boolean canFire = true;
int lastFired = 0;
int reloadTime;
Blaster(PVector p, int reload) {
position = p;
reloadTime = reload;
}
void draw() {
strokeWeight(1);
fill(0, 255, 0);
ellipse(position.x, position.y, width / 20, width / 20);
fill(0, 200, 255);
ellipse(position.x, position.y, width / 40, width / 40);
}
void update() {
if (millis() - lastFired > reloadTime) {
canFire = true;
}
}
void shoot(Thing thing) {
if (canFire) {
beams.add(new ParticleBeam(position, thing));
thing.targeted = true;
canFire = false;
lastFired = millis();
}
}
}
class ParticleBeam {
PVector start, velocity, end;
Thing target;
float speed = height / 40;
boolean alive = true;
ParticleBeam(PVector s, Thing t) {
start = s;
target = t;
velocity = PVector.sub(t.position, s);
velocity.normalize();
velocity.mult(speed);
end = new PVector(start.x, start.y);
}
void update() {
if (end.dist(target.position) < 2 * velocity.mag()) {
alive = false;
target.alive = false;
}
velocity = PVector.sub(target.position, end);
velocity.normalize();
velocity.mult(speed);
end.add(velocity);
}
void draw() {
stroke(lerpColor(color(254, 254, 34), color(255, 0, 0), 1 - end.dist(target.position) / start.dist(target.position)));
strokeWeight(15);
point(end.x, end.y);
}
}