TowerDefense takes all of CPU on iPhone

Hei! We are developing a towerdefense game for a school project. We have never written in LUA before, so bear with us. Our main problem is that the CPU on the iPhone 3GS hits 100% load and the game wont run. If that doesnt happen, then the game wont start at all.

We have tried to get rid of heavy code that might have been the problem, but no matter what we do the game seems to overload or timeout.

What we are trying to achieve for now is:
-make enemies follow a path (physics or transitions?)
-make towers shoot bullets and hit enemies

It would have been nice if someone could just take a look at the code. Maybe we have missed something crucial general lua code.

The code is as follows:

--main.lua  
  
display.setStatusBar(display.HiddenStatusBar)  
  
require("towers")  
require("enemies")  
physics = require("physics")  
physics.start()  
physics.setGravity(0,0)  
  
currentLvl = 1  
currentEnemy = 0 --the current enemy that we're creating from the array  
enemyTime = 0 --how many frames have elapsed since the last enemy was created  
enemyLimit = 15 --how many frames are allowed before another enemy is created  
enemyArray = {} --this array will tell the function when to create an enemy  
enemiesLeft = -1 --how many enemies are left on the field  
startBlock = 0  
turnOne = 0  
enemyArray1 = {1,1,1,1,1,2,1,1,1,2,1,1,1,1,1,1,2,2,2,1,1}  
enemyArray2 = {}  
health = 100  
cash = 50  
  
enemyHolder = {}  
lvlHolder = {}  
turnHolder = {}  
enemyHP = {}  
  
lvlArray = { 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,   
 10, 10, 10, 10, 10, 26, 11, 11, 11, 11, 11, 11, 11, 42, 10,   
 10, 10, 10, 10, 10, 22, 10, 10, 10, 10, 10, 10, 10, 22, 10,   
 10, 26, 11, 42, 10, 22, 10, 10, 10, 10, 10, 10, 10, 22, 10,   
 10, 22, 10, 22, 10, 68, 11, 11, 11, 11, 24, 10, 10, 22, 10,   
 77, 48, 10, 22, 10, 10, 10, 10, 10, 10, 22, 10, 10, 22, 10,   
 10, 10, 10, 22, 10, 10, 10, 10, 10, 10, 22, 10, 10, 22, 10,   
 10, 10, 10, 86, 11, 11, 11, 11, 11, 11, 48, 10, 10, 84, 88,   
 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,   
 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,   
 }  
  
--enemiesLeft = table.maxn(enemyArray1)  
print(enemiesLeft)  
  
function makeRoad()  
 w = 0  
 row = 0 --the current row we're working on  
 block = nil --this will act as the block that we're placing down  
 for i=0, 150 do --creating a loop that'll go through the level array  
 if(lvlArray[i] == 10) then --if the current index is set to 0  
 block = display.newImage("blocks/grass.png") --create a gray empty block  
 --//and set the coordinates to be relative to the place in the array  
 block.x= (i-row\*15)\*32-16  
 block.y = row\*32+16  
 block.number = i  
 block:addEventListener( "tap", makeTower )  
 physics.addBody( block, { isSensor = true } )  
 block:addEventListener("collision", newDir)  
 table.insert(lvlHolder, i, block)  
 elseif(lvlArray[i] == 11) then --if there is supposed to be a row  
 --just add a box that will be a darker color and won't have any actions  
 block = display.newImage("blocks/roadH.png")  
 block.x= (i-row\*15)\*32-16  
 block.y = row\*32+16  
 elseif(lvlArray[i] == 22) then --if there is supposed to be a row  
 --just add a box that will be a darker color and won't have any actions  
 block = display.newImage("blocks/roadV.png")  
 block.x= (i-row\*15)\*32-16  
 block.y = row\*32+16  
  
  
  
  
 elseif(lvlArray[i] == 86) then --if there is supposed to be a row  
 --just add a box that will be a darker color and won't have any actions  
 block = display.newImage("blocks/cornerNE.png")  
 block.x= (i-row\*15)\*32-16  
 block.y = row\*32+16  
 block.dx = 0.3  
 block.dy = 0  
 physics.addBody( block, { isSensor = true } )  
 block:addEventListener("collision", setDirRIGHT)  
 table.insert(turnHolder, w, block)  
 w = w + 1  
 elseif(lvlArray[i] == 84) then --if there is supposed to be a row  
 --just add a box that will be a darker color and won't have any actions  
 block = display.newImage("blocks/cornerNW.png")  
 block.x= (i-row\*15)\*32-16  
 block.y = row\*32+16  
 block.dx = -0.3  
 block.dy = 0  
 physics.addBody( block, { isSensor = true } )  
 block:addEventListener("collision", setDirLEFT)  
 table.insert(turnHolder, w, block)  
 w = w + 1  
 elseif(lvlArray[i] == 24) then --if there is supposed to be a row  
 --just add a box that will be a darker color and won't have any actions  
 block = display.newImage("blocks/cornerSW.png")  
 block.x= (i-row\*15)\*32-16  
 block.y = row\*32+16  
 block.dx = -0.3  
 block.dy = 0  
 physics.addBody( block, { isSensor = true } )  
 block:addEventListener("collision", setDirLEFT)  
 table.insert(turnHolder, w, block)  
 w = w + 1   
 turnOne = block  
 elseif(lvlArray[i] == 26) then --if there is supposed to be a row  
 --just add a box that will be a darker color and won't have any actions  
 block = display.newImage("blocks/cornerSE.png")  
 block.x= (i-row\*15)\*32-16  
 block.y = row\*32+16  
 block.dx = 0.3  
 block.dy = 0  
 physics.addBody( block, { isSensor = true } )  
 block:addEventListener("collision", setDirRIGHT)  
 table.insert(turnHolder, w, block)  
 w = w + 1  
 elseif(lvlArray[i] == 68) then --if there is supposed to be a row  
 --just add a box that will be a darker color and won't have any actions  
 block = display.newImage("blocks/cornerNE.png")  
 block.x= (i-row\*15)\*32-16  
 block.y = row\*32+16  
 block.dx = 0  
 block.dy = -0.3  
 physics.addBody( block, { isSensor = true } )  
 block:addEventListener("collision", setDirUP)  
 table.insert(turnHolder, w, block)  
 w = w + 1  
 elseif(lvlArray[i] == 48) then --if there is supposed to be a row  
 --just add a box that will be a darker color and won't have any actions  
 block = display.newImage("blocks/cornerNW.png")  
 block.x= (i-row\*15)\*32-16  
 block.y = row\*32+16  
 block.dx = 0  
 block.dy = -0.3  
 physics.addBody( block, { isSensor = true } )  
 block:addEventListener("collision", setDirUP)  
 table.insert(turnHolder, w, block)  
 w = w + 1  
 elseif(lvlArray[i] == 42) then --if there is supposed to be a row  
 --just add a box that will be a darker color and won't have any actions  
 block = display.newImage("blocks/cornerSW.png")  
 block.x= (i-row\*15)\*32-16  
 block.y = row\*32+16  
 block.dx = 0  
 block.dy = 0.3  
 physics.addBody( block, { isSensor = true } )  
 block:addEventListener("collision", setDirDOWN)  
 table.insert(turnHolder, w, block)  
 w = w + 1   
 turnOne = block  
 elseif(lvlArray[i] == 62) then --if there is supposed to be a row  
 --just add a box that will be a darker color and won't have any actions  
 block = display.newImage("blocks/cornerSE.png")  
 block.x= (i-row\*15)\*32-16  
 block.y = row\*32+16  
 block.dx = 0  
 block.dy = 0.3  
 physics.addBody( block, { isSensor = true } )  
 block:addEventListener("collision", setDirDOWN)  
 table.insert(turnHolder, w, block)  
 w = w + 1  
  
  
  
  
  
  
 elseif(lvlArray[i] == 77) then --if there is supposed to be a row  
 --just add a box that will be a darker color and won't have any actions  
 block = display.newImage("blocks/roadH.png")  
 block.x= (i-row\*15)\*32-16  
 block.y = row\*32+16  
 block.name = "start"  
 startBlock = block  
 elseif(lvlArray[i] == 88) then --if there is supposed to be a row  
 --just add a box that will be a darker color and won't have any actions  
 block = display.newImage("blocks/roadH.png")  
 block.x= (i-row\*15)\*32-16  
 block.y = row\*32+16  
 block.name = "finish"  
 table.insert(turnHolder, w, block)  
 w = w + 1  
 end  
 --print(turnHolder)  
 for c=1,11 do  
 if(i == c\*15) then  
 --if 10 columns have gone by, then we move onto the next row  
 row = row +1  
 end  
 end  
 end  
end  
  
function eFrame(e)  
 makeEnemies() --we'll just make some enemies  
end  
  
function makeEnemies() --//this function will add enemies to the field  
 if(enemyTime \< enemyLimit) then --//if it isn't time to make them yet  
 enemyTime = enemyTime + 1--;//then keep on waiting  
 elseif(enemyTime \>= enemyLimit) then  
 spawnEnemy()  
 currentEnemy = currentEnemy +1--;//move on to the next enemy   
 enemyTime = 0 --;//and reset the time  
 end  
end  
  
function countEnemies()  
 enemyNumber = table.maxn(enemyArray1)  
 --print(enemyNumber)  
 for i = 0, enemyNumber do  
 if(enemyArray1[i] ~= 0) then  
 enemiesLeft = enemiesLeft +1  
 end  
 --print(enemiesLeft)  
 end  
end  
  
countEnemies()  
makeRoad()  
Runtime:addEventListener( "enterFrame", eFrame )  
--UI  
  
hearticon = display.newImage("UI/heart.png")  
hearticon.xScale = 0.1  
hearticon.yScale = 0.1  
hearticon.x = 12&nbsp;  
hearticon.y = 12  
  
goldbar = display.newImage("UI/gold.png")  
goldbar.xScale = 0.17  
goldbar.yScale = 0.17  
goldbar.x = 465  
goldbar.y = 12  
  
--healthText = display.newText((health), 22, 0, "minecraft")  
--goldText = display.newText((cash), 420, 0, "minecraft")  
  
function refreshText(e)  
 healthText.text = health  
 goldText.text = cash  
end  
  
--Runtime:addEventListener("enterFrame", refreshText)  
  
--Runtime:addEventListener( "collision", setDir )  
--enemies.lua  
  
counter2 = 0  
enemyHolder = {}  
turnCoordX = 0  
turnCoordY = 0  
  
--print(currentEnemy)  
ct = 0  
function onCollision(e)  
 print("CRASH!!" .. ct)  
 ct = ct + 1  
end  
  
function spawnEnemy()  
 if(enemyArray1[currentEnemy] == 1) then  
 counter2 = counter2 + 1  
 --print("enemySpawned "..counter2)  
  
 enemy = display.newImage("enemies/zombiesmall2.png")  
 --enemy.xScale = 0.5  
 --enemy.yScale = 0.5  
 enemy.maxSpeed = 4  
 enemy.x = startBlock.x - 50   
 enemy.y = startBlock.y  
 enemy.dx = 1  
 enemy.dy = 0  
 enemy.speed = 1  
 enemy.money = 1  
 enemy.id = "enemy"  
  
 physics.addBody( enemy, { isSensor = true } )  
 --enemy:addEventListener( "collision", onCollision )  
 table.insert(enemyHolder, currentEnemy, enemy)   
 table.insert(enemyHP,currentEnemy, 50)  
 --print("currentEnemy " ..currentEnemy)  
 --print("enemyArray "..table.maxn (enemyHolder))  
 --moveEnemy()   
 elseif(enemyArray1[currentEnemy] == 2) then  
 counter2 = counter2 + 1  
 --print("enemySpawned "..counter2)  
  
 enemy = display.newImage("enemies/skeleton2.png")  
 --enemy.xScale = 0.9  
 --enemy.yScale = 0.9  
 enemy.maxSpeed = 4  
 enemy.x = startBlock.x - 50   
 enemy.y = startBlock.y  
 enemy.dx = 1  
 enemy.dy = 0  
 enemy.speed = 1.2  
 enemy.money = 1.5  
 enemy.id = "enemy"  
  
 physics.addBody( enemy, { isSensor = true } )  
 --physics.addBody(enemy)  
 table.insert(enemyHolder, currentEnemy, enemy)  
 table.insert(enemyHP,currentEnemy, 100)  
 end  
  
 if(enemyArray1[currentEnemy] == 0) then  
 --print("no enemy")  
 end  
 end  
  
--function killEnemy()  
 --enTarget = display.newImage("enemies/zombie\_left1.png")  
 --enemyHolder[, i] --enTarget = enemyHolder[i+1]  
 --health = health -1  
 --print(health)  
--end  
  
function moveEnemy2()  
 for i = 1, table.maxn (enemyHolder) do --{//create a loop  
 if( enemyHolder[i].x ~= nil) then  
  
 enemyHolder[i].x = enemyHolder[i].x + (enemyHolder[i].dx\*enemyHolder[i].speed)  
 enemyHolder[i].y = enemyHolder[i].y + (enemyHolder[i].dy\*enemyHolder[i].speed)  
 end  
 end  
end  
  
function moveEnemy()  
  
  
 for a = 0, table.maxn (turnHolder) do  
 turnCoordX=turnHolder[a].x  
 turnCoordY=turnHolder[a].y  
  
  
 for i = 1, table.maxn (enemyHolder) do --{//create a loop  
 if( enemyHolder[i].x ~= nil) then  
  
 enemyHolder[i].x = enemyHolder[i].x + (enemyHolder[i].dx\*enemyHolder[i].speed)  
 enemyHolder[i].y = enemyHolder[i].y + (enemyHolder[i].dy\*enemyHolder[i].speed)  
  
  
 if(enemyHolder[i].x \<= turnHolder[a].x+3 and enemyHolder[i].x \>= turnHolder[a].x-3 and enemyHolder[i].y \<= turnHolder[a].y+3 and enemyHolder[i].y \>= turnHolder[a].y-3) then  
  
 enemyHolder[i].dx = turnHolder[a].dx  
 enemyHolder[i].dy = turnHolder[a].dy  
 if(turnHolder[a].name == "finish")then  
 --table.remove(enemyHolder[i])  
 enemyHolder[i]:removeSelf()  
 enemiesLeft = enemiesLeft -1  
 health = health -1  
 cash = cash +(enemyHolder[i].money\*50)  
 print(enemiesLeft)  
  
 if(enemiesLeft == 0) then  
 currentLvl = currentLvl + 1  
 print("current lvl " ..currentLvl)  
 end  
 --print(health)  
 --print(enemyHP[i])  
  
  
  
 end   
 end   
 end  
 end end  
end  
  
function newDir(e)  
 if(e.other.id =="enemy") then  
 if(e.other.nextDir == "UP") then  
 e.other.dx = 0  
 e.other.dy = -1  
 elseif(e.other.nextDir == "DOWN") then  
 e.other.dx = 0  
 e.other.dy = 1  
 elseif(e.other.nextDir == "LEFT") then  
 e.other.dx = -1  
 e.other.dy = 0  
 elseif(e.other.nextDir == "RIGHT") then  
 e.other.dx = 1  
 e.other.dy = 0  
 end  
  
 end  
end  
  
function setDirUP(e)  
 if(e.other.id =="enemy") then  
 e.other.nextDir = "UP"  
 print("up")  
 end  
end  
  
function setDirDOWN(e)  
 if(e.other.id =="enemy") then  
 e.other.nextDir = "DOWN"  
 print("down")  
 end  
end  
  
function setDirLEFT(e)  
 if(e.other.id =="enemy") then  
 e.other.nextDir = "LEFT"  
 print("left")  
 end  
end  
  
function setDirRIGHT(e)  
 if(e.other.id =="enemy") then  
 e.other.nextDir = "RIGHT"  
 print("right")  
 end  
end  
--function addListener(e)  
 Runtime:addEventListener( "enterFrame", moveEnemy2 )  
--end  
  

[code]

–towers.lua

counter = 0
canPlaceTower = true

towerArray = {}

function makeTower(e)
if(canPlaceTower == true) then
tower = display.newImage(“towers/m1.png”)
tower.x= e.target.x
tower.y =e.target.y
tower.number = e.target.number
e.target:removeEventListener( “tap”, makeTower )
tower:addEventListener( “tap”, removeTower )
counter = counter + 1
canPlaceTower = false
timer.performWithDelay( 10, towerTrue )
–print (counter)
table.insert(towerArray,e.target.number,tower)
end
end

remember = 0

function removeTower(e)
print(“remove tower”)
e.target:removeSelf()
remember = e
timer.performWithDelay( 10, addBlockListener )
end
function addBlockListener(f)
lvlHolder[remember.target.number]:addEventListener(“tap”, makeTower)
end

function towerTrue()
canPlaceTower = true
end
[/code] [import]uid: 51903 topic_id: 9800 reply_id: 309800[/import]

Hi.

Do the game work in the simulator?
error messages?
First thing that i see, you don’t have a
module(…, package.seeall)
line in the two extra lua-files. [import]uid: 42078 topic_id: 9800 reply_id: 35731[/import]

Yes, the code works excellent in the simulator, no errors. But the corona simulator drags a lot of cpu power when we load many enemies, this on a iMac i7. In the IOS simulator however, we have some problems with text that wont show (might be a font related problem).

Anyways, like I said, we have never worked with lua before, so go easy on us. Could you try to explain what the seeall package does exactly?

Thanks for the reply! [import]uid: 51903 topic_id: 9800 reply_id: 35746[/import]

Also, not sure if it’s really relevant, but we tried to strip the code down to find out what was totally wrong and took all of the power. We ended up with a display.newImage line, and it still took 40% cpu. Is this normal? [import]uid: 51903 topic_id: 9800 reply_id: 35748[/import]

i am also new to corona/lua, so i don’t understand all by myself.
you can find some infos here: http://developer.anscamobile.com/reference/index/module

in your code i see, that you use the zero for the first value of an array. but in lua it starts with one!
(see http://developer.anscamobile.com/content/introduction at the bottom)
[import]uid: 42078 topic_id: 9800 reply_id: 35752[/import]

Thanks for the reply, sidasa!

Would be nice if someone else also just took a quick look! Something is very off… [import]uid: 51903 topic_id: 9800 reply_id: 35858[/import]

Unless you narrow it down, it is too much work to look at it. Plus, it’s not commented so it’s hard to understand what you’re trying to achieve.

Anyway, you’re using way too much physics body and even tap listeners. Might be what’s causing the slowdown.

Also, you can’t rely on frames to spawn enemies. If the game is slowing down, your game will spawn an enemy after 10 sec, then 1 min, then …
You should rely on elapsed time instead. [import]uid: 51516 topic_id: 9800 reply_id: 35859[/import]

Thanks for the pointers! We’ll try to clear up the code some more, and if we still get crazy slow speed, we’ll comment the code and post it again. [import]uid: 51903 topic_id: 9800 reply_id: 35860[/import]

why you are not using local? maybe that’s what causing all those problems? [import]uid: 58846 topic_id: 9800 reply_id: 36135[/import]