Hey guys,
I am currently making a runner game with Gideros, I am using the class method to move multiple backgrounds, and each of the obstacles is spawned as a class itself with enterFrame event attached. Although it runs smoothly, however I found out that the FPS might drop occassionally, (i.e. 60, 59.5, 60, 59.8, "57", 60.2, 59.8, 60, 59.5, "56"), making the movement unsmooth on an iPhone 4 and iPod touch 4th gen.
The event loop are the same during the drop of FPS, as I just constant update the position of the backgrounds and obstacles as such:
Background = Core.class(Sprite)
function Background:init()
local bgTexture = Texture.new("gfx/bg.png", true)
self.bg = {}
for i = 1, 3 do
self.bg[i] = Bitmap.new(bgTexture)
self.bg[i]:setAnchorPoint(0.5, 0.5)
self.bg[i]:setPosition(480*i - 240, 160)
self:addChild(self.bg[i])
end
self:addEventListener(Event.ENTER_FRAME, self.onEnterFrame, self)
end
function Background:onEnterFrame()
self:setX(self:getX() - 6)
for i = 1, #self.bg do
local x, y = self.bg[i]:localToGlobal(0, 0)
if x < -240 then
self.bg[i]:setX(self.bg[i]:getX() + 960)
end
end
end |
I have tried to reduce the amount of obstacles of backgrounds, however it is still the same. I think the code has no problem running at 60 FPS, just I don't understand the sudden drop of FPS to 57 or 58 occasionally.
Comments
What you could do would be to ensure that your not accidentally creating references or new objects at any other point in your app - generating strings to display on the screen can do this.
I was going to suggest printing out the value of "collectgarbage("count")" on the console and then realised that this in itself would cause garbage as the returned value would need to be turned into a string ready for printing.
On a slight tangent however - personally, I'd actually stay away from the whole "add an onEnterFrame listener" way of coding and instead have an "update" method that basically did the same thing, the difference would be that I'd then have ONE main app level OnEnterFrame listener that actually called the individual update methods as and when appropriate.
There can be fair amount of background overhead and scheduling involved in swapping between the various "listeners" assigned to objects so the less times you have to do it the better.
Just my $0.02
EDIT----
In another thread @Atilim suggested changing print(collectgarbage("count")) to print(math.floor(collectgarbage("count")))
which will display the current memory usage without incurring the extra string generation overhead. If you put this in your main OnEnterFrame listener you'll be able to see if any extra memory is being used.
Another thought that occurred to me is what would happen if you called "collectgarbage("collect")" every frame, that way any work that need's to be done might be more evenly distributed and not cause periodic slowdown.???
#MakeABetterGame! "Never give up, Never NEVER give up!" - Winston Churchill
I have tried print(math.floor(collectgarbage("count"))), it shows the memory is increased and decreasing with a stable rate: 130, 131, 132, 130 etc.
I have also tried collectgarbage every frame but i think that causes even more slow downs...
Edit: I've also tried using event.deltaTime to adjust the speed factor accordingly, but doesn't seem as smooth as movement without the speed factor.
I don't know - but is it possible to actually disable the garbage collection during time critical updates and then re activate it later (say between levels ???)
Likes: atilim
#MakeABetterGame! "Never give up, Never NEVER give up!" - Winston Churchill
collectgarbage("stop")
collectgarbage("setpause", value)
collectgarbage("setstepmul", value)
But not sure what value is the best though.