Isometric Zones and map optimization.

Started by
15 comments, last by hustlerinc 12 years, 1 month ago
Hi, I'm creating a game in Javascript and im stuck.
Im using 2D isometric tiles.

What i want to know is how to divide the map up in zones, and more importantly only draw the tiles visible on the canvas.

My current drawMap function looks like this:
function drawMap(){
var tileW = 64;
var tileH = 32;

for(i=0;i<map.length;i++){
for(j=0;j<map.length;j++){
var drawTile= map[j];
var xpos = (i-j)*tileH + mapX;
var ypos = (i+j)*tileH/2 + mapY;
ctx.drawImage(tileImg[drawTile],xpos,ypos);

if(i == playerX && j == playerY){
ctx.drawImage(charImg[0],xpos,ypos-(charImg[0].height/2));
}

if(i == xmouse && j == ymouse){
ctx.fillStyle = 'rgba(110, 160, 255, 0.5)';
ctx.beginPath();
ctx.moveTo(xpos, ypos+16);
ctx.lineTo(xpos+32, ypos);
ctx.lineTo(xpos+64, ypos+16);
ctx.lineTo(xpos+32, ypos+32);
ctx.fill();
}
}
}
}


Any examples of how i can adjust my code to improve it are appreciated.
Advertisement
Given that an isometric camera is fixed in angle, what you can do is pre-calculate a visible volume, or view frustum, at game start then translate that view volume to center on the visible map center when the map is drawn. The volume can be used to test intersection of tiles with the view, and cull those that are not visible.

Now, of course, you can simplifiy this process immensely for an isometric game. JTippetts on this site wrote a journal post some time back about writing an isometric game using SFML, where he details one of the commonly used approaches. You can read that post here. In essence, you calculate where the corners of the screen intersect the ground and roof planes (the minimum and maximum vertical extents of the world) and from those you derive a set of visible tiles.
Yeah i saw that post earlier while searching but i dont understand much, since my knowledge of sfml = 0.
I will read it through though and make the best of it, but if someone has a Javascript example of the above it would be awesome.
What do you mean by dividing them up?

You could store each map in a separate array, or an array inside an array. Then:

for (int sectionY = 0 ; sectionY < Ysections; sectionY++)
{
for (int sectionY = 0 ; sectionY < Ysections; sectionY++)
{
for (int tileY = 0; tileY < YtilesInThisSection; tileY++)
{
for (int tileY = 0; tileY < YtilesInThisSection; tileY++)
{
//now draw this tile and add it's X and Y position bysectionY * (amount of tiles in section * tilewidth). Same goes for X.
{
}
}
}


For drawing only the tiles on screen, get the center of the screen relative to the map, then with your tilepick method you could calculate what tiles need to be drawn. Then just take this into account in your draw loop.

What do you mean by dividing them up?

You could store each map in a separate array, or an array inside an array.


Instead of loading everything on the full world (planning a big world) and having to send calls from every online player with every action. To save bandwith ill split it into section (as i understand is a way to optimize).
Which of your methods is the most efficient one?

And for drawing only inside the viewport it wouldve been easy if it was square tiles, but since its isometric it gets complicated, and im only just learning JS, so im little stuck.
I've learned the technique and teory, but i cant figure out how to translate it into javascript.
(Yeah I might have taken on a big first project but i find this is the best way for me to learn :P just wish there was more info and tutorials.)
Drawing only the ones on the viewport is the most efficient, but you might want to buffer some way outward so they get loaded faster if you player scrolls through the map. So i'd say just draw the tiles necessary on screen and load tiles a couple of screens off.

Yes, isometric maps complicates things like this a bit. But you could just draw the "diamond" just as large to fit the screen (so the outer corners will be drawn further outside the screen), this is less efficient but i don't think it would matter that much.

You could also use this to just make the loop, then for each tile calculate it's position and check if it's within the screen bounds. If so draw it, if not leave it.

Otherwise, what i have seen browser games do, is just that array method i described above. This will be less efficient but might give better results for a browser type game. Just check what map array the screen is on and load all the adjacent tile arrays. Then when the screen switches to another array load the new adjacent arrays.

Drawing only the ones on the viewport is the most efficient, but you might want to buffer some way outward so they get loaded faster if you player scrolls through the map. So i'd say just draw the tiles necessary on screen and load tiles a couple of screens off.

Yeah thats what i was thinking, and i found what seems to be the most efficiant way to do it on FLeBlanc's link: http://www.gamedev.net/blog/33/entry-2250273-isometric-map-in-sfml?pg=3 I just cant translate it into javascript.

And here's a picture describing wich tiles to draw: http://www.gamedev.net/index.php?app=core&module=attach&section=attach&attach_rel_module=blogentry&attach_id=3487

But how do i translate that code into javascript, and even better to fit my drawMap() function?
Well how you would write any code. Cut it all down in little steps and start coding. Can't help you much on javascript let alone your drawmap function so i'm not sure what your asking. If your not able to translate pseudo code into the language your programming in then it might be a step to high. You might want to try all this on a regular tilegrid if you haven't done so.

Otherwise, ask a more specific language because nobody here is going to write the code for you.

Otherwise, ask a more specific language because nobody here is going to write the code for you.

I get that nobody is going to write the code for me, but i cant understand what the SFML example does, so I dont even know where to start.
I get that on even rows I'm supposed to do 16 tiles (based on my sizes) and odd rows 15.
I understand where to do -1/+1 X/Y, but what i cant grasp is how do i calculate the first tile to draw? In my case map[0] is top right corner, and X-axis goes down-left from there.
Should i start drawing from there? Tried to figure it out in the SFML example but I just get dizzy.

And there is no use first trying it in a normal 2d up-down array since then the math gets really simple and i would learn nothing.
Interesting link it is. But i don't have much time....

I believe he is linking nodes to each cell when building the map.

He makes nodes like this on a diamond isometric map.

xx0xx
x012x
01234
x012x
xx0xx

An he uses these nodes to draw the map. Read the complete link, not just "where the magic happens" and you should be able to figure it out. I will look into this later since it's pretty interesting.

This topic is closed to new replies.

Advertisement