漆 Cocos2d-xで物理エンジンを使う 接触したら”何か”したい
目次
1 はじめに
2 物体の接触設定と処理
2.1 物体の分類を設定する
2.2 物体の接触対象を設定する
2.3 接触時に呼び出される関数を記述し登録する
3 今後の予定
はじめに
本記事は、cocos2d-xおよびCocos Code IDEを導入し、絵(スプライト)を表示し、タッチに反応して絵を動かし、BGMや効果音を鳴らし、物理エンジンchipmunkを使って物体を落下させた人で、特定の物体が接触した時に何かしたい人向けの、覚書です。まず、接触時に物体を特定するための情報を設定し、実際に接触させ、設定した情報を元に、物体を移動する例を使って説明します。
物体の接触設定と処理
下のコードを使って説明します。実行すると、画面上から物体が落下し、地面に触れると上にまた上から落ち始めます。
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でのビルドおよび実行について説明します。
Author And Source
この問題について(漆 Cocos2d-xで物理エンジンを使う 接触したら”何か”したい), 我々は、より多くの情報をここで見つけました https://qiita.com/CasualGameDev/items/33304d107755ff2983d3著者帰属:元の著者の情報は、元のURLに含まれています。著作権は原作者に属する。
Content is automatically searched and collected through network algorithms . If there is a violation . Please contact us . We will adjust (correct author information ,or delete content ) as soon as possible .