I do not understand why I get the following error:
Line: 107
Bad argument #1 to 'newLine' (number expected, got nil)
I am trying to create a line between two touched objects.
Here is my code:
function createstar()
ie = ie - 300
astar = display.newImage('ls.png', math.random( 1, 10) * 33, ie)
astar:addEventListener( "touch", star)
physics.addBody(astar)
stars:insert(astar)
sceneGroup:insert(stars)
end
function update(e)
if(stars ~= nil)then
for i = 1, stars.numChildren do
stars[i].y = stars[i].y + 3
end
end
end
function star:touch( event )
if event.phase == "began" then
-- Insert touched star into array
table.insert(touchedStarArray, self)
-- Check if array holds 2 stars yet
if table.getn(touchedStarArray) >= 2 then
-- if it does then draw a line between the 2 stars
line = display.newLine( touchedStarArray[1].x, touchedStarArray[1].y, touchedStarArray[2].x, touchedStarArray[1].y)
-- and empty array
touchedStarArray = {}
end
end
end
Thanks in advance, all help is greatly appreciated!
I assume from code you pasted that you have one table listener and it's not the same object as each star created.
The problem is in this line
table.insert(touchedStarArray, self)
There are to ways to solve it.
One, very simple would be to put into touchedStarArray event.target not self (self is table star, not star's objects you are createing in createstar function.
table.insert(touchedStarArray, event.target)
Other solution would be to put listener into star creation function
function createstar()
ie = ie - 300
astar = display.newImage('ls.png', math.random( 1, 10) * 33, ie)
astar:addEventListener( "touch", astar)
function astar:touch( event )
if event.phase == "began" then
-- Insert touched star into array
table.insert(touchedStarArray, self)
-- Check if array holds 2 stars yet
if table.getn(touchedStarArray) >= 2 then
-- if it does then draw a line between the 2 stars
line = display.newLine( touchedStarArray[1].x, touchedStarArray[1].y, touchedStarArray[2].x, touchedStarArray[1].y)
-- and empty array
touchedStarArray = {}
end
end
end
physics.addBody(astar)
stars:insert(astar)
sceneGroup:insert(stars)
end
I would put in some print statements and make sure that touchedStarArray[1] really has a .x attribute.
\
Related
recently I was coding a new game when I ran across a problem of which I cannot seem to be able to fix.
This is the code :
function newPower()
rand = math.random( 100 )
if (rand < 80) then
powerup = display.newImage("power.png");
powerup.class = "powerup"
powerup.x = 60 + math.random( 160 )
powerup.y = -100
physics.addBody( powerup, { density=0.9, friction=0.3, bounce=0.3} )
powerup:addEventListener( "touch", handlePowerTouch )
end
end
local function handlePowerTouch( event )
if event.phase == "began" then
currentScore = currentScore * 2
currentScoreDisplay.text = string.format( "%06d", currentScore )
event.target:removeSelf()
return true
end
end
local function spawnpowers()
-- Spawn a new powerup every second until canceled.
spawnPower = timer.performWithDelay( 1000, newPower, -1 )
end
Any help fixing this issue would be greatly appreciated!
The issue I'm having is when I click "run" or "play" the game starts working then crashes and displays this message:
addEventListener: listener cannot be nil: nil stack traceback:
?: in function 'addeventListener'
game.lua63: in function'_listener' <-- i have given you game.lua:63 above.
Thanks
powerup:addEventListener( "touch", handlePowerTouch )
Here handlePowerTouch is nil as the function definition follows after this line.
Move your function definition in front of that line, then it should work.
Btw, is there any reason why you have so many global variables? You should use local variables wherever possible.
What is the best way to remove all spawned coins when the game is over?
Here is the code that spawns the coins:
screenGroup = self.view
coin = {}
coinspawn = function()
i = display.newSprite( imageSheet1, sequenceData1 )
i.x = display.contentWidth
i.y = math.random(0, display.contentHeight-50)
i:play()
i.collided = true
i.name = "coin"
physics.addBody(i, "dynamic",
{density=.1, bounce=0.1, friction=.2, shape= shape2 ,filter=playerCollisionFilter }
)
--player.gravityScale = 0.5
coinIntro = transition.to(i,{time=2500, x=display.contentWidth - display.contentWidth -500 ,onComplete=jetReady , transition=easing.OutExpo } ) --
coin[#coin+1] = i
end
tmrcoin = timer.performWithDelay( 1000, coinspawn, 0 )
First you would remove all coins from the display. Then you would clear the coin table:
for i=1,#coin do
coin[i]:removeSelf()
end
coin = {} -- forget all coins
Assuming coin table is the only other place you store your coins, this will do it.
Note that you can't use coin[i]=nil in the loop after removeSelf: as soon as table has holes, the # operator is basically unusable. You can't use table.remove either, because i gets incremented every time, so you'll miss items (try, you'll see). Same issue with pairs: you can't edit a table while iterating through it. You could however do this:
local numCoins = #coin
for i=1,numCoins do
coin[i]:removeSelf()
coin[i]=nil
end
-- now coin is {}
The only reason I can think of to nil N items instead of letting the gc take care of it with one table = {} statement is if you have more than one reference to your coin table (which I would rename to coins, BTW, for clarity).
I am making a shooter game using the corona sdk...
My problem is that i am trying to delete an object(that is part of an array)when it leaves the screen.. when i do, i get an error that says 'trying to compare nil value to variable' which refers to a simple move function for every object in the array. Here is relevant parts of code:
function addAlien()
listeners('add')
end
function listeners(action)
if(action == 'add') then
Runtime:addEventListener('enterFrame',update)
enemyTimer = timer.performWithDelay(800,addEnemy,0)
else
Runtime:removeEventListener('enterFrame',update)
timer.cancel(enemyTimer)
end
end
function addEnemy(e)
enemy = display.newImage('drone.png')
enemy.x = 500
enemy.y = math.floor(math.random()*300)
enemy:scale(-0.1,0.1)
enemy.speed = math.random(2,6)
enemies.insert(enemies,enemy)
enemy.enterFrame = moveEnemy
Runtime:addEventListener('enterFrame',enemy)
end
function moveEnemy(self,event)
--if self.x < 100 then
---self:removeSelf()
--self = nil
--removeSelf()
--else
self.x = self.x-self.speed
--end
end
function update(e)
if(enemies.numChildren ~= 0)then
for i = 1,enemies.numChildren do
if(enemies[i] ~= nil)then
--enemies[i].x = enemies[i].x-3
if(enemies[i].x<100)then
--enemies:remove(enemies[i])
--display.remove(enemies[i])
--enemies[i] = nil
end
end
end
end
end
I have commented out the parts that give me errors.
Any help would be appreciated,
thanks
You might want to try and put the delete code in it's own function and then use a timer to remove it so that the function where you are currently deleting the object can return and you're not deleting yourself.
Another option would be to make it temporarily invisible and then loop through the table periodically and remove anything outside of the move handler.
You have a problem with the following code:
function listeners(action)
if(action == 'add') then
Runtime:addEventListener('enterFrame',update)
enemyTimer = timer.performWithDelay(800,addEnemy,0)
else
Runtime:removeEventListener('enterFrame',update)
timer.cancel(enemyTimer)
end
end
You only want to Runtime:addEventListener('enterFrame', update) once. If you do it everytime you add an enemy things will go wrong. The problem is your code runs again and again after the objects have been removed already.
hmmm. did you use the scene template? if so, you should only put the :removeself () and = nil values in the scene destroy section at the bottom. you also dont need the second removeself that is not attached to an object as that is probably the nil issue.
to summarize.
1-put all remove self () and = nil at the destroy section of scene template and use object.isVisible = false instead.
2-the nil error is most likely coming from the removeself() statement with no object. so change it to moveenemy:removeself ()
if my understanding is right this is how i would do it without using runtime
and using timer instead. ask away if you have question
local scrWidth = display.actualContentWidth
local scrHeight = display.actualContentHeight
local enemy = {} --this will hold your aliens
function addEnemy()
enemy[#enemy + 1] = display.newImage("drone.png")
enemy[#enemy].x = 500
enemy[#enemy].y = math.floor(math.random()*300)
enemy[#enemy]:scale(-0.1,0.1)
enemy[#enemy].speed = math.random(2,6)
end
local function update()
addEnemy()
--this will move the enemy to the left from right
for i=1,#enemy,1 do
enemy[i].x = enemy[i].x - enemy[i].speed
end
--the below codes will destroy each enemy that is out side the screen on the left
local function destroyWhenOutside()
for i=1,#enemy,1 do
if enemy[i].x < 0 - enemy[i].width then
enemy[i]:removeSelf()
enemy[i] = nil
elseif enemy[i].y < 0 - enemy[i].height then
enemy[i]:removeSelf()
enemy[i] = nil
end
end
end
destroyWhenOutside()
end
--this will loop the update every 1/1000 seconds
local timerUpdate = timer.performWithDelay(1,update,-1)
.
Using Corona, i would like to move object when i delete it from a table. The problem is that i iterate the table on every frame. When x > WIDTH - 50 i would like for the monkey to stop moving in a sinuswave form and jump into the removeMonkeys function.
My Code:
local function removeMonkeys(obj)
transition.to(obj, {time = 1500, y = 2*HEIGHT/3, onComplete = obj:removeSelf()})
numMonkeys = numMonkeys - 1;
end
function startGame()
timer.performWithDelay(500, spawn, maxNumMonkeys)
local function onEveryFrame( event )
for i = 1, #monkeySet do
if(monkeySet[i] ~= nil) then
monkeySet[i].x = monkeySet[i].x + 2
monkeySet[i].y = monkeySet[i].y + math.sin(monkeySet[i].x/monkeySpeed)*Amplitude/5
if(monkeySet[i].x > WIDTH -50) then
removeMonkeys(monkeySet[i])
table.remove(monkeySet, i)
print(#monkeySet)
end
end
end
end
Runtime:addEventListener( "enterFrame", onEveryFrame )
Is there anything I'm missing here?
Not sure what exactly you're asking here, but if your transition.to doesn't work check that you aren't you killing the only reference to monkeySet[i] when you do
table.remove(monkeySet, i)
i have a problem (obviusly :P)
i'm create a mini game, and when i touch a Object-A , creates an Object-B.
If i touch N times, this create N Object-B.
(Object-B are Bubbles in my game)
so, i try when I touch the bubble (object-B), that disappears or perform any actions.
I try adding Object-B to Array
local t = {}
.
.
.
bur = display.newImage("burbuja.png")
table.insert(t,bur)
and where i have my eventListeners i wrote:
for i=1, #t do
bur[i]:addEventListener("tap",reventar(i))
end
and my function 'reventar'
local function reventar (event,id)
table.remove(t,id)
end
i'm lost, and only i want disappears the bubbles.
you're probably gonna want to do something like this:
local t = {}
bur = display.newImage("burbuja.png")
table.insert(t,bur)
-- declaring the function first so it can be used later in the for loop
local function reventar(event)
t[event.target.id] = nil -- We remove object from table
event.target:removeSelf() -- Also remember to remove from display
end
for i=1,#t do
t[i].id = i
t[i]:addEventListener("tap", reventar)
end
Hope this helps.
EDIT
I would do it this way, because it's better when you want to loop through the objects:
local t = {}
-- declaring the function first so it can be used later
local function reventar(event)
event.target.kill = true -- Mark the clicked object for later destruction
end
bur = display.newImage("burbuja.png")
bur:addEventListener("tap", reventar)
table.insert(t,bur)
local function loop(event)
for i = #t, 1, -1 do
local object = t[i]
-- Do stuff to object here, such as object.y = object.y + 1
if object.kill then -- Check if object is marked for destruction
local child = table.remove(t, i) -- Remove from table
if child ~= nil then
-- Remove from display and nil it
child:removeSelf()
child = nil
end
end
end
end
Runtime:addEventListener("enterFrame", loop) -- Remember to remove this when no longer needed