We have made some simple video games using the normal drawing
commands available in Processing. That approach leads to
complex, messy programs with lots of variables and lots of
commands.
A sprite is a moving character in a video game.
Each sprite is a package containing:
- variables with data about the position and speed of the
Sprite
- methods that can do things like moving the Sprite,
changing directions, hiding, etc.
By using a Sprite class, we gain several advantages :
- someone else can do all the really tricky coding
- we can hide all the complexity in the package, so our program
only contains the control commands that we want to write
This program has 2 Sprites - the Cookie and the Player. The
user presses the arrow keys to move the Player around, to get it
under the falling cookie and "eat" it.
Here is the code for the CookieMonster program. It won't
run by itself, because you also need the Sprite class (available
in the .zip archive above).
Sprite player,cookie; void setup() { size(800, 600); textFont(createFont("Arial",36)); frameRate(20); player = new Sprite("grinch",16); player.setSides(0,800,200,600,1); player.place(400,450); cookie = new Sprite("cookie.jpg"); cookie.place(200,0); cookie.setSpeed(0,20); cookie.setSides(2); } int points = 0; void draw() { background(0); if(frameCount <= 100) { text("== Cookie Monster ==",50,50); text("Use the arrow keys to eat cookies",50,100); text("Starting automatically after 5 seconds",50,200); return; } fill(255); if(points >= 500) { text("YOU WIN",350,300); text("Total time = " + frameCount / 20.0,350,350); noLoop(); } else { text(points,400,40); } if(keyPressed) { if(keyCode==UP) { player.setSpeed(0,-5); } if(keyCode==DOWN) { player.setSpeed(0,5); } if(keyCode==LEFT) { player.setSpeed(-5,0); } if(keyCode==RIGHT) { player.setSpeed(5,0); } } player.display(); cookie.display(); if(player.hit(cookie)) { points = points + 100; cookie.place((int)random(700),0); } } |
The Cookie is quite simple. It is a single image -
Cookie.jpg - stored in the sketch folder.
In setup, the Cookie Sprite is created by these commands:
cookie = new Sprite("cookie.jpg"); //
load the image
cookie.place(200,0);
// starting position
cookie.setSpeed(0,20);
// speed of movement
cookie.setSides(2);
// side behavior = wrap around
The image is loaded, the cookie's
starting position is set to (200,0), it's speed will be 0 across
and 20 down, and it will wrap around when it reaches the bottom of
the screen.
In the draw method, the Cookie only needs one
single command:
cookie.display();
That command does 2 things - draws the Cookie AND
moves it. We don't need a movement command like : cy =
cy + 20; , because the Sprite code takes care of moving
the Sprite - that's automatic.
The Player is considerably more complex than the Cookie.
The Player has 16 different images. These are displayed one
after another, creating an animation.
In setup, the Player Sprite is created by thise commands:
player = new Sprite("grinch",16);
player.setSides(0,800,200,600,1);
player.place(400,450);
The new Sprite command load 16 images named :
grinch0001.jpg, grinch0002.jpg, .... , grinch0015.jpg
The .setSides command says that the Player will STOP at the edges
of the movement box, which extends from 0 to 800 across and from
200 to 600 up and down.
The .pl.ace command puts the Player at location
(400,450).
The Player will not move automatically, because there is no
.setSpeed command.
The user presses the arrow keys to move the Player. These
commands take care of moving the Player around:
if(keyPressed)
{
if(keyCode==UP)
{ player.setSpeed(0,-5); }
if(keyCode==DOWN)
{ player.setSpeed(0,5); }
if(keyCode==LEFT)
{ player.setSpeed(-5,0); }
if(keyCode==RIGHT)
{ player.setSpeed(5,0);
}
}
player.display();
Notice that the .setSpeed commands take care of moving the
Player, which moves automatically when .display executes.
The .hit command checks whether two Sprites have collided -
whether they are overlapping. These commands check whether
the Player and the Cookie are touching:
if(player.hit(cookie))
{
points = points + 100;
cookie.place((int)random(700),0);
}
After the cookie is touched, it moves to a random x-position, at
the top of the screen (y=0).
Notice that cookie.hit(player) would do exactly the same
thing as player.hit(cookie) .
Every time the Player eats a Cookie, he scores 100 points - using
the command:
points = points + 100;
The following command displays the score at the top of the
screen:
text(points,400,40);
The game ends when the Player has 500 points - after eating 5
Cookies. Here are the commands to check the score:
if(points >= 500)
{ text("YOU WIN",350,300);
text("Total time = " +
frameCount / 20.0,350,350);
noLoop();
}
The Draw method executes automatically, over and over again -
normally at 60 frames per second. This program uses a slower
speed of 20 frames per seconds, set by this command:
frameRate(20);
At the end of the game, the total number of seconds played are
calculated by this command:
text("Total time = " + frameCount
/ 20.0 , 350 , 350 );
frameCount is a system variable that counts the number of
frames that have been displayed. Dividing by 20.0 changes
frameCount into seconds.
Adding a new Sprite (monster) is relatively straightforward, buy
involves several steps.
The rules and strategy for your game are implemented by various if..
commands that respond to events like one Sprite hitting
another.
The appearance of the game depends largely on the animations
you create.
It's possible to create an animation by using a graphics program,
like GIMP, to draw a series of frames, where each frame is
slightly different than the previous frame. But drawing
animations is quite time-consuming. There are plenty of GIF
Animations available on Google Images - search for "GIF
Animation".
Find a good GIF animation and save a copy on your local
hard-disk. This is a single file containing several
different frames. You need to extract the frames into
separate images. You can do this at the following web-site:
http://ezgif.com/split
At the web-site, upload your .GIF animation. The web-site
will automatically separate your animation into separate images
that you can copy into the data folder of your program. Save the
files into the DATA folder in your program. Then rename them
so the all look like this:
picture0000.jpg
picture0001.jpg picture0002.jpg ......
Or you might end up with .GIF or .PNG files, but those will work
too.
Speed - The .setSpeed(x,y) command tells
how far across and how far up and down the Sprite will move after
each .display command.
Sides - When a Sprite reaches the edge of the screen, it
behaves as specified in the .setSides command:
.setSides(xmin, xMax, ymin, yMax, mode)
The
first 4 numbers tell the limits of movement.
MODE
tells what to do when the Sprite reaches an edge:
0 = no action, keep moving
1 = stop moving at the edge
2 = wrap around to the oppoite edge
3 = bounce in opposite direction