Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

[C++] Nice way to load data objects

2 views
Skip to first unread message

skreeg

unread,
Nov 6, 2009, 6:49:02 AM11/6/09
to
Hi folks,
This is more of a general C++ question than a specific RL one. I, like
most, intend to have a large number of different terrain tiles. Each
terrain currently has the following attributes;

gfxId (ascii char shown)
name
color
totalhitpoints
currenthitpoints (terrain is desctructable)

Tile's are like this;

class Tile{
//objects
Terrain terrain;
};

At the moment to create my hardcoded map I simply parse the map text
file, and depending on the char it creates a tile and populates it's
Terrain object. What I'd rather do though is pre create Terrain
objects for each Terrain type then when parsing the map file, pass a
copy of the correct Terrain to the Tile.

What I'm asking is how to store the definitions for the Terrains and
how to load them in with a nice loop. This is where my knowledge of C+
+ is lacking. How to do all the nice fluffy macro style stuff that
automates things like this. I presume I need my terrain data in a
define.h file of a sort. Is there a way to have structs or something
defined for this purpose?

Krice

unread,
Nov 6, 2009, 8:37:15 AM11/6/09
to
On 6 marras, 13:49, skreeg <skr...@gmail.com> wrote:
> What I'm asking is how to store the definitions for the Terrains and
> how to load them in with a nice loop.

There is no single proper way to do that, but one thing that
you could do is remove Terrain object as Tile's data and use
Terrain objects as static data. For example there is no need
to copy the tile's name in each Tile class instance unless each
tile name can be changed. You can get the name from separate
data class/array that holds the static data. I think you should
always try to keep dynamic (changing) and static data in
different places, so it reduces the copying of data.

pol

unread,
Nov 6, 2009, 6:27:07 PM11/6/09
to
The way I do it is I have a text file that defines each object's data.
This data is loaded into a base-object-holder before the game begins.
The base-object-holder holds only the data that defines the
differences between the objects (it would hold the color and the name,
but not the current hitpoints). I store all the base-object-holders in
a map (or vector) and then when I want to load a grass tile (which
would be tile # 4 for example) my createTile function access the data
from base-tile-holder[4] (or whatever you decide to call it).

That method doesn't worry about the amount of duplicated information
that I copy to all the different tiles. To be more efficient, you can
have permanent values (like the name & tile if those never change) and
instead of storing them in each tile, just read those from the base-
tile-holder and only hold the changing values in the tile (like
current hitpoints)

The text file would look something like this:

[1:":grass:GREEN_LIGHT:3]
[2:.:dirt:BROWN_LIGHT:6]

etc.

let me know if you want any examples and I'll be happy to share.

skreeg

unread,
Nov 6, 2009, 10:45:58 PM11/6/09
to
hmm, I think I was making it into a bigger problem than it is. I
fairly certain I'm only going to have 20 odd tiles at most so I've
"upgraded" my terrain code to just hardcode the details into the
Terrain class constructors with a big switch statement parsing an enum
terrainType. It'll do just now and I'm not keen on having terrain data
outside in an easily editable text file.

Gerry Quinn

unread,
Nov 7, 2009, 9:15:47 AM11/7/09
to
In article <44edcef8-e33c-49aa-bd7f-659e470a26e0
@g1g2000pra.googlegroups.com>, skr...@gmail.com says...

The way you do it seems reasonable, but what you want to do is easy
enough too.

I would use constructors, for example the following constructor would
do what I understand you to be doing now:

Terrain::Terrain( "g" )
{
gfxID = 'g';
name = "grass";
color = RGB( 0, 128, 0 );
totalhitpoints = 100;
currenthitpoints = totalhitpoints;
}

Right now you would simply write in your map construction loop:

map[x][y] = Terrain( ascVal );

But you could create alternatives, perhaps as follows:

vector keys< char >;
vector data< Terrain >;

Terrain toughGrass( 'g' );
toughGrass.currenthits *= 2;
toughGrass.totalhits *= 2;

keys.push_back( 'g' );
data.pushback( toughgrass );

Now you read your map as normal for the level, but when you read 'g'
from the map file, you check to see if there is any 'g' in keys, and if
there is you copy the corresponding terrain value for data into map[x]
[y], instead of using the default constructor. So you will have a
level with grass that is tougher than normal, whereas other terrains
will have their default value.

Is this the sort of thing you were intending?

- Gerry Quinn


skreeg

unread,
Nov 7, 2009, 9:43:37 PM11/7/09
to

>
> Is this the sort of thing you were intending?
>
> - Gerry Quinn

That's more or less what I've done. A simple enum first

enum terrainType{
GRASS,
STONEWALL,
RUBBLE
};

Then a constructor;

Terrain::Terrain(terrainType_t terrain)
{
switch (terrain)
case GRASS;
gfxid='.';
name="Grass";
etc..
}

In GameWorld.generateMap() I create a Terrain object for each
terrainType. Read in the mapfile and copy the terrain object into the
Tile at map[x][y]. Seems to work well. Damage messages now go directly
to &world instead of the dodgy pointer nonsense I had before in Tile
objects and I now have destructable terrain. Only thing now is to
concentrate on getting my AI working for a release instead of being
tempting into coding grenades. :)

Jeff Lait

unread,
Nov 8, 2009, 5:01:31 AM11/8/09
to
On Nov 7, 9:43 pm, skreeg <skr...@gmail.com> wrote:
> > Is this the sort of thing you were intending?
>
> > - Gerry Quinn
>
> That's more or less what I've done. A simple enum first
>
> enum terrainType{
> GRASS,
> STONEWALL,
> RUBBLE
>
> };
>
> Then a constructor;
>
> Terrain::Terrain(terrainType_t terrain)
> {
>      switch (terrain)
>      case GRASS;
>      gfxid='.';
>      name="Grass";
> etc..
>
> }

Too much typing.

I believe this is a good point to let your compiler do some of the
work for you. Write a program to take a nice, succinct, version of
your data and output C structs with the data. Then you get the best
of both worlds.

This is my approach in my 7DRLs and POWDER where enummaker.exe will
create the glbdef.cpp and glbdef.h from my source.txt

DEFINE TERRAIN
{
u8 gfxId ' '
cst name 'terrain'
passable true
}

TERRAIN GRASS
{
gfxId 'g'
name "grass"
}

TERRAIN MOUNTAIN
{
gfxId '^'
name "mountain"
passable false
}
--
Jeff Lait
(POWDER: http://www.zincland.com/powder)

0 new messages