Great Game Maker Wall Optimization Script

Posted by TamerKoh on Sept. 28, 2012, 8:39 a.m.

After reading about how to optimize Game Maker games to make them run faster, I decided to try out one method mentioned before, to combine all of the Wall objects into one sprite using a surface, then deleting them all, and creating one big wall, it worked out TREMENDOUSLY. So I thought it would be useful for me to share my script with everyone. It's not hard to do of course, but it could save time, and I recommend using it with every game that's bound to have a lot of Wall objects. You call this script in the Room Creation Code.

var; wallsurface=0; w=0;  //Variables for the Surface on which all the wall sprites will be put on, and the New Wall object that will be made.
wallsurface=surface_create(room_width,room_height+1);  //Prepare a surface as big as the room, adding an extra pixel vertically so we can have transparency.

surface_set_target(wallsurface);  //Prepare to draw on the surface.
draw_clear(c_white);  //Clear the entire surface with the desired transparent color.
with objWall{  //With all of the walls in the room...
    if object_index==objWall{  //If it's not inheriting from anything (you may want to handle slopes with their own combined slope object, for example...
        draw_sprite(sprite_index,-1,x,y);  //Draw their sprite on the surface at their location.
        instance_destroy();  //Then delete theirself.
    }
}
if sprite_exists(global.wallopsprite){sprite_delete(global.wallopsprite);}  //If there was a combined wall surface sprite made before, get rid of it.  This is crucial you store this, as these will build up if you don't get rid of them, and can crash the game.
global.wallopsprite=sprite_create_from_surface(wallsurface,0,0,surface_get_width(wallsurface),surface_get_height(wallsurface),true,false,0,0);  //Make a new sprite from the surface made of all the Wall objects.
w=instance_create(0,0,objWall);  //Make a brand new Wall object at the top left of the room;
w.sprite_index=global.wallopsprite;  //Set its sprite to the sprite made from the surface.
w.mask_index=w.sprite_index;  //Set its mask to its sprite.
surface_free(wallsurface);  //Free up the memory from that surface.
surface_reset_target();  //Reset the drawing location.

It's not much, but it's effect on a game with a lot of Wall objects like my game is TREMENDOUS. I have no lag whatsoever now. You are all free to use this :).

Comments

ludamad 13 years, 1 month ago

Isn't this a large trade-off in terms of memory usage ?

sirxemic 13 years, 1 month ago

Quote:
surface_create(room_width,room_height+1);
Nice, you just make 99% of PCs crash when room_width and room_height are larger than 2048px.

Moikle 13 years, 1 month ago

@luda computers nowadays have so much RAM it is a non issue

ludamad 13 years, 1 month ago

Moikle: I suppose so, but things that grow linearly for room size can really get out of hand, especially with persistent rooms/improperly freed structures.

TamerKoh 13 years, 1 month ago

@sirxemic: Why would they crash? Also, once the sprite is made for the combined walls, and all the sprite creation and setting is done, the surface is deleted.

TamerKoh 13 years, 1 month ago

Also, I forgot to note that I've already tested this with my game. Before I made the script, I was getting some lag until I killed the enemies in the room. But now that I made this and used it, I no longer have lag issues, and anyone who lagged before probably won't now :).

sirxemic 13 years, 1 month ago

Through my experience (and at least 1 other) surfaces bigger than 2048x2048 (or was it 4096x4096?) might raise issues. Maybe in your case it works fine since it's used for just 1 thing and then immediately is discarded. Anyhow, if you could try it out, please do. I can't because I don't have GM on this PC and I am curious :P

TamerKoh 13 years, 1 month ago

It already works fine, but I understand what you're saying. I plan to write an alternate version that handles it in 4 chunks (512x512 surfaces) or more (256x256, 128x128, etc), so the lower end computers could benefit from this also. In addition, I also plan to write a script that combines all the tiles on a layer into a single tile like above (or chunks for the alternate script), as a bunch of tiles also slow the game down.

Rob 13 years, 1 month ago

I had my levels for last year's S4D entry as one big sprite. They were between 1600x800 and 2800x1400. Almost all of them wouldn't even fully render on my laptop. Oops!

Also, someone fix the damned code tags:

TamerKoh 13 years, 1 month ago

After having friends test this, I realize there is no need to make a separate script that divides this into chunks, as this script is running perfectly fine even on a computer that only has 1.5 GB of RAM. This script would probably not be the best way to optimize walls in a REALLY large room, probably bigger than 4800x4800, however, this should be fine for things smaller. Also, as mentioned, the surface after used is deleted right afterwards (As are the previous combined sprites made) so it's not lingering in memory.