Collision Detection with Ceramic Tile Engine & Box 2D

隐身守侯 提交于 2019-12-08 05:19:14

问题


Follow up of this question, Storyboard with Ceramic Tile Engine, and with Collision Detection is still a mystery. Here is the code:

-- hide status bar
display.setStatusBar(display.HiddenStatusBar)
local storyboard = require("storyboard")
--Set up the physics world
local physics = require("physics")
physics.start()
physics.setGravity(0, 0)
physics.setDrawMode('hybrid')
local scene = storyboard.newScene()
local widget = require("widget")

-- Add Hero to Physics
local hero = display.newImage("images/man.png")
hero.x = 40
hero.y = 80
local heroCollisionFilter = { categoryBits = 4, maskBits = 2 }
local heroBody = { filter=heroCollisionFilter, isSensor=true }
physics.addBody(hero, "dynamic", heroBody)

function scene:createScene( event )
    local group = self.view
    local ceramic = require("Ceramic")
    ceramic.showPrints = false
    local map = ceramic.buildMap("maps/map.lua")
    -- collisionLayer = map.layer['Collision']
    -- collisionLayer.ccName = "map"
    -- physics.addBody(collisionLayer, "static", { friction=0.5, bounce=0.3 } )
    map.y = 0
    map.setCameraDamping(10)
    map.layer['World']:insert(hero)
end

function onGlobalCollision(event)
    if(event.phase == "began") then
        print( "Global report: " .. event.object1.ccName .. " & " .. event.object2.ccName .. " collision began" )
    elseif(event.phase == "ended") then
        print( "Global report: " .. event.object1.ccName .. " & " .. event.object2.ccName .. " collision ended" )
    end
    print( "**** " .. event.element1 .. " -- " .. event.element2 )
end

Runtime:addEventListener("collision", onGlobalCollision)
scene:addEventListener( "createScene", scene )

return scene

And the screenshot looks like:

However, collision never triggers, as the print message does not appear in Terminal at all.

I'm using:

  • Corona SDK
  • Ceramic Tile Engine
  • Corona module: storyboard, physics

How can I enable Collision Detection ? Are the parameters correct ?


Edit 2013/10/27

The Tiled map settings are as follow:

When running in Mac OS X, the collision does not happen ( only the hybrid layer changes color ).

When running in Windows 7, the code crashes on this line:

ceramic.buildMap("maps/map.lua")

with error:

attempt to call global 'reversePolygon' (a nil value) in Ceramic.lua: 617

After I comment out the following lines, the error is gone:

collisionLayer = map.layer['Collision']
collisionLayer.ccName = "map"
physics.addBody(collisionLayer, "static", { friction=0.5, bounce=0.3 } )

but the collision function does not get called.


回答1:


Box2D collision detection is specified through the properties of a layer, tile, or object in an object layer. Ceramic adds physics automatically if the physics:enabled property is set to true.

Physics parameters are also set within properties. This:

physics.addBody(myObject, {friction = 0.5, bounce = 0.1})

Would correspond, in Tiled's properties, to this:

physics:friction              = 0.5
physics:bounce                = 0.1



回答2:


For future people who are stuck in Collision Detection in Corona SDK with Tiled and Ceramic Tile Engine

In further testing, I found out that the issue of collision event not firing is I used a wrong set of collision events. The working collision events are :

local function onLocalCollision(self, event)
    print("collision")
    if event.phase == "began" then
        print("Collision began")
    elseif event.phase == "ended" then
        print("Collision ended")
    end
end

function onGlobalCollision(event)
    if(event.phase == "began") then
        print( "Global report: " .. event.object1.ccName .. " & " .. event.object2.ccName .. " collision began" )
    elseif(event.phase == "ended") then
        print( "Global report: " .. event.object1.ccName .. " & " .. event.object2.ccName .. " collision ended" )
    end
    print( "**** " .. event.element1 .. " -- " .. event.element2 )
end

function onPostCollision(event)
    print("postCollision")
end

-- Local Collision
hero.collision = onLocalCollision
hero:addEventListener("collision", hero)
-- Global Collision
Runtime:addEventListener("collision", onGlobalCollision)
Runtime:addEventListener("postCollision", onPostCollision)

and each collision object has to have a name ( the property name ccName , you can pick any name you want , but it has to be set in Tiled's object list ).

Also, I removed the categoryBits and maskBits, seems they make the collision detection invalid.

Points to note:

  • Collision layer does not have to add to scene by programming ( it will be added automatically )
  • Only 1 set of collision detection methods ( Local / Global ) is needed ( but 2 sets can be run in parallel )
  • Turn off hybrid display mode when not needed, for better performance
  • It doesn't matter what the Layer format is ( Base64 / CSV works fine )
  • Remember to add physics:enabled in Collision Layer properties ( physics:friction and physics:bounce are optional , as per @CalebP's comment )


来源:https://stackoverflow.com/questions/19511038/collision-detection-with-ceramic-tile-engine-box-2d

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!