Welcome, Guest. Please login or register.

Login with username, password and session length

 
Advanced search

1411471 Posts in 69369 Topics- by 58423 Members - Latest Member: antkind

April 23, 2024, 10:36:06 AM

Need hosting? Check out Digital Ocean
(more details in this thread)
TIGSource ForumsCommunityTownhallForum IssuesArchived subforums (read only)TutorialsGame Maker: Optimizing For Speed/Memory
Pages: [1] 2 3
Print
Author Topic: Game Maker: Optimizing For Speed/Memory  (Read 122777 times)
Derek
Bastich
Administrator
Level 10
******



View Profile WWW
« on: November 25, 2008, 07:32:45 PM »

Optimizing Your Game Maker Game


Intro: Since I'm a pretty mediocre programmer, I often go for an easy solution to my coding problems rather than an efficient one.  Game Maker is kind of notorious for being slow anyway, so it didn't take long for me to hit its limits.  But with a little research, and some good advice from experienced GM users, I started to make some optimizations to my game that significantly increased its speed.  And now I pass that knowledge down to you!

Here are some tips, from what I think is the most important, to leaster.

1. Deactivate/Destroy Unused Instances

Object instances slow down Game Maker a LOT.  I've heard that ~50 instances is the most that you should have awake at once.  And the more work an object is doing each step, the slower it will be, so take care to make sure nothing is awake if it's not needed.

To that effect, instance_destroy() and instance_deactivate() are your friends.  Try deactivating anything that's outside of the player's view, and destroy anything that's outside of the room.

For example, put this in the Step Event of an invisible object that sits in each level:

Code:
instance_deactivate_region(view_xview[0], view_wview[0], view_hview[0], false, true);
instance_activate_region(view_xview[0], view_yview[0], view_wview[0], view_hview[0], true);

Make sure you don't deactivate important objects (like the object calling the code!).  If you set the argument "notme" to true, the object will ignore itself in the deactivation.

2. Use Tiles Instead of Objects

Tiles are much, MUCH faster than objects, so you should use them in place of objects whenever you can.  You can actually do a lot of things with tiles, like create and destroy them, set their depth, get their position, etc.  They're not completely static.

Background details that you don't actually interact with are perfect tile material.

3. Do Fewer Collision Checks

Objects that have collision events are much slower than objects that don't.  So place those events in the objects which will have the fewest instances.  A good example is the player versus the 100 bullets.  You obviously have to do a collision check between the two objects... make sure that event goes in the player object instead of the bullet.

Collision functions (and trig calculations) in general are pretty heavy, so it's a good idea to have as few of them as possible.  Make sure you're not doing the same collision check more than once in a single step.  If you need to look up the return value of any slow function more than once, consider putting the value of the collision in a variable and check the variable instead.

Whenever possible, turn off "Precise collision checking," which is a per-pixel collision detection method.

4. Optimize Your Use of Step Events

Step Events are, of course, called every step... so the more you do in the Step Event, the slower your game will be.  Whenever possible, reduce the size of your Step Events, and also the number.  If you don't have to do it every step, then don't!

One alternative is to use Alarms.

5. Do Less Drawing

The less drawing you do, the better.  Optimize your drawing routines.

Quote from: Game Maker Manual
If you have a covering background, make sure you switch off the use of a background color.

Quote from: Game Maker Manual
Also be careful with the use of many views. For each view the room is redrawn.

6. Sample Down Your Sound/Music

Sound can take up a lot of memory and space, especially wavs and mp3s, so sample them down if you can.  Ask yourself if the higher bitrate or extra channel is worth the hit!

Keep in mind that Game Maker doesn't support mods or oggs, and it barely supports mp3s, so consider using a library like supersound.dll for your sound needs.

7. Crop Your Sprites

Quote from: Game Maker Manual
First of all, look carefully at the sprites and backgrounds you use. Animated sprites take a lot of memory and drawing lots of sprites takes a lot of time. So make your sprites as small as possible. Remove any invisible area around it (the command crop in the sprite editor does that automatically). The same applies to background images.

--- Newly Added ---

8. Turn Off Synchronization

Under "Global Game Settings -> resolution" there is an option "Use synchronization to avoid tearing"... make sure it is unchecked!  Not only does it do very little to help with tearing problems, it can also drastically reduce your game's speed.  I had it checked accidentally and it increased my CPU usage about 10-20% (from about 20-30% to 40-50%).

9. Use Smaller Screen Resolutions

Quote from: rinkuhero
640x480 is fine for most games. I kind of regret making [Immortal Defense] 1024x768 -- it looks nice, but just the fill rate makes it much slower. Use dedicated resolutions, they work faster than windowed and much, much faster than stretched.

10. Use Bigger Tiles, Rather than More Tiles

While tiles are lighter than objects, having a lot of them will still cause slowdown.  If you can use a handful of large tiles rather than a lot of little ones, do so.

11. Draw Primitives to a Surface First

Regarding functions like draw_circle, draw_rectangle, or draw_line: first draw the primitive to a surface, then draw the surface to the screen.  It's much faster that way.

12. Don't Use execute_string()

It's really slow.



In conclusion, do more with less and compromise when you can!  Thanks to Melly, rinkuhero, ChevyRay, and whoever else for the tips.  Please share your own, or let me know if I've made any mistakes.
« Last Edit: March 19, 2009, 09:03:58 PM by Derek » Logged
___
Vice President of Marketing, Romeo Pie Software
Level 10
*


View Profile
« Reply #1 on: November 25, 2008, 08:37:45 PM »

SO... Can tiles be used for collision checking or are they just for show...? :I
Logged
Derek
Bastich
Administrator
Level 10
******



View Profile WWW
« Reply #2 on: November 25, 2008, 10:33:35 PM »

Not that I know of.  I think if they did, that would make them slow, too. Cry
Logged
William Broom
Level 10
*****


formerly chutup


View Profile
« Reply #3 on: November 26, 2008, 04:15:00 AM »

This is really useful. I'm guilty of a lot of things myself but fortunately they haven't caused me many problems yet since my games have been small and not system-intensive.

One thing I noticed with my CPB entry was that once it had even a handful sounds in it, it took a long time to load on startup. Which of the above steps will help in this regard? And does it help to put the sounds and graphics in separate folders rather than binding them up inside the .exe?
Logged

___
Vice President of Marketing, Romeo Pie Software
Level 10
*


View Profile
« Reply #4 on: November 26, 2008, 04:26:31 AM »

This is really useful. I'm guilty of a lot of things myself but fortunately they haven't caused me many problems yet since my games have been small and not system-intensive.

One thing I noticed with my CPB entry was that once it had even a handful sounds in it, it took a long time to load on startup. Which of the above steps will help in this regard? And does it help to put the sounds and graphics in separate folders rather than binding them up inside the .exe?

I believe if you use external sources, they don't have to be loaded when the game starts?  I'm not really an expert in GM ... yet ;p
Logged
Pishtaco
Level 10
*****


View Profile WWW
« Reply #5 on: November 26, 2008, 05:17:15 AM »

I have some questions:

1. Are lots of instances a problem if they aren't doing anything on screen, and don't have any step events, but are just being used as data storage somewhere in the background?

5. & 7. What is the difference between sprites, surfaces and backgrounds? And aren't they all done as textures through 3d cards, these days? If so, it seems to me they should be drawn quickly, even if they are big; but what limits you will be the texture memory on the graphics card and how long it takes to copy to it. But maybe I'm misunderstanding things here. This question has come up for me in the game I am working on for the commonplace competition. It has a typewriter ribbon in it, which is quite big on the screen (maybe 100*200), but which is simple and only has two frames of animation. At the moment I am drawing it as a two-frame sprite; but would it be better to do it as two backgrounds? Or to draw it from primitives?

Also - it's probably a good idea to use low-colour images rather than 24 bit ones, since the game will be smaller and load faster; but does it make any difference to drawing speed?
Logged

Derek
Bastich
Administrator
Level 10
******



View Profile WWW
« Reply #6 on: November 26, 2008, 06:56:36 AM »

I think an object that is only holding variables is probably not a threat, unless you have like 500 of them floating around.

Not too sure about the rest, except that I don't think it would be any faster to draw a background or tile rather than a sprite.

I did find out tonight that enabling "Use synchronization to avoid tearing" increases the CPU usage of my games by at least 10-20% on my Macbook Pro (in Windows mode).  I've had it checked on accident, and only now noticed!  I've never heard of that being a problem, but if you have it enabled and are experiencing slowdown, try turning it off.  Anyone know why that would be, though?
Logged
Mr Dumle
Level 1
*



View Profile
« Reply #7 on: November 26, 2008, 08:37:46 AM »

What is the difference between sprites, surfaces and backgrounds? And aren't they all done as textures through 3d cards, these days?

I'm a beginner when it comes to programming but I read once that surfaces are drawn from the graphics card and that's why you can't resize the game window without the surfaces screwing themselves up. So that means the sprites and background is drawn with the cpu because resizing them works.
Logged

Gnarf
Guest
« Reply #8 on: November 26, 2008, 09:08:23 AM »

I'm a beginner when it comes to programming but I read once that surfaces are drawn from the graphics card and that's why you can't resize the game window without the surfaces screwing themselves up. So that means the sprites and background is drawn with the cpu because resizing them works.

Drawing some things with the graphics card and some things with the regular processor like that doesn't make a lot of sense. I think the thing is that surfaces are only kept in texture memory. While sprites and backgrounds are also on disk and/or in regular memory somewhere that Game Maker knows of. So I'd assume that Game Maker can load sprites and backgrounds into the texture memory again after destroying the old rendering context (by resizing or something) all by itself, but it won't do that with surfaces because you just create them as texture memory and render stuff to them or something.

Also - it's probably a good idea to use low-colour images rather than 24 bit ones, since the game will be smaller and load faster; but does it make any difference to drawing speed?

I would guess no, for I would guess that every image takes the same amount of bits per pixel (16 or 32, depending on display settings) in (texture) memory anyway.
Logged
Melly
Level 10
*****


This is how being from "da hood" is like, right?


View Profile
« Reply #9 on: November 26, 2008, 01:56:10 PM »

GM objects are heavily bloated. If you really want to know GM's limits, experiment.

Once, I did a little test. I did a GM example where one object called a collision detection function 1000 times in a step. The FPS was around 100 at most (set the room FPS to 9999 or something to see how fast it can go). Then I did 1000 object instances doing one collision detection each step each. The FPS went down to around 10 or so, proving that even if an object isn't doing much, just for it being there it bogs down your game. Objects instances need to be used as little as possible.

No, tiles can't be checked directly for collision, and I'm not sure if you could do it with code, but it wouldn't hurt to try.

One golden rule in GM is: If it's a static graphic that you may at most create/destroy/set-depth on the fly, use tiles. If you have animations that are static, have an object call all of them by drawing sprites (with code you might be able to make them move as well). Object instances are for things like actual game entities and graphics moving in complex patterns.

Like Derek mentioned, step events are a last resort. They're code that will be run every single frame. If you can, use self-reseting alarm events instead of step events, as you can basically dictate how often the code will be run. You can have a shmup with guided bullets where the bullets don't change their direction every step, but once every 5-6 or so. At 60 FPS only the most observant players will notice, and with many bullets that does improve things a little.
Logged

Feel free to disregard the above.
Games: Minus / Action Escape Kitty
___
Vice President of Marketing, Romeo Pie Software
Level 10
*


View Profile
« Reply #10 on: November 26, 2008, 02:22:48 PM »

So just a toss up question.  Say for a particle system.  Is it better to have an object that maybe has an array of every particle currently on screen, and have it loop through that array to control and draw them?  Instead of each particle being an object that behaves independently.
Logged
Alevice
Level 10
*****



View Profile WWW
« Reply #11 on: November 26, 2008, 02:31:50 PM »

I did find out tonight that enabling "Use synchronization to avoid tearing" increases the CPU usage of my games by at least 10-20% on my Macbook Pro (in Windows mode).  I've had it checked on accident, and only now noticed!  I've never heard of that being a problem, but if you have it enabled and are experiencing slowdown, try turning it off.  Anyone know why that would be, though?

It is probably a fancier way of saying it is vsync mode. I am pretty bad explaining, but every emulation forum has quite often this question. here is what some source have to say:

Quote from: Wikipedia link="http://en.wikipedia.org/wiki/Vsync"
Vertical synchronization (v-sync, vbl-sync) refers generally to the synchronization of frame changes with the vertical blanking interval. Since CRTs were nearly the only common video display technology prior to the widespread adoption of LCDs, the frame buffers in computer graphics hardware are designed to match the CRT characteristic of drawing images from the top down a line at a time by replacing the data of the previous frame in the buffer with that of the next frame in a similar fashion. If the frame buffer is updated with a new image while the image is being transmitted to the display, the frame buffer gives it the current mishmash of both frames, producing a page tearing artifact partway down the image.
Vertical synchronization eliminates this by timing frame buffer fills to coincide with the vertical blanking interval, thus ensuring that only whole frames are seen on-screen.
Computer games often allow vertical synchronization as an option, because it delays the image update until the vertical blanking interval. This can cause lowered frame rates due to latency (the period of the refresh rate at maximum), which might be undesirable in games that require fast response (e.g. first person shooters).
VSYNC is also the name of the signal indicating this frame change in analogue RGB component video.
Logged

Gnarf
Guest
« Reply #12 on: November 26, 2008, 02:33:20 PM »

GM objects are heavily bloated. If you really want to know GM's limits, experiment.

Once, I did a little test. I did a GM example where one object called a collision detection function 1000 times in a step. The FPS was around 100 at most (set the room FPS to 9999 or something to see how fast it can go). Then I did 1000 object instances doing one collision detection each step each. The FPS went down to around 10 or so, proving that even if an object isn't doing much, just for it being there it bogs down your game. Objects instances need to be used as little as possible.

It's not immediately apparent what that has got to do with object bloat. Checking for collision probably takes longer if there's a ton of other objects to check for collision against. Like, in the first test you check for collision against nothing in particular 1000 times while in the other test you check for collision against 999 other objects 1000 times. They're not "just being there".

That is, it sounds more like something that possibly might say something about how Game Maker handles collision detection than something about object bloat.
Logged
ஒழுக்கின்மை (Paul Eres)
Level 10
*****


Also known as रिंकू.


View Profile WWW
« Reply #13 on: November 26, 2008, 02:50:59 PM »

Turning vsync off is generally a good idea, as is mentioned in another thread it doesn't even work very well to reduce tearing, so unchecking it is usually harmless and increases your fps drastically.

I have a few techniques of optimization that I use in special cases, but Derek covered most of the important stuff.

A few things more:

- pick a low resolution when possible. 640x480 is fine for most games. I kind of regret making ID 1024x768 -- it looks nice, but just the fill rate makes it much slower. use dedicated resolutions, they work faster than windowed and much, much faster than stretched.

- if you use a lot of tiles, make them as big as possible. although tiles are faster than objects, they still do slow down a game, and using as few tiles as possible does increase speed significantly. in Alphasix, I replaced all the tiles which just plain background images (by taking a screenshot of the map and using that as the background) and it worked much better.

- don't draw primitives like draw_circle or draw_rectangle or draw_line. instead, draw the primitive on a surface, and then draw the surface (scaled, if need be). it's far faster.

You may also want to read through this thread: http://gmc.yoyogames.com/index.php?showtopic=189532 -- it's an old GMC topic, but has tons of tips on this.
Logged

Gnarf
Guest
« Reply #14 on: November 26, 2008, 03:35:45 PM »

Turning vsync off is generally a good idea, as is mentioned in another thread it doesn't even work very well to reduce tearing, so unchecking it is usually harmless and increases your fps drastically.

If it works at all, it eliminates tearing. Though my impression is that something bizarre is up with it and LCD screens. If your game can keep up with the refresh rate, FPS is not effected. If you use vsync and triple buffering, FPS is not effected, unless you run out of texture memory. And stuff. I'd say leaving it off until you have a problem with tearing is a good idea. Then I'd try different things.

I would guess that the increased CPU usage is nothing to worry about. That the game is wasting cycles while waiting for the screen to be ready for drawing to. Chances are that's a horribly stupid guess though.
Logged
Derek
Bastich
Administrator
Level 10
******



View Profile WWW
« Reply #15 on: November 26, 2008, 03:40:47 PM »

Awesome, added! Beer!

I know all this info is out there somewhere, but it's nice to have it in one place.  Hope this is useful for people - I really would have appreciated it when I started out.  (Although not having any info kind of forced me to examine my code more carefully.)
Logged
Blaster
Pixelhead
Level 1
******


*wiggle*


View Profile WWW
« Reply #16 on: November 26, 2008, 04:49:23 PM »

This is much appreciated!
Logged

Pixel Art: Portfolio || Twitter: @pita_akm || Tumblr: silver deluxe
Matt Thorson
Level 7
**

c'est la vie


View Profile WWW
« Reply #17 on: November 26, 2008, 05:06:42 PM »

12. Don't Use execute_string()

It's really slow.

This is true in most cases, but execute_string() is also super useful and not noticeable if you use it at specific times.

For example:  For the room system for An Untitled Story I used it.  Each room is named for its x/y co-ordinates (ie: rm_5_6).  The player's current room x and y are stored in global variables, and when you exit off the side or top/bottom of a room, it modifies the x/y accordingly then runs:

Code:
execute_string( "room = rm_" + string(mapX) + "_" + string(mapY) + ";" );

This is by far the easiest method of doing this.  Since Game Maker already keeps track of the room names internally, adding an array or grid to keep track of which room goes where would be a huge waste of memory.  Plus adding every room to the grid/array manually would be super tedious.  Also, because the function is only ever done on room change, it isn't noticeable anyways.
Logged

ஒழுக்கின்மை (Paul Eres)
Level 10
*****


Also known as रिंकू.


View Profile WWW
« Reply #18 on: November 26, 2008, 06:20:03 PM »

Yeah, I think as long as it's not done in the step or draw event, and as long as it's only done once in a blue moon (such as when changing rooms), it's fine -- but it's never a good idea to use it in the step or draw event, it's probably by far the slowest function in GML (besides "sleep()" or something).

Also, I'm surprised you used individual rooms, I never use different rooms for different levels anymore. ID only uses 4 rooms (title, stage select, game, level editor), and SD only uses one room so far. I just store level data to file, and then load it on use. It's also easier to create a level editor if you do it that way.
Logged

ஒழுக்கின்மை (Paul Eres)
Level 10
*****


Also known as रिंकू.


View Profile WWW
« Reply #19 on: November 26, 2008, 06:26:22 PM »

Oh, one more tip: drawing text (using GM's True Type Font system) is slow when you have a lot of text on the screen (anything more than about a paragraph). There are two ways to speed text up. The first is to do the same thing you do with primitives: draw the text on the surface once, and then just display the surface. The second way is to not use True Type Fonts, but use bitmapped fonts (which takes more work, but is faster and looks nicer, because you can color it like pixel art). To do the latter, you have to create an image for your font, and then you can either code your own font display system to show it, or you can use this function to turn it into a GM font:

Quote
font_add_sprite(spr,first,prop,sep) Adds a new font and returns its index. The font is created from a sprite. The sprite should contain a subimage for each character. first indicate the index of the first character in the sprite. For example, use ord('0') if your sprite only contains the digits. prop indicates whether the font is proportional. In a proportional font, for each character the width of the bounding box is used as the character width. Finally, sep indicates the amount of white space that must separate the characters horizontally. A typical value would lie between 2 and 8 depending on the font size.
Logged

Pages: [1] 2 3
Print
Jump to:  

Theme orange-lt created by panic