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

sprites

Started by nex7 May 21, 2006 at 10:35 AM 14 replies 2.1k views
Original Post
nex7
nex7
I've got my terrain rendering down and I'm thinking about sprites now. I implemented a little 3D array, layer 1 for terrain, layer 2 for static world objects and layer 3+ for anything else. Now my question is should all things be tied to specific tiles or should they be independent. Also if they are tied to tiles how am I to move the characters or mobs around the map without them jumping from tile to tile. Is it a smooth scrolling thing like the terrain or do I need to do something else. I have read all of the tutorials and didn’t really see anything useful about object management. also...for rendering everything im using Direc3d....and have a nested loop to do the drawing. Is that the most efficient way to do the drawing? it's a 3D array so For all in x For all in Y For all things to draw draw()
evillive2
evillive2
Your ideal solution may be different depending on how your game works.

That being said, I have used/am using a combination of both. I am doing an overhead 2d action/RPG (non-isometric like Zelda3) tile based game so it may be different than what you are doing.

My entities all reside in a large list that gets insert sorted by y value when they move. I pop the entity from the list and search from it's last position in the list where to sort it. I also check to see what tile it's new position is on and do the same type of pop/insert on the tile if it is necessary (most times it isn't depending on how populated the area is). The lists are all lists of pointers btw.

My rendering is done from the large list as they are already sorted in drawing order already (and doing it on a per tile basis causes some wierd drawing order issues with neighboring tiles). The AI is figured out on a radius basis to which the smaller lists on the tiles help out. For example certain agressive NPC's attack within a 1-2 tile radius (or box as it happens) while others like guards will notice from up to 8 tiles away if you are so flagged. This is made easy by just traversing the lists of the surrounding tiles instead of the whole list.

I hope that helps a little.
Evillive2
nex7
nex7
I would also like some help on drawing large sprites like say...beds.

Things that take up more than one tile confuse me. If an objects spans more than one tile do i have to figure out which tiles it crosses and make those non walkable? In the case of things standing up...walls and the like..the character just walks behind it...but that doesn't work for things that lay flat on the ground like a bed.

thanks
nex7
nex7
The only thing i have found so far is that i need to define in the meta data that this certain sprite will take up 4 tiles....and i need to make those 4 tiles non walkable. It might get quite annoying to do all of that by hand. I am about to go implement this as its the only solution i have. It just seems a bit primitive.
nex7
nex7
So something like a bed that takes up 4 tiles would be cut into 4 pieces and then drawn?

what if its say...a very large monster like a dragon or something. This dragon is drawn and he takes up 8 tiles. His feet are on the corners of the tiles so any tile that he is covering needs to be non walkable. the Parent tile is of course non walkable but how do i know that he takes up 7 other tiles?

nex7
nex7
Actually the dragon would take up an 8 tile standing area with the rest of him extending up...wings and neck and the like. so the sprite actually covers

8 for his standing area and another 4 for his neck and wings....

now the tiles behind his wings and neck are still walkable while the 8 that he is standing over are non walkable.

I am just at a loss as to how to get that into code other than to hardcode the parameters in some sort of meta data for each sprite...

sprite
Height
Width
TileCoverage
Image
nex7
nex7
i present to you...the bed problem


bed problem

red is auto marked non walkable...

green is walkable

and i really really want to mark the yellow tiles non walkable.
streamer
streamer
There are two solutions I can think off:
1. I assume you have map editor [smile]. You may add to every tile bool variable that shows is a tile walkable or not. In map editor simply check or uncheck values.
2. You can make it with pointer to object, so tiles will have pointer that there is some object and make again tile non-walkable. Your object is located on red tile, yellow tiles have reference to object tile.

I'll prefere first solution. It is fast, simple, no precompute.
nex7
nex7
ok so the bed was a bad example....

lets pretend that a wizard animated the bed..and it now has huge teeth and can walk around in our world causing all manner of trouble.

Those walkable tiles have to be updated as our evil bed moves around the world.

The best solution I have come up with is a sort of Walkable Mask...

i would make an 4bit bitmap the size of my world...so say a 2000x4000 bitmap and each monster bed would also come along with a walkable mask... a tiny bitmap that would represent the tiles it takes up. then every time something moves it would blit its walkability mask to the main bitmap and you would have a nice bitreference to check.

if color == red non walkable
if color == blue water..use boat
if color == green walkable terrain
if color == white air must use flying carpet
streamer
streamer
Quote:
Original post by nex7
ok so the bed was a bad example....

lets pretend that a wizard animated the bed..and it now has huge teeth and can walk around in our world causing all manner of trouble.

Those walkable tiles have to be updated as our evil bed moves around the world.

The best solution I have come up with is a sort of Walkable Mask...

i would make an 4bit bitmap the size of my world...so say a 2000x4000 bitmap and each monster bed would also come along with a walkable mask... a tiny bitmap that would represent the tiles it takes up. then every time something moves it would blit its walkability mask to the main bitmap and you would have a nice bitreference to check.

if color == red non walkable
if color == blue water..use boat
if color == green walkable terrain
if color == white air must use flying carpet



hmm personaly I don't like that approach. Here is my thinking: Use one class for terrain and static objects(walls, trees etc) and one class for dynamic objects and players and NPCs (humans, creatures, beds that turns into jaws [smile]etc).
Do it with pointers. Make class that holds all graphic in your game, and on tile just provide a reference to it. With this approach you can have same looking things with different actions.
When rendering on screen do it in two pass. First draw background, then all other things. In first pass also clear(before all movement is made) and fill again values for trigers (after movement is made).
Personaly I tile checking mechanisam I would do something like this:
enum myTriger { trPassable, trNonPassable, trWater, trFlying };enum tilesize { tsOne, tsTwo, tsThree,tsFour };class TileProp{public: TileProp(myTriger mt) { m_triger = mt;}myTriger m_Triger;};class tile{public:tile() {m_TileProperties = NULL; }TileProp *m_TileProperties;void SetTilePropertie(myTriger type, tilesize size, tile* othertile){switch(size){case tsOne: {  if(TileProperties)       TileProperties = new TileProp(type);   else       m_TileProperties->m_Triger = type;  }  break;case tsTwo: {  // same as tsOne +  // you set pointer for m_TileProperties in NEIGHBOUR tile  // to this->  // neighbour tile: othertile->m_TileProperties = m_TileProperties; //  etc... }break;}}};


in map draw function:

for(int x = 0; x< WIDTH;x++)
for(int y = 0; y< WIDTH;y++)
{
// clear properties
if(tile[x][y]->m_TileProperties)
{
delete tile[x][y]->m_TileProperties;
tile[x][y]->m_TileProperties = NULL;
}
}

then make everything move, players , monsters, etc.
after that you fill again your m_TileProperties values, and then draw
map.
nex7
nex7
ok so that was my first option before the bitmap....

I currently have the concept of Tiles and Sprites in my system now.


So when you say Tilesize...how do you know what the demensions of that tile...


it could be 4 tiles in a straight line...or 4 in a square...or 3tiles up and one to the left.

streamer
streamer
Quote:
Original post by nex7
So when you say Tilesize...how do you know what the demensions of that tile...


it could be 4 tiles in a straight line...or 4 in a square...or 3tiles up and one to the left.


That's why is there :
enum tilesize { tsOne, tsTwo, tsThree,tsFour };
:
you can define with it any shape you like, or even work with WORD:
with WORD you can make mask 0000 0000 0000 0000 (binary)
that in game terms looks like
0000
0000
0000
0000

for empty tile.
for example binary 1000100010001000 in hex is 0x8888.
With simple bit checking you can solve which tile should be trigered.
void SetBit(WORD &data, int bit){int i = 1;i = i << bit;data |=i;}void ClearBit(WORD &data, int bit){int bitmask = ~(1 << bit);data &=bitmask;}bool IsBitSet(int flags, int checkBit){        return (flags & checkBit) == checkBit;}bool IsBitClear(int flags, int checkBit){      return (flags & checkBit) == 0;}


nex7
nex7
ahhhhhhhh

lightbulb


Thank you...full steam ahead!
evillive2
evillive2
Why would your bed or dragon need to know how big the tiles are? Seems a bit inflexible to me.

Why not (purely preference on my part I suppose) do 2 checks? One to see if the player has collided with a non walkable tile (quite simple) and another to make sure it hasn't collided with any objects in a (largest object size) radius?

This way you assign bounding geometry (obviously boxes or circles are easiest) to a sprite and then it doesn't matter if the underlying map is top down, isometric, 3d etc. because the bounding geometry is in world coordinates and doesn't care how large a tile is or isn't, just that other objects know where it is.

You need to perform some form of sprite vs sprite collision anyway in most games especially if there are small objects that obviously wouldn't fill an entire tile (bullets for example) so I don't think this would be a bad idea to implement anyway.
Evillive2
nex7
nex7
honestly i hadn't thought about collision detection for this (duh)....walkable tiles applies to terrain and all other objects get a bounding box for which collision detection is calculated.

not sure where my brain was...

Thanks a lot you saved me a lot of code!

Topic Locked

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

Sign in to reply to this topic.