GameMaker Creating objects from the tile layer

PlayerOne

Member
I'm trying to make to improve this code by spawning all the collision objects for any given level by placing tiles in the room. Current I got the intended effect but it's very slow and I need to make this instant when the room starts. Tried using a for loop but it doesn't work at all. Any help is appreciated.

Code:
//STEP
//Layer Data
   var tile_name = "layer_collision"; //Name of layer
   var lay_id = layer_get_id(tile_name); //Gets layer ID
   var map_id = layer_tilemap_get_id(lay_id); //Gets tilemap ID
   var data = tilemap_get_at_pixel(map_id,x,y) //When player collides into tile layer


   if (data!=0){instance_create_depth(x,y,10,oWall1);}   
   x+=32   
   if x>=room_width{y+=32 x=0;}
   if x>=room_width && y>=room_height{loop=false;}
 

Freddy Jones

Your Main Detective
All you go to do is slightly modify your code to work with loops. It's almost the same thing. I wouldn't recommend a for loop for this since you've kind of developed already to be drop-and-play with a while loop. So you could just take your code to look something like ....


Code:
//CREATE
//Layer Data
var loop = true;
while loop begin
   var tile_name = "layer_collision"; //Name of layer
   var lay_id = layer_get_id(tile_name); //Gets layer ID
   var map_id = layer_tilemap_get_id(lay_id); //Gets tilemap ID
   var data = tilemap_get_at_pixel(map_id,x,y) //When player collides into tile layer


   if (data!=0){instance_create_depth(x,y,10,oWall1);} 
   x+=32 
   if x>=room_width{y+=32 x=0;}
   if x>=room_width && y>=room_height{loop=false;}
end
I didn't quite test it, but that's the idea. This isn't how I would write it, but im sure you can refactor the code and get more familiar with it.
 
I

immortalx

Guest
No need to do that in a step event. You can either do it like Freddy Jones suggested, or with a for loop in a create event:
Code:
var lay_id = layer_get_id("Tiles_1");
var map_id = layer_tilemap_get_id(lay_id);
var grid_unit = 64;

for (var xx = 0; xx < room_width; xx += grid_unit)
{
    for (var yy = 0; yy < room_height; yy += grid_unit)
    {
        if (tilemap_get_at_pixel(map_id, xx, yy) == 1)
        {
            instance_create_layer(xx, yy, "Instances", obj_wall);
        }
    }
}
You could of course handle tile collisions since there are already there. Alternatively, If you'd like to have the tiles as artwork and have invisible collision instances, you can do a slightly more complicated way that creates "strips" of instances, in order to lower the instance count:
Code:
var lay_id = layer_get_id("Tiles_1");
var map_id = layer_tilemap_get_id(lay_id);
var grid_unit = 64;
var has_adjacent = false;
var strip_count = 0;
var curr_tile, next_tile, strip_start_xx;
var xx = 0;
var yy = 0;

while (yy < room_height)
{
    while (xx < room_width)
    {
        curr_tile = tilemap_get_at_pixel(map_id, xx, yy);
        next_tile = tilemap_get_at_pixel(map_id, xx + grid_unit, yy);
        
        if (curr_tile != 0 && next_tile == 0)
        {
            instance_create_layer(xx, yy, "Instances", obj_wall);
        }
        else if (curr_tile != 0 && next_tile != 0)
        {
            has_adjacent = true;
            strip_start_xx = xx;
            strip_count++;
        }
        
        while (has_adjacent)
        {
            xx += grid_unit;
            strip_count++;
            
            if (xx + grid_unit < room_width)
            {
                next_tile = tilemap_get_at_pixel(map_id, xx + grid_unit, yy);
            }
            
            if (next_tile == 0)
            {
                has_adjacent = false;
                var inst = instance_create_layer(strip_start_xx, yy, "Instances", obj_wall);
                inst.image_xscale = strip_count;
                strip_count = 0;
            }
        }
        xx += grid_unit;   
    }
    xx = 0;
    yy += grid_unit;
}
 
Top