Tutorial 4 - Spawn Points and Factories

Continuing from Tutorial 3 - Game Objects, Sprites and Scrolling, we will add space mines to the playfield.

The Mine Class

Let's start by programming the space mine class. (Note: I added a sprite, called "sprMine," to the resource script.) If you followed the last tutorial, there shouldn't be anything surprising here:

#define MINE_ROTSPEED  2.0f
class SpaceMineObj : public GameObj {
    private:
        hgeSprite * m_sprite; // Mine sprite
        Vector2D    m_pos;    // Mine position
        float       m_size;   // Mine scaling
        
    public:
        SpaceMineObj ( Vector2D pos, float size ) {
            m_pos = pos;
            m_size = size;
            m_sprite = pResManager->GetSprite( "sprMine" );
        }
        
        void render ( int objLayer, float scrollX, float scrollY ) {
            // Render the mine, slowly rotating...
            m_sprite->RenderEx(
                m_pos.x - scrollX, m_pos.y - scrollY,
                MINE_ROTSPEED * Environment::time,
                m_size, m_size );
        }
};

It is possible to simply insert space mines into the playfield by using Environment::addGameObj(), but that's tedious and error-prone. Instead, we will use the Room Editor to tell Qaf where it should create mines; that way, we'll know exactly where they will appear.

Object Spawn Points

Open the room from the last tutorial, tut03.qr, in the Room Editor. From the Room menu, choose New game object and you should see this dialog:

tut04newobjdlg.png

Type "SpaceMineObj" in the Object ID field, then double-click on (New value...) in the attribute table. Type "size" as the key and "1.0" as the value, then click OK.

tut04objattributes.png

Click OK in the New game object dialog, and you'll see a small red square appeared at the center of the screen. You've determined the first mine's spawn point!

To move the object, use the Game Object Selection tool (just left-click and drag the red square).

Make a duplicate of the object by selecting it, copying it with Ctrl + C and pasting it with Ctrl + V. Now, click on the Edit game object button in the window's lower right. Double-click on the "size" attribute and change its value to "2.5" so the second mine will appear bigger than the first.

Repeat the process as many times as you want, changing the value of "size" so the playfield will have lots of mines with different sizes.

Now, go to Room -> New game object again, but this time type "ShipObj" as the object's ID. Click OK and place the ship at the center of the room.

tut04roomfinished.png

Save it as tut04.qr and close the Room Editor.

Everything we've written so far is just a bunch of strings, which are meaningless to Qaf. We'll have to somehow translate this data into actual GameObj instances.

The Game Object Factory

qaf::GameObjFactory is an abstract class with just one method:

qaf::GameObj* qaf::GameObjFactory::createObject ( std::string & objID,
                                                  int objX,
                                                  int objY,
                                                  qaf::AttributeTable & attributes );

Its parameters include everything you defined in the Room Editor: ID, position, and attributes. There's nothing Qaf can do with these values, so it's up to us to decode them and create a GameObj.

// Game object factory implementation:
class GameObjFactoryImpl : public GameObjFactory {
    public:
        GameObj * createObject ( std::string & objID, int objX, int objY, AttributeTable & attributes ) {
            // Which object ID?
            if ( objID == "ShipObj" ) {
                // Create ship at (objX, objY) coordinates, facing up:
                return new ShipObj( Vector2D(objX, objY), Vector2D(0, -1) );
            }
            else
            if ( objID == "SpaceMineObj" ) {
                // Get "size" attribute, and convert it to a floating point
                // number:
                float fSize = (float) atof( attributes["size"].c_str() );
                
                // Could not convert?
                if ( fSize == 0.0f )
                    fSize = 1.0f;
                
                // Create mine at (objX, objY), scaled by fSize:
                return new SpaceMineObj( Vector2D(objX, objY), fSize );
            }
            else
                // Unknown ID:
                return NULL;
        }
};

Bringing It All Together

Rather than creating the space ship through Environment::addGameObj(), we will now let our factory take care of object creation. In WinMain:

    // Load the room:
    Environment::loadRoom( "tut04.qr" );
    
    // "Hey, Qaf, this is what you should use to create game objects":
    Environment::setGameObjFactory( new GameObjFactoryImpl() );
    
    // Start the game loop:
    if ( !hge->System_Start() ) {
        MessageBox( NULL, hge->System_GetErrorMessage(), "Error", MB_OK | MB_ICONERROR | MB_SYSTEMMODAL );
    }

See the full source code for this tutorial in the file: tutorials/tutorial04.cpp


Generated on Sun Mar 25 12:32:13 2007 for Qaf Framework by  doxygen 1.5.1-p1