Smoke trails

back

Source

/* @pjs preload="rocket.png"; */

PImage rocket;

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;

// 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");
}

// 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;
  }
  
  pushMatrix();
  translate(rocket_x, rocket_y);
  rotate(rotation);
  image(rocket, 0, 0);
  popMatrix();
}

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

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