Collision detection : myName nil value - lua

I'm trying to set up collision for my game with code from Corona SDK sample called "Collision Detection".
I'm getting this realy strange error every time ball collides with something -
Runtime error
...er 1\documents\corona projects\earthyball\level1.lua:114: attempt to concatenate field 'myName' (a nil value) stack traceback:
[C]: ?
...er 1\documents\corona projects\earthyball\level1.lua:114: in function <...er 1\documents\corona prRuntime error
...er 1\documents\corona projects\earthyball\level1.lua:118: attempt to concatenate field 'myName' (a nil value) stack traceback:
[C]: ?
This is my code
display.setStatusBar(display.HiddenStatusBar)
local storyboard = require "storyboard"
local scene = storyboard.newScene()
local physics = require "physics"
physics.start()
physics.setScale( 60 )
physics.setGravity( 0, 12 )
system.setAccelerometerInterval( 100 )
function scene:createScene(event)
local screenGroup = self.view
bkg = display.newImage("bkg.png")
screenGroup:insert(bkg)
finish = display.newImage("finishflag.png")
finish.x = 400
finish.y = 260
finish.myName ="flag"
physics.addBody(finish,"static",element)
blockl1 = display.newImage("blockl1.png")
blockl1:setReferencePoint(display.CentreReferencePoint)
blockl1.x = 165
blockl1.y = 230
physics.addBody(blockl1,"static",element)
screenGroup:insert(blockl1)
l1block2 = display.newImage("l1block2.png")
l1block2:setReferencePoint(display.CentreReferencePoint)
l1block2.x = 300
l1block2.y = 90
physics.addBody(l1block2,"static",element)
screenGroup:insert(l1block2)
line1 = display.newImage("line1.png")
line1:setReferencePoint(display.CentreReferencePoint)
line1.x = 230
line1.y = 300
physics.addBody(line1, "static", element)
line1.myName = "pod"
screenGroup:insert(line1)
line2 = display.newImage("line1.png")
line2:setReferencePoint(display.CentreReferencePoint)
line2.x = 230
line2.y = 10
physics.addBody(line2, "static", element)
line2.myName = "pod2"
screenGroup:insert(line2)
line1Ver = display.newImage("lineVer.png")
line1Ver:setReferencePoint(display.CentreReferencePoint)
line1Ver.x = 20
line1Ver.y = 230
physics.addBody(line1Ver, "static", element)
screenGroup:insert(line1Ver)
line2Ver = display.newImage("lineVer.png")
line2Ver:setReferencePoint(display.CentreReferencePoint)
line2Ver.x = 440
line2Ver.y = 230
physics.addBody(line2Ver, "static", element)
screenGroup:insert(line2Ver)
ball = display.newImage("ball.png")
ball.x = 50
ball.y = 30
physics.addBody(ball,"dynamic",{density=3.1, bounce=0.6, friction=0.5, radius=17})
finish.myName ="ball"
screenGroup:insert(ball)
end
function scene:enterScene(event)
finish.collision = onLocalCollision
finish:addEventListener( "collision", finish )
line1.collision = onLocalCollision
line1:addEventListener( "collision", line1 )
line2.collision = onLocalCollision
line2:addEventListener( "collision", line2 )
ball.collision = onLocalCollision
ball:addEventListener( "collision", ball )
end
function onLocalCollision( self, event )
if ( event.phase == "began" ) then
print( self.myName .. ": collision began with " .. event.other.myName )
elseif ( event.phase == "ended" ) then
print( self.myName .. ": collision ended with " .. event.other.myName )
end
end
function onTilt( event )
physics.setGravity( ( 12.5 * event.xGravity ), ( -12.5 * event.yGravity ) )
end
function scene:exitScene(event)
end
function scene:destroyScene(event)
end
Runtime:addEventListener( "accelerometer", onTilt )
element = { friction=0.5, bounce=0.3 }
scene:addEventListener("createScene",scene)
scene:addEventListener("enterScene",scene)
scene:addEventListener("exitScene",scene)
scene:addEventListener("destroyScene",scene)
return scene
Thanks for helping!

Your all objects are a part of physics. That means, they all collide with each other. Thats why in every collision, it is possible to call a collision event listener. What I'm trying to saying is that, you have a collision event listener on your ball object, line1, line2 and finish. And you think that if there is a collision pnly between these objects your event listener will be called. But for example, when ball object collides with line2ver, line1ver etc., your event listener ball() is calling and that function trys to reach line1ver.myName which does not exist.
So, you must wheter add .myName part to all your objects, or just didn't print .myName part.
And a little tip to you:
I think you want to detect collisions with ball - other objects. For that purpose, you can use just one collision event listener, which is ball()
Hope it helps...

Related

Attempt to perform arithmetic on field 'y' (a nil value)

I'm new here and I'm struggling with this error in Corona, when game ends (lives=0) and I try to remove the background (that is moving with a function "move"):
"Attempt to perform arithmetic on field 'y' (a nil value)"
in line "background.y = background.y + 4"
Is there anybody who can explain me what is the mistake?
THE CODE:
--add PHYSICS
local physics = require( "physics" )
physics.start()
physics.setGravity( 0, 0 )
local lives = 1
local died = false
--###
--add background
background = display.newImageRect( "background.png", 800, 14000 )
background.x = display.contentCenterX
background.y = 730
background.myName = "background"
--add bottle
bottiglia = display.newImageRect( "bottiglia.png", 41, 104 )
physics.addBody( bottiglia, "dynamic", { radius=45, bounce=0.5 } )
bottiglia.x = display.contentCenterX
bottiglia.y = 10
bottiglia.myName = "bottiglia"
--function move
local function move()
bottiglia.y = bottiglia.y + 4
background.y = background.y + 4
end
Runtime:addEventListener( "enterFrame", move )
--###
--add player
studente = display.newImageRect( "studente.png", 98, 79 )
studente.x = display.contentCenterX
studente.y = display.contentHeight - 100
physics.addBody( studente, { radius=40, isSensor=true } )
studente.myName = "studente"
--###
--function collision
local function onCollision( event )
if ( event.phase == "began" ) then
local obj1 = event.object1
local obj2 = event.object2
if ( ( obj1.myName == "studente" and obj2.myName == "bottiglia" ) or
( obj1.myName == "bottiglia" and obj2.myName == "studente" ) )
then
if ( died == false ) then
died = true
-- lives update
lives = lives - 1
livesText.text = "Lives: " .. lives
if ( lives == 0 ) then
display.remove( studente )
display.remove( background)
timer.performWithDelay( 100, endGame )
end
else
studente.alpha = 0
timer.performWithDelay( 500, restoreStudente )
end
end
end
end
Runtime:addEventListener( "collision", onCollision )
livesText = display.newText( "Lives: " .. lives, 200, 80, native.systemFont, 36 )
--thank you all
The Runtime listener (move function) is working all the time. It changes position of bottiglia and background objects but since background does not exist any more you get an error.
A simple solution is to remove the global listener using Runtime:removeEventListener() before you remove the background object.
Use Runtime:removeEventListener("enterFrame", move)
If you don't want remove listener, you can add checks for nil:
--function move
local function move()
if (bottiglia ~= nil and bottiglia.y ~= nil) then
bottiglia.y = bottiglia.y + 4
end
if (background~= nil and background.y ~= nil) then
background.y = background.y + 4
end
end
This is also pretty risky to use such global variables: bottiglia and background.
You can make it little safer if make them as (or something like that):
myGlobalsVars = { }
myGlobalsVars.myGlobalsVars = display.newGroup()
myGlobalsVars.background = display.newGroup()

attempt to index global 'volMusicTickOn' (a nil value). Listener Errors

I was trying to make a simple videogame for smartphones, well, what i'm now trying to do is that when i click on the 'volMusicTickOn' object, this must disappear and the music stops. I've done this with a function listener but i got an error on calling the listener, here's the code:
local settings = composer.newScene()
local particlesTable = {}
local particlesGroup = display.newGroup()
local options =
{
width = 600,
height = 600,
numFrames = 2,
sheetContentWidth = 1200,
heetContentHeight = 600
}
local tickSheet = graphics.newImageSheet( "rectTick_sheet.png", options )
--
--
function settings:create( event )
-- Dichiarazione oggeti e codice eseguibile
num=0
local sceneGroup = self.view
background = display.newImageRect( sceneGroup, "background.png", 1280 , 720 )
background.x = display.contentCenterX
background.y = display.contentCenterY
volMusicTickOn = display.newImageRect( "rectTick_on.png", 100, 100 )
volMusicTickOn.name = "volMusicTickOn"
volMusicTickOn.x = display.contentCenterX - 250
volMusicTickOn.y = display.contentCenterY - 100
end
function settings:show( event )
local sceneGroup = self.view
local phase = event.phase
if ( phase == "will" ) then
-- Code here runs when the scene is still off screen (but is about to come on screen)
elseif ( phase == "did" ) then
if event.phase=="began"then
end
if event.phase=="ended"then
end
end
end
function settings:hide( event )
local sceneGroup = self.view
local phase = event.phase
if ( phase == "will" ) then
-- Code here runs when the scene is still off screen (but is about to come on screen)
elseif ( phase == "did" ) then
-- Code here runs when the scene is entirely on screen
end
end
function settings:destroy( event )
local sceneGroup = self.view
end
-- Funzioni
local function remove(particle)
display.remove( particle )
table.remove( particlesTable, num)
end
local function removeParticle( particle )
timer.performWithDelay(1000, transition.to( particle, {alpha=0, time=350, onComplete=remove(particle) } ))
end
local function removetotally( particle )
display.remove( particle )
table.remove( particlesTable, num )
end
function dimParticle( particle )
transition.to( particle, {alpha=0, time=500, onComplete = removetotally, onCompleteParams = particle})
end
local function generateParticles()
local xy=math.random(30,70)
local newParticle = display.newImageRect( particlesGroup, objectSheet , chooseColor(math.random(3)), xy, xy )
table.insert( particlesTable, newParticle )
num = num+1
newParticle.x = (math.random(1280)*math.random(88932))%1280
newParticle.y = (math.random(720)*math.random(13546))%720
newParticle.alpha = 0
transition.to( newParticle, {alpha=1, time=150, onComplete=dimParticle, onCompleteParams=newParticle})
end
local function generateParticlesSmall()
local xy=math.random(5,15)
local newParticle = display.newImageRect( particlesGroup, objectSheet , 1, xy, xy )
table.insert( particlesTable, newParticle )
num = num+1
newParticle.x = (math.random(1280)*math.random(88932))%1280
newParticle.y = (math.random(720)*math.random(13546))%720
newParticle.alpha = 0
transition.to( newParticle, {alpha=1, time=150, onComplete=dimParticle, onCompleteParams=newParticle})
end
local function chooseColor(n)
if n==1 then
return 8
elseif n==2 then
return 9
elseif n==3 then
return 10
end
end
function changeMusicVolumeStatus(event)
if audio.isChannelPaused( 1 ) then
audio.resume( 1 )
else
audio.pause( 1 )
end
return true
end
local function changeEffectsVolumeStatus(event)
if audio.isChannelPaused( 2 ) then
audio.resume( 2 )
else
audio.pause( 2 )
end
return true
end
-- Chiamate e Listener Del Runtime
bigPTimer1=timer.performWithDelay( 1, generateParticles, 0 )
bigPTimer2=timer.performWithDelay( 1, generateParticles, 0 )
smallPTimer=timer.performWithDelay( 1, generateParticlesSmall, 0 )
settings:addEventListener( "create", settings )
settings:addEventListener( "show", settings )
settings:addEventListener( "hide", settings )
settings:addEventListener( "destroy", settings )
volMusicTickOn:addEventListener( "tap", changeMusicVolumeStatus )
volMusicTickOff:addEventListener( "tap", changeMusicVolumeStatus )
--
return settings
Here is the error i got
16:49:45.126 ERROR: Runtime error
16:49:45.126 C:\Users\lpasi\Downloads\Progetto 1-20170725T134427Z-001\Progetto 1\settings.lua:167: attempt to index global 'volMusicTickOn' (a nil value)
16:49:45.126 stack traceback:
16:49:45.126 [C]: in function 'error'
16:49:45.126 ?: in function 'gotoScene'
16:49:45.126 C:\Users\lpasi\Downloads\Progetto 1-20170725T134427Z-001\Progetto 1\menu.lua:36: in function '_onRelease'
16:49:45.126 ?: in function '?'
16:49:45.126 ?: in function <?:654>
16:49:45.126 ?: in function <?:169>
I've tried to use also table listeners but nothing changed, pleas lemme know if you solve my problems, Thank You.
Are you sure settings:create is called before you try to reference volMusicTickOn? Because settings:create defines volMusicTickOn and thus it will be nil until it is called.
As I see it, the create event may not be fired until after you reference volMusicTickOn for the first time. Your code, because it is event based, is not guaranteed to run what this line sets up:
settings:addEventListener( "create", settings )
Before this line:
volMusicTickOn:addEventListener( "tap", changeMusicVolumeStatus )
volMusicTickOff:addEventListener( "tap", changeMusicVolumeStatus )
And this, volMusicTickOn might be nil
The solution would be to actually move those lines into settings:create so you know that volMusicTickOn is not nil for sure!

Listen Event for Any Object in a Table

Another newbie query. Now on my third day of working with Corona.
The following code works fine: Balloons are generated and float into the air. Now I want to use :addEventListener( "tap", pushBalloon ) to make it so that when a balloon is clicked the pushBalloon is executed. Can anyone tell me what variable I would use and how I would define it? And also I guess I would have to change the pushBalloon function too for the new variable.
Thank you.
local function createBalloon()
local randomBalloon = math.random( 10 )
local newBalloon = display.newImageRect( objectSheet, randomBalloon, 112, 142 )
table.insert( balloonsTable, newBalloon )
physics.addBody( newBalloon, "dynamic", { radius=70, bounce=0 } )
newBalloon.myName = "bigBalloon"
newBalloon.alpha = 0.75
newBalloon.gravityScale = randomBalloon/-150
local whereFrom = math.random( 3 )
if ( whereFrom == 1 ) then
-- From the left
newBalloon.x = 100
newBalloon.y = display.contentHeight+150
elseif ( whereFrom == 2 ) then
-- From the top
newBalloon.x = 160
newBalloon.y = display.contentHeight+150
elseif ( whereFrom == 3 ) then
-- From the right
newBalloon.x = 220
newBalloon.y = display.contentHeight+150
end
end
local function gameLoop()
-- Create new balloon
createBalloon()
-- Remove balloons which have drifted off screen
for i = #balloonsTable, 1, -1 do
local thisBalloon = balloonsTable[i]
if ( thisBalloon.x < -100 or
thisBalloon.x > display.contentWidth + 100 or
thisBalloon.y < -100 )
then
display.remove( thisBalloon )
table.remove( balloonsTable, i )
end
end
end
local function pushBalloon()
-- balloon:applyLinearImpulse( 0.2, -2, balloon.x, balloon.y )
-- tapCount = tapCount + 1
-- tapText.text = tapCount
newBalloon.gravityScale = 10
end
You are adding the newBalloon objects to a table, but you should add the event listener to each newBalloon DisplayObject as it is instantiated. This doesn't do exactly what you ask in the title (where simply inserting an object into a table would effectively add an event listener to that object), but achieves the event response I think you are looking for.
If you are tapping the balloon, you would put the listener on the balloon. If you use a "tap" event, the target property tells you which object was touched, so your pushBalloon() function works for any balloon.
local pushBalloon( event )
local balloon = event.target
if event.phase == "began"
-- do something to the balloon object (apply impulse, etc.)
end
end
local function createBalloon()
...
local newBalloon = display.newImageRect( ... )
if newBalloon then
-- set properties of DisplayObject and add event listener
newBallon:addEventListener( "tap", pushBalloon )
end
...
end
I have wrapped the call to addEventListener() in a check to make sure newBalloon ~= nil.

Corona Touch Listener

I am learning corona sdk
This is the following code
when the two objects overlaps it becomes 1 objects(Moves together), i have no clue whats going on...
-----------------------------------------------------------------------------------------
--
-- main.lua
--
-----------------------------------------------------------------------------------------
-- Your code here
local physics = require( "physics" )
physics.start()
local crate1 = display.newImage( "crate.png", display.contentCenterX, 100 )
crate1.name = "crate1"
local crate2 = display.newImage( "crate.png", display.contentCenterX + 100, 100 )
crate2.name = "crate2"
crate1:scale(0.2, 0.2)
crate2:scale(0.2, 0.2)
local bodyTouched = function(event)
if(crate1.name == event.target.name and event.phase == "moved")
then
print("Moved " , event.target.name )
crate1.x = event.x
crate1.y = event.y
elseif (crate2.name == event.target.name and event.phase == "moved")
then
print( "Moved ", event.target.name )
crate2.x = event.x
crate2.y = event.y
end
end
physics.addBody( crate1, "static")
physics.addBody( crate2, "static")
crate1:addEventListener( "touch", bodyTouched )
crate2:addEventListener( "touch", bodyTouched )
Please refer to the Corona SDK documentation.
https://docs.coronalabs.com/daily/guide/events/detectEvents/index.html#TOC
Section: Understanding Hit Events
In general you should read the documentation on anything you use.
Your touch event will propagate through all display objects that intersect with the event coordinate. The event will trigger all registered event listeners on its way.
To avoid having multiple listeners triggered your event listener bodyTouch has to return true which will tell Corona that you handled the event and no further listeners should be invoked.

Corona SDK Level: Can't integrate my level into Storyboard - Assertion Failed error

I hope someone can help me because this problem has been driving me crazy the last few days. So I just started with corona - made a few tutorials and really having fun discovering the possibilities.
Problem: I want to integrate a simple game into a storyboard. I somehonw can't manage to find the right combination and always get this error pop up.
File: assertion failed!
Assertion failed!
stack traceback:
[C]: ?
[C]: in function 'assert'
?: in function 'get0rCreateTable'
?: in function 'addEventListener'
?: in function 'addEventListener'
...ik/Desktop/_DummyProjekt2/Fruit Fliesv10/level01.lua:51: in function
<. . . ik/Desktop/_DummyProjekt2/ Fruit Fliesv10/level0l. lua:44>
?: in function 'dispatchEvent'
?: in function <?:1096>
(tail call): ?
?: in function <?:466>
?: in function <?:218>
It's probably a rookie mistake, but I have been stuck for a few days now and definitely need some help. I've gone thru most of the tutorials and documentation I could find with no luck. So any help would be greately welcome :) So this is my level 1
local storyboard = require( "storyboard" )
local scene = storyboard.newScene()
local widget = require ("widget")
local playfile = require ("play")
function scene:createScene(event)
local screenGroup = self.view
local spawnEnemy
local gameTitle
local scoreTxt
local score = 0
local hitBowl
local planet
local speedBump = 0
background = display.newImage("images/background.png")
background.y = centerY
background.x = centerX
bowl = display.newImage("images/bowl2.png")
bowl.x = centerX
bowl.y = centerY
scoreTxt = display.newText( "Score: 0", 0, 0, "orange juice", 22 )
scoreTxt.x = centerX
scoreTxt.y = 10
scoreTxt:setFillColor(1,1,1)
scoreTxt.y = 255
end
function scene:enterScene(event)
enemypics = {"images/blue.png","images/pink.png", "images/green.png"}
enemy = display.newImage(enemypics[math.random (#enemypics)])
enemy:addEventListener ( "tap", shipSmash )
if math.random(2) == 1 then
enemy.x = math.random ( -100, -10 )
else
enemy.x = math.random ( display.contentWidth + 10, display.contentWidth + 100 )
enemy.xScale = -1
end
enemy.y = math.random (display.contentHeight)
enemy.trans = transition.to ( enemy, { x=centerX, y=centerY, time=math.random(2500-speedBump, 4500-speedBump), onComplete=hitBowl } )
speedBump = speedBump + 50
end
function startGame()
text = display.newText( "Tap here to start. Protect the Fruit Bowl!", 0, 0, "orange juice", 24 )
text.x = centerX
text.y = display.contentHeight - 30
text:setFillColor(0, 0, 0)
local function goAway(event)
display.remove(event.target)
text = nil
display.remove(gameTitle)
spawnEnemy()
scoreTxt.alpha = 1
scoreTxt.text = "Score: 0"
score = 0
bowl.numHits = 10
bowl.alpha = 1
speedBump = 0
end
text:addEventListener ( "tap", goAway )
end
local function bowlDamage()
bowl.numHits = bowl.numHits - 2
bowl.alpha = bowl.numHits / 10
if bowl.numHits < 2 then
bowl.alpha = 0
timer.performWithDelay ( 1000, startGame )
--audio.play ( sndLose )
else
local function goAway(obj)
bowl.xScale = 1
bowl.yScale = 1
bowl.alpha = bowl.numHits / 10
end
transition.to ( bowl, { time=200, xScale=1.2, yScale=1.2, alpha=1, onComplete=goAway} )
end
end
function hitBowl(obj)
display.remove( obj )
bowlDamage()
--audio.play(sndBlast)
if bowl.numHits > 1 then
spawnEnemy()
end
end
local function shipSmash(event)
local obj = event.target
display.remove( obj )
--audio.play(sndKill)
transition.cancel ( event.target.trans )
score = score + 5
scoreTxt.text = "Score: " .. score
spawnEnemy()
end
function scene:exitScene(event)
end
function scene:destroyScene(event)
end
scene:addEventListener( "createScene", scene )
scene:addEventListener( "enterScene", scene )
scene:addEventListener( "exitScene", scene )
scene:addEventListener( "destroyScene", scene )
return scene
So LUA is fun in lots of regards and this is one you'll learn quickly. So I only think this might be the problem, if not it could lead you on the correct trail.
In your top error message you'll see that it gives you this:
...ik/Desktop/_DummyProjekt2/Fruit Fliesv10/level01.lua:51: in function
That level01.lua:51 signifies a line number, so line 51 (or around there). And the lines above it in the error mention addEventListener. Those two things are our clues.
Here's some code from around there:
enemy = display.newImage(enemypics[math.random (#enemypics)])
enemy:addEventListener ( "tap", shipSmash )
if math.random(2) == 1 then
Looks like there's an addEventListener there, one parameter is a string, the other is a function. Where is that function? It's on line 117 which is after line 51 which is most likely the problem. In LUA (and some other languages) you have to declare things in order. So you could do two things. You could move the shipSmash function up above line 51 or you could forward declare that variable. So up in the top part of your file you could do local shipSmash. This assures line 51 that that name exists (what it's trying to check) and then you can declare it later (sometimes I do this for code structure).
Hopefully that helps. I've been using LUA/Corona SDK since about July, I'm still getting used to a lot of the small things like this that I've spent hours ripping my hair out over.

Resources