Linux Game Programming for PC & Embedded Systems using SDL
Presented by
Fore June
Author of Windows Fan, Linux Fan

Games and SDL
SDL Installation
SDL for Embedded
SDL API
SDL Events
 SDL Graphics
SDL Threads
Thread Example
SDL Animation
SDL Sound
 Raw Video Player
Video Formats
Video Compression
 Game Trees
About The Author

An Introduction to Video Compression in C/C++ now available at Amazon

An Introduction to Digital Video Compression in Java now available at Amazon
An Introduction to Digital Video Data Compression in Java now available at Amazon
Click here to see table of contents.

@Copyright by Fore June, 2006
SDL Animation
1 2
    In the chapter SDL API you have learned the basics of SDL video display. Even with that basic knowledge, you can do turtle graphics, simple games and many other interested things that need graphics. In the chapter, we discussed the use of the function IMG_Load() to load an image to the memory and the use of SDL_BlitSurface() to display a specified portion of an image on the screen. In this chapter, we shall utilize these two functions to present slighlty more advanced features such as animation on the screen. Some readers may think that animation is simply sliding an image across the screen. In practice, animation involves the continuous change of shape and appearance of an image object on the screen. The is done by drawing a sequence of incrementally changing bitmapped images on the screen over a controlled time interval. Because of the persistent perception of human eyes, the displayed object appears changing or moving smoothly on the screen rather than jittering in discrete steps. Each screen update in an animation sequence is called a frame, and the number of frames drawn per unit time is referred to as framerate.

    We shall employ two images used in the popular game Bejeweled to illustrate some basic techniques in graphical animation. In a later chapter, we shall discuss a full implementation of this game; in this Chapter, we just discuss the animated features: how to flash and rotate the jewels and how to swap two adjacent jewels. The following two images, "jboard.jpg" ( left )and "jewels.png" (right ) shown in Figure 1 will be used in the examples of our discussion ( you can download each of the images by pointing your mouse at it and right-clicking the mouse button ).


    jboard.jpg
     
    jewels.png
    Figure 1

  1. Organizing Images

    Utilizing the above images we can form the jewel board for the game. We use "jboard.jpg" as our background image and we pick the jewels to be displayed from "jewels.png". As shwon in "jewels.png", there are seven different kinds of jewels; the first and second row show a yellow diamond with different features; the third and fourth row show a grey octagonal jewel and so on. We shall randomly populate the board with these seven kinds of jewels. At the beginning only the one shown in the first column and upper row is chosen for display. By randomly picking the jewel images from "jewels.png" and displaying them on top of "jboard.jpg" at the appropriate positions, you should be able to generate an image like the one shown below.

    Figure 2

    To achieve realistic animation effect, you simply select the jewel images in a row from "jewels.png" and display them one by one at the same board position with a desired time lapse. For example, to rotate the yellow diamond-jewel, you display in the first time frame the jewel image at ( column 1, row 1 ) of "jewels.png"; in second time frame, you display the image at ( column 2, row 1 ) and so on. To flash the yellow diamond-jewel, you choose the images from the second row of "jewels.png". To swap two adjacent-column jewels of Figure 2, you move the left-jewel right one pixel and the right-jewel left one pixel in a time frame until the the two jewels have got into the right positions. We discuss how to achieve these animation effects in detail in the following paragraphs.

  2. Animation with SDL_BlitSurface

    SDL_BlitSurface() is the main function that we shall use to achieve the rotating or flashing animation effects. We define two classes, Jewel which holds the properties of a jewel ( i.e. What kind of jewel is it? Where is it located? ), and JBoard which contains information of the jewel board. Obviously, the jewel board holds jewels; in the jargon of object-oriented programming, we say that JBoard has-a Jewel. We also define a Point class to facilitate our programming. As shown below, the Point class is particularly simple, having only two data fields, x and y and two constructors. ( Remember that we are writing programs for both PC and embedded systems which have limited resources. Also, in many cases simplicity is needed to present some concepts more clearly. So the programming style presented here may not be the most eloquent but its easy to understand. )

    The Point class can be used to denote the coordinates of a position on an SDL screen, like the point where we click the mouse button. Since the number of rows and columns of jewels we consider ( see Figure 2 ) is 8, we can label the row number or column number of a jewel with an integer value between 0 and 7. For clarity, we define an alias to Point and call it Location: When we refer to the location of a jewel in column number and row number, we use the class Location.

    As shown below, the Jewel class is also very simple; it is basically a struct.

    The JBoard class shown below represents the jewel board and has member functions to do the animation effects discussed above.

    The constructor of JBoard shown below saves the information where to get the seven different kind of jewels from "jewels.png" ( saved in array jSource[] ) and where to put jewels on the board ( saved in array jewels[][].dest ).

    Note that the two image sources "jboard.jpg" and "jewels.png" are located in a subdirectory "images". So if you want to try the example you have to create a subdirectory "images" and put the two image files there. The data members imageMain and image of JBoard point to the memory that has "jboard.jpg" and "jewels.png" loaded respectively. Each jewel image size is only 48x48 pixles and it is about 52 pixels apart from a neighbour jewel.

    After loading the required images into memory and saving the jewel image positions in the constructor, you can construct the jewel board and populate it with various kinds of jewels using the init() member function as shown below.

    The statement displays the image "jboard.jpg" on the screen. This image acts as the background or the board for the jewels. The statement inside the for loop puts a jewel image on the board. A random number generator ( rand() ) is used to randomly select jewels from the seven kinds to populate the board. After this step you should see a board full of jewels as shown in Figure 2.

    The functions x2Col(), y2Row(), and jewelLocation() are responsible for converting a point cooridinate ( x, y ) to a location coordinate ( i, j ) where i, j are column number and row number of jewel, ranging from 0 to 7.

    The neighbour() function shown below is to determine if two jewels located at Locations m and n are adjacent neighbours of each other. If the jewels are neighbours of the same row, the function returns 1 and if of same column, it returns 0 otherwise it returns -1.

    With the few functions defined above, we can write a function to show the animation effects of swapping two adjacent jewels. The function swapJewels() shown below will do the job. In the code, the macros JWIDTH and JHEIGHT are defined to be 52 pixels, which is approximately the height and width of a square that holds a jewel. ( The height and width of a jewel are held in the data fields width and height, which are 48 pixels.

    In the code, if two adjacent jewels are on the same row, the statement calculates the distance in pixels between the two jewels; to swap the two jewels one has to move left d pixels and the other move right for the same distance. The variables, source0, dest0, source1, and dest1 handle the background of the square holding the swapping jewels. To achieve the effect of moving the jewels over a fixed background, we must first display the background image data at the square before displaying the jewel image. Otherwise, the old jewel image will appear as residuals in the screen. This is done by the two statements On the other hand, the two statments, are used to display the jewel images at the new positions. The function SDL_UpdateRect() is to present the new data of the affected regions to the screen; you won't see the change until this function is executed. This function only updates the region specified ( which is 104x104 in our example ) and is lot faster than the function SDL_Flip() which updates the entire screen. After moving the jewels, we have to update the state of the jewel board. This is achieved by the code: You can test the class with a piece of code like the following.

  3. Animation with Frames

    In this section, we discuss how to write a piece of code that can rotate or flash a jewel. For simplicity, we select a jewel by pointing the mouse at it and clicking on the mouse button; the chosen jewel is randomly set for action of rotation or flashing. If two adjacent jewels are chosen, they will be swapped with each other.

    We define a class JMouse that implements the actions.

    The constructor of JMouse shown below is simple. We simply let its data member jBoard point to the jewel board we are working with. Through this pointer jBoard we can access the functions and data members of the class JBoard. We could have used inheritance for JMouse to inherit everything from JBoard and achieve the same results. However, we don't want to use inheritance at this point because an instance ( object ) of the resulted class will be much larger.

    The function doJewel() shown below implements the rotation or flashing animation of the jewels.

    The function doJewel() takes two input arguments, a Point p parameter specifying the jewel to be acted upon and a short action parameter to specify whether you want to rotate or to flash the specified jewel. The codes for the two actions, rotation and flashing only differ in the row of jewels you need to select. As you can see from the code, the for-loop draws the sequence of incrementally changing jewel images at a position on the screen; the jewel images are obtained from "jewels.png" which has been loaded in the memory and is pointed at by jBoard->image; there are totally 16 different images in a sequence ( one row ). The statement SDL_Dealy ( 30 ) ( delaying for 30 ms ) controls the time interval between two frames.

    Finally, to demonstrate the flashing, rotating, and swapping animation effects, we create a thread named mouse_thread() to handle the actions:

    Whenever we click the mouse, the point at which we clicked at is saved in the queue mouse_down_queue. The thread examines this queue and extract the point if its not empty. It randomly sets the action for rotation or flashing. If two adjacent jewels are clicked, it swaps the two jewels.

    To run the thread, you should have a piece of code like the following to create and run it:

    For clarity of presentation, we have omitted the step of using a mutex to protect the shared global variable mouse_down_queue but in practice you should include the protection mechanism as discussed in the Chapters SDL Thread and Thread Example.