Hi, I have an issue with my game, in my game will spawn a sprite every X seconds and it moves with transition.to, if I spawn several times only that sprite it is all good, no lag, 60 fps always.
But when I decided to add another sprite and that the game decide randomly if spawn the first or the second sprite it lags with big stutter. If I spawn even only the second there isn’t stuttering.
The strange thing is that I don’t think that the game is overloaded when I spawn two sprites because it spawn always once at time.
This is my code simplified:
local function spawnRedThing() -- code for spawn the first type of sprite end local function spawnGreenThing() -- code for spawn the second type of sprite end local function spawn() local randSpawn = math.random(0,1) if (randSpawn == 0) then spawnRedThing() end if (randSpawn == 1) then spawnGreenThing() end end spawnTimer = timer.performWithDelay(seconds, spawn, -1)
The first and the second function are very similiar, in these functions I add a sprite (that I didn’t created never before) with an animation (about 15 frames for every object and their size is about 600kb cad.), I add the sprite in a group and I add to the object a physic body.
At the same time there is only an update function called every tick that compare the score for incrementing the speed of the transition and update the score text.
Another thing, if instead of using “transition.to” I use the gravity, there is always some stutter but a little bit less. (nothing compared with when I run the game with only one sprite.)
This is the code on the first function (the second is almost equal):
local function spawnRedThing() local sheetInfo = require("sheetcosored") local sheet1 = graphics.newImageSheet( "spriteSheetRT2.png", sheetInfo:getSheet() ) local sequence1Data = { { name = "redthingan", start = 1, count = 11, time = 100, loopCount = 1, loopDirection = "forward" } } local xCoord = math.random(display.contentWidth \* 0 + 60, display.contentWidth \* 1.0 - 60) local redthing = display.newSprite(sheet1, sequence1Data) groupgam:insert(redthing) redthing:scale(1.5,1.5) physics.addBody(redthing, "dynamic", {density=5, friction=500, bounce=0.3}) redthing.x = xCoord redthing.y = -500 transition.to(redthing, {rotation=360, time=speed, x=redthing.x, y = redthing.y + 3000}) local function redthingTouch(event) if (event.phase == "began") then if event.target then local removething = function() display.remove(redthing) redthing = nil end local function particle1() -- little particle code end redthing:play() timer.performWithDelay(100,removething,1) particle1() score = score + 1 return true end end end redthing:addEventListener("touch", redthingTouch) end
You are declaring sheetInfo, sheet1, and sequence1Data every time this function is called. I would remove them and make them global to your module… declare them outside of this function. You only need to declare these one time.
Same with redthingTouch… you are declaring this every time the function is called. Move that outside of this function.
If you want to go a bit further, I make it a habit of never creating new objects (especially with physics) during game play. I always create them before (in scene:create if using composer, for example) and then reuse these objects. There is greater overhead to creating/removing objects and physics.
I don’t fully understand what you mean about the score update function, but it sounds like you are using a Runtime event to check the score and then change the speed… is that correct? If so, a better way would be to call a score update function when needed (instead of 60 times a second) to update the score and change speed.
Thank you, the problem decreased about of 70%… I did some things that you have writed but not all…
I can’t move redthingTouch outside of this function because if I do this, when I touch the red thing it not removes it self but removes the last red thing spawned. And I don’t know how create the physics object before and then reuse them.
If you have a solution for this problems, can you explain me?
You can create an object and add physics to it so it can be reused. When not in use, you disable physics on that object by setting isBodyActive = true. Also object.isVisible = false.
You can probably move redthingTouch outside of the function if you modify your code a bit. event.target is the actual object triggering the event so you can either turn off physics and hide object (like I explain in this post above), or use event.target:removeSelf().
If you are going to keep spawning the same object over and over again, I would recommend reusing by creating a pool of objects. I wrote a blog post that explains it a bit better here. (I’ve posted this link a few times in the past, so my apologies to those that have seen it before, but I believe this will be helpful in this situation/solution). Depending on how you want to proceed (reuse or recreate), some of your code may change in order to support your method.
The first and the second function are very similiar, in these functions I add a sprite (that I didn’t created never before) with an animation (about 15 frames for every object and their size is about 600kb cad.), I add the sprite in a group and I add to the object a physic body.
At the same time there is only an update function called every tick that compare the score for incrementing the speed of the transition and update the score text.
Another thing, if instead of using “transition.to” I use the gravity, there is always some stutter but a little bit less. (nothing compared with when I run the game with only one sprite.)
This is the code on the first function (the second is almost equal):
local function spawnRedThing() local sheetInfo = require("sheetcosored") local sheet1 = graphics.newImageSheet( "spriteSheetRT2.png", sheetInfo:getSheet() ) local sequence1Data = { { name = "redthingan", start = 1, count = 11, time = 100, loopCount = 1, loopDirection = "forward" } } local xCoord = math.random(display.contentWidth \* 0 + 60, display.contentWidth \* 1.0 - 60) local redthing = display.newSprite(sheet1, sequence1Data) groupgam:insert(redthing) redthing:scale(1.5,1.5) physics.addBody(redthing, "dynamic", {density=5, friction=500, bounce=0.3}) redthing.x = xCoord redthing.y = -500 transition.to(redthing, {rotation=360, time=speed, x=redthing.x, y = redthing.y + 3000}) local function redthingTouch(event) if (event.phase == "began") then if event.target then local removething = function() display.remove(redthing) redthing = nil end local function particle1() -- little particle code end redthing:play() timer.performWithDelay(100,removething,1) particle1() score = score + 1 return true end end end redthing:addEventListener("touch", redthingTouch) end
You are declaring sheetInfo, sheet1, and sequence1Data every time this function is called. I would remove them and make them global to your module… declare them outside of this function. You only need to declare these one time.
Same with redthingTouch… you are declaring this every time the function is called. Move that outside of this function.
If you want to go a bit further, I make it a habit of never creating new objects (especially with physics) during game play. I always create them before (in scene:create if using composer, for example) and then reuse these objects. There is greater overhead to creating/removing objects and physics.
I don’t fully understand what you mean about the score update function, but it sounds like you are using a Runtime event to check the score and then change the speed… is that correct? If so, a better way would be to call a score update function when needed (instead of 60 times a second) to update the score and change speed.
Thank you, the problem decreased about of 70%… I did some things that you have writed but not all…
I can’t move redthingTouch outside of this function because if I do this, when I touch the red thing it not removes it self but removes the last red thing spawned. And I don’t know how create the physics object before and then reuse them.
If you have a solution for this problems, can you explain me?
You can create an object and add physics to it so it can be reused. When not in use, you disable physics on that object by setting isBodyActive = true. Also object.isVisible = false.
You can probably move redthingTouch outside of the function if you modify your code a bit. event.target is the actual object triggering the event so you can either turn off physics and hide object (like I explain in this post above), or use event.target:removeSelf().
If you are going to keep spawning the same object over and over again, I would recommend reusing by creating a pool of objects. I wrote a blog post that explains it a bit better here. (I’ve posted this link a few times in the past, so my apologies to those that have seen it before, but I believe this will be helpful in this situation/solution). Depending on how you want to proceed (reuse or recreate), some of your code may change in order to support your method.