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

Warning: Cannot load module "http" because required module "raphf" is not loaded in Unknown on line 0