Re: A89: Tile-based Game Engine in C (read _this_ one)


[Prev][Next][Index][Thread]

Re: A89: Tile-based Game Engine in C (read _this_ one)




Let me try this again - Outlook Express is acting up on me.  It let me
finish the message this time - my apologies to the list =)
----------------------------

> in C would it be something similar to:
> int sometile1[] = { 0x...};
> char tilearray[] = {&sometile1,...};

That could use a little of refinement, since the second array's type is
completely wrong. . .

First, each sprite must be defined.  The exact declaration will vary
depending on the sprite format and blitting (drawing) routine you use.  For
simplicity's sake, let's assume you're using Zeljko's nice TIGCCLIB sprite
specifications, and you're using 16x16 sprites.

The format for defining sprite data is covered by TIGCCLIB.

You then need an array indexing all of the sprites.  This is an array of
pointers, but since our sprite type is already a pointer, it can just be an
array of type (sprite type).  Since a 16x16 TIGCCLIB sprite is of type
pointer to int (it's an array, so it's a pointer), our array would look like
this:

int* tile_array[] = {tile_zero_name, tile_two_name, ... };
/* you sould, of course, use your own sprite names above    */

For simplicity's sake, I suggest the doing following:
typedef int* sprite;
sprite tile_array[] = {tile_zero_name, tile_two_name, ... };

The most basic map format will assume that every map is the same size and
consist of a simple two-dimensional array of ints, with each number
representing the tile of that index in tile_array.  If we had a 10x10 map,
it might look like this:

int map_data[][] =
 {
    {1,1,1,1,1,1,1,1,1,1},
    {1,3,3,3,3,3,3,3,3,1},
    {1,3,5,4,4,4,4,5,3,1},
    {1,3,5,4,4,4,4,5,3,1},
    {1,3,5,5,5,5,5,5,3,1},
    {1,3,0,0,0,0,0,0,3,1},
    {1,3,0,0,2,2,0,0,3,1},
    {1,3,0,0,2,2,0,0,3,1},
    {1,3,3,3,2,2,3,3,3,1},
    {1,1,1,1,2,2,1,1,1,1}
 };

I'll leave the map drawing routine up to you, but it's pretty
straightforward: one "for" loop nested inside another.

If we only have 256 or fewer tiles, then we're wasting a ridiculous amount
of space using ints.  If you understand the calculator's workings at an
assembly-language level (which is pretty important if you want to achieve
efficiency on such a low-level device), you'll realize that we simply want
to use a byte, which is, in C, an unsigned char.  Try this slight
improvement:

typedef unsigned char BYTE;
BYTE map_data[][] =
 {
    {1,1,1,1,1,1,1,1,1,1},
    {1,3,3,3,3,3,3,3,3,1},
    {1,3,5,4,4,4,4,5,3,1},
    {1,3,5,4,4,4,4,5,3,1},
    {1,3,5,5,5,5,5,5,3,1},
    {1,3,0,0,0,0,0,0,3,1},
    {1,3,0,0,2,2,0,0,3,1},
    {1,3,0,0,2,2,0,0,3,1},
    {1,3,3,3,2,2,3,3,3,1},
    {1,1,1,1,2,2,1,1,1,1}
 };

When you start doing things like this, it may be smart to typecast the value
to an unsigned int before using it as an array index.

If you want to make the map of variable size, try this:

struct map
 {
    unsigned int width;
    unsigned int height;
    BYTE* data[][];
 };

Note that it contains a _pointer_ to the data, and not the data itself.
This is because of what is, IMHO, one of C's major fallacies - ANSI C does
not allow for structs to contain arrays whose size is not always the same.
Our data is of size width*height, but since width and height vary, we would
_want_ our array to look like this:

/* WARNING: THIS DEFINITION IS ILLEGAL IN ANSI C    */
struct map
 {
    unsigned int width;
    unsigned int height;
    BYTE data[height][width];
 };
/* WARNING: THIS DEFINITION IS ILLEGAL IN ANSI C    */

But that definition is not allowed in ANSI C.  GCC has some extensions that
allow it to be done, but here it would be wise to just use a pointer to the
data, which _can_ be declared as a different size in each instance.

So using out variable size maps, our map might look like this:
map sample_map = {10, 10, sample_map_data};
BYTE sample_map_data[][] =
 {
    {1,1,1,1,1,1,1,1,1,1},
    {1,3,3,3,3,3,3,3,3,1},
    {1,3,5,4,4,4,4,5,3,1},
    {1,3,5,4,4,4,4,5,3,1},
    {1,3,5,5,5,5,5,5,3,1},
    {1,3,0,0,0,0,0,0,3,1},
    {1,3,0,0,2,2,0,0,3,1},
    {1,3,0,0,2,2,0,0,3,1},
    {1,3,3,3,2,2,3,3,3,1},
    {1,1,1,1,2,2,1,1,1,1}
 };

The routine to draw a variable size map is a bit more complex, but only
slightly so in C.  I'll leave that as an exercise to the reader, too =)

Obviously map formats can get much, much, much more complex than this and
contain much more than an int representing each tile, and they can also be
compressed, but this is a start =)

    -Scott




References: