Legacy GM Isometric Top Down Engine (with height) Method

Pandavim

Member
Hey everyone,
I recently had this game idea and I've been thinking about how to make the engine. The game will be top down, but with a 3D effect; (a bit like Age of Empires 2).

I also like the look of this tile engine:

The world will be randomly generated and can be changed in the game by the player. I made a test engine myself by drawing each tile out every frame and using an array to store the heights of the corners of the tiles. But it didn't run very well:
Picture.png
I was wondering if anyone knew of a good optimized way of doing this in game maker? Thanks! :D
 

Surgeon_

Symbian Curator
Well since you already got a working drawing method, not just use it to draw the terrain on a surface and from there on draw that surface on the screen. Of course, you'd redraw that surface once a part of the terrain changes or the view/camera moves. But overall it would be a much faster way of doing things.

-Surgeon_
 

YanBG

Member
Your work is pretty good! How did you achieve the elevated look of the tiles and their seamless transitions?

Age of Empires use up to 100 frames for each terrain(e.g. grass), some of them are skewed and the engine draws them on the elevations.
Now in the HD version on Steam for AoE2, the terrains got reworked and the engine does all the work with the skewing from a single large(512x512) and "flat" image.
 

Pandavim

Member
Surgeon_ - Oh yeah that's probably the best way to do it, thanks! I'll probably update the surface every time the player walks 5 tiles to the right/ left and then it loads the next 5 tiles and deletes the 5 tiles that are now out of view.

YanBG - Thanks! Ah I see, I probably don't have time to draw hundreds of frames! As for how I did it... I drew each tile out with a script, an array stored the height of each tile and the the corner of the tile's y position will be changed by 25 * corner of tile height, it's surprisingly mathy (for me anyway). I drew each tile with 2 triangles. It's probably better for me to show the actual (unoptimized) code:
/// tile x, tile y

var t_x = argument0;
var t_y = argument1;

if t_x < 1 or t_y < 2
{
return false;
};

if (t_y mod 2 = 1)
{
var t_offset = 0;
}
else
{
var t_offset = 100;
};

var tile_x_real = t_x * 200 + t_offset;
var tile_y_real = t_y * 60;

var t_draw_x1 = tile_x_real - global.main_x;
var t_draw_y1 = tile_y_real - global.main_y - global.D_M_height[t_x,t_y] * 50;
var t_draw_x2 = tile_x_real - global.main_x + 100;
var t_draw_y2 = tile_y_real - global.main_y - global.D_M_height[t_x + 1 - t_y mod 2,t_y - 1] * 50 - 60;
var t_draw_x3 = tile_x_real - global.main_x + 200;
var t_draw_y3 = tile_y_real - global.main_y - global.D_M_height[t_x + 1,t_y] * 50;
var t_draw_x4 = tile_x_real - global.main_x + 100;
var t_draw_y4 = tile_y_real - global.main_y - global.D_M_height[t_x + 1 - t_y mod 2,t_y + 1] * 50 + 60;

var hue = 96

draw_triangle_colour(t_draw_x1,t_draw_y1,t_draw_x2,t_draw_y2,t_draw_x3,t_draw_y3,make_color_hsv(hue, 255, 255 - global.D_M_height[t_x,t_y] * 64),make_color_hsv(hue, 255, 255 - global.D_M_height[t_x + 1 - t_y mod 2,t_y - 1] * 64),make_color_hsv(hue, 255, 255 - global.D_M_height[t_x + 1,t_y] * 64),0);
draw_triangle_colour(t_draw_x1,t_draw_y1,t_draw_x4,t_draw_y4,t_draw_x3,t_draw_y3,make_color_hsv(hue, 255, 255 - global.D_M_height[t_x,t_y] * 64),make_color_hsv(hue, 255, 255 - global.D_M_height[t_x + 1 - t_y mod 2,t_y + 1] * 64),make_color_hsv(hue, 255, 255 - global.D_M_height[t_x + 1,t_y] * 64),0);

draw_set_colour(c_black);
draw_line(t_draw_x1,t_draw_y1,t_draw_x2,t_draw_y2);
draw_line(t_draw_x2,t_draw_y2,t_draw_x3,t_draw_y3);
draw_line(t_draw_x3,t_draw_y3,t_draw_x4,t_draw_y4);

draw_line(t_draw_x4,t_draw_y4,t_draw_x1,t_draw_y1);

(the indents slightly messed up, sorry!)
 

seanm

Member
Its pretty much guaranteed to lag if you are drawing thousands of line segments.

But right off the bat, make sure you are using the YYC. It will probably seriously improve your cpu usage
 

Pandavim

Member
Thanks for the tip, once I've worked on this engine more I will probably not draw the line segments and just vary the colour of each tile a bit more. I've also changed it so that each tile is 4 times bigger (height and width are 2 times bigger) so now I runs better than it did.
 

Mike

nobody important
GMC Elder
Batch, batch, batch, batch, batch, batch, batch, batch, batch!

You can easily draw this amount in a frame, but you have to make sure you're batching things properly. Create 2 vertex builders. into one add lines (as a line list), and into the other add your triangles (as a triangle list) (if you can use a Z buffer, all the better). Then you can draw the triangles, and then the lines.

Doing this also means you have a "screens" worth of prims, meaning you don't have to rebuild it if it doesn't change.

if you draw a triangle, then some lines, then a triangle, then some lines, your going to lose all your performance in just CPU->GPU submission.; But if you batch them, the whole thing will be drawn in 2 draw calls, which a GFX card can easily handle.
 

Pandavim

Member
You can easily draw this amount in a frame, but you have to make sure you're batching things properly. Create 2 vertex builders. into one add lines (as a line list), and into the other add your triangles (as a triangle list) (if you can use a Z buffer, all the better). Then you can draw the triangles, and then the lines.

Doing this also means you have a "screens" worth of prims, meaning you don't have to rebuild it if it doesn't change.
Thanks for the information! What I had done before this was draw it into a large surface and every time the player moves into an 'unloaded' area I refresh the surface. Would you recommend I use your method instead? Thanks!
Here's what it looks like now:
 

Mike

nobody important
GMC Elder
To be honest, whatever your happy with. If you include the "lines" in your isometric tiles, you'll be able to "texture" the ground easily if you want to, and still only draw sprites. Your image at the top was using vertex colouring to get inner tile shading, but if your going to use flat shading (as above) then I'd just use tiles. You could probably just draw that every frame if you wanted - see the isometric demo that's included with Studio.
 

YanBG

Member
Yes the first screenshot was more interesting for me, because i want to make seamless beaches with my tiles but i haven't yet tested the OP's code.

However the second version shows some difference in the grid's color shading as well.
 

Mike

nobody important
GMC Elder
You can always do transitions with more tiles, and you can always colour tint the tile for shading if you really want to, but since a tile is drawn in a specific light direction, you usually don't have to.
 

YanBG

Member
How many more tiles? I don't want to draw all the half tile combinations, what about some kind of alpha tile with jagged line in the middle that makes parts of the solid color tiles merge together?
 
Top