Snake Game- Performance Issue

Hi all, I’m making a snake game with corona, without box2d, without physycs. I use for cycle in Runtime events for snake elements moves and collision detect functions always in Runtime events. 

Unfortunately when the snake grows, and it is composed of 60 elements or more, the framerate go down really bad.

What is the limit of instructions per second for a constant framerate?

There isn’t any set limit or amount before performance is affected from Runtime functions, as there are so many variables that there isn’t any empirical way to gauge performance.

That said, when developing your app, you need to keep an eye on your performance. This can be done with a performance meter. I posted one in the Corona code exchange. Also, I’m assuming that since you didn’t post a test device name, you’re seeing slowdown in the simulator, which means you’re going to see crazy slowness on any real-time device testing.

Best way to move forward: evaluate your code to confirm your really need all the Runtime checks. Put in the performance monitor, and test on a device to make sure you have a playable game.

Feel free to post your Runtime code here so we can give you some pointers.

Thanks for reply Alex. I have tried to use demo version of Lua Glider and its performance analyzer tool. Two collision border functions ate l’80% of game resources. I have rewritten them and now is much butter. Snake now can grow more than 100 elements.

Unfortunately, I have not solved all the problems. The runtime function that moves the head and the snake can not be eliminated and it cant be modified because it is very simple, does nothing but increase every frame the x of the serpent element of 5 px in a for cycle fol all snake elements.

There are also few other runtime function that control snake teleport and complex moves not removable.

When you start the game, even without touching anything, leaving the serpent moving back and forth, we see that the movement is not smooth, there are always random spikes where the snake seems to hang and then recover.

You might just want use a timer to move the snake rather than a Runtime listener. You could smooth it out, and you wouldn’t need to worry about the Runtime listener you have running in whichever scene you’re in.

Are you testing on a device, or in the simulator?

I’m testing on simulator, galaxy s2, galaxy tab2 2 10.1, and galaxy s5. Galaxy s2 and Galaxy Tab have cyanogenmod and they have better performance, galaxy s5 with touchwiz give me more problem. I have tried to use timer in loop for moves but they freeze always the game on start and i don’t understand why, this is my second little game and I am not very expert. 

At this point the best move would be to throw up some code for us to peek at, so we can speak intelligently regarding what you might be running in to. Remember to use the /lua tags so it’s formatted correctly.

These are the listeners invoked inside scene:create in principal game composer scene.

Name of function and variables are often in italian, I hope you understand it.

I have set as comment not complete code in this topic.

[lua]

–//snake vector/–

local serpente={}

for i=lungSerp,1,-1 do

serpente[i] = creaScaglia(serpente[i])

gruppoSerpente:insert( serpente[i] )

end

---------------------------LISTENERS-----------------------------------------

–avvio(serpente)

vT = function() velocitaTesta(serpente,1,VX,VY); end

Runtime:addEventListener( “enterFrame”, vT )

vC=function() velocitaCoda(serpente); end

Runtime:addEventListener( “enterFrame”, vC )

–[[

mVm=function() movimento(serpente); end

Runtime:addEventListener(“enterFrame”, mVm )

aC=function() aggiornaCelle(serpente); end

Runtime:addEventListener(“enterFrame”, aC )

sV=function() svolta(serpente); end

Runtime:addEventListener(“enterFrame”, sV )

if opzioniControllo==0 then

aD = function() where=“dx”; end 

areaDestra:addEventListener( “tap”, aD )

aS = function() where=“sx”; end 

areaSinistra:addEventListener( “tap”, aS )

else

sfondo:addEventListener( “touch”, swipe )

end

if opzioniMuri==0 then

sM=function() scontroMargini(margineSx,margineDx,margineUp,margineDn,serpente) end

Runtime:addEventListener( “enterFrame”, sM )

else

cM=function() if stopGioco==0 then stopGioco=crashMargini(margineSx,margineDx,margineUp,margineDn,serpente) end end

Runtime:addEventListener( “enterFrame”, cM )

end

gC=function() gioco(serpente); end

Runtime:addEventListener(“enterFrame”, gC )

mS=function() morsoSerpente(serpente); end

Runtime:addEventListener(“enterFrame”, mS )

pG=function(event) pausa(serpente); return true; end

pauseGroup:addEventListener( “tap”, pG )

pS=function(event) play(serpente); return true; end

playShape:addEventListener( “tap”, pS )

homeShape:addEventListener( “tap”, ritornaCasa )

–]]

[/lua]

These are the function that moves head and body and the function that create the snake in other modules

[lua]

function creaScaglia(scaglia)

scaglia = display.newRect( 150 + margine, 150, 15, 15 )

scaglia.anchorX = 1

scaglia.anchorY = 1

scaglia:setFillColor( Rgb2,rGb2,rgB2 )

margine=margine+15

scaglia.xSvolta=1000

scaglia.ySvolta=1000

scaglia.ind=1

scaglia.stato=""

scaglia.direz=""

scaglia.xSegno=1*fasterVar

scaglia.ySegno=0*fasterVar

scaglia.NextxSegno=0

scaglia.NextySegno=0

scaglia.teleport=0

    return scaglia

end

–snake moves–

function velocitaCoda(snake)

for i=#snake,2,-1 do

snake[i].x=snake[i].x+snake[i].xSegno

snake[i].y=snake[i].y+snake[i].ySegno

end

end

–head moves–

function velocitaTesta(snake,part,vx,vy)

snake[part].x=snake[part].x+vx

snake[part].y=snake[part].y+vy

snake[part].xSegno=vx; 

snake[part].ySegno=vy;

end

[/lua]

I think that if you look around this forum for optimization techniques, one of them will be to use translate to update the x and y position of an object.

Your snake move would look something like this:

  1. snake[i]:translate(snake[i].xSegno, snake[i].ySegno)

There isn’t any set limit or amount before performance is affected from Runtime functions, as there are so many variables that there isn’t any empirical way to gauge performance.

That said, when developing your app, you need to keep an eye on your performance. This can be done with a performance meter. I posted one in the Corona code exchange. Also, I’m assuming that since you didn’t post a test device name, you’re seeing slowdown in the simulator, which means you’re going to see crazy slowness on any real-time device testing.

Best way to move forward: evaluate your code to confirm your really need all the Runtime checks. Put in the performance monitor, and test on a device to make sure you have a playable game.

Feel free to post your Runtime code here so we can give you some pointers.

Thanks for reply Alex. I have tried to use demo version of Lua Glider and its performance analyzer tool. Two collision border functions ate l’80% of game resources. I have rewritten them and now is much butter. Snake now can grow more than 100 elements.

Unfortunately, I have not solved all the problems. The runtime function that moves the head and the snake can not be eliminated and it cant be modified because it is very simple, does nothing but increase every frame the x of the serpent element of 5 px in a for cycle fol all snake elements.

There are also few other runtime function that control snake teleport and complex moves not removable.

When you start the game, even without touching anything, leaving the serpent moving back and forth, we see that the movement is not smooth, there are always random spikes where the snake seems to hang and then recover.

You might just want use a timer to move the snake rather than a Runtime listener. You could smooth it out, and you wouldn’t need to worry about the Runtime listener you have running in whichever scene you’re in.

Are you testing on a device, or in the simulator?

I’m testing on simulator, galaxy s2, galaxy tab2 2 10.1, and galaxy s5. Galaxy s2 and Galaxy Tab have cyanogenmod and they have better performance, galaxy s5 with touchwiz give me more problem. I have tried to use timer in loop for moves but they freeze always the game on start and i don’t understand why, this is my second little game and I am not very expert. 

At this point the best move would be to throw up some code for us to peek at, so we can speak intelligently regarding what you might be running in to. Remember to use the /lua tags so it’s formatted correctly.

These are the listeners invoked inside scene:create in principal game composer scene.

Name of function and variables are often in italian, I hope you understand it.

I have set as comment not complete code in this topic.

[lua]

–//snake vector/–

local serpente={}

for i=lungSerp,1,-1 do

serpente[i] = creaScaglia(serpente[i])

gruppoSerpente:insert( serpente[i] )

end

---------------------------LISTENERS-----------------------------------------

–avvio(serpente)

vT = function() velocitaTesta(serpente,1,VX,VY); end

Runtime:addEventListener( “enterFrame”, vT )

vC=function() velocitaCoda(serpente); end

Runtime:addEventListener( “enterFrame”, vC )

–[[

mVm=function() movimento(serpente); end

Runtime:addEventListener(“enterFrame”, mVm )

aC=function() aggiornaCelle(serpente); end

Runtime:addEventListener(“enterFrame”, aC )

sV=function() svolta(serpente); end

Runtime:addEventListener(“enterFrame”, sV )

if opzioniControllo==0 then

aD = function() where=“dx”; end 

areaDestra:addEventListener( “tap”, aD )

aS = function() where=“sx”; end 

areaSinistra:addEventListener( “tap”, aS )

else

sfondo:addEventListener( “touch”, swipe )

end

if opzioniMuri==0 then

sM=function() scontroMargini(margineSx,margineDx,margineUp,margineDn,serpente) end

Runtime:addEventListener( “enterFrame”, sM )

else

cM=function() if stopGioco==0 then stopGioco=crashMargini(margineSx,margineDx,margineUp,margineDn,serpente) end end

Runtime:addEventListener( “enterFrame”, cM )

end

gC=function() gioco(serpente); end

Runtime:addEventListener(“enterFrame”, gC )

mS=function() morsoSerpente(serpente); end

Runtime:addEventListener(“enterFrame”, mS )

pG=function(event) pausa(serpente); return true; end

pauseGroup:addEventListener( “tap”, pG )

pS=function(event) play(serpente); return true; end

playShape:addEventListener( “tap”, pS )

homeShape:addEventListener( “tap”, ritornaCasa )

–]]

[/lua]

These are the function that moves head and body and the function that create the snake in other modules

[lua]

function creaScaglia(scaglia)

scaglia = display.newRect( 150 + margine, 150, 15, 15 )

scaglia.anchorX = 1

scaglia.anchorY = 1

scaglia:setFillColor( Rgb2,rGb2,rgB2 )

margine=margine+15

scaglia.xSvolta=1000

scaglia.ySvolta=1000

scaglia.ind=1

scaglia.stato=""

scaglia.direz=""

scaglia.xSegno=1*fasterVar

scaglia.ySegno=0*fasterVar

scaglia.NextxSegno=0

scaglia.NextySegno=0

scaglia.teleport=0

    return scaglia

end

–snake moves–

function velocitaCoda(snake)

for i=#snake,2,-1 do

snake[i].x=snake[i].x+snake[i].xSegno

snake[i].y=snake[i].y+snake[i].ySegno

end

end

–head moves–

function velocitaTesta(snake,part,vx,vy)

snake[part].x=snake[part].x+vx

snake[part].y=snake[part].y+vy

snake[part].xSegno=vx; 

snake[part].ySegno=vy;

end

[/lua]

I think that if you look around this forum for optimization techniques, one of them will be to use translate to update the x and y position of an object.

Your snake move would look something like this:

  1. snake[i]:translate(snake[i].xSegno, snake[i].ySegno)