Collision Filters Still having some problems

Hi to all and thank you for the help in the past but i am still having some problems getting the filters to work.

The code:

badc1CollisionFilter = { categoryBits = 1, maskBits = 16 } badc2CollisionFilter = { categoryBits = 2, maskBits = 16 } badc3CollisionFilter = { categoryBits = 4, maskBits = 16 } wallCollisionFilter = { categoryBits = 8, maskBits = 16 } playerCollisionFilter = { categoryBits = 16, maskBits = 15 } if ( temp.imgpath == "BCloud1.png" ) then physics.addBody( randomStar, { density=.1, bounce=0.1, friction=.2, radius=45, filter=badc1CollisionFilter } ) randomStar.myName = "star1" temp.imgpath = "BCloud"..tostring(math.random(1, 3))..".png"; end if ( temp.imgpath == "BCloud2.png" ) then physics.addBody( randomStar, { density=.1, bounce=0.1, friction=.2, radius=45, filter=badc2CollisionFilter } ) randomStar.myName = "star2" temp.imgpath = "BCloud"..tostring(math.random(1, 3))..".png"; end if ( temp.imgpath == "BCloud3.png" ) then physics.addBody( randomStar, { density=.1, bounce=0.1, friction=.2, radius=45, filter=badc3CollisionFilter } ) randomStar.myName = "star3" temp.imgpath = "BCloud"..tostring(math.random(1, 3))..".png"; end physics.addBody(player, "static", {density=.1, bounce=0.1, friction=.2, radius=10, filter=playerCollisionFilter } ) player:addEventListener( "collision", newCollisionHandler ) function newCollisionHandler( self, event ) if event.other.myName == "star1" then print( "Collided with star1" ) elseif event.other.myName == "star2" then print( "Collided with star2" ) elseif event.other.myName == "star3" then print( "Collided with star3" ) end end  

But now corona is trowing a error ? :

DkYpg.png

Any ideas ? 

Regards Kevin,

Lua is saying that you’re using a variable called event and attempting to index into it as if it were a table, but event is actully nil.  It’s pointing to line 296 of game.lua.  So, you should inspect that line in your code and try to understand why event is nil there.  What line in your code snippet above doe sline 296 correspond to?

  • Andrew

Hi Andrew

line 296 is: player:addEventListener( “collision”, newCollisionHandler )

playerSpriteSheet = sprite.newSpriteSheet("player.png", 113, 55) playerSprites = sprite.newSpriteSet(playerSpriteSheet, 1, 4) sprite.add(playerSprites, "players", 1, 4, 1000, 0) player = sprite.newSprite(playerSprites) local newCollisionHandler player:addEventListener( "collision", newCollisionHandler ) player.x = -80 player.y = 350 player:prepare("players") player:play() player.collided = false player:setReferencePoint(display.CenterReferencePoint); physics.addBody(player, "static", {density=.1, bounce=0.1, friction=.2, radius=10, filter=playerCollisionFilter } ) player.gravityScale = 0 screenGroup:insert(player) playerIntro = transition.to(player,{time=2000, x=150, onComplete=playerReady})  

Regards Kevin,

Hi Kevin,

Looks like the problem is that newCollisionHandler is in fact nil.  The line 295 “local newCollisionHandler” sets up newCollisionHandler as a local variable with a default value of nil.  You then immediately try to add it as a collision listener to the player object, but since it’s nil, you’ll get an error.  Instead, you need to first define newCollisionHandler as a function, and then add it as a listener.  It looks like from your original post, you may have defined newCollisionHandler as a global function, but the line “local newCollisionHandler” will overwrite that, rescoping newCollisionHandler as local and giving it a default value of nil.

See some of the samples here: http://developer.coronalabs.com/content/game-edition-collision-detection

Hope this helps.

  • Andrew

Hi Andrew,

so when i try this :

    function newCollisionHandler()       playeraddEventListener( "collision", newCollisionHandler )     end

The errors go but now its not detecting any collisions.

-Kevin

Hi Kevin,

Looks like there are two issues with what you pasted there.  First, there’s a colon missing between “player” and “addEventListener”.  But more importantly, you’re defining newCollisionHandler as a function which adds itself(?) as a collision listener.

I’d suggest taking a close look at the example called “Local collision listeners” on this page: http://developer.coronalabs.com/content/game-edition-collision-detection

A quick look at your original post, and nothing is jumping out at me as wrong except that you define newCollisionHandler after you attempt to add as a listener.  You need to define the function before.  In your original post, just move the line “player:addEventListener( “collision”, newCollisionHandler )” below where you define the newCollisionHandler function.

  • Andrew

Oky thanks Andrew, 

i will have a look at it :smiley:

-kevin

oky so from you comments Andrew i have done this :

badc1CollisionFilter = { categoryBits = 1, maskBits = 16 } badc2CollisionFilter = { categoryBits = 2, maskBits = 16 } badc3CollisionFilter = { categoryBits = 4, maskBits = 16 } wallCollisionFilter = { categoryBits = 8, maskBits = 16 } playerCollisionFilter = { categoryBits = 16, maskBits = 15 } function getRandomStar()     local temp = starTable[math.random(1, #starTable)] -- Get a random star from starTable     local randomStar = display.newImage(temp.imgpath) -- Set image path for object          if ( temp.imgpath == "BCloud1.png" ) then     physics.addBody( randomStar, { density=.1, bounce=0.1, friction=.2, radius=45, filter=badc1CollisionFilter } )     randomStar.myName = "star1"     temp.imgpath = "BCloud"..tostring(math.random(1, 3))..".png";     end          if ( temp.imgpath == "BCloud2.png" ) then     physics.addBody( randomStar, { density=.1, bounce=0.1, friction=.2, radius=45, filter=badc2CollisionFilter } )     randomStar.myName = "star2"     temp.imgpath = "BCloud"..tostring(math.random(1, 3))..".png";     end          if ( temp.imgpath == "BCloud3.png" ) then     physics.addBody( randomStar, { density=.1, bounce=0.1, friction=.2, radius=45, filter=badc3CollisionFilter } )     randomStar.myName = "star3"     temp.imgpath = "BCloud"..tostring(math.random(1, 3))..".png";     end          randomStar.myName = "star" -- Set the name of the object to star     randomStar.movementSpeed = temp.movementSpeed; -- Set how fast the object will move     randomStar.x = math.random(-30, \_W);         randomStar.y = -35;     randomStar.rotation = math.random(0,20) -- Rotate the object          starMove = transition.to(randomStar, {         time=randomStar.movementSpeed,          y=500,         onComplete = function(self) self.parent:remove(self); self = nil;          end         }) -- Move the star end--END getRandomStar()     playerSpriteSheet = sprite.newSpriteSheet("player.png", 113, 55)     playerSprites = sprite.newSpriteSet(playerSpriteSheet, 1, 4)     sprite.add(playerSprites, "players", 1, 4, 1000, 0)     player = sprite.newSprite(playerSprites)     player.x = -80     player.y = 350     player:prepare("players")     player:play()     player.collided = false     player:setReferencePoint(display.CenterReferencePoint);     physics.addBody(player, "static", {density=.1, bounce=0.1, friction=.2, radius=10, filter=playerCollisionFilter } )           player.gravityScale = 0         screenGroup:insert(player)     playerIntro = transition.to(player,{time=2000, x=150, onComplete=playerReady}) function newCollisionHandler( self, event )    if event.other.myName == "star1" then         print( "Collided with star1" )    elseif event.other.myName == "star2" then         print( "Collided with star2" )    elseif event.other.myName == "star3" then         print( "Collided with star3" )    end end function scene:enterScene(event)     player:addEventListener( "collision", newCollisionHandler ) end  

and now i got the error : attempt to index local event (a nil value).

But this time the error corespondents to the image it collides whit, (so that a good sign ?)

ps if i add ‘function newCollisionHandler() end’ to the codel like so : 

   

 function newCollisionHandler() end     playerSpriteSheet = sprite.newSpriteSheet("player.png", 113, 55)     playerSprites = sprite.newSpriteSet(playerSpriteSheet, 1, 4)     sprite.add(playerSprites, "players", 1, 4, 1000, 0)     player = sprite.newSprite(playerSprites)     player.x = -80     player.y = 350     player:prepare("players")     player:play()     player.collided = false     player:setReferencePoint(display.CenterReferencePoint);     physics.addBody(player, "static", {density=.1, bounce=0.1, friction=.2, radius=10, filter=playerCollisionFilter } )           player.gravityScale = 0         screenGroup:insert(player)     playerIntro = transition.to(player,{time=2000, x=150, onComplete=playerReady})

its not detecting any collision

-kevin

Hi Kevin,

When you get an error, it’ll always refer to the line number in your code it occurred on.  What line number did it refer to, and which line does that correspond to in your code above?

I’m not sure I understood what you mean by your P.S.

  • Andrew

sorry :

if collision on star1 error is on line: “if event.other.myName == “star1” then”

if collision on star2 error is on line: “if event.other.myName == “star2” then”

if collision on star3 error is on line: “if event.other.myName == “star3” then”

from:

function newCollisionHandler( self, event )

   if event.other.myName == “star1” then
        print( “Collided with star1” )
   elseif event.other.myName == “star2” then
        print( “Collided with star2” )
   elseif event.other.myName == “star3” then
        print( “Collided with star3” )
   end
end

-kevin

Hi there,

In your enterScene event, try replacing

[lua]

player:addEventListener( “collision”, newCollisionHandler )

[/lua]

with

[lua]

player.collision = newCollisionHandler

player:addEventListener( “collision”, player )

[/lua]

Hi Andrew,

when i do this :

function newCollisionHandler( self, event )         print("oh hello i have a Collision")    if event.other.myName == "star1" then         print( "Collided with star1" )    elseif event.other.myName == "star2" then         print( "Collided with star2" )    elseif event.other.myName == "star3" then         print( "Collided with star3" )    end end function scene:enterScene(event)     player.collision = newCollisionHandler     player:addEventListener( "collision", player )  

The terminal prints : ‘oh hello i have a Collision’ but not the ‘Collided with star1/2/3’ ?

-kevin

Hi Kevin,

My suggestion would be to put the statement “print_r(event)” in your newCollisionHandler function.  It’ll print out the entire contents of the event table so you can inspect it and see exactly what it’s reporting about the collision.

You can get an implementation of print_r here: http://developer.coronalabs.com/code/printr-implementation-dumps-everything-human-readable-text

  • Andrew

looks like it cant find the  ‘myName’ in the code if i add ‘print( "test " … myName )’ to the newCollisionHandler it cant find it end trows a global ‘newCollisionHandler’ a nil value.

snip: 

function getRandomStar()     local temp = starTable[math.random(1, #starTable)] -- Get a random star from starTable     local randomStar = display.newImage(temp.imgpath) -- Set image path for object          if ( temp.imgpath == "BCloud1.png" ) then     local object1 =      physics.addBody( randomStar, { density=.1, bounce=0.1, friction=.2, radius=45, filter=badc1CollisionFilter } )     randomStar.myName = "BCloud1"     temp.imgpath = "BCloud"..tostring(math.random(1, 3))..".png"; print( "BC1 print name test " .. randomStar.myName )      end          if ( temp.imgpath == "BCloud2.png" ) then     physics.addBody( randomStar, { density=.1, bounce=0.1, friction=.2, radius=45, filter=badc2CollisionFilter } )     randomStar.myName = "BCloud2"     temp.imgpath = "BCloud"..tostring(math.random(1, 3))..".png";     end          if ( temp.imgpath == "BCloud3.png" ) then     physics.addBody( randomStar, { density=.1, bounce=0.1, friction=.2, radius=45, filter=badc3CollisionFilter } )     randomStar.myName = "BCloud3"     temp.imgpath = "BCloud"..tostring(math.random(1, 3))..".png";     end          randomStar.myName = "star" -- Set the name of the object to star     randomStar.movementSpeed = temp.movementSpeed; -- Set how fast the object will move     randomStar.x = math.random(-30, \_W);         randomStar.y = -35;     randomStar.rotation = math.random(0,20) -- Rotate the object     starMove = transition.to(randomStar, {         time=randomStar.movementSpeed,          y=500,         onComplete = function(self) self.parent:remove(self); self = nil;          end         }) -- Move the star                  end--END getRandomStar() function newCollisionHandler( self, event )         print("oh hello i have a Collision")         print( "test " .. myName )     if myName == "BCloud1" then         print("Collided with star1")    elseif event.other.myName == "BCloud2" then         print("Collided with star2")    elseif event.other.myName == "BCloud3" then         print("Collided with star3")    end end  

Hi Kevin,

When you do this:

[lua]

print( "test " … myName )

[/lua]

myName is undefined. You haven’t specified that it’s a property on the object, so Lua looks for it as a global variable and can’t find it. You need to specifiy it as a property of either “self” or “event.other”, just like you do in the lines below it.

Hi this is complacently driving me bonkers. but is it possible to to use preCollision ?

local platform = display.newImage( "platform.png" ) platform.collType = "passthru" physics.addBody( platform, "static", { bounce=0.0, friction=0.3 } ) function character:preCollision( event ) local collideObject = event.other if ( collideObject.collType == "passthru" ) then event.contact.isEnabled = false --disable this specific collision! end end

here is a bigger snip of my code :

local starTable = {} -- Set up star table badc1CollisionFilter = { categoryBits = 1, maskBits = 16 } badc2CollisionFilter = { categoryBits = 2, maskBits = 16 } badc3CollisionFilter = { categoryBits = 4, maskBits = 16 } wallCollisionFilter = { categoryBits = 8, maskBits = 16 } playerCollisionFilter = { categoryBits = 16, maskBits = 15 } function initStar()     local star1 = {}     star1.imgpath = "Cloud1.png"; --Set Image Path for Star     star1.movementSpeed = 10000; --Determines the movement speed of star     table.insert(starTable, star1); --Insert Star into starTable     local star2 = {}     star2.imgpath = "Cloud2.png";     star2.movementSpeed = 12000;     table.insert(starTable, star2);                          local star3 = {}     star3.imgpath = "Cloud3.png";     star3.movementSpeed = 14000;     table.insert(starTable, star3);     local star4 = {}     star4.imgpath = "BCloud"..tostring(math.random(1, 3))..".png";     star4.movementSpeed = 16000;     table.insert(starTable, star4);              local star5 = {}     star5.imgpath = "Cloud5.png";     star5.movementSpeed = 18000;     table.insert(starTable, star5);     end --END initStar()     function getRandomStar()     local temp = starTable[math.random(1, #starTable)] -- Get a random star from starTable     local randomStar = display.newImage(temp.imgpath) -- Set image path for object          if ( temp.imgpath == "BCloud1.png" ) then     local objectb1 =      physics.addBody( randomStar, { density=.1, bounce=0.1, friction=.2, radius=45, filter=badc1CollisionFilter } )     randomStar.myName = "BCloud1"          temp.imgpath = "BCloud"..tostring(math.random(1, 3))..".png";     end          if ( temp.imgpath == "BCloud2.png" ) then     physics.addBody( randomStar, { density=.1, bounce=0.1, friction=.2, radius=45, filter=badc2CollisionFilter } )     randomStar.myName = "BCloud2"     temp.imgpath = "BCloud"..tostring(math.random(1, 3))..".png";     end          if ( temp.imgpath == "BCloud3.png" ) then     physics.addBody( randomStar, { density=.1, bounce=0.1, friction=.2, radius=45, filter=badc3CollisionFilter } )     randomStar.myName = "BCloud3"     temp.imgpath = "BCloud"..tostring(math.random(1, 3))..".png";     end          randomStar.myName = "star" -- Set the name of the object to star     randomStar.movementSpeed = temp.movementSpeed; -- Set how fast the object will move     randomStar.x = math.random(-30, \_W);         randomStar.y = -35;     randomStar.rotation = math.random(0,20) -- Rotate the object     starMove = transition.to(randomStar, {         time=randomStar.movementSpeed,          y=500,         onComplete = function(self) self.parent:remove(self); self = nil;          end         }) -- Move the star     end--END getRandomStar() function newCollisionHandler( self, event )         print("oh hello i have a Collision")    if myName == "BCloud1" then         print("Collided with star1")    elseif event.other.myName == "BCloud2" then         print("Collided with star2")    elseif event.other.myName == "BCloud3" then         print("Collided with star3")    end end     playerSpriteSheet = sprite.newSpriteSheet("player.png", 113, 55)     playerSprites = sprite.newSpriteSet(playerSpriteSheet, 1, 4)     sprite.add(playerSprites, "players", 1, 4, 1000, 0)     player = sprite.newSprite(playerSprites)     player.x = -80     player.y = 350     player:prepare("players")     player:play()     player.collided = false     player:setReferencePoint(display.CenterReferencePoint);     physics.addBody(player, "static", {density=.1, bounce=0.1, friction=.2, radius=10, filter=playerCollisionFilter } )           player.gravityScale = 0         screenGroup:insert(player)     playerIntro = transition.to(player,{time=2000, x=150, onComplete=playerReady}) function scene:enterScene(event)    jet.collision = newCollisionHandler     jet:addEventListener( "collision", jet ) end

Hi Kevin,

You could use pre-collision, but I don’t think it’s necessary here, and I don’t suggest it because it’s a bit “greedy” and should generally be used with good cause. What you have here should be possible with normal collision filters, and I’m not sure what’s “not working” at this point. Could you possibly simplify this project down to one collision filter and two physics objects, so we can get the core in place before expanding it?

Regards,

Brent

Lua is saying that you’re using a variable called event and attempting to index into it as if it were a table, but event is actully nil.  It’s pointing to line 296 of game.lua.  So, you should inspect that line in your code and try to understand why event is nil there.  What line in your code snippet above doe sline 296 correspond to?

  • Andrew

Hi Brent,

so i made this small code to test the filters but I’m missing something here i think 

local physics = require "physics" physics.start() myObject1CollisionFilter = { categoryBits = 1, maskBits = 3 } myObject2CollisionFilter = { categoryBits = 2, maskBits = 3 } movebox = { friction=0.4, bounce=0.8, filter=myObject1CollisionFilter } box = { friction=0.4, bounce=0.8, filter=myObject2CollisionFilter } local myObject1 = display.newRect( 0, 0, 100, 100 ) myObject1:setFillColor( 255 ) myObject1.myName = "movebox" physics.addBody( myObject1, "static", movebox ) local myObject2 = display.newRect( 0, 0, 100, 100 ) myObject2:setFillColor( 100 ) myObject2.x = 250 myObject2.y = 250 myObject2.myName = "box" physics.addBody( myObject2, "static", box ) function newCollisionHandler( self, event )     print("oh hello i have a Collision")    if myName == "box" then     print("test 1")     end end function myObject1:touch( event )     if event.phase == "began" then         self.markX = self.x          self.markY = self.y           elseif event.phase == "moved" then              local x = (event.x - event.xStart) + self.markX         local y = (event.y - event.yStart) + self.markY                  self.x, self.y = x, y    -- move object based on calculations above     end     return true end myObject1:addEventListener( "touch", myObject1 ) myObject1.collision = newCollisionHandler myObject1:addEventListener( "collision", myObject1 )  

Kevin-

Hi Kevin,

I think this still goes back to where you say…

[lua]

if myName == “box” then

[/lua]

…because “myName” isn’t defined in that scope. You’ve set that as a property for both objects, so you need to specify the same in the collision handler. In this case, it will either be…

[lua]

self.myName

–OR–

event.other.myName

[/lua]

…depending on which object you want to detect is equal to “box”.

Brent