CakeEater 4: Sprites and Animations

Planning
Step 1
In this lesson we will create a Sprite class which we can use to display images and play Animations
Temp1537487269
Step 2
Create a new file, Sprite.js, and use it to declare a new class named "Sprite"
Temp1537488775 Temp1537488793
Step 3
Also create another new file named Images.js
Temp1537488679

Inside this file we will preload() all of the images we will be using

Temp1537488697

setup() will not run until preload has finished loading

Step 4
Make sure Sprite.js and Image.js are included in index.html's header
Temp1537492326
Step 5
Download this file which contains the images we'd like to use
Temp1537489428 Download CakeEaterImages.zip

You should see these images when you open the folder:

Temp1537570375
Step 6
Drag an drop each image into the Asset pane to upload them
Temp1537568421
Step 7
Create a variable for the cake tile image then set it's value using loadImage()
Temp1537489821
Step 8
Copy and Paste the image source into the loadImage function
Temp1537489662

This source link should be a String, so we need to add "s around it!

Temp1537489893
Information
Step 9
You can get the image address of any image uploaded to the web by right clicking and choosing "Copy image address"
Temp1537568687

We don't need an image of a puppy right now, but it's still nice to see one isn't it?

Step 10
Make a global variable for each and every image
Temp1537570495

We'll assign them with loadImage() next...

Step 11
Each of these variable need an image loaded into them...
Temp1537570548
Step 12
Use the clipboard image next to each image file to copy the image source

Paste each image source into the loadImage() function for it's respective variable

Temp1537490810

It may be tedious to add all seven of these images, but you only have to do it once and it's much faster when you add a single image at a time.

Check Your Work
Step 13
All images are loaded into variables and ready to use in our project!
Temp1537570593
Planning
Step 14
Now let's start defining our Sprite class

First of all a Sprite is an image, so let's add a constructor that takes in one of these image variables we just made

Temp1537491755
Step 15
And the first thing a Sprite should be able to do is draw itself

Add a draw method which uses the image function to draw the Sprite's image

Temp1537491877
Step 16
To draw an image we need an x, and y, position as well as a width and height

We'll let the Sprite's owner supply these properties, so let's add some parameters

Temp1537569340
Planning
Step 17
Instead of our Tiles and Player being colored squares, we'll assign them Sprites
Temp1539211544
Step 18
Remove the color property from Tiles and Walls and replace them with a new Sprite
Temp1537492906 Temp1537569569
Step 19
Also give the crumbs a new Sprite using `crumbsImg`
Temp1539210342
Step 20
Instead of Tile.draw drawing a rectangle, we'll simply have it call its Sprite's draw method
Temp1537493336

Remember we need to supply Sprite.draw() with an x, y, width, and height.

Check Your Work
Step 21
You should now see cake for Tiles and candles for Walls
Temp1537493416

Something is weird about the candle image though...

Planning
Step 22
This candle image contains two separate animation frames
Temp1537569901

We want our Sprite to display one frame at a time, and later we'll make it animate

Planning
Step 23
The image function can take an additional 4 parameters, the source parameters

We can have image() display only a portion of the image source:

Temp1537571297

We refer to these colored boxes as the Source Image and the Display Image.

Planning
Step 24
In our case we want to take the first candle image from the group and display it on the canvas

Here I've labeled the Source Width (sw) and Source Height (sh) as well as the Destination Width (dw) and Destination Height (dh):

Temp1537572219
Planning
Step 25
We can display the other image by changing the "source x" and "source y"
Temp1537572532

Source x and y tells the program where from the source image to grab from

Display x and y tells the program where on the canvas to display the image

Step 26
Add a "Source Width" and "Source Height" property to the Sprite class
Temp1537573761

By default all of these images have a source width and height of 32

Step 27
Add sx, sy, sw, and sh to the image function in Sprite.draw()

For now we'll leave sx and sy at 0 so to always grab the first image

Temp1537573573
Check Your Work
Step 28
Your candles should now display one candle per tile
Temp1537573837
Information
Step 29
If we slide the Source X over by the Source Width, we should move to the next candle tile
Temp1537574013
Planning
Step 30
Each animation frame can be retrieved by increasing the source x by some number of source widths

Frame 0's sx is at 0 * sw

Frame 1's sx is at 1 * sw

Shown below: Frame 2's sx is at 2 * sw

Temp1537574743
Step 31
Add a frame property to the Sprite's constructor
Temp1537574869

We'll start at frame 0

Step 32
In the Sprite's draw method, set the "source x" to the "frame number" times the "source width"
Temp1537914557 Temp1537914509
Check Your Work
Step 33
So far nothing has changed
Temp1537913847

But now we can change the frame value to slide the source image x over...

Information
Step 34
If we set the starting frame to 1, we see this

The Candles display their second frame.

The Cake doesn't have a second frame, so it displays nothing...

Temp1537913806
Planning
Step 35
We're going to use this frame advancing to make our Sprites animate

In particular, we'll be making our Candle's flicker

Step 36
First add a property named "numFrames" to the Sprite class

Make it the second parameter in the constructor, and set its default value to 1:

Temp1539122963

I like to name my parameters with long-form names numberOfFrames but keep my property names short numFrames.

Step 37
Now create an animate method
Temp1539123158
Step 38
Animation of a Sprite is where the frame number increases by 1
Temp1539123822
Step 39
If the frame number is greater than the number of frames, we reset it back to 0
Temp1539123887

We actually need to write >= because frame starts counting at 0

Step 40
We'll have each Sprite call it's animate method from it's draw method
Temp1539124103
Step 41
We'll also set the numFrames of the candle to 2
Temp1539124404
Check Your Work
Step 42
You should see the candle flickering, but way too fast

Your computer's frameRate might make the animations look like they aren't playing.

If you are having trouble, try adding frameRate(40) into your code and see if that helps.

Planning
Step 43
What we want is to only advance the frame number every few frames

For example, we may want the candle to only flicker once every 30 frames like this:

Information
Step 44
To do this we can use the modulo operator like so:

frameCount is a p5js value which records the number of game frames since the program began

Here is what we get if we console.log(frameCount % 4)

Temp1539126616

And here if we console.log(frameCount % 10)

Temp1539126728
Step 45
We can advance the Sprite's frame once every 30 frames, by only increasing it when (frameCount % 30 === 0)
Temp1539126899

frameCount % 30 will count 0, 1, 2, 3, 4...28, 29, and then 0 again. Repeating once every 30 frames.

Check Your Work
Step 46
Now the candle flickers at a much more reasonable rate
Step 47
Let's add a frameSpeed parameter to control this speed
Temp1539127100

We'll set a default value of 0 assuming most Sprites will not be animated.

Step 48
Instead of using the flat number 30, let's use the frameSpeed property
Temp1539127544

Note that a higher value for frameSpeed actually makes the candle flicker more slowly

Step 49
Now remember to set the frameSpeed when we make the Wall sprite
Temp1539127687

The default frameSpeed is 0, so we need to set the candle's sprite's frameSpeed to 30

Step 50
Just for safety, let's cancel the animate method if the frameSpeed is 0 or negative

We use return to exit the function if frameSpeed <= 0

Temp1544080044

We would get an error if we tried to modulus by zero.

Planning
Step 51
Next we're going to add a sprite for the CakeEater

This sprite has 4 directions, and if you take a look at it's spritesheet you will see it looks like this:

Temp1539128381

Each row displays the CakeEater in a different direction..

Challenge
Step 52
Add a sprite property to the CakeEater

Fill in the missing parameters:

Temp1539132323
  • The CakeEater is 32 x 32 pixels on it's spritesheet.
  • How many animations frames does it have?
  • It's frameSpeed should be set to the same speed as the candles.
Step 53
Have it draw the sprite in its draw() method
Temp1539132656
Check Your Work
Step 54
The CakeEater should now open and close its mouth

But it still faces to the left no matter what direction it's moving in...

Planning
Step 55
We can change the direction of the sprite by changing the "Row" on the source image

Our Source Y has been at 0 pixels and so the Sprite is facing to the left.

Temp1539132928

If the Source Y is at 32 pixels the sprite will be facing down.

What direction will it be facing if the Source Y is set to 3 x 32px which is 96px?

Step 56
We will call the row number the "animation number". Add it as a property of the Sprite class

Open Sprite.js

Temp1539133514

Add this property

Temp1539133478
Step 57
If we multiply this animation number by the height of the source window we obtain the source Y

Say we wanted the sprite to face down

Temp1539134265

The animation number would be 1, multiplied by 32 gives us a source height of 32px

Challenge
Step 58
Create a local variable for source y and calculate it using the animation number and the source height
Temp1539134520

Fill in the blank area with the formula and plug sy into the image function

Check Your Work
Step 59
If you set the animationNumber to 1, you should see the CakeEater face downwards
Temp1539210609

The other sprites will disappear if their animation number is set to 1.
(Except for the crumbs)

Step 60
In the CakeEater's setVelocity method, set the sprite's animation number to 3 when the RIGHT_ARROW is pressed
Temp1539135274 Temp1539210678
Challenge
Step 61
Try to get the CakeEater to face every direction by changing the animation number when each arrow is pressed
Challenge
Step 62
At the bottom of the setVelocity method, add logic to make the animation play faster when the CakeEater is moving

I'll start you off with some code, but see if you can replace the comments to make it work:

if ( //the xvelocity and yvelocity are both 0) {
    //Set this object's sprite's frameSpeed to 10
} else {
    //Set frameSpeed to 30
}
Check Your Work
Step 63
You should now see the character's chomping speed increase while moving!
Planning
Step 64
Next lesson we're going to get FANCY by adding some CSS styling and making the cake look more 3D
Temp1539211410
CakeEater 4: Sprites and Animations Info

Account

MVCode Clubs

Created By

Newprofile jamie

Course:

CakeEater

Access Level

premium

For Teachers and Schools

Teach coding to your students with MVCode Teach

MVCode offers an integrated product designed to teach coding to students.

Learn more about MVCode Teach