Godar's Game Development Package Tutorial.



Sprite Animation and Movement.

APPLET HERE: My code for tutorial 2.
(Meet Whitie our new mascot)

Controls:

Arrow keys: movement
Space: Animation on/off
Mouse: Drag, reposition sprite

Plan:

The aim of this tutorial is to create a class that will animate a sprite and adjust that animation for the current mode of movement or situation that the character can be in. Before we get started it is imperative that we identify the modes that the character can be in. If you require to add more modes you will need to setup a class to cater for those modes which will be discussed later, the modes that will be covered by this class will be:

    • STOP (Stationary )
    • UP
    • DOWN
    • LEFT
    • RIGHT

You might want to add modes like firing a missile, death of sprite, angle movement. For now we will just concentrate on movement of the sprite not it's individual characteristics.

Implementation:

Fig 1: The image block used for this tutorial.

The first step in creating the image block is to identify the actions that the sprite will be able to perform. In this case the actions are:

      1. UP
      2. DOWN (used for stationary as well)
      3. LEFT
      4. RIGHT

In this example there are five actions which will require four rows of animation strips each animation has 3 frames of animation (foa) which calculates to each row having 3 columns. Fig 1 shows how the image block should be divided if we have four actions with three frames of animation. Initially there is no real limit to the number of actions and number of animation's per action you can implement. To create the image block the same principle applies as was used in Tutorial 1 when making the image block make each row an action that the character will be performing and make each column of that row a frame of animation for that action. Take a look at the BS_Action class description for more information on creating action image blocks. To initiate the BS_Action object you are required to supply a multidimensional Image array and as in the previous tutorial I have a utility that splits an image block into an image array. It requires that all the frames are of the same dimensions but none the less it is a very useful tool. Look at the code example below for how to use the method Image[][] ImgUtil.splitImgBlock(Image img, int rows, int cols).

It wise however to minimize the image size/colors to allow for faster loading times if it is to be run as an applet. The final block image is up to you! Feel free to use the provided block image of whitie for testing your programs.

I suggest using Photoshop's ImageReady utility to create the block image. Experiment with different characters, I found whitie by searching Google images for "sprite" or "image strip" and the like, you will find plenty of sprites to use and create block image's. Please e-mail me any block images or strip images you create and I will post them on this tutorial site here.

Now we have an image to use we must create a class to control the final sprite character (In this case Whitie). The Whitie class is fairly straight forward in this example, we will build on it in later tutorials however.

1
2
3
4
5
6
7
8
9
10
11
12
13

14
15
16
17
18
19
20
21
22
23
24
25

import sprite.*;

public class Whitie extends BS_Action {

// This is where you define the characters (whitie) action constants.
public static final int W_STOP = 1;
public static final int W_UP = 0;
public static final int W_DOWN = 1;
public static final int W_RIGHT = 2;
public static final int W_LEFT = 3;

/** Creates a new instance of Whitie */
public Whitie() {
// Send relevant data to BS_Action, Whitie's super class.
super(ImgUtil.splitImgBlock(Global.imgs[Global.IMG_1], 4, 3));
// Set the initial action that the sprit is at.
setAction(W_STOP);
super.update();

}
// TODO: you could write methods for direction control here.
// Effects like random animation's while sprite is inactive.
// AI for the sprite could be implemented here also.
// Get creative on your sprite..... ;-)
// I will implement directions in the GMainPanel.

}

List 1: Whitie class source code.

This simple wrapper class has one main function at present and that is to provide information to the BS_Action class in a human readable way using constants that can be referenced globally. As you can see the action constants (lines 6-10) define the actions available to this sprite. Then we have the number of actions and the number of animation frames per action. In the constructor (line 19) we call the BS_Action's constructor and send it the required data. If you recall tutorial 1 in our basic Java section, images are loaded into the imgs[] array in the Global class. I cut a corner here and neglected to implement direction control methods within the class. You can achieve this yourself call them void left(), void right()... etc. That wasn't to painful I hope. Now lets see how easy it is to use the new sprite.

Like any other object it must first be initiated. I also initiated a few other vars as well. For a list of methods inherited by the whitie check out the API of BS_Action. When I initiate the Whitie class I also positioned the sprite, set the type of animation mode to use, set the size of the displayed sprite and finally restore the sprite to visible and active. If you feel the sprite animates to fast try increasing the value in the setSkip(..) method.

	/** Tutorial 2 - Initialize class. */
        whitie = new Whitie();
        whitie.setLocation(Global.frameSize.width/2, Global.frameSize.height/2);
        whitie.setMode(BS_Loop.BS_SCAN);
        whitie.setSize(64,52);
        whitie.setSkip(1);
	whitie.restore();

A call to whitie.paint(g2) should be placed in the panel's paintComponent() method. Next a decision must be made on where to place the whitie.update() method which animates the sprite. It could be placed in a threads run() method or in the paintComponent() method which will create a constant animation (which is what happens when you press the space bar in the above applet). Or optionally you could place the update() call after a key is pressed so that the sprite is updated after each movement. Se the source code to see what I have don, if you press the space bar the sprite animates while not moving if you hit the space bar again the sprite only animates when the user move it.

switch(kc) {
    case KeyEvent.VK_UP:            //
        whitie.setAction(Whitie.W_UP);
        if(whitie.y > 0)
            whitie.y -= 5;
        break;
    case KeyEvent.VK_DOWN:          //
        whitie.setAction(Whitie.W_DOWN);
        if(whitie.y < getHeight()-whitie.getHeight())
            whitie.y += 5;
        break;
    case KeyEvent.VK_RIGHT:         //
        whitie.setAction(Whitie.W_RIGHT);
        if(whitie.x < getWidth() - whitie.getWidth())
            whitie.x += 5;
        break;
    case KeyEvent.VK_LEFT:          //
        whitie.setAction(Whitie.W_LEFT);
        if(whitie.x > 0)
            whitie.x -= 5;
        break;
    case KeyEvent.VK_SPACE:     // Auto animate on/off
        whitie.setAction(Whitie.W_STOP);
        animate = !animate;
        break;
}
List 2: A code fragment dealing with change of action and movement. (old version)

As you can see with every user input we make a call to whitie.setAction(..). This sets the action image strip that is to be animated. Now it becomes clear why we created the Whitie class with static int values. The optional implementation of this would be to create movement methods within the Whitie class and simply call them from here as I mentioned before. The movement methods could also update the sprites location, size and ensure that the sprite does not leave the screen area.

Well I hope that helps you animate a basic sprite feel free to send me any of your creations, I would be interested to see what gets created. That's all for this tutorial. To gain a greater understanding of what is going on here look at the GGD documentation.


Download Source: movement.zip

 


Copyright ©2000-2003 Michael Mifsud. All rights reserved.
godar@cairns.net.au