Optimizing a game for mobile platforms. Your tips?

  • Update.

    It appears that half of the post got cut off...

    I'll upload to pastebin or a similar site.

    posted here as text: pastebin.com/aiFyQtjQ

    Also, here's the post, uploaded as an imgur album (with links below the images):

                  IMGUR ALBUM

    You'll have to excuse me for this method of posting, but it appears that the forums tried to remove links from my posts and because of some error removed more than half of all the text (i've tried to re-post it a couple of times, but the post just won't update properly).

    Update.

    The whole post, now right here on the forums!

    <img src="http://www.officialcneblog.com/wp-content/uploads/2012/04/horizontal-divider.png" border="0">

    tl;dr - a rather long post describing things i've found about optimizing the performance, asking for you to share your own experiences etc.

    Let's say that you are making a game for mobile platforms, more specifically, a game that would work on the older/cheaper Android smartphones which don't have dedicated graphics chips (graphics are not "accelerated", system memory is used instead). Now, since we are going for optimal compatibility, let's say that you've decided to opt for exporting the application to an .apk file (or simply because you intend to upload it to Play Store, once it's finished), using something like CocoonJS, so you can forget about the fancy WebGL and shader effects - canvas2d is what you'll be using.

    While this means generally worse performance (and inability to use certain features, such as the image memory stat in the debugger), it also guarantees that the performance will be more consistent across the board (since you won't have such a gap between devices that support WebGL and the ones that don't -> no huge performance difference). Obviously, this will create some limitations for you, but also encourage you to use better practices in creating the game, so that the memory is used more efficiently (unless you go "hnnng" while playing games that run at <10 frames per second), which is one of the reasons this thread was made - to share experience and tips.

    First off, let's assume that you've lurked the site and have found and read (to a degree) read some articles describing things that are commonly done to ensure decent performance:

    - Best practices

    - Performance Tips

    - Performance Tips for Mobile Games

    - Remember not to waste your memory

    - Optimisation: don't waste your time

    And that you have a rough idea (a tl;dr, if you will) of things that affect the framerate of your game:

       processing the game logic (usually little impact, <10%) - if your game isn't stuck in endless loops and doesn't have memory leaks, you really shouldn't have to worry much about this part

       rendering things on screen (most of the processing time goes here, >90%) - this is where you will be spending most of your time while optimizing the game, this includes things like drawing the sprites, moving and rescaling them, changing opacity and blend modes, effects (however those require shader support and WebGL), pretty much most of the things you see happening on screen at any given time, such as particles being emitted, various objects moving across the screen, and even text being drawn, will have some effect on how well the game performs

    So, you eventually come across do's and don'ts of design process, a couple of which (the ones i think should be mentioned) i'll list here.

    /mind that the things mentioned might be out of date, as noone is capable of keeping up with all of the changes made by newer updates, however in such case someone would probably point these things out

    Sprites and other visuals.

    The amount of pixels rendered will have the most effect on your memory usage, therefore most attention should go into ensuring that things are done as efficiently as possible. So, the question is "Wat do?" Before giving the answers (or trying to), however, i feel like i should also point out what not to do.

    /most of the list turned out to be about the things you should not do, such is life, i guess

    DO NOT use unnecessarily large textures for your objects - if you are making a game for mobile platforms, anything above 512x512 is overkill

    DO NOT make huge background images - while this tip is similar to the previous one, i'd like to point out that, in case you have a need for backgrounds that take up large portions of the screen, then you should consider creating the background from many different images of lower resolution on a separate layer (so you can manipulate it later), perhaps tiling things or stretching them, where possible

    DO NOT make images with large areas of transparency - as described in one of the articles i linked, transparent particles also take up space, therefore you should try to keep empty areas to minimum, perhaps slice up your image (but only bother if it's pretty big) in many smaller and use something like the "Pin" behaviour to keep them together

    DO NOT have too many semi-transparent pixels in your images, change the transparency in steps - it is generally more efficient to have either full transparency or no transparency (image format-wise too) in case you need to make a fade effect, i'd suggest that you avoid fade/sine behaviour, and opt for changing transparency in increments of 5 or 10, perhaps by using a function, as this should be more effective (because it's not done every tick)

    DO NOT resize/rotate sprites every tick - see above, you could move the image by x pixels at regular intervals, small changes shouldn't even be noticeable to the eye, animations should also be played at moderate speeds

    DO NOT have too many images in your layers - reuse things where possible, delete any obsolete ones as all of the images in a layout will be loaded into memory as the layer starts and will be cleared only after a new one is opened, keep this in mind when making animations

    DO NOT assume that the images that are invisible don't take up processing time, this is false - they are still rendered if the object is not destroyed, so you should consider either destroying it, or moving it off the screen, which will stop rendering it, i guess you could do this for whole layers (in situations where a layer represents)

    DO NOT use effects for permanent changes - don't do things like applying a grayscale effect to an image as a permanent way to alter it, use image editing software such as GIMP or PAINT.NET and add another frame as an animation, instead

    DO NOT use particles unless necessary - if you intend to create an explosion or another effect, where a big amount of particles is needed (to create an area covered in them, or similar effects), then you should consider using animated sprites with an additive blend mode, or at least keep the sprite resolution low (e.g. something like 4x4 pixels, scaled up). of course, keep in mind that if your sprite would have large areas of transparency, you would be better off using the particles

    DO NOT use retina display - as shown in the performance benchmark, the framerates are almost 2 times lower when this feature is on (then again, Android devices don't have those :P)

    DO compress your images - while this will not improve performance, since the images are decompressed they're loaded into memory, this will decrease the download size immensely, allowing your game to load much faster. you should use .jpg for compressing images with no transparency and .png for images with transparency (also, if there are no semi-transparent pixels and less than 256 colors in the image, you could use PAINT.NET to save the image as png-8). if you want to see how much space the image takes up when decompressed, open it in GIMP and look at the lower left of the screen, keeping tabs on this information helps you figure out ways to optimize your game further(example of what i'm doing)

    DO use Spritefont instead of Text - it is often mentioned how the spritefont object is faster than the text, and of course there is also the added ability of having various symbols you wouldn't normally have access to if you used the normal font plugin (also, incompatibilities with webfonts were/are present when the game is opened in Chrome with WebGL on - might be somewhat irrelevant to this particular thread, however). what i like to do, is to create a low resolution font and then scale it up as needed, as this should be quite memory efficient (example text spritesheet, 64x96)

    DO create your images in lower resolution and rescale them - memory usage is only affected by the source size of the image, not what size it is drawn at on the screen (or so i've been told), so you could create your image at 32x32 and rescale it to 64x64 and save a decent amount of memory (percentage-wise). because of this, i recommend that you use pixel art - just remember to set your sampling method to "point" and rescaled images won't be smoothed, otherwise some ugly visual effects will appear

    ??? stretching vs tiling - this part is what i am not sure about, yet to me it seems that stretching a 1x1 pixel to 256x256 would be more efficient than tiling it for producing a solidly colored background (of course, usually the layer background color parameter should be used for that). either way, it was pointed out that using the tiled background object is more efficient than doing the same thing with a bunch of sprites, so there's that...

    Sounds.

    I really haven't got much advice to give in regards to this, but there always are a couple of intuitive things you should know (unless i got this wrong).

    DO NOT use higher bitrates than needed - 96-128 kbit/s should be good enough for most sounds used in mobile games, as the sound quality is often limited by the hardware on these platforms, therefore it most likely won't be necessary to use high bitrates (such as 256 kbit/s). it should be remembered, however, that the format is of little importance here, as the sounds are converted upon being imported into C2

    DO split your music tracks into looping parts, or split the repeating sections (e.g. bass or drum rolls) and repeat them over the main beat - while this might be somewhat cumbersome, there really is no need to have the same fragment of audio repeated twice (or 3, 4, 5, n times) in a song, as that is wasted memory. just remember not to have too many channels playing sounds at once.

    ??? mono vs stereo - it would seem to me that there should be little difference in regards to sound quality between using mono and stereo sounds, as the speakers are pretty close together on mobile devices (unless peripherals are used), which means that using mono sounds would be pretty effective in saving memory, as the trade-off in quality would be minor

    CPU intensive processes (behaviours).

    Little snippets of information i've gathered in regards to physics, pathfinding and collisions

    DO NOT use physics, unless absolutely necessary - physics can slow your game down quite a bit, therefore you should seek alternatives, such as writing your own formulas for simpler tasks, where the full list of physics features is not needed

    DO NOT re-generate the obstacle map unless something changes - this is listed as a CPU intensive process, so you should only do this if something changes in your map, that would prevent movement (tiles that don't affect pathfinding are unimportant), upping the grid size is sometimes also mentioned as a remedy

    DO NOT check for collisions too often - if the movement speeds of objects in question are slow, then you can do this at regular intervals

    This sums up what i've read on the forums pretty well.

    And yet, i'd like more advice. What have you guys got to add?

    Also, can anyone explain to me, why my Spritefonts and 9-patches are garbled up like this in the layout editor but perfectly fine in preview? (i made this in r139 or something, shown here opened in r142 - this was persistent in r139 too)

    <img src="http://i.imgur.com/gn4GI2y.jpg" border="0">

    The PC in question doesn't support shaders, if this helps explaining the situation.

  • Bump?

    I'd really like it if you could spare a minute and look at this post, so i can finally get some answers about the validity of these statements.

  • Interesting post.

    Thanks

  • thanks for tips if i read this i think we cant do good game with big world to mobile.

    I do some research and i see if i have game with resolution 480x 240 and when switch game to full screen with letterbox scale, game runs in lower FPS

    An i have question better to have one big tiled background or 5 smaller?

  • Very nice summary. I have been using some of these practices in my game already. Although, I still think there is something bogging down my game. Not sure what it is yet.

  • Wow, thanks for this post. And I would really like to see what some of our members think of its efficiency as well.

  • Try Construct 3

    Develop games in your browser. Powerful, performant & highly capable.

    Try Now Construct 3 users don't see these ads
  • The responses took a while, someone must have done some serious lurking... :)

    @delgado - the problem with the fps is most likely caused because the amount of pixels that has to be rendered has increased, you could try working around this by using the low quality scaling option present in the newer releases of C2 to get similar performance.

    It is indeed better to have 5 smaller background images as opposed to having one large one, because those off-screen won't be rendered, you could probably destroy the image objects to clear some memory, too!

  • Use Tilemap heavily. If there are any sprites left in the project that have no code tied to them, transport them over to Tilemap.

  • Stiivais you say and this is true :"the problem with the fps is most likely caused because the amount of pixels that has to be rendered has increased, "

    but it should not be.

  • I don't think that i entirely understand what you mean by this.

    Let's suppose that we have a game that is running at a resolution of 320x240. This means that the game's area is represented by 76'900 pixels, which have to be redrawn each tick. Now, if we increase the resolution up to 640x480, then there are 307'200 pixels that need to be updated now, a difference of 3x the original amount! This will obviously be a performance hit for any game...

  • The problem on old mobile is that:

    1/ their RAM is super low: it means you'll hit a limit of resource you can use for the game. Even if you use highly optimized small image, since you have no control over loading/unloading them to/from RAM, you can't really use too much of them.

    2/ rendering is slow: it's in general the bottleneck of the game. And the headache is that :

    - You can't use too big images like said before (so avoid having something like 5 different big background for each of your levels)

    - The work around is to compose a background out of small modular pieces like trees and grass and flowers you can spread accross your level, but then you hit another problem: pixel redraw. Basically if you have a 800 x 600 screen to fill, you have to paint about 480,000 pixels. But if you start layering objects on top of each other, this number will increase since some pixels will have to be redrawn. And the more pixel you have to draw, the more rendering computation. And the more object, the more draw calls. Also, the more object C2 has to handle, the more computation (though at a lesser extend than for rendering)

    3/ When using phonegap, or any wrapper based on the built-in webview, you'll have problems, like touch input failure, on some android, with an error on logcat saying "Miss a drag as we are waiting for WebCore's response for touch down". But I guess with CocoonJS it should be ok since I believe it's Android's default WebView bug.

    The problem on new mobile is that:

    1/ They often stupidely blow up their resolution to gain in image crispiness... (you only really notice a difference when you have two mobile side by side...), Anyway, more resolution means more pixel to draw, and often their performance don't really match the rendering demand.

    2/ dunno.. I needed a 2/

    In the end, I'm not convinced that using HTML5 for mobile games is such a good choice. It's not C2's fault, it's more that javascript is not tailored for games... at all.

    See this interesting article http://sealedabstract.com/rants/why-mobile-web-apps-are-slow/

    On top of that C2 converts all your events into a big tree that is parsed every tick, so it adds a layer of potential slowness.

    Concurrent softwares like Game Maker took the option to instead, export directly a native apk with their interpreter written in Java. Same for iOS. I think scirra did the right thing to stick with HTML5 and try to optimize it as much as they can, because working on android/iOS exporter would require way more man power than what they can currently afford.

    But I honestly think that you shouldn't try to make too ambitious games for mobile using C2.

    Turn by turn, puzzle games, games where speed and responsiveness isn't a requirement should be good enough. But high paced platformers, fighting games or things of this nature should be avoided. I even had problems with a tetris game (I had to use the canvas plugin to paint the bricks placed and just paint this canvas every tick along with the falling piece... and it's still a bit slow on some devices... hmpf v_v)

    Anyway, that's all I got on the top of my head.

  • Yann That's a pretty good post you made there, quite a bit of information! Either way, i think that this can be worked around:

    On top of that C2 converts all your events into a big tree that is parsed every tick, so it adds a layer of potential slowness.

    Just have a variable called "tick" (or just use the system expression) and divide events into groups, for example, player input should be processed every 2 ticks, but enemy A.I. should be processed between the player input ticks - it'd look like this: INPUT - AI - INPUT - AI ...

    Then just have a condition for the groups that checks if the current tick number is an odd or even one (tick mod 2 = 0/other, assuming there is a "mod" command or similar in C2).

  • Mobile performance is improving so fast, I find that it doesn't really matter as long as you avoid these two things (currently):

    1. WebGL effects, it will cripple mobile performance.

    2. Physics, again, performs horribly since it has issues with CocoonJS and Crosswalk acceleration, its not even close to native, since I've also experienced using AndEngine with Box2D and it was blazing fast.

    I just avoid these two, my game has huge PNG backgrounds, lots of massive 256 and even 512 (Bosses) sprites, heaps of objects on screen as well as particles, and even on an old dual-core 1ghz HTC Incredible S, its smooth. Anything Tegra 3 or Samsung S3 beyond pretty much runs at 60 fps.

    What to look out for if you use CocoonJS, is to not have too much art assets, because it loads everything into vram (not layout by layout as needed).

  • Stiivais

    Well, yeah of course you can do that kind of optimization, but I was merely describing why C2 was adding an extra processing layer that isn't trivial. Some times ago I made a Conway's game of life on C2 and another directly in javascript and the difference was kind of stricking even if I tried my best to make the C2 version as fast as I could.

    @Silverforce

    If you have time to read the link I posted in my previous post, you would see that we are hitting some kind of limit as far as mobile performance goes in general and specifically with javascript.

    Even if you manage to make some complex games go fast enough (and I honestly doubt you can manage that on Android < 4.x), you can't really compete with Native games. And I'm not sure you will ever be able to compete with them using javascript.

    If you find some nice turn by turn mecanics like desktop dungeon C2 should be more than enough to make a pretty and enjoyable game.

    But if you want some fast paced game with reactive flawless controls... Well... I'd like to see that =)

  • Its going to depend on your cutoff point for acceptable hardware... for me, anything less than dual core 1ghz is not even a consideration.

    My own game is very fast paced on later levels, so many objects, explosions and particles on the screen. Runs flawless on Tegra 3, which is already quite old now. I was shocked an old HTC dual core 1ghz ran it perfectly smooth as well, using Crosswalk.

    The only limit is the flawed acceleration of physics and webgl with the wrappers we have. It's not even 10% of the performance what native Box2D is via Android SDK/Eclipse and 2d engines such as AndEngine. As soon as physics is used, even on a Samsung S4, the performance is horrible. There IS a problem there.

Jump to:
Active Users
There are 1 visitors browsing this topic (0 users and 1 guests)