GM:S 1.4 Isometric Top Down Engine (with height) Method

Discussion in 'Programming' started by Pandavim, Jun 25, 2016.

  1. Pandavim

    Pandavim Member

    Joined:
    Jun 20, 2016
    Posts:
    34
    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).
    [​IMG]
    I also like the look of this tile engine:
    [​IMG]
    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
     
    Turgon likes this.
  2. Surgeon_

    Surgeon_ Symbian Curator

    Joined:
    Jun 22, 2016
    Posts:
    248
    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_
     
  3. YanBG

    YanBG Member

    Joined:
    Jun 25, 2016
    Posts:
    576
    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 likes this.
  4. Pandavim

    Pandavim Member

    Joined:
    Jun 20, 2016
    Posts:
    34
    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!)
     
  5. seanm

    seanm Member

    Joined:
    Jun 20, 2016
    Posts:
    332
    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 likes this.
  6. Pandavim

    Pandavim Member

    Joined:
    Jun 20, 2016
    Posts:
    34
    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.
     
  7. begjan

    begjan Guest

    wow cool... :D
     
  8. Mike

    Mike nobody important GMC Elder

    Joined:
    Apr 12, 2016
    Posts:
    2,356
    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.
     
    Lonewolff and Pandavim like this.
  9. Pandavim

    Pandavim Member

    Joined:
    Jun 20, 2016
    Posts:
    34
    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:
    [​IMG]
     
  10. Mike

    Mike nobody important GMC Elder

    Joined:
    Apr 12, 2016
    Posts:
    2,356
    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.
     
    Pandavim likes this.
  11. YanBG

    YanBG Member

    Joined:
    Jun 25, 2016
    Posts:
    576
    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.
     
  12. Mike

    Mike nobody important GMC Elder

    Joined:
    Apr 12, 2016
    Posts:
    2,356
    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.
     
  13. YanBG

    YanBG Member

    Joined:
    Jun 25, 2016
    Posts:
    576
    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?
     
  14. Pandavim

    Pandavim Member

    Joined:
    Jun 20, 2016
    Posts:
    34
    Ah I see, thanks for all the help. I'll check out the isometric demo
     

Share This Page

  1. This site uses cookies to help personalise content, tailor your experience and to keep you logged in if you register.
    By continuing to use this site, you are consenting to our use of cookies.
    Dismiss Notice