GML [SOLVED] ds_grid Collision Question(s)

N

noino

Guest
So at the suggestion of a friendly user on this forum i converted my randomly generated sandbox game to utilize ds_grid collisions to improve it's dismal performance; however, using the same sizes (room and block) the performance dives from the original (instance) system: 58~ fps to a substantially slower 45~ fps.

In the tutorial I was referenced I needed to draw every sprite 60 times per second, with the estimated tile count being 45,000.
approximately 100-300 repetitions of the tile (in both systems) were actually on screen. Knowing of instance_deactivate_all I could manage all the instances with, as mentioned earlier, just under 60fps.
But it just isn't the case with the new system.

sadasd.png lagh.png
 

Nocturne

Friendly Tyrant
Forum Staff
Admin
If you are using tiles then yes, this may affect performance MORE than instances, as GMS has no way to cull tiles outside the view (although the graphics card won't try to render anything outside the view, tiles still have properties and still need to be processed for position etc...), so deactivating instances in this case could actually be quicker.

That said, there are various workarounds that you can use. For example, split the tiles into "chunks" on different layers (or depths if using GMS1.4) then make the layers/depths visble/invisible based on the player position within the room. This way you'd have at most two layers visible at any one time, and performance will improve as only visible tiles are processed.

Another option would be to use surfaces. Draw all your tiles onto various surfaces and then draw the surfaces other than the tiles themselves. This option is slightly more complex as surfaces are volatile but it's certainly doable.
 
N

noino

Guest
Technically they aren't "tiles", just using it as lack of a better word. In heinsight "cells" would be more appropriate, but I'll consider the advice.
Using chunks could be a good idea; however I'm unsure what the most effective method for this would be.
 

Nocturne

Friendly Tyrant
Forum Staff
Admin
So, you are looping through the DS grid to draw the "tiles"? If so then that should actually be very fast as long as you limit the grid lookup to only check the area of the grid that's in the view currently.
 
N

noino

Guest
So, you are looping through the DS grid to draw the "tiles"? If so then that should actually be very fast as long as you limit the grid lookup to only check the area of the grid that's in the view currently.
Oh my thank you very much! I didn't think to limit my "for" loops to just the view. My mistake, thanks for the help :D
 
N

noino

Guest
So, if anyone sees this from now, I have another question. In my old system using instances, multiple variables were stored. This includes health, harvest minimum and tool requirement variables. How could I store these variables in every cell and have a cell create an instance and disappear when health is less than 0?
would a ds_list, array, or multiple ds_grids be the most appropriate approach, or would it be another, more effective method? I'm very new to data structures unfortunately, but any help is appreciated
 

Nocturne

Friendly Tyrant
Forum Staff
Admin
You could assign a ds_map each cell. Maps are fast and very easy to use, especially for what you are doing... each key would be a variable (as a string) making them very easy to read and use. So something like:
Code:
var _map = ds_map_create();
_map[? "health"] = 0;
_map[? "harvest_min"] = 10;
_map[? "tools"] = "spade";
global.grid[# xpos, ypos] = _map;
Just remember at the end of the room you'll have to loop through every cell of the grid, check for a ds_map and delete it if one exists to free up the memory...
 
N

noino

Guest
You could assign a ds_map each cell. Maps are fast and very easy to use, especially for what you are doing... each key would be a variable (as a string) making them very easy to read and use. So something like:
Code:
var _map = ds_map_create();
_map[? "health"] = 0;
_map[? "harvest_min"] = 10;
_map[? "tools"] = "spade";
global.grid[# xpos, ypos] = _map;
Just remember at the end of the room you'll have to loop through every cell of the grid, check for a ds_map and delete it if one exists to free up the memory...
Thank you very much!
 
N

noino

Guest
I'm still so lost. I have the basic concept down but I fail to correctly execute it.
I feel like I've done something completely wrong xdd
Code:
for(var xx = view_xview div 35; xx < (view_xview+view_wview+35) div 35; xx++;){
    for(var yy = view_yview div 35; yy < (view_yview+(view_hview)+70) div 35; yy++;){
        if(xx > 0 and yy > 0 and xx < room_width and yy < room_height){
            var sprite = ds_grid_get(grid,xx,yy);
            if(sprite = spr_tile_grass
            or sprite = spr_tile_stone
            or sprite = spr_tile_dirt){
                ds_grid_set(collidegrid,xx,yy,1);
            }else{
                ds_grid_set(collidegrid,xx,yy,0);
            }
            if(sprite){
                draw_sprite(sprite,0,xx*cell_size,yy*cell_size);
            }
            var _map = ds_map_create();
            if(sprite = spr_tile_grass){
                _map[? "health"] = 120;
                _map[? "harvest_min"] = 1;
                _map[? "tools"] = "shovel";
            }else{
                _map[? "health"] = 60;
                _map[? "harvest_min"] = 1;
                _map[? "tools"] = "shovel";
            }
            datagrid[# xx, yy] = _map;
            if(mouse_x div 35 = xx and mouse_y div 35 = yy){
                if(mouse_check_button(mb_left)){
                    _map[? "health"] -= 160;
                    if(_map[? "health"] <= 0){
                        ds_map_destroy(_map)
                        grid[# mouse_x div 35,mouse_y div 35] = 0;
                    }
                }
            }
            ds_map_destroy(_map);
        }
    }
}
Thank you for your time
 
Top