PS2 Linux Programming

 

2D Sprite Movement and Animation

 

Introduction

 

This tutorial will show how to draw and manipulate 2D sprites. A textured 2D sprites will be drawn using the sprite primitive. Simple sprite movement and animation will be performed.

 

 

Sprite Structure

 

The structure PS2Sprite_t, shown below, is defined in PS2Types.h to hold relevant information relating to the drawing, movement and animation of the sprite.

 

typedef struct

{

        int x, y;                             // Position on screen (top left)

        int z;                                 // z depth (big = near)

        int w, h;                            // Width and height

        int u, v;                             // Offset from texture top left

        unsigned char r, g, b, a;       // Colour and alpha

        int dx;                               // Direction for x

        int dy;                               // Direction for y

        int FCountMax;                   // Counter max value

        int FCount;                         // Frame Counter

        int NFrames;                      // Number of animation frames

} PS2Sprite_t;

 

The parameters of the structure are as follows. (x,y) is the position of the top left hand corner of the sprite on screen and z is the z depth used for z ordering. w and h are the width and height of the sprite. u and v are the offset into the texture, from the top left hand corner of the texture area to be used for the sprite. r, g, b and a are the colour and alpha value for the sprite. The other parameters are added to the structure to aid with the game logic. dx and dy are used to store the direction that the sprite is moving in the x and y directions respectively. NFrames is the number of animation frames that are used to define an animation sequence and FCount and FCountMax are used for timing of the animation.

 

The texture that is used in this example is shown in the diagram below. The first row of the texture consists of some tiles that can be used to draw a background and the next three rows consist of animation sequences, two of characters with walking/running animations and one explosion sequence. All of the sections within the texture are based on a square grid of 32 x 32 pixels. Notice that only half of the 256 x 256 texture is used, the right hand half of the texture is filled with black and can be filled with image data at a later time.

 

 

 

Sprite Texture

 

 

The main Program

 

Much of the initialisation that is performed in main.cpp has been described in previous tutorials and this will not be repeated here. Before the render loop is entered, the sprite structures are initialised with appropriate information. Within the render loop there is a function to move the sprite across the screen, MoveSprite(), and a function to animate the Sprite, AnimateSprite(). The GS packets are constructed using the BuildSprite2D() function which is contained in the file packet.cpp. BuildSprite2D takes two parameters, the first is a pointer to the structure describing the sprite to be drawn and the second is a pointer to the start of the area of memory where the primitive data is to be built. Once the primitive data is built, it is sent to the GS using the DMAC operating in normal mode. This could be extended to accommodate stitching if necessary but for the purposes of the present tutorial normal mode transfer is sufficient.

 

 

The BuildSprite2D function

 

The prototype for this function is:

 

 

int BuildSprite2D(PS2Sprite_t * pSprite, char *& pMem)

 

Notice that the actual memory pointer, pMem, (rather than a copy of the pointer) is passed to this function so that it can be incremented to reflect the amount of data written into the packet memory ( this is the function of the *& operator). The prim field of the GIFtag is set up to draw a sprite primitive and texture mapping is enabled. The register data that following the GIFtag is the primitive colour and the UV and XYX value for the two vertices. Notice that the UV and XYZ data for the registers are constructed from the current information that is contained within the sprite structure passed to this function – this means that every frame the new position, animation data, etc for the sprite will be written into the GS Packet. At the end of the function, the memory pointer, pMem in set to point to the next free location after the written data.

 

On running the program, two sprites are drawn on screen, one is static – e.g. a background tile, the other is an animated character which walks back and forward across the screen.

 

 

Conclusion

 

In this tutorial 2D sprites have been drawn using the sprite primitive. This primitive is sufficient for generating background images and some very simple movement/animation but it has many limitations. Two major limitations of the sprite primitive are (1) that the z depth over the complete surface of the sprite must be the same and (2) it is not possible to rotate the sprite. Considerably more functionality and control is obtained if a triangle strip primitive is used to draw a sprite and this will be introduced in the next tutorial.

 

 

Dr Henry S Fortuna

University of Abertay Dundee

h.s.fortuna@abertay.ac.uk