2
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

漆 Cocos2d-xで物理エンジンを使う 接触したら”何か”したい

Last updated at Posted at 2015-08-27

目次

1 はじめに
2 物体の接触設定と処理
2.1 物体の分類を設定する
2.2 物体の接触対象を設定する
2.3 接触時に呼び出される関数を記述し登録する
3 今後の予定

はじめに

本記事は、cocos2d-xおよびCocos Code IDEを導入し、絵(スプライト)を表示し、タッチに反応して絵を動かし、BGMや効果音を鳴らし、物理エンジンchipmunkを使って物体を落下させた人で、特定の物体が接触した時に何かしたい人向けの、覚書です。まず、接触時に物体を特定するための情報を設定し、実際に接触させ、設定した情報を元に、物体を移動する例を使って説明します。

物体の接触設定と処理

下のコードを使って説明します。実行すると、画面上から物体が落下し、地面に触れると上にまた上から落ち始めます。

7 repeat fall.png

GameScene.lua
local WALL  = 0x01
local BALL  = 0x02 

local GameScene = class("GameScene",function()
    -- l)物理エンジンをこの場面に対し有効化
    return cc.Scene:createWithPhysics()
end)

function GameScene.create()
    local scene = GameScene.new()
    scene:addChild(scene:createLayer())

    return scene
end


function GameScene:ctor()
    self.visibleSize = cc.Director:getInstance():getVisibleSize()
    self.origin = cc.Director:getInstance():getVisibleOrigin()
    self.schedulerID = nil
end

function GameScene:playBgMusic()
    -- BGMを再生する
    local bgMusicPath = cc.FileUtils:getInstance():fullPathForFilename("background.mp3") 
    cc.SimpleAudioEngine:getInstance():playMusic(bgMusicPath, true)
    -- 効果音を先に読み込んでおく
    local effectPath = cc.FileUtils:getInstance():fullPathForFilename("effect1.wav")
    cc.SimpleAudioEngine:getInstance():preloadEffect(effectPath)
end

-- create layer
function GameScene:createLayer()
    local layer = cc.Layer:create()

    -- n)ゲーム画面の中央を基点とする接続点を作る
    local node = cc.Node:create()
    node:setAnchorPoint(0.5, 0.5)
    node:setPosition(self.visibleSize.width/2, 0)
    -- l)その接続点(但し位置は画面下端)に四角の壁をつける
    local bodyWall = cc.PhysicsBody:createEdgeBox(cc.size(self.visibleSize.width, 10))
    bodyWall:setDynamic(false) 
    node:setPhysicsBody(bodyWall)
    layer:addChild(node)
    
    -- 落下物(スプライト)を追加し物体を取り付ける
    local sprite = cc.Sprite:create("land.png")
    sprite:setPosition(270,900)
    layer:addChild(sprite)
    local bodyBall = cc.PhysicsBody:createBox(sprite:getContentSize())
    sprite:setPhysicsBody(bodyBall)

    -- o)壁と落下物それぞれの分類と接触対象を設定
    bodyWall:setCategoryBitmask(WALL)
    bodyWall:setContactTestBitmask(BALL)
    bodyBall:setCategoryBitmask(BALL)
    bodyBall:setContactTestBitmask(WALL)

    -- p)接触時に呼ばれる関数
    local function onContactBegin(contact)
        local a = contact:getShapeA():getBody()
        local b = contact:getShapeB():getBody()
        
        -- q)接触した物体aとbのどちらかがボールなら、そのスプライト部を取得して、
        if a:getCategoryBitmask()== BALL then
            ball = a:getNode()
        elseif b:getCategoryBitmask()== BALL then
            ball = b:getNode()
        end
        
        -- 上に戻す
        if ball ~= nil then
            local jump = cc.JumpTo:create(1,cc.p(270,800),30,5) 
            ball:runAction(jump)
        end

        return true -- trueを返すこと
    end

    -- r)接触時に呼び出す関数を登録し、このレイヤーでの接触イベント取得を有効にする
    local contactListener = cc.EventListenerPhysicsContact:create()
    contactListener:registerScriptHandler(onContactBegin, cc.Handler.EVENT_PHYSICS_CONTACT_BEGIN)
    local eventDispatcher = layer:getEventDispatcher()
    eventDispatcher:addEventListenerWithSceneGraphPriority(contactListener, layer)

    return layer
end

return GameScene

重要な点のみ順番に説明します。

o)で、下壁と落下物それぞれの分類および接触対象を設定します。
例えば、ある物体Aが物体Bと接触したときにイベントが発生するようにしたいときは
物体Aの分類は1で、物体Aの接触対象は2(物体Bの分類)、
物体Bの分類は2で、物体Bの接触対象は1(物体Aの分類)、
という風に設定します。お互いの分類が接触対象に設定されていると、接触イベントが発生します。これが設定されていないと、接触イベントが発行されません。また、分類番号はビット列(1,2,4,..)で分けます。
p)が接触イベントが発生時に呼び出される関数です。
q)で、a = contact:getShapeA():getBody()は接触した物体を取得する命令です。これに対しさらにgetNode()することで、その物体が取り付けられている絵の部分を取得できます。ここで、a、bどちらに落下物の情報が入るかは分からないため、両方を調べる必要があります。
r)で、p)の関数を接触イベント開始時に呼び出す関数として登録し、このレイヤーに対する接触イベントの取得を有効化しています。

物理エンジンの重力計算にまかせて落下させ、落下物が壁に触れた瞬間、今度はジャンプアクションで開始点まで戻すようになっています。

今後の予定

次回は、Cocos Code IDEを使ったAndroid、iPhone端末でのデバッグ実行と、Cocos Code IDEから生成されたプロジェクトファイルのEclipse、xCodeでのビルドおよび実行について説明します。

2
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?