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