Collision detector for stacking sandwich game

To Whom it May Concern,

I’m new to corona SDK and I’ve ran into a problem with my game I’m building. The point of the game is to stack parts of a hamburger until you complete it. Some parts are bad and are to be avoid by dragging the bottom bun left and right. I run into a problem upon collision. When an item is caught on the bottom bun, it’s supposed to move (left or right) with the bottom bun that has a touch listener on it. Because I created a function that spawns different parts of the burger to fall down, my physics.newJoint() function isn’t working, maybe I’m calling it in the wrong place. Instead it says "ERROR: main.lua:10: physics.newJoint() cannot be called when the world is locked and in the middle of number crunching, such as during a collision event"

Here is a script of my code 

local physics = require “physics”

physics.start()

physics.setDrawMode( “hybrid” )

physics.setGravity( 0.0, 1.0 )

– Calling Objects

objects = {“topbun”, “tomato”, “cheese”, “patty”};

function weldTogether(boo, you)

  physics.newJoint(“welded”, boo, you, boo.x, boo.y)

  

end

–Spawns New Objects

function spawnObject( )

  objIdx = math.random(#objects)

  objName = objects[objIdx]

  object = display.newImageRect(“images/” … objName … “.png”, 200, 50)

  object.x = math.random(30,300)

  object.y = screenTop

  

  if objIdx == 1 then

      object.id = “topbun”

     

  elseif  objIdx == 2 then

      object.id = “tomato”

   

  elseif  objIdx == 3 then

      object.id = “cheese”

      

  else

    object.id = “patty”

  end

  

  object_image_outline = graphics.newOutline( 14, “images/cheese.png”, “/” )

  physics.addBody(object, “dynamic”, {density = 2, friction = 40, bounce = 0})

  

–Collision Listener for Objects that drop onto bottom bun

function objectCollision(self, event )

  if event.phase == “began” then

    if event.target.id == “topbun” and event.other.id == “bottomBun” then 

      

      print(“You finished”)

      print(event.target.id)

    elseif event.target.id == “topbun” and event.other.id == “tomato” then 

      print(“You finished”)

      print(event.target.id)

    elseif event.target.id == “topbun” and event.other.id == “patty” then 

      print(“You finished”)

      print(event.target.id)

    elseif event.target.id == “topbun” and event.other.id == “cheese” then 

      print(“You finished”)

      print(event.target.id) 

      

    elseif event.target.id == “patty” and event.other.id == “bottomBun” then

      print(“One Patty”)

     print(event.target.id)

    elseif event.target.id == “patty” and event.other.id == “patty” then

      print(“Double Patty”)

     print(event.target.id)

    elseif event.target.id == “patty” and event.other.id == “cheese” then

      print(“Patty and cheese”)

     print(event.target.id)

    elseif event.target.id == “patty” and event.other.id == “tomato” then

      print(“Patty and Tomato”)

     print(event.target.id)

    elseif event.target.id == “tomato” and event.other.id == “tomato” then

      print(“Double Tomato”)

     print(event.target.id)

    elseif event.target.id == “tomato” and event.other.id == “bottomBun” then

      print(“You must be hungry”)

     print(event.target.id)

    elseif event.target.id == “tomato” and event.other.id == “patty” then

      print(“Patty and Tomato”)

     print(event.target.id)

    elseif event.target.id == “tomato” and event.other.id == “cheese” then

      print(“Cheese and Tomato”)

     print(event.target.id)

    elseif event.target.id == “cheese” and event.other.id == “cheese” then

      print(“Double Cheese”)

     print(event.target.id)

    elseif event.target.id == “cheese” and event.other.id == “patty” then

      print(“Cheese and Patty”)

     print(event.target.id)

    elseif event.target.id == “cheese” and event.other.id == “tomato” then

      print(“Cheese and tomato”)

     print(event.target.id)

    elseif event.target.id == “cheese” and event.other.id == “bottomBun” then

      print(“Just Cheese”)

     print(event.target.id)

     

     

        end

  end

   

end

object.collision = objectCollision

object:addEventListener( “collision”, object )

end

– New Snippet

Obj71 = timer.performWithDelay( 7000, spawnObject, 6 )

– fn to handle collisions on Obj75

https://docs.coronalabs.com/api/event/collision/index.html

– note: this fn must be positioned in the stack above Obj75

–DISREGARD THIS

function Obj75CollisionHandler( event )

  – Obj110: default collision support

  – information about the collision:

  if event.phase == “began” then

    if event.other ~= nil then

      if event.other.name ~= nil then

        print("Obj75 colliding with "…event.other.name )

      elseif event.other.id ~= nil then

        print("Obj75 colliding with "…event.other.id ) 

       end

    end

  end

end

– fn to handle collisions on Obj101

https://docs.coronalabs.com/api/event/collision/index.html

– note: this fn must be positioned in the stack above Obj101

function bottomBunTouch( event, params)

 local body = event.target

local phase = event.phase

local stage = display.getCurrentStage()

if “began” == phase then

  stage:setFocus( body, event.id )

  body.isFocus = true

  buny = body.y

  body.x0 = event.x - body.x

  body.y0 = event.y - body.y

  print(“welding obj1 and obj3”)

  if joint == nil then

    if (object.x >= .9*bottomBun.x 

     and object.x <= 1.1*bottomBun.x

     and object.y > 408

     and object.y < 412

    ) then 

      joint=timer.performWithDelay( 700, weldTogether(bottomBun,object), 1 )

    end

  end

  – Create a temporary touch joint and store it in the object for later reference

  body.tempJoint = physics.newJoint( “touch”, body, body.x, body.y )

elseif body.isFocus then

  if “moved” == phase then

    body.x = event.x - body.x0

    body.y = event.y - body.y0

    – Update the joint to track the touch

    body.tempJoint:setTarget( event.x, body.y )

  elseif “ended” == phase or “cancelled” == phase then

   

    stage:setFocus( body, nil )

    body.isFocus = false

   

    – Remove the joint when the touch ends   

    body.tempJoint:removeSelf()

   

  end

  body.y = buny

end

– Stop further propagation of touch event

return true

  – touch has been handled (optional final statement):

  – return true

end

– image “images/bottombun.png”

bottomBun = display.newImageRect( “images/bottombun.png”, 200, 50 )

bottomBun.x = 300

bottomBun.y = 900

bottomBun.id = “bottomBun”

bottomBun.type = “bottomBun”

bottomBun.collision = bottomBunCollision

bottomBun:addEventListener(“touch”, bottomBunTouch)

physics.addBody( bottomBun, “static”, { bounce = 0, friction = 6, density = 1.0, outline = bottomBun_image_outline })

burgerComplete = display.newGroup()

burgerComplete:insert(bottomBun)

burgerComplete.avgX= bottomBun.x

burgerComplete.avgY=bottomBun.y

burgerComplete.id = “burgerComplete”

Generally speaking, when you get that error message, you’re in the middle of some other event like a collision and you’re trying to change the physics world. The typical solution is to do what ever activity you are trying to do, in this case, creating a new joint, by wrapping it in a brief timer:

function weldTogether(boo, you) timer.performWithDelay(10, function() physics.newJoint("welded", boo, you, boo.x, boo.y) end) end

or something like that.

Rob

Thanks, it doesn’t give me an error anymore, instead the item that collides with the bottom bun welds, then becomes stationary in space. It’s not until another object collides with it that it stacks on top of the bottom bun. The hybrid box color goes from yellow to clear until something else collides with it. I’d like the hybrid color to stay yellow throughout. Again, here is my code along with the zip file. 

local physics = require “physics”

physics.start()

physics.setDrawMode( “hybrid” )

physics.setGravity( 0.0, 1.0 )

– Calling Objects

objects = {“topbun”, “tomato”, “cheese”, “patty”};

function weldTogether(boo, you)

  timer.performWithDelay(10, function()

    physics.newJoint(“weld”, boo, you, boo.x, boo.y)

  end)

end

function spawnObject( )

  objIdx = math.random(#objects)

  objName = objects[objIdx]

  object = display.newImageRect(“images/” … objName … “.png”, 200, 50)

  object.x = math.random(30,300)

  object.y = screenTop

  

  if objIdx == 1 then

      object.id = “topbun”

     

  elseif  objIdx == 2 then

      object.id = “tomato”

   

  elseif  objIdx == 3 then

      object.id = “cheese”

      

  else

    object.id = “patty”

  end

  

  object_image_outline = graphics.newOutline( 14, “images/cheese.png”, “/” )

  physics.addBody(object, “dynamic”, {density = 2, friction = 40, bounce = 0})

  

  function objectCollision(self, event )

  if event.phase == “began” then

    if event.target.id == “topbun” and event.other.id == “bottomBun” then 

      weldTogether(event.target, event.other)

      print(“You finished”)

      print(event.target.id)

    elseif event.target.id == “topbun” and event.other.id == “tomato” then 

     weldTogether(event.target, event.other)

     print(“You finished”)

      print(event.target.id)

    elseif event.target.id == “topbun” and event.other.id == “patty” then 

      print(“You finished”)

      print(event.target.id)

    elseif event.target.id == “topbun” and event.other.id == “cheese” then 

      print(“You finished”)

      print(event.target.id) 

      

    elseif event.target.id == “patty” and event.other.id == “bottomBun” then

      weldTogether(event.target, event.other)

      print(“One Patty”)

     print(event.target.id)

    elseif event.target.id == “patty” and event.other.id == “patty” then

      print(“Double Patty”)

     print(event.target.id)

    elseif event.target.id == “patty” and event.other.id == “cheese” then

      print(“Patty and cheese”)

     print(event.target.id)

    elseif event.target.id == “patty” and event.other.id == “tomato” then

      print(“Patty and Tomato”)

     print(event.target.id)

    elseif event.target.id == “tomato” and event.other.id == “tomato” then

      print(“Double Tomato”)

     print(event.target.id)

    elseif event.target.id == “tomato” and event.other.id == “bottomBun” then

      weldTogether(event.target, event.other)

      print(“You must be hungry”)

     print(event.target.id)

    elseif event.target.id == “tomato” and event.other.id == “patty” then

      print(“Patty and Tomato”)

     print(event.target.id)

    elseif event.target.id == “tomato” and event.other.id == “cheese” then

      print(“Cheese and Tomato”)

     print(event.target.id)

    elseif event.target.id == “cheese” and event.other.id == “cheese” then

      print(“Double Cheese”)

     print(event.target.id)

    elseif event.target.id == “cheese” and event.other.id == “patty” then

      print(“Cheese and Patty”)

     print(event.target.id)

    elseif event.target.id == “cheese” and event.other.id == “tomato” then

      print(“Cheese and tomato”)

     print(event.target.id)

    elseif event.target.id == “cheese” and event.other.id == “bottomBun” then

      weldTogether(event.target, event.other)

      print(“Just Cheese”)

     print(event.target.id)

     

     

        end

  end

   

end

object.collision = objectCollision

object:addEventListener( “collision”, object )

end

– New Snippet

Obj71 = timer.performWithDelay( 7000, spawnObject, 6 )

– fn to handle collisions on Obj75

https://docs.coronalabs.com/api/event/collision/index.html

– note: this fn must be positioned in the stack above Obj75

function Obj75CollisionHandler( event )

  – Obj110: default collision support

  – information about the collision:

  if event.phase == “began” then

    if event.other ~= nil then

      if event.other.name ~= nil then

        print("Obj75 colliding with "…event.other.name )

      elseif event.other.id ~= nil then

        print("Obj75 colliding with "…event.other.id ) 

       end

    end

  end

end

– fn to handle collisions on Obj101

https://docs.coronalabs.com/api/event/collision/index.html

– note: this fn must be positioned in the stack above Obj101

function bottomBunTouch( event)

  – Obj5: default touch/drag support

  – smart drag for Obj3:

  t = event.target

  

  if event.phase == “began” then

  

    if t.id ~= nil then print("started dragging "…t.id); end

    if t.name ~= nil then print("started dragging "…t.name); end

    display.getCurrentStage():setFocus( t )

    t.isFocus = true

  

    – drag starts at:

    t.x0 = event.x - t.x

  

  

  elseif t.isFocus then

  

    if event.phase == “moved” then

  

      t.x = event.x - t.x0

  

  

    elseif event.phase == “ended” or event.phase == “cancelled” then

  

      display.getCurrentStage():setFocus( nil )

      t.isFocus = false

  

    if t.id ~= nil then print("stopped dragging "…t.id); end

    if t.name ~= nil then print("stopped dragging "…t.name); end

    end

  

  end

  

  – touch has been handled (optional final statement):

  – return true

end

– image “images/bottombun.png”

bottomBun = display.newImageRect( “images/bottombun.png”, 200, 50 )

bottomBun.x = 300

bottomBun.y = 900

bottomBun.id = “bottomBun”

bottomBun.type = “bottomBun”

bottomBun.collision = bottomBunCollision

bottomBun:addEventListener(“touch”, bottomBunTouch)

physics.addBody( bottomBun, “static”, { bounce = 0, friction = 6, density = 1.0, outline = bottomBun_image_outline })

burgerComplete = display.newGroup()

burgerComplete:insert(bottomBun)

burgerComplete.avgX= bottomBun.x

burgerComplete.avgY=bottomBun.y

burgerComplete.id = “burgerComplete”

Generally speaking, when you get that error message, you’re in the middle of some other event like a collision and you’re trying to change the physics world. The typical solution is to do what ever activity you are trying to do, in this case, creating a new joint, by wrapping it in a brief timer:

function weldTogether(boo, you) timer.performWithDelay(10, function() physics.newJoint("welded", boo, you, boo.x, boo.y) end) end

or something like that.

Rob

Thanks, it doesn’t give me an error anymore, instead the item that collides with the bottom bun welds, then becomes stationary in space. It’s not until another object collides with it that it stacks on top of the bottom bun. The hybrid box color goes from yellow to clear until something else collides with it. I’d like the hybrid color to stay yellow throughout. Again, here is my code along with the zip file. 

local physics = require “physics”

physics.start()

physics.setDrawMode( “hybrid” )

physics.setGravity( 0.0, 1.0 )

– Calling Objects

objects = {“topbun”, “tomato”, “cheese”, “patty”};

function weldTogether(boo, you)

  timer.performWithDelay(10, function()

    physics.newJoint(“weld”, boo, you, boo.x, boo.y)

  end)

end

function spawnObject( )

  objIdx = math.random(#objects)

  objName = objects[objIdx]

  object = display.newImageRect(“images/” … objName … “.png”, 200, 50)

  object.x = math.random(30,300)

  object.y = screenTop

  

  if objIdx == 1 then

      object.id = “topbun”

     

  elseif  objIdx == 2 then

      object.id = “tomato”

   

  elseif  objIdx == 3 then

      object.id = “cheese”

      

  else

    object.id = “patty”

  end

  

  object_image_outline = graphics.newOutline( 14, “images/cheese.png”, “/” )

  physics.addBody(object, “dynamic”, {density = 2, friction = 40, bounce = 0})

  

  function objectCollision(self, event )

  if event.phase == “began” then

    if event.target.id == “topbun” and event.other.id == “bottomBun” then 

      weldTogether(event.target, event.other)

      print(“You finished”)

      print(event.target.id)

    elseif event.target.id == “topbun” and event.other.id == “tomato” then 

     weldTogether(event.target, event.other)

     print(“You finished”)

      print(event.target.id)

    elseif event.target.id == “topbun” and event.other.id == “patty” then 

      print(“You finished”)

      print(event.target.id)

    elseif event.target.id == “topbun” and event.other.id == “cheese” then 

      print(“You finished”)

      print(event.target.id) 

      

    elseif event.target.id == “patty” and event.other.id == “bottomBun” then

      weldTogether(event.target, event.other)

      print(“One Patty”)

     print(event.target.id)

    elseif event.target.id == “patty” and event.other.id == “patty” then

      print(“Double Patty”)

     print(event.target.id)

    elseif event.target.id == “patty” and event.other.id == “cheese” then

      print(“Patty and cheese”)

     print(event.target.id)

    elseif event.target.id == “patty” and event.other.id == “tomato” then

      print(“Patty and Tomato”)

     print(event.target.id)

    elseif event.target.id == “tomato” and event.other.id == “tomato” then

      print(“Double Tomato”)

     print(event.target.id)

    elseif event.target.id == “tomato” and event.other.id == “bottomBun” then

      weldTogether(event.target, event.other)

      print(“You must be hungry”)

     print(event.target.id)

    elseif event.target.id == “tomato” and event.other.id == “patty” then

      print(“Patty and Tomato”)

     print(event.target.id)

    elseif event.target.id == “tomato” and event.other.id == “cheese” then

      print(“Cheese and Tomato”)

     print(event.target.id)

    elseif event.target.id == “cheese” and event.other.id == “cheese” then

      print(“Double Cheese”)

     print(event.target.id)

    elseif event.target.id == “cheese” and event.other.id == “patty” then

      print(“Cheese and Patty”)

     print(event.target.id)

    elseif event.target.id == “cheese” and event.other.id == “tomato” then

      print(“Cheese and tomato”)

     print(event.target.id)

    elseif event.target.id == “cheese” and event.other.id == “bottomBun” then

      weldTogether(event.target, event.other)

      print(“Just Cheese”)

     print(event.target.id)

     

     

        end

  end

   

end

object.collision = objectCollision

object:addEventListener( “collision”, object )

end

– New Snippet

Obj71 = timer.performWithDelay( 7000, spawnObject, 6 )

– fn to handle collisions on Obj75

https://docs.coronalabs.com/api/event/collision/index.html

– note: this fn must be positioned in the stack above Obj75

function Obj75CollisionHandler( event )

  – Obj110: default collision support

  – information about the collision:

  if event.phase == “began” then

    if event.other ~= nil then

      if event.other.name ~= nil then

        print("Obj75 colliding with "…event.other.name )

      elseif event.other.id ~= nil then

        print("Obj75 colliding with "…event.other.id ) 

       end

    end

  end

end

– fn to handle collisions on Obj101

https://docs.coronalabs.com/api/event/collision/index.html

– note: this fn must be positioned in the stack above Obj101

function bottomBunTouch( event)

  – Obj5: default touch/drag support

  – smart drag for Obj3:

  t = event.target

  

  if event.phase == “began” then

  

    if t.id ~= nil then print("started dragging "…t.id); end

    if t.name ~= nil then print("started dragging "…t.name); end

    display.getCurrentStage():setFocus( t )

    t.isFocus = true

  

    – drag starts at:

    t.x0 = event.x - t.x

  

  

  elseif t.isFocus then

  

    if event.phase == “moved” then

  

      t.x = event.x - t.x0

  

  

    elseif event.phase == “ended” or event.phase == “cancelled” then

  

      display.getCurrentStage():setFocus( nil )

      t.isFocus = false

  

    if t.id ~= nil then print("stopped dragging "…t.id); end

    if t.name ~= nil then print("stopped dragging "…t.name); end

    end

  

  end

  

  – touch has been handled (optional final statement):

  – return true

end

– image “images/bottombun.png”

bottomBun = display.newImageRect( “images/bottombun.png”, 200, 50 )

bottomBun.x = 300

bottomBun.y = 900

bottomBun.id = “bottomBun”

bottomBun.type = “bottomBun”

bottomBun.collision = bottomBunCollision

bottomBun:addEventListener(“touch”, bottomBunTouch)

physics.addBody( bottomBun, “static”, { bounce = 0, friction = 6, density = 1.0, outline = bottomBun_image_outline })

burgerComplete = display.newGroup()

burgerComplete:insert(bottomBun)

burgerComplete.avgX= bottomBun.x

burgerComplete.avgY=bottomBun.y

burgerComplete.id = “burgerComplete”