물리 시뮬레이션으로 물체 충돌시 처리(Cocos Code IDE, Lua 언어)

18752 단어 cocos2d-x루아
Cocos Code IDE를 사용하여 Lua 언어로 물리 시뮬레이션의 물체 충돌 처리 샘플입니다.


실행 환경, IDE
Cocos2d-x 버전
언어


Cocos Code IDE Mac OS X 1.0.0-RC2
Cocos2d-x V3.2
Lua 언어


Code IDE와 Lua에서의 물리 시뮬레이션의 기본은 여기에 게시했습니다. 참고하십시오.
물리 시뮬레이션 기본(Cocos Code IDE, Lua 언어)

샘플 코드



프로젝트를 새로 생성합니다. (File 메뉴의 New->Cocos Lua Project...에서 만들 수 있습니다.)
프로젝트명은 적당히 붙여 주세요. 화면은 세로 화면(portrait)을 지정합니다.

main.lua 파일을 수정합니다.

main.lua/26행
cc.Director:getInstance():getOpenGLView():setDesignResolutionSize(320, 480, 0) -- 縦画面用に(480, 320, 0)から(320, 480, 0)に変更

main.lua/31행
--gameScene:playBgMusic() --使わないのでコメントアウト

GameScene.lua를 다시 씁니다.

GameScene.lua
require "Cocos2d"
require "Cocos2dConstants"

local GameScene = class("GameScene",function()
    return cc.Scene:createWithPhysics()
end)

function GameScene.create()
    local scene = GameScene.new()

    scene:getPhysicsWorld():setDebugDrawMask(cc.PhysicsWorld.DEBUGDRAW_ALL) -- デバッグ表示用(任意)

    local visibleSize = cc.Director:getInstance():getVisibleSize()

    -- 画面と同じサイズの枠を作ります
    local node = cc.Node:create()
    node:setAnchorPoint(0.5, 0.5) -- アンカーポイントを設定しないとwarningが出る
    node:setPosition(visibleSize.width/2, visibleSize.height/2)
    scene:addChild(node)

    -- 物体を作成し、四角いエッジの形を割り当てます
    local body = cc.PhysicsBody:create()
    local rectangle = cc.PhysicsShapeEdgeBox:create(cc.size(visibleSize.width, visibleSize.height))
    body:addShape(rectangle)
    body:setDynamic(false) 
    node:setPhysicsBody(body)  

    -- スプライトを作る
    local sprite1 = cc.Sprite:create("box.png")
    sprite1:setPosition(100, 400)
    scene:addChild(sprite1)

    -- 同型の物体を割り当てる
    local physicsBody1 = cc.PhysicsBody:createBox(sprite1:getContentSize())
    sprite1:setPhysicsBody(physicsBody1)

    -- スプライトを作る
    local sprite2 = cc.Sprite:create("circle.png")
    sprite2:setPosition(80, 300)
    scene:addChild(sprite2)

    -- 同型の物体を割り当てる
    local physicsBody2 = cc.PhysicsBody:createCircle(sprite2:getContentSize().width/2)
    sprite2:setPhysicsBody(physicsBody2)

    -- カテゴリービットマスクと衝突判定ビットマスクを設定します
    physicsBody1:setCategoryBitmask(1)    -- 00000001
    physicsBody1:setContactTestBitmask(2) -- 00000010
    physicsBody2:setCategoryBitmask(2)    -- 00000010
    physicsBody2:setContactTestBitmask(1) -- 00000001

    -- 衝突時に呼ばれる関数
    local function onContactBegin(contact)
        local a = contact:getShapeA():getBody()
        local b = contact:getShapeB():getBody()

        print("衝突しました")

        return true
    end

    -- 衝突時のイベントで指定した関数を呼び出すようにする
    local contactListener = cc.EventListenerPhysicsContact:create()
    contactListener:registerScriptHandler(onContactBegin, cc.Handler.EVENT_PHYSICS_CONTACT_BEGIN)
    local eventDispatcher = scene:getEventDispatcher()
    eventDispatcher:addEventListenerWithSceneGraphPriority(contactListener, scene)

    return scene
end

return GameScene


사각형 이미지를 box.png, 둥근 이미지를 circle.png 이름으로 만들고 res 디렉토리에 추가합니다.
box.png
circle.png

실행하면 객체 충돌 시 onContactBegin 함수가 호출됩니다.


물체 충돌 시 함수 호출



충돌 판정을 실시하기 위해서는, 어느 물체와 충돌 판정을 실시할지를 설정해 둘 필요가 있습니다.

우선 PysicsBody:setCategoryBitmask(int)로 물체의 카테고리를 설정합니다.
다음으로 PysicsBody:setContactTestBitmask(int)로 충돌하는 대상이 되는 상대의 카테고리를 설정합니다. setContactTestBitmask는 2개의 물체로 서로 설정하지 않으면 충돌 판정되지 않습니다.

비트 마스크이므로 비트 연산하여 ContactTestBitmask에 포함된 카테고리가 충돌 대상이 됩니다.
예를 들어 ContactTestBitmask가 0011이면 CategoryBitmask가 0001 또는 0010의 물체와 충돌 판정됩니다.
-- カテゴリービットマスクと衝突判定ビットマスクを設定します
physicsBody1:setCategoryBitmask(1)    -- 00000001
physicsBody1:setContactTestBitmask(2) -- 00000010
physicsBody2:setCategoryBitmask(2)    -- 00000010
physicsBody2:setContactTestBitmask(1) -- 00000001

-- 衝突時に呼ばれる関数
local function onContactBegin(contact)
    local a = contact:getShapeA():getBody()
    local b = contact:getShapeB():getBody()

    print("衝突しました")

    return true
end

-- 衝突時のイベントで指定した関数を呼び出すようにする
local contactListener = cc.EventListenerPhysicsContact:create()
contactListener:registerScriptHandler(onContactBegin, cc.Handler.EVENT_PHYSICS_CONTACT_BEGIN)
local eventDispatcher = scene:getEventDispatcher()
eventDispatcher:addEventListenerWithSceneGraphPriority(contactListener, scene)

잘 함수가 호출되지 않을 때



충돌시에 함수가 불려 가지 않을 때는, setCategoryBitmask나 setContactTestBitmask가 잘못되어 있는 것이 많기 때문에 확인해 주세요.

호출된 함수 내에서 처리



onContactBegin 함수 내에서 객체를 처리하지만 두 객체 모두 a와 b
에 들어갈지는 모르기 때문에 함수 내에서 판단하고 처리를 할 필요가 있습니다.

객체의 CategoryBitmask를 얻으려면a:getCategoryBitmask()
노드를 얻으려면a:getNode()처럼 얻을 수 있습니다.

보충



여기의 예에서는 사용하고 있지 않습니다만, 특정의 2개의 물체의 충돌 판정을 실시할 수가 있습니다.

특정 두 객체의 충돌 시 함수 호출



특정 2개의 물체의 충돌시에 함수를 호출하려면 cc.EventListenerPhysicsContactWithBodies를 사용합니다.

다시 CategoryBitmask, ContactTestBitmask를 설정해야 합니다.
local contactListener = cc.EventListenerPhysicsContactWithBodies:create(sprite1:getPhysicsBody(), sprite2:getPhysicsBody())
contactListener:registerScriptHandler(onContactBegin, cc.Handler.EVENT_PHYSICS_CONTACT_BEGIN)
local eventDispatcher = scene:getEventDispatcher()
eventDispatcher:addEventListenerWithSceneGraphPriority(contactListener, scene)

물체의 충돌 설정(특정 물체와 충돌하지 않도록 함)



이것도 여기의 예에서는 사용하고 있지 않습니다만, 물체끼리가 부딪히는지 어떤지를 설정할 수가 있습니다.

초기 상태에서는 모든 물체끼리의 충돌이 일어나게 되어 있으므로, 물체끼리가 부딪치면 튀어 돌아옵니다.

특정 물체와만 충돌을 제어하려면,

우선 PysicsBody:setCategoryBitmask(int)로 물체의 카테고리를 설정합니다.
다음으로 PysicsBody:setCollisionBitmask(int)로 충돌하는 대상이 되는 상대의 카테고리를 설정합니다.

비트 마스크이므로 비트 연산하여 CollisionBitmask에 포함된 카테고리가 충돌 대상이 됩니다.

다만, 여기에서 충돌하지 않도록 설정해도 ContactTestBitmask의 설정과는 관계가 없기 때문에, 물체가 빠져도 ContactTestBitmask에 의한 충돌 판정은 따로 행해집니다.

좋은 웹페이지 즐겨찾기