Animation Overview - News - Installation - Reference - Examples - FAQ  
 

A simple shooting game
This demonstrates a number of techniques: nested and chained animations, altering animations on-the-fly, and basing an animation off of mouse location.

 

 

BImage ship, badship, shot, cloud;
BFont font;
int score = 0;
Animation shot_fired, attacker, explosion, noise;

void setup()
{
  size(300,500);
  smooth();
  
  // load images
  ship = loadImage("ship.gif");
  badship = loadImage("attacker.gif");
  shot = loadImage("shot.gif");
  cloud = loadImage("cloud.gif");
  
  // setup font
  font = loadFont("RotisSanSer.vlw.gz");
  textFont(font, 18);
  
  // initialize shot animation & set as done (so it doesn't draw yet.)
  shot_fired = new Animation(this, shot, 0,475, 0,-475);
  shot_fired.setDuration(2500);
  shot_fired.setRepetitions(1);
  shot_fired.setDone();
  
  // initialize nested noise method for attacker & set as done.
  noise = new Animation(this, badship, 0,0, 0,0);
  noise.setStep("NOISE");
  noise.setDone();
  
  // initialize explosion animation & set as done.
  explosion = new Animation(this, cloud, 0,0, 0,0);
  explosion.setRepetitions(1);
  explosion.setDuration(250);
  explosion.setStep("SCALE");
  explosion.setEnd("makeAttacker");   // set explosion-end method to create a new attacker.
  explosion.setDone();
  
  // create an attacker.
  makeAttacker();  
}

void loop()
{
  background(0);
  fill(255);
  text("Score: " + score, 5, 20);
  fill(200);
  text("(Click to fire.)", 200, 20);
  image(ship, mouseX, 475);

  // check whether or not the shot has hit the attacker.  
  if (shotHitTest())
    shotHit();
    
  shot_fired.draw();
  attacker.draw();
  explosion.draw();
}

// when the mouse is clicked, (re)start the shot from the ship's location.
void mouseClicked()
{
  shot_fired.setRectangle(mouseX+ship.width/2, shot_fired.y(), shot_fired.w(), shot_fired.h());
  shot_fired.reset();
}

boolean shotHitTest()
{
  if (shot_fired.done())
    return false;

  // check for collision between the shot and attacker
  if ( (shot_fired.currentX() >= noise.currentX())
   && (shot_fired.currentX() <= noise.currentX() + badship.width)
   && (shot_fired.currentY() >= noise.currentY())
   &&(shot_fired.currentY() <= noise.currentY() + badship.height) )
    return true;
  else
    return false;
}

// if the shot has hit the attacker, start the explosion & increment the score.
// the explosion calls makeAttacker() when it finishes.
void shotHit()
{
  attacker.setDone();
  explosion.setRectangle(noise.currentX()-explosion.image().width/2,
                         noise.currentY()-explosion.image().height/2,
                         explosion.image().width*2, explosion.image().height*2);
  explosion.reset();
  shot_fired.setDone();
  score++;
}

// randomize a start position, path and velocity for the attacker.
void makeAttacker()
{
  noise.setRectangle(0,0, 20+(int)(Math.random()*30f), 20+(int)(Math.random()*30f));
  noise.reset();
  attacker = new Animation(this, noise, (int)(Math.random()*200f),0,
                          (int)(Math.random()*100f), 500+badship.height);
  attacker.setDuration(5000+(int)(Math.random()*5000));
  attacker.setRepetitions(1);
  attacker.setEnd("lost");
}

// if the attacker makes it all the way to the bottom of the screen, decrement the score.
void lost()
{
  score--;
  makeAttacker();
}