Jump to content
  • Advertisement

Archived

This topic is now archived and is closed to further replies.

OoMMMoO

more tile engine help

This topic is 6414 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

k Im working on a tile engine and was wondering how objects that the character can walk under are put on a map. Do you first make a simple map that lays your grass,rocks,water,cliff edge,tree base, ect... Then make a map to lay on top of the basic one that blts interactive items? like tree top''s, arches, tables ect...? But wouldnt I have to run a loop that moves through the map that should be displayed and check if the character is higher in the y-axis and if it is blt the character first then the interactive stuff?

Share this post


Link to post
Share on other sites
Advertisement
This is the way I handled it:

I have a 2 layered map.

Layer 1 is base tiles.
Layer 2 are objects.

Objects in Layer 2 have a height (z order) associated with them.
I can stack object upon object building a *theoretically* unlimited height tower of objects. (I do limit it at a reasonable value for performance)

I blit all the base tiles first.
I then blit all objects like this:

Left to Right, Top to Bottom, then each object in that tile sorted by Z order. This gives the proper depth perseption. My maps are isometric, but the same applys to square maps.

I handle players/monsters as objects so they are correctly rendered in the scene.

You can check it out here, play with the map editor and you''ll see what I mean by stacking objects. Thats how I built all the buildings and the bridge, etc. There''s also a few screenshots up there.


Share this post


Link to post
Share on other sites
I am very curious to know if you went looking for tile-based articles that explain the basics as was suggested in a reply to your other post by someone???

..if not, i recommend you go do a little homework on the subject. I mean, the articles are 3 to sometimes 12 pages and explain what you want to do, and its not realistic to present all the points up here. So, ill give you the 1 sentence answer to your question and hope you go look around this site..there is a whole section devoted to your subject if you just move that mouse.
Answer:
A basic way to start tile-based games is the 3-layer scheme: base layer, fringe layer, and object layer where base is your ground(dirt, water) and fringe are transparent tiles(like some grass to make smooth transitions to grass to brick) and object tiles can be anything else(npc''s, trees, rocks, etc); each are drawn: base,fringe, you or objects depending on position in that order with a loop that iterates through all this stuff for each map point.

Like i said earlier i cant understate the fact that their are plenty of articles that you could have looked into right on this site alone explaining this stuff much better...which is probably why you dont get responses to your questions..



aka John M.
Never give up. Never surrender!


Share this post


Link to post
Share on other sites
I have looked for many articles the ones Ive found are very basic and just teach the very basics. I would like you to find me a article somewere that teaches me what I need to know and I will stop posting here for help about tile based games. Ive read all the ones at GameDev and at most other sites.

Share this post


Link to post
Share on other sites
Hello Hello Hello and salutions everyone.

Let''s see here... OoMMMoO wants to know how to render an isometric map in a more advanced way. I understand your frustration because at times the layered approach doesn''t properly clip the objects. Here''s my recommendation on rendering the map: Create a rendering order list.

Question: Now Dino... what on earth is a Rendering Order List?
Answer: Well questioner, A Rendering Order List (ROL for short) is simply a double linked list that contains pointers to all the objects that need to be drawn to the screen in the proper order. When I say objects, I mean every single piece of information on the map, which includes the tiles, non-interactive objects, and interactive objects. EVERYTHING!

[NOTE: If you don’t know what a linked list is or a double linked list then go find your old data structures book and read up on it… don’t continue reading…]

When it is time to draw the map, you first will need to loop through everything that is visible. This algorythm is up to you. I''ll just take the quick and easy way.

Say my viewport on fits 20 rows of tiles with 10 tiles per row. The quick and easy way to do it process 22 rows (+2 at the bottom) with 12 tiles in each row (+1 to the left and +1 to the right). The reason for the extra 2 rows at the bottom is for anything that is tall and the extra tiles on each side of the rows is for anything that is wider than a tile or anything that will spill over onto a visible tile.

Now that you have your range of map tiles that will need to be scanned, lets say (9, 10) to (11, 32), we can populate the ROL.

We first need 3 variables that I recommend being globals:

typedef struct ROLNODE{
ROLNODE *Prev; //Previous node in the list
ROLNODE *Next; //Next node in the list
void *ObjPtr; //Pointer to the map object.
long DispBase; //Display Base value. Described later
} *ptrROLNODE;

ptrROLNODE *gROLStart; //Ptr to the first node in the ROL
ptrROLNODE *gROLEnd; //Ptr to the last USED node in the ROL
unsigned long gROLMaxSize = 1024; //The max num. of elements in the ROL


When your engine is being initialized, allocate memory for the ROL. The amount of memory you initially allocate is important so that you don’t have to re-allocate a lot more later and over and over again. This size ROL will support a 16 x 16 size visible map with 4 objects at each tile. If that’s too few for you, then increase it. 4096 elements will allow you to have a 32 x 32 x 4 size viewable map. Don’t go over-board though because you can always re-allocate the ROL if you need to.


ptrROLNODE AllocROL(unsigned long ROLSize, ptrROLNODE PrevNode){
//Allocates memory for the ROL. This function is a recursive function that allocates
// one node at a time and returns a pointer to that node. The function gets called
// until ROLSize == 0.
// PrevNode is the a pointer to the previous node. This should be NULL when
// first calling this function.

//This should be done only in the beginning or when you need more memory
ptrROLNODE cur_node;

//Check to see if we should even bother allocating memory
if(ROLSize < 1) return NULL;

//Shrink up the size of the ROL
ROLSize--;

//AllocMem is a macro that allocates memory of a given size
// AllocMem can be replaced with any memory allocation function you want (like malloc).
cur_node = (ptrROLNODE)AllocMem(sizeof(ROLNODE));

//Set the previous node
cur_node->Prev = PrevNode;

//Set the next node (which is a call to this function)
cur_node->Next = AllocROL(ROLSize, cur_node);

//All done
return cur_node;
}


Ok… now our ROL is allocated. Now comes the time to populate it and the reasons why you use a double linked list instead of an array (which would take less memory).

First reset the gROLEnd to the beginning of the list.


gROLEnd = gROLStart;


Now start with the top-left map point in the area we decided to scan. For each object that is over that map point do the following (this is where it gets tricky):

Get the display base of that object. For tiles it’s normally the top-left position of where the tile is drawn. For most other objects it’s the top-left position plus the height of the graphic. The reason it is different for objects than tiles is because most, if not all, objects stand on tiles.

Starting with the last node in the ROL, traverse the linked list backwards until you find a node that have a lower display base value than the object being added. This is why a double linked list is used. It is easier to insert nodes in the middle of a linked list than it is in an array.

Here’s sample code of the process explained. The main function called is AddMapObjsToROL(). This code hasn’t been tested though…


void AddObjToROL(ptrMAPOBJ MapObj){
//Add the map object to the end of the ROL and reset
// the pointer gROLEnd
ptrROLNODE new_node, prev_node;

//Initialize some variables
end_node = NULL;
cur_node = NULL;

//Get a pointer to a node. If there are no more free nodes,
// allocate a small chunk at the end of the list
new_node = gROLEnd->Next;
if(new_node == NULL) new_node = AllocROL(32, gROLEnd)

//First set the variables in new_node
new_node->DispBase = GetObjDispBase(MapObj);
new_node ->ObjPtr = MapObj;

//Find out which node is to come before new_node
prev_node = new_node->Prev;
while(prev_node != NULL){
if(prev_node->DispBase > new_node->DispBase)
prev_node = prev_node->Prev;
}

//Now insert new_node in the new spot. If the position
// of new_node didn’t change, then new_node is the new gROLEnd.
if(prev_node == NULL){
//new_node is now gROLStart.
new_node->Prev = NULL;
new_node->Next = gROLStart;
gROLStart = new_node;
return;
}

if(prev_node == new_node->Prev){
//new_node didn’t move so simply reset gROLEnd
gROLEnd = new_node;
return;
}

//Reposition new_node since it moved
new_node->Next = prev_node->Next;
prev_node->Next = new_node;
new_node->Prev = prev_node;
}

void AddMapObjsToROL(ptrMAPOBJ *MapObjs, unsigned long NumObjs){
//Adds the array of map objects passed (MapObjs) to the ROL.
// NumObjs is the size of MapObjs.
ptrMAPOBJ cur_obj;

//Check to see if there is anything to add.
if(MapObjs == NULL) return;
if(NumObjs == 0) return;

//Get a pointer to the first map object and then start going
// through the list of objects
cur_obj = MapObjs;
while(NumObj > 0){
//Add this object to the ROL
AddObjToROL(cur_obj);

//Advance to the next objects
cur_obj++;
NumObjs--;
}
}



Wheew… That was a mouth full. After all this is said and done, you now have a list of objects in the proper order that they are to be drawn.

Also, you can use this list to determine what objects are under the cursor. If you start with gROLEnd and move backwards in the list, you can query each object to see if they contain the point. This will give you the exact object that’s under the point and not anything that may be covered by another object.


I hope this helps and I apologize that it was such a long response.

Good Luck.

Dino M.Gambone

Dino M. Gambone
Good judgement is gained through experience. Experience, however, is gained through bad judgement.

Share this post


Link to post
Share on other sites

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

Participate in the game development conversation and more when you create an account on GameDev.net!

Sign me up!