Advertisement

Tiles

Started by December 29, 1999 02:09 AM
6 comments, last by magal 24 years, 11 months ago
Why are you using a single-dimensional array?
Why not store your world as a 2-dimensional array? Thus you could do something like this:

(note : In my example, i'm statically creating the array for simplicity, you can pretty easily convert this code to dynamically allocate it. I'm also pretending that there is a "LoadWorldFromFile()" function, that loads your world from a file into the array. So let's assume that the world is correctly put in the array after the second line.).
(I'm assuming that the variables playerX and playerY have the players position in the world).

char world[100][100];
int playerX, playerY;
LoadWorldFromFile(world);
....
//at this point in the code the player is attempting to move right, so check to make sure he can.
if(playerX<99)
if(world[playerX+1][playerY]!=CANNOT_BE_STEPPED_ON)
playerX++;


Then your map drawing code will handle moving the player.
See if that helps.

------------------
gameguru4@yahoo.com

Thanx RPGElite for the suggestion, but when I try to dynamically allocate an array on VC++5 (I used: "field = new char[width][height];"), I get 'error C2540: non-constant expression as array bound' on compile time and I can't even compile the sources. And there also some type conversion errors too, but I guess the deal is that "When allocating a multidimensional array, all dimensions except the first must be constant expressions.", as it's written in the Language Quick Reference (Topic: the new operator).

So the only way to do as you say would be to used presized arrays, and that would be very very bad for my case. So, any other solutions?

I still could use some help on these...

[This message has been edited by magal (edited December 29, 1999).]

Advertisement
I use a dual-dimensioned array for some map representations, and a single-dimensioned array for others. Usually it's a question of performance vs frequent use. So, the dimension of the map array isn't really the problem.

To solve the "edge" case presented by the original post, I suggest simply using a "mod" operator on the array subscript.

For a given subscript, you mod it with the "width" dimension of the map. If the result is 0, you're on the left edge. If it's (width-1) you're on the right edge.

You didn't mention you had a problem with up-down position in the array, but if you're curious, you can get that by using the "div" (integer division) operator against the subscript.


------------------
DavidRM
Samu Games

Gerr didnt see your other msg untill i posted this. But maybe itll be some help anyways.

Hmm i belive you can have dynamic multidimension arrays in vc++. I use code like this.

typedef struct {
unsigned int base;
unsigned int fringe;
unsigned int type;
} mapdata;

mapdata **map
I then read in the level/map and get its width and height then call this.

void create_map(int w, int h){
int i;
w = w;
h = h;
if ((map = calloc(w, sizeof(mapdata *))) == NULL){
printf("Out of memory during first dimension calloc()");
exit(-1);}
for(i = 0; i < w; i++){
if ((map = calloc(h, sizeof(mapdata))) == NULL){<BR>printf("Out of memory during second dimension calloc()");<BR>exit(-1);}}}<P>And this gives me a nice dynamic 2 dimensional array for my map. <BR><p>[This message has been edited by Zenroth (edited December 28, 1999).]

Thanx for the replies so far guys...now I'm now doubtful of which solution I will actually implement. On other forums I received other solution as well, and I'll present them so you can help me choose one:
- dyn allocate a two-dimensional array and check for bounds on every move;
- pad all the sides of the tiled field with a row/column that can be checked (with a flag or something);
- precompute an array of bitfields (each element of the array contains which sides has tiles, and which sides are the borders).

These are all good methods and I guess they're not hard to implement, but which one is the most efficient?


Well, in my opinion it would be easiest to do as follows:

Dynamically allocate memory for you map..
ex: MapData = new char[(Map_Width*Map_Height)];

Now, before you check the tile to the left,right,above,or below, first see what the location of the current tile you are on is. If you are at the edge of the map (done by checking the Map_Width & Map_Height variables), then don't attempt to get data from the tile which doesn't exist.

P.S. even though you allocate the MapData as a single dimensional array. You can still easily access the tiles by their location in map coordinates.

ex: MapData[(Y_Loc*Map_Width)+X_Loc]
X_Loc & Y_Loc representing the physical map coordinates.

Advertisement
I'm building up a class to handle tiles on my 2D games and the class contains a pointer to char, which I dynamically allocate at run time using the new operator. Thus the pointer points to an array with n bytes (the tiles). The array is single-dimensional.

On the processing for the game, I have to check , for example, if the tile to the right of MyTile has some properties. Thus, I just sum 1 to the subscript of the current tile (MyTile). But if MyTile is in the last column to the right, then the tile I select summing 1 is the leftmost tile on the next line, not what I wanted, of course. This same thing can happen on all borders of the tiled field. How can I solve this?

I have tried to manually check if the tile was in the corners or last columns or rows and handle each case differently (thus there were 8 ifs in the function), but that completely sucked, it was too much code. I guess there must be some other way to solve this.

What I have in mind right now is to create another function that will return a byte containing what are the tile's neighbors, for example, if I call the function with the first tile on the field, it will return me a bitfield (supposedly a class or struct with 8 bitfields of 1 bit each), containing 1s on the members bRight, bBottomRight, bBottom and 0s on the members bBottomLeft, bLeft, bUpLeft, bUp, bUpRight; and then, before I check for the neighboring tiles, I just use a if before, like "if (structTile.bUp)". How does this sound? Or you guys have better ideas to help me out?

What i do is just check everymove. Basicly i do this.
int logic(){
int oldx = playerx, oldy = playery;
//do input,ai,ect
if(map[playerx*tilesize][playery*tilesize].nonwalkable){playerx=oldx,playery=oldy;}

This generaly has worked well for me.

This topic is closed to new replies.

Advertisement