http://gmc.yoyogames.com/index.php?showtopic=539230&st=0#entry3953653
I must say, my first method was stupid. As you read the topic you'll see I went towards using an array. Now I'm using a trigger that checks the array for collisions then I create the block (sometimes a few, depending on the nature of the object) at the right place on the grid and trigger the collision event that is meant to happen when that block is hit. The block will check every second for a collision and, if there is none, it destroys itself.
I don't mess with the slopes or any other terrain, just the squares. Adding slopes may be easy and I will try is a bit, but I wanted to post this and see what others thought of what I'm doing.
I am doing this so I can have the benefit of a reduced object count (before: 1849, after: 346) without completely rewriting my physics system. The game has gone too far and I don't want that setback. Hopefully such a system as this may help others as well, but I am not going to make an engine out of it. So here is my code. If anyone is helped or inspired by it, awesome.
Code
Generating the array/cleaning up the blocks:
//Get the width and height of the array
_width = ceil(room_width/32);
_height = ceil(room_height/32);
//Loop through the array and set the default value to false
for (_i = 0; _i < _width; _i+=1){
for (_ii = 0; _ii < _height; _ii+=1){
global.map[_i,_ii] = false;
}
}
//Loop through the terrain objects and delete all the ones on the 32x32 grid
with objBlock {
if (x mod 32 = 0 && y mod 32 = 0){ //if there is a remainder the object is not on the grid
global.map[x/32,y/32] = object_index; //write position to the array
instance_destroy();
}
}Trigger: It checks for the global variable just in case the map was NOT optimized. The game should run no differently if the above code is not run.
if (variable_global_exists("map"))
{
_l = sprite_get_bbox_left(mask_index) - sprite_get_xoffset(mask_index);
_t = sprite_get_bbox_top(mask_index) - sprite_get_yoffset(mask_index);
_r = sprite_get_bbox_right(mask_index) - sprite_get_xoffset(mask_index);
_b = sprite_get_bbox_bottom(mask_index) - sprite_get_yoffset(mask_index);
//checks every side of the sprite for a collision.
return global.map[floor((x+_l)/32),floor((y)/32)] || global.map[floor((x+_r)/32),floor((y)/32)] || global.map[floor((x)/32),floor((y + _b)/32)] || global.map[floor((x)/32),floor((y + _t)/32)];
}
Example collisions:
In Event Trigger Collide Map (the above code) in objGrenade
_x = floor(x/32); _y = floor(y/32); if (global.map[_x - 1, _y] && !instance_position((_x - 1) * 32, _y*32, objBlock)) instance_create((_x - 1) * 32, _y*32, objBlock); if (global.map[_x, _y] && !instance_position(_x * 32, _y*32, objBlock)) instance_create(_x * 32, _y*32, objBlock); if (global.map[_x + 1, _y] && !instance_position((_x + 1) * 32, _y*32, objBlock)) instance_create((_x + 1) * 32, _y*32, objBlock); if (global.map[_x, _y - 1 ] && !instance_position(_x*32, (_y-1)*32, objBlock)) instance_create(_x*32, (_y-1)*32, objBlock); if (global.map[_x, _y + 1 ] && !instance_position(_x*32, (_y+1)*32, objBlock)) instance_create(_x*32, (_y+1)*32, objBlock); event_perform(ev_collision, objCollision);
Note for the above: This object is a grenade. If I don't pad the area around the collision block with other blocks it will bounce off the side of the block. The code checks to see if the map should have block in places before trying to place one and creates one if there is not one there already.
In Event Trigger Collide Map (the above code) in objShell_casing
if (!instance_position(floor(x/32)*32, floor(y/32)*32, objBlock)){
instance_create(floor(x/32)*32, floor(y/32)*32, objBlock);
}
event_perform(ev_collision, objSolid);
Note for above: This is a very small object that just does a small bounce. Like before, I check if there is a block there before creating one. This time I don't need to check the map array at all because by triggering this event we know the object is at a place where a block is.
objBlock:
In Event Create
if ((variable_global_exists("map")) && (x mod 32 = 0) && (y mod 32 = 0))
alarm[0] = 30;In Event Alarm 0if (place_free(x,y)){
instance_destroy();
}
alarm[0] = 30;Note for above: The creation code checks if the map has been created and, if so, if the block is on the grid. This is so the blocks will not delete themselves if the optimization init was not run or they were skipped by it.
I would use instance_activate and such but until Game Maker has instance_activate_region_object and instance_deactivate_region_object that method is not an option for my type of game.
Here is a video showing the difference and some code that I had shown here. I forgot to show the trigger.
http://www.youtube.com/watch?v=lY4giL1lGFA
The dark spots on the map are the blocks I seek to reduce. I've only done the squares so far because the rest were only a minor concern. The second time I run the game I've enabled the map optimization and those blocks are gone, only being created when needed. I programmed the player to not require those blocks anymore, same with bullets. They use the array data directly so that is why they don't create blocks when they hit walls. I may take this back, it depends. Either way, I'm happy with the results of this code so far.
I hope you can read the instance count but the numbers are:
Before: 1849
After: 346
If I missed anything or something needs explaining be sure to ask.
Edit: Fixed some logic errors and changed the collision checking for when a block will delete itself.



Find content
Male




