Exploding missile
back
Source
/* @pjs preload="rocket.png, explosion.png"; */
PImage rocket;
PImage explosion;
float SPEED = 4.5;
float TURN_RATE = 0.125;
float WOBBLE_LIMIT = 0.25;
float WOBBLE_SPEED = 0.75;
int SMOKE_LIFETIME = 200;
int NUMBER_OF_SMOKE_PARTICLES = 100;
int SMOKE_EMISSION_SPEED = 2;
// Create a variable called wobble that tweens back and forth between
// -WOBBLE_LIMIT and +WOBBLE_LIMIT forever
float wobble = WOBBLE_LIMIT;
float wobble_direction = 1;
float rocket_x;
float rocket_y;
float velocity_x;
float velocity_y;
float rotation;
Smoke[] smokeParticles;
int currentParticle;
int emitTimer;
ArrayList explosions = new ArrayList();
// Setup the example
void setup(){
size(640, 480);
imageMode(CENTER);
smokeParticles = new Smoke[NUMBER_OF_SMOKE_PARTICLES];
for(int i = 0; i < smokeParticles.length; i++){
smokeParticles[i] = new Smoke();
}
// Load images
rocket = loadImage("rocket.png");
explosion = loadImage("explosion.png");
rocket_x = width/2;
rocket_y = height - 16;
}
// The draw() method is called every frame
void draw(){
background(#4488cc);
// Calculate the angle from the missile to the mouse cursor game.input.x
// and game.input.y are the mouse position; substitute with whatever
// target coordinates you need.
float targetRotation = atan2(mouseY - rocket_y, mouseX - rocket_x);
// Add our "wobble" factor to the targetRotation to make the missile wobble
targetRotation += wobble;
wobble = lerp(wobble, WOBBLE_LIMIT * wobble_direction, WOBBLE_SPEED);
if(wobble == WOBBLE_LIMIT * wobble_direction)
wobble_direction *= -1;
// Gradually (this.TURN_RATE) aim the missile towards the target angle
if(rotation != targetRotation){
// Calculate difference between the current angle and targetAngle
float delta = targetRotation - rotation;
// Keep it in range from -180 to 180 to make the most efficient turns.
if(delta > PI) delta -= TWO_PI;
if(delta < -PI) delta += TWO_PI;
if(delta > 0){
// Turn clockwise
rotation += TURN_RATE;
}else{
// Turn counter-clockwise
rotation -= TURN_RATE;
}
// Just set angle to target angle if they are close
if(abs(delta) < radians(TURN_RATE)){
rotation = targetRotation;
}
}
// Calculate velocity vector based on rotation and this.SPEED
velocity_x = cos(rotation) * SPEED;
velocity_y = sin(rotation) * SPEED;
rocket_x += velocity_x;
rocket_y += velocity_y;
for(int i = 0; i < smokeParticles.length; i++){
smokeParticles[i].display();
}
emitTimer++;
if(emitTimer > SMOKE_EMISSION_SPEED){
emitTimer = 0;
smokeParticles[currentParticle].reset(rocket_x - velocity_x, rocket_y - velocity_y);
currentParticle = (currentParticle + 1) % smokeParticles.length;
}
float distance = dist(rocket_x, rocket_y, mouseX, mouseY);
if(distance < 50){
explosions.add(new Explosion(explosion, 4, (int)rocket_x, (int)rocket_y));
rocket_x = width/2;
rocket_y = height - 16;
}
pushMatrix();
translate(rocket_x, rocket_y);
rotate(rotation);
image(rocket, 0, 0);
popMatrix();
ArrayList deadExplosions = new ArrayList();
for(Explosion s : explosions){
s.display();
if(s.isDead()){
deadExplosions.add(s);
}
}
for(Explosion s : deadExplosions){
explosions.remove(s);
}
}
class Smoke{
float x;
float y;
float velocity_y;
int ttl;
void display(){
if(ttl <= 0)
return;
y += velocity_y;
ttl--;
pushStyle();
noStroke();
fill(255, 255, 255, (int)(255 * ( ttl / (float) SMOKE_LIFETIME)));
ellipse(x, y, 10, 10);
popStyle();
}
void reset(float x, float y){
this.x = x;
this.y = y;
this.velocity_y = random(-0.8, -0.5);
ttl = SMOKE_LIFETIME;
}
}
class Explosion{
PImage[] frames;
float currentFrame;
int x;
int y;
Explosion(PImage img, int noFrames, int x, int y){
int frameWidth = img.width / noFrames;
frames = new PImage[noFrames];
for(int i = 0; i < frames.length; i++){
frames[i] = img.get(frameWidth * i, 0, frameWidth, img.height);
}
this.x = x;
this.y = y;
}
void display(){
currentFrame = (currentFrame + 0.5);
if(currentFrame < frames.length){
image(frames[(int)currentFrame], x, y);
}
}
boolean isDead(){
return currentFrame >= frames.length;
}
}