Skip to main content
GameDev.net gamedev.net
🔒 Locked

How to manage level data

Started by Storyyeller Nov 20, 2009 at 3:24 PM 3 replies 600+ views
Original Post
Storyyeller
Storyyeller
I am currently making a 2d platformer game in C++. One issue I've run into is how do you manage level data? Currently, everything is hardcoded into the game, but I think this is not a very scalable solution. I assume that the usual practice is to store level data is some sort of external format, but I'm not sure how to do this. How do you format your level files? What parts do you put in the files, and what parts do you code into the game? It is relatively straightforward to put something like basic level geometry into the file, but what about complex triggers? It seems like some things have to be coded into the game, even if they are only used in a single room. Otherwise you may as well rewrite the game in a scripting language. Here is an example of what my code looks like right now. Doomed Hometown is a nearly empty room with one exit and one simple trigger that causes a house to fly upwards when the player walks over it.

#include "DoomedHometown/house.h"
namespace DoomedHometown
{
    inline void LoadCamera(Camera& target) {target.SetBounds(0,0,800,600);}
    inline WorldCoordAnim* GetBackground() {return new WorldCoordAnim( new PlainImage(zlBACKGROUND, ImgDataStruct("DoomedHometown/homescreen.bmp")),0,0);}
    inline CollisionProfile GetActiveBounds() {return CollisionProfile(0,-32,864,600);}

    inline void LoadEntities(entitymanager_ptr myManager, RoomLoader* myRoomManager)
    {
        assert(myManager);
        assert(myRoomManager);

        //Brushes
        myManager->AddEntity(new eBrush(0,-32,32,864)); //Top
        myManager->AddEntity(new eBrush(832,0,32,600)); //Right side
        myManager->AddEntity(new eBrush(800,40,32,390)); //Right side 2
        myManager->AddEntity(new eBrush(0,0,134,600)); //Office building
        myManager->AddEntity(new eBrush(134,511,730,25)); //road

        //Entities
        myManager->AddEntity(new SavePoint(myManager, 456,400, HARD));
        myManager->AddEntity(new TinyHouse(229,475));
        for(int y=430;y>0;y-=130)   {myManager->AddEntity(new Spike(768,y, Spike::LEFT));}
        myManager->AddEntity(new TriggerBrush(800,430,32,211, new WarpCallback(myRoomManager, WarpDest::TUTORIALTUNNEL_TOPLEFT)));

        entity_sptr temp(myManager->AddEntity(new TinyHouse(763,540)));
        myManager->AddEntity(new TriggerBrush(756,462,44,50,
            new trigAddBehavior(temp,
                new MoveBehavior(temp.get(), .04, -3.25, 1000))));
    }
};


I trust exceptions about as far as I can throw them.
Codarki
Codarki
I'm not that experienced at 2d games, but I can give my insight concerning the data.

First idea is to have those magic numbers separated to datafile. Something like XML might be better than having all hard-code. Have level bounds and structures bounds, like house, defined in it.

Second choice would be to use some sort of binary data to represent the level. Now you'd need some kind of way to edit the level, level editor.

--
Off topic, your manager looks pretty generic. You can add anything to it, and while it returns value, you need to keep it in special cases. Too much abstraction can cause a lot of type checking, casting, and other difficulties. Type erasure isn't always for better. Good explicitly defined structure in application is often better than super flexible abstract thingie.
Codarki
Codarki
Bitmaps can be used as attributes to level data. Say grayscale bitmap is height, or black-white mean wheter its passable tile. This make any paint program your level editor.
jtagge75
jtagge75
To not hard code something like a trigger you probably need to start using a scripting language. If you use something like XML you can have a trigger tag that describes the size/attributes of the trigger as well as the script file to execute when entering the trigger.
highowl
highowl
I've been working on a 2-D platformer. For levels I simply made a *.dat file that contains all the background images for each screen of the world.

Directory structure is:

.
game.exe
./lvl/#/world.dat
./lvl/#/world.cfg

Where '#' is the level number.

world.dat, as I said earlier is a datafile containing just images.
world.cfg is a text file that holds the data for each screen in the world.


Example:

world.w 5world.h 1[0][0][0].solid 0,0,20,600[0][0][1].solid 500,300,600,800[3][0][0].npc cop 400,500[5][1][0].obj grapple 500,100


Then I just wrote some code to parse the file and perform actions based on it.
the '[#][#][#]' portion of it corresponds to [X][Y][n] where X and Y are the x,y coordinates of the screen in the map, and 'n' is the number of the array the object is in. (The first two ".solid" lines make 2 solid objects on screen(0,0))

It's not the simplest approach, it's not the easiest, and most likely not the most efficient way of accomplishing this. But it does mean your limited only by your imagination and ability to parse text files. :P

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.