SDL Gamer

Search this site

Lesson 14. Create An Object In A Game


Here demonstrate a way to create an object in a game.   The object can be a
bullet , a missile , a house , a creature , an item , a box or anything.

This event can be triggered by press a button , open a treasure box , hit a
special square , etc.

The program here , creates a ball and a warrior dart by hit a key "f" and "d".
Depends on how you define it.    In here , the ball will move to the x+ direction
(move to the right) with accelerate 1.   The warrior dart move to the x+ and y-
direction(y- is going up while y+ going down) with a y+ accelerate 1.

The propeller is a decoration here , it does not move but just changing
pictures.    It's an animation effect here.

WARNING : This lesson may be a challenge for a beginner.    Make sure
you understand & familiar with previous lessons before continue reading.
Got the program idea by reading Program Flowchart is the key to under-
stand this lesson.

Skip to Lesson 15. Shoot A SDL_Rect Bullet


Download this program here :
ATest_L14.zip 752k

Screen Shot

Ball
 
 
 
 
 
 
 

Warrior Dart
 
 
 
 
 
 
 
 
 
 
 
 

Propeller
 
 
 
 


Program Flowchart :
1. Create a class for an object
2. Initialize this object
3. Waiting for trigger event
4. When triggered , searching for a vacancy to active this object (see PS1.)
5. If found one , register and initialize it into this vacancy 
6. If no vacancy available , then doing nothing
7. Show all the active objects
8. Execute the code that describes how the objects move
9. Checking for destroy condition for objects
10. Goto Step 3.

PS1. Creating an object will occupy memory , so usually we need to define a limit
          number for a type of objects.


Program Code :

test.h

#define MaxObjPic_No 12
#define ActBall_No 6
#define ActDart_No 3


 
// We see that animation as an object , so it should contain all pictures
// : anim[Pic_No] , coordinate infomation : animRect , and current picture
// index : pidx
class _ANIM_OBJ {
    public:
        struct _OBJ {
            bool alive; // Display the obj if it is alive
            SDL_Surface *anim[MaxObjPic_No];
            SDL_Rect aRect ; // The position of a picture
            int aTick;
            short pidx , pDelay; // The delay for changing to next pic
            short xidx , yidx ; // The coordinate of an object
            short offsetX , offsetY; // The offset value from xidx to aRect.x
            short picNo; // The picture no of this object
            // For Move Funtion
            short vx,vy , ax,ay; // VelocityX,Y , AccelerateX,Y
            } ball[ActBall_No] , dart[ActDart_No] , propeller;

        SDL_Rect animRect;
        short xidx , yidx ; // The coordinate of an object
        short picNo; // The picture no of this object
        void Initialize(_ANIM_OBJ & Xao);
        // Show this obj on a dst surface
        void showOn(_ANIM_OBJ & Xao , _SYSTEM & Xsys );
        void CreateObj( _OBJ & obj , short Xo , short Yo , short VX ,
                short VY , short AX , short AY);
        // OBJ Functions
        void showOnObj( _ANIM_OBJ & obj , _SYSTEM & sys );
        void MoveObj( _OBJ & obj );

    private: // The members in private are for internal usage.
        SDL_Surface *anim[MaxObjPic_No];
        int pidx;
        int aTick;
        void Move(_ANIM_OBJ & Xao , _SYSTEM & Xsys );
    };


test.cpp
 void _ANIM_OBJ::Move(_ANIM_OBJ & Xao , _SYSTEM & Xsys ) {
    if(Xsys.bKeyUP) Xao.yidx = Xao.yidx - 2;
    if(Xsys.bKeyDOWN) Xao.yidx = Xao.yidx + 2;
    if(Xsys.bKeyLEFT) Xao.xidx = Xao.xidx - 2;
    if(Xsys.bKeyRIGHT) Xao.xidx = Xao.xidx + 2;
    if(Xsys.bKeyA) {
        Xsys.ATick++;
        if(Xsys.ATick%6 == 1) {
            // Searching a vacant slot for this request
            for(int i=0 ; i < ActBall_No ; i++ ) if( Xao.ball[i].alive == 0 ) {
                Xao.CreateObj( Xao.ball[i] , Xao.xidx , Xao.yidx - 20 , 10 , 0 , 1 , 0 );
                break; // Got one vacancy and break for loop
                }

            } // if(Xsys.ATick%5 == 1) { END
        } // if(Xsys.bKeyA) { END
    if(Xsys.bKeyB) {
        Xsys.BTick++;
        if(Xsys.BTick == 1) {
            // Searching a vacant slot for this request
            for(int i=0 ; i < ActDart_No ; i++ ) if( Xao.dart[i].alive == 0 ) {
                Xao.CreateObj( Xao.dart[i] , Xao.xidx , Xao.yidx - 20  , 10 , -15 , 0 , 1 );
                break; // Got one vacancy and break for loop
                }
            } // if(Xsys.BTick == 1) { END
        } // if(Xsys.bKeyB) { END
    // The offset from obj(x,y) to its pic
    Xao.animRect.x = Xao.xidx - 50 ;
    Xao.animRect.y = Xao.yidx - 90 ;
    return;
    }

void _ANIM_OBJ::showOnObj( _ANIM_OBJ & obj , _SYSTEM & sys ) {
    // Searching alive object and show on screen
    for(int i=0 ; i < ActBall_No ; i++ ) if( obj.ball[i].alive == 1 ) {
        obj.ball[i].aTick++ ;
        if( obj.ball[i].aTick % obj.ball[i].pDelay == 0 ) obj.ball[i].pidx++;
        if( obj.ball[i].pidx >= obj.ball[i].picNo) obj.ball[i].pidx = 0;
        obj.MoveObj(obj.ball[i]);
        SDL_BlitSurface( obj.ball[i].anim[obj.ball[i].pidx] , NULL , sys.screen , &obj.ball[i].aRect );
        }
    // Searching alive object and show on screen
    for(int i=0 ; i < ActDart_No ; i++ ) if( obj.dart[i].alive == 1 ) {
        obj.dart[i].aTick++ ;
        if( obj.dart[i].aTick % obj.dart[i].pDelay == 0 ) obj.dart[i].pidx++;
        if( obj.dart[i].pidx >= obj.dart[i].picNo) obj.dart[i].pidx = 0;
        obj.MoveObj(obj.dart[i]);
        SDL_BlitSurface( obj.dart[i].anim[obj.dart[i].pidx] , NULL , sys.screen , &obj.dart[i].aRect );
        }
    if( sys.aTick % obj.propeller.pDelay == 0 ) obj.propeller.pidx++;
    if( obj.propeller.pidx >= obj.propeller.picNo) obj.propeller.pidx = 0;
    SDL_BlitSurface( obj.propeller.anim[obj.propeller.pidx] , NULL , sys.screen , &obj.propeller.aRect );
    return;
    }

void _ANIM_OBJ::MoveObj( _OBJ & obj ) {
    if(obj.vx > 20) obj.vx = 20;
    if(obj.vx < -20) obj.vx = -20;
    obj.xidx = obj.xidx + obj.vx ;
    obj.vx = obj.vx + obj.ax ;

    if(obj.vy > 20) obj.vy = 20;
    if(obj.vy < -20) obj.vy = -20;
    obj.yidx = obj.yidx + obj.vy ;
    obj.vy = obj.vy + obj.ay ;

    obj.aRect.x = obj.xidx - obj.offsetX ;
    obj.aRect.y = obj.yidx - obj.offsetY ;
    // Destrol an object when....
    if(obj.xidx > 500 || obj.xidx < -100 ) obj.alive = 0;
    if(obj.yidx > 400 || obj.yidx < -100 ) obj.alive = 0;
    return;
    }

void _ANIM_OBJ::CreateObj( _OBJ & obj , short Xo , short Yo , short VX ,
                    short VY , short AX , short AY) {

    obj.alive = 1; // Register a vacancy
    obj.xidx = Xo; // Initialize this object
    obj.yidx = Yo;
    obj.vx = VX;
    obj.vy = VY;
    obj.ax = AX;
    obj.ay = AY;
    obj.pidx = 0;
    obj.aTick = 0;
    return;
    }



In here , the motion of an object alone x-axis is define by :
X= Xo + Vx t
Vx = Vo + Ax t
Since t = 1 frame , So we got :
X= Xo + Vx
Vx = Vo + Ax

.
Lesson 14 END

Do you notice a bug in the example program?

test.h
 
// Draw string on screen : Convert Variable Argument into a string then blit
inline void txtIt(_SYSTEM & Xsys , short x , short y , short fsize ,
                            short r , short g , short b , char *pStr , ...) {
    Xsys.txt.imgTemp = TTF_RenderText_Solid( Xsys.txt.font16 , Xsys.txt.string , Xsys.txt.fColor );
    SDL_BlitSurface( Xsys.txt.imgTemp , NULL , Xsys.screen , &Xsys.txt.imgRect );
    SDL_FreeSurface(Xsys.txt.imgTemp); // Release the memory asked by TTF_(...)
    return;
    }


Missing SDL_FreeSurface(...) after return *SDL_Surface to Xsys.txt.imgTemp;
I thought we can re-use the same *SDL_Surface again and again without SDL_FreeSurface( ).  But I was wrong.
This will result in the memory be eaten little by little.


bdragon
Copyright © 2009 bdragon All rights reserved.
Č
ċ
ď
Bdragon Ho,
Aug 22, 2009, 11:36 PM
Comments