@community,
Hi folks. If you are like me, you have at one time or another experimented with side-scrolling and other game types that require a ‘camera system’.
In my time using Corona I have noticed that in certain cases such camera systems suffer from hiccups. That is, the action is smooth and then suddenly there is discernible pause, followed by a jump in the movement
This question/complaint comes up so frequently, that I decided to figure this out once and for all and to post a list of best-in-class solutions for a basic camera algorithm.
In order to do this, I am hoping to enlist members of the community to:
- Test Solutions
- Suggest Solutions
- Discuss this topic in general
Experiments
To get the ball rolling, I’ve created a baseline test case and a number of experiments varying that case:
- Baseline (see code below) - Player moving left to right at 250 pixels per second, with 60 objects in world at time. Player stays in center of ‘world’ while all other objects move ‘around’ player. Player uses physics setLinearVelocity() to move.
- No Garbage Collection - Garbage collection turned off.
- Object Re-use - Objects reused instead of deleting and creating new ones.
- Manual Movement - Player uses enterFrame listener and obj:translate() to move. (delta time is smoothed to account for frame variation versus target speed).
- Experiment #4 + No Garbage Collection
- Experiment #4 + Re-use
Sub-Experiments
In addition to the experiment_xx.lua files, I have done some config.lua FPS and scaling experiments.
- 30 versus 60 FPS - Changes to this value can exacerbate or reduce the problem, but not make it go away.
- Fixed Resolution (config_fixed.lua) - 640X960 + letterbox.
- Smart Resolution (config_smart) - Sergey Lerg’s solution set to 640 x 960 as the base resolution.
Note: In all of these cases, the hiccups persist, so I’m not doing more experiments with FPS and scaling. However, if you want to add more please do!
Note2: All experiments use SMART config @60 FPS
The Kind Of Participation I Am Hoping For
If you want to participate in this discussion I welcome (in fact ask for):
- Suggested experimentation variations.
- Suggestions on ‘causes’ for hiccups.
- Lua insights
- … Basically anything that forwards the discussion towards its end-goal: ‘Hiccup free cameras’.
Download The Code
If you want to write your own experiments and share them, you can get the current experiments here:
http://github.com/roaminggamer/RG_FreeStuff/blob/master/AskEd/2016/07/camera_hiccups.zip
Add Your Experiments
Have you coded up your own variation of the baseline that you think contributes to the discussion? If so, send it to me here and I’ll add it to the kit (with credits to you if you want):

Run the Experiements (Android Only)
If you want to run the experiments and not build them yourself, get them here:
Note 1: All experiments built with Corona SDK 2016.2906
Note 2: Double tap screen when running to bring up FPS and Memory meters.
Note 3: Be aware, the hiccup effect can be very subtle and you may need to re-run experiments to see the issue as well as watch the experiment run for a while.
Baseline Test Case
main.lua
---------------------------------------------- -- Configure experiments (common variables to allow quick change of all experiments) ---------------------------------------------- \_G.maxObjs = 60 -- Max objects (not including player) \_G.maxSpeed = 250 -- Player speed in 'pixels per second' ---------------------------------------------- -- Load (and run) experiment of choice below ---------------------------------------------- --require "experiment\_01" -- Baseline --require "experiment\_02" -- Baseline + Garbage Collection OFF --require "experiment\_03" -- Re-use objects when 'limit' reached instead of making new ones. --require "experiment\_04" -- Manual movement (instead of setLinearVelocity) --require "experiment\_05" -- Experiment #4 + + Garbage Collection OFF --require "experiment\_06" -- Experiment #4 + Re-use require "experiment\_01"
experiment_01.lua
-- -- Baseline Experiment - Player moving at 'maxSpeed' pixels-per-second to right w/ 'maxObjs' objects in world at time. -- local physics = require "physics" physics.start() physics.setGravity(0,0) -- A group to contain all display objects in 'world' -- local world = display.newGroup() -- Object to track with 'camera' code local player = display.newImageRect( world, "smiley.png", 40, 40 ) player.x = display.contentCenterX player.y = display.contentCenterY player.lx = player.x player.ly = player.y physics.addBody( player ) player:setLinearVelocity( \_G.maxSpeed, 0 ) -- Basic camera code. Keeps player in center of screen; moves world 'around' player -- function world.enterFrame( self ) local dx = player.x - player.lx local dy = player.y - player.ly self:translate(-dx,-dy) player.lx = player.x player.ly = player.y end Runtime:addEventListener( "enterFrame", world ) -- Generate objects to show 'hiccup' more clearly local mRand = math.random local period = 100 -- create and delete up to 10 objects per second local maxCount = \_G.maxObjs local objs = {} -- table to hold 'object' references timer.performWithDelay( period, function() local obj = display.newCircle( world, player.x + 600, player.y + mRand( -200, 200), mRand( 10, 15 ) ) obj:setFillColor(mRand(),mRand(),mRand()) obj:toBack() objs[#objs+1] = obj if( #objs \> maxCount ) then display.remove(objs[1]) table.remove( objs, 1 ) end end, -1)
https://www.youtube.com/watch?v=V7F6uQQmPeg&feature=youtu.be