EndlessRunner Game Stutter

Hi guys I have been working on an endless runner like game for the past month. For sake of simplicity I won’t post my code for my basic level which generates endless levels with obstacles. The idea however is that i use timer.performWithDelay to call a LOCAL update fucntion which calls GLOBAL functions such as moving the background, and obstacles(which are tables) using “:translate(dx, dy)” .I also have a runner sprite which has a physics body attached to it along with relevant obstacles. I also obviously remove obstacles and power-ups that have moved off to the left of the screen to keep everything clean and tidy. Since I’m spawning a lot of these random things I have caches in the createScene storyboard event along with initialization with all other relevant elements such as the HUD. These are global variables so that “enterScene” can access them to move them. Correct me if I am doing that wrong please.

My problem is that all thought I think this is very cleanly coded and there are absolutely no errors and runs fine in the simulator at 60 fps(I have an fps counter function to) it is stuttery on my android phone. I have an Optimus 2x dual core and I make sure to close all background apps before starting mine. The game runs at around 55 - 60 fps at times, but sometimes stutters and dips down to 20 randomly! Its unacceptable that a reflex based game be laggy. What’s wierd though is that my friends US Tmobile Galaxy S2 runs it perfectly event though it is not much more powerful in terms of cpu and gpu. My other friend also has some dual core htc phone(not sensation) from att and it also runs fine. Could my 512 mb ram be a problem since I have fairly large sprite sheets (about 1800 * 50 and another about 900 * 600 plus a 2000 * 480 pixel background)?

I would really appreciate if someone could help me or would be willing to test my app? If you guys need to see the code I’ll gladly share. Thanks in advance and I hope this post wasn’t too much! [import]uid: 118482 topic_id: 27811 reply_id: 327811[/import]

**UPDATE** terminal shows 8.9 mb texture memory usage [import]uid: 118482 topic_id: 27811 reply_id: 112612[/import]

Somebody please I really really need help. My level1 code can be found here: http://codeviewer.org/view/code:2759 [import]uid: 118482 topic_id: 27811 reply_id: 112917[/import]

Hey there,

I don’t normally work with Android but I believe you may want to try downsizing your background (maybe break it into 3 or 4 parts rather than one large image) and also making your spritesheet smaller. I suggest this because I know some devices don’t like anything larger than 1024*1024.

Could you give that a go and let me know if it makes a difference, please?

Peach :slight_smile: [import]uid: 52491 topic_id: 27811 reply_id: 112947[/import]

Thanks for the reply Peach,

My largest image I’m using is the background which is 1000 * 480 in jpg format to reduce memory use. These are attached to 2 background objects which simply loop around each other for an “endless” effect.

Then I have another ground image used in a similar way which is 1000 * 113. They are separate objects because I need them to move at different speeds for a parallax effect. Lastly I have an obstacles image which is 20 * 500 pixels, a crate image which is 50*50, and a runner sprite sheet which is 264 * 68. Note: the obstacles image is used for 2 objects and crates image is used or 4. These get re-positioned for a new cycles once they are off screen so there is no creation done in “enterScene.” All images are in a “levelImgs” directory, could this in any way affect performance versus them being in the root folder?

I’m hoping this is a device specific issue(Optimus 2X) not for lower powered androids…

Note: yes I did change my image dimensions after my 1st post [import]uid: 118482 topic_id: 27811 reply_id: 112969[/import]

I’m going to see if I can get a colleague to give some insight on this if possible; hang tight. [import]uid: 52491 topic_id: 27811 reply_id: 113028[/import]

I recommend that you watch the Android log as you run your app. Check if garbage collection is happening on your device frequently or something in the background is causing it to stutter. You can view a real-time log by connecting your Android device to your computer via USB and running the “adb logcat” command line or use DDMS.

Other gotchas that would cause stuttering is writing to file or a SQLite database (which really writes to file). This is because file IO is a blocking operation. The IO write speed varies on different devices, and because of this, you do not want to write to file during gameplay. For example, the Samsung Galaxy S is famous for very slow file read/writes. [import]uid: 32256 topic_id: 27811 reply_id: 113081[/import]

Thanks for the reply. IO read and writes can be thrown aside because I only load up and save a high score right at the beginning of the level or at the end once gameplay has finished. Also after looking at ddms there is nearly nothing running in the background (I kill apps with task killer) and the logcat reports some errors, but they are related to my OS, such as something to do with the notifications bar, and wifi. You said there was a way to check garbage collection and I don’t know how to do that. Could you possibly give a pointer? In the end could one of you test my same apk on an android and tell me how it goes? [import]uid: 118482 topic_id: 27811 reply_id: 113109[/import]

– [import]uid: 118482 topic_id: 27811 reply_id: 113108[/import]

Guys here is my latest code that works.

http://codeviewer.org/view/code:275f

Right now I’m working on using groups more to try increase performance. However, considering I only have about 7 moving objects at the most, I can’t see why it would stutter… If any staff wants me to email them my whole project I can along with an apk. I’m getting the ios /android combo pro subscription when I’m at the point when this project becomes a full fledged game and if I can’t reach that point due to this issue that day may never come… Just some motivation:) [import]uid: 118482 topic_id: 27811 reply_id: 113143[/import]

Updating text objects is a major performance killer on Android too. This is because it involves generating a new bitmap in memory, drawing the text to that bitmap, and then pushing that bitmap to OpenGL. It’s expensive on both iOS and Android, but especially on Android because it can cause havoc with the Java garbage collector. In fact, based on my testing, I’ve found that the garbage collector is overly active on newer devices such as the Galaxy Nexus versus the Galaxy SII, where the rendering performance was better on the SII.

For example, a huge performance killer would be to show a FPS counter on the “enterFrame” event. Generating new FPS text on every frame actually hurts the frame rate.

So, if you think your app is updating text on every frame, then that might be what is killing performance. As a quick test, you can try commenting out all of your text updating code. If you have confirmed that is the issue, then you can work-around this by updating text based on a timer instead. Say every 100 or 200 milliseconds. [import]uid: 32256 topic_id: 27811 reply_id: 113238[/import]

alright well I disabled updating any kind of text at all and there is still stuttering. Now it’s not like the game isn’t playable its just it can be fluid at one point and then stutter for a second or two. Now I have looked over the code for “horse Animation” which is a sample app that comes with corona and in fact I even feel like its smoother at 30fps than my own game at 60(tested on device)… Also with all the demos I noticed that changing fps doesn’t do anything except make the game more fluid(doesn’t speed up or slow it down) while when I use enterFrame listeners or timers to call update function in my game, regardless which I use, at 60 fps the game runs well in the simulator but at 30 fps setting it slows down to a crawl. Does this mean my code is terribly optimized or something else? [import]uid: 118482 topic_id: 27811 reply_id: 113255[/import]

It sounds like something needs to be optimized in your code, but you’ll have to isolate it and find the bottleneck. It’s going to involves commenting out sections of code and adding print statements. Not sure what else to suggest.

There have been other run-forever apps made with Corona that don’t have this stutter issue. The most recent example being “Go Ninja”. So, a smooth running run-forever game is definitely possible. I hope that would give you some confidence that this is doable.
http://www.coronalabs.com/blog/2012/06/04/app-of-the-week-go-ninja/
[import]uid: 32256 topic_id: 27811 reply_id: 113258[/import]

Wow thats such a more complex game than mien yet it runs much smoother. Alright I’l ask you one last question. Could you tell me if the following approach would be better.

have the runner himself run and move the display group to follow him and then once objects are off the screen simply reposition them to the right of the screen and let them go through again WITHOUT spawning any new objects.

I plan on moving the runner by adding values to his “.x” property or by using “translate” which is almost the same and NOT transitions.
[import]uid: 118482 topic_id: 27811 reply_id: 113260[/import]

Yes, re-using display objects that have scrolled off the screen will improve the performance. You see, every time you create a new display object, Corona does a memory allocation which is a slight performance hit… and all of those memory allocations combined will add up and cause an even bigger performance hit. Re-using objects will prevent the memory allocation and make things a lot smoother.

Also, if your app has sound effects, then you will want to load them into memory first and then play them. The idea is to avoid playing them from file every time you want to play a sound effect. The only time you want to stream from file is when playing large audio files such as music.

I hope this helps! [import]uid: 32256 topic_id: 27811 reply_id: 113392[/import]

Hey, I developed GoNinja so I can probably help you out.

The most basic advice I can give you is to only do the following operations during each frame, and do them as sparingly as possible:

  1. Move objects using translate()
  2. Hide/Show objects
  3. Play animation sequences

If you do any of the following during a frame then the game will stutter:

  1. Load images, load sounds, or load anything.
  2. Unload images, sounds, or unload anything
  3. Write or read from any files (including sqlite)

I wrote some more suggestions here – http://developer.anscamobile.com/forum/2012/06/05/performance-tips-get-your-game-run-60fps

Good luck :slight_smile:
[import]uid: 135827 topic_id: 27811 reply_id: 113859[/import]

Wow thanks for such a great article man I really appreciate it!

Well I just started to modify my code based on some of your tips, especially caching .x and .y variables once a frame, not having to “re-get” them every time I need them. The reason this helps me is because I decided to not use the physics engine, and make sort of my own very high performance but low functionality engine which is enough for basic collisions and power-ups.

I also have a very important question… how do you manage to run your game well @30 fps. Mine runs great at 60 but at 30 it feels like its at 15fps not 30… right now I’m using an"enterframe" listener to move stuff, sholdl I use a timer instead?

Lastly, the way I move my map is I move the runner however many units I need to the right within the “map” display group, then move the whole map to the left to create an illusion of running and then just loop around the ground and other stuff… is that a good approach?

Again thanks a lot for your post, I’m already seeing great performance improvements! [import]uid: 118482 topic_id: 27811 reply_id: 113863[/import]

Using enterframe should be fine. Not sure why you you’re seeing problems at 30fps.

Try timing your frames. Use system.getTimer() at the start of a frame and then call it again at the end of a frame and subtract the two numbers to see how long your frames take to execute. It should never go above 16milliseconds if you want to run the game at 60fps, and never above 32milliseconds if you want to run your game at 30fps. If you do see any frames get above that number, track down what might have caused that frame to be slow.

In our case I ended up putting a system.getTimer() call pretty much between every couple lines and measuring exactly where the slow points were, and then speeding up the slow parts as much as possible.

Lastly, the way I move my map is I move the runner however many units I need to the right within the “map” display group, then move the whole map to the left to create an illusion of running and then just loop around the ground and other stuff… is that a good approach?

Yeah sounds like that should work. We actually don’t move the runner at all, only the background. He stays in place the whole time. However, in some cases the physics engine will push him back a little bit when he collides with a surface. We tried to minimize this as much as possible (No solid surfaces are supposed to be within the same X axis region as him unless he’s above/below them). Just in case, we check his position on every frame and move him back into place if he got moved around. [import]uid: 135827 topic_id: 27811 reply_id: 113985[/import]

Oh, and make sure that you’re doing these measurements on a device using adb logcat. The simulator will perform completely differently than a device in many cases. [import]uid: 135827 topic_id: 27811 reply_id: 113986[/import]