物理シミュレーション基本（Cocos Code IDE, Lua言語）


Cocos Code IDEを使ってLua言語で、物理シミュレーションを扱うサンプルです。

|実行環境、IDE|Cocos2d-xバージョン|言語|
|:--|:--|:--|
|Cocos Code IDE Mac OS X 1.0.0-RC2|Cocos2d-x V3.2|Lua言語|

## サンプルコード

プロジェクトを新規作成で作成します。（FileメニューのNew->Cocos Lua Project...から作成できます。）
プロジェクト名は適当につけてください。画面は縦画面(portrait)を指定します。

main.luaファイルを修正します。

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

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

GameScene.luaを書き換えます。

```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 function onTouchBegan(touch, event)
        local location = touch:getLocation()
        
        -- スプライトを作る
        local sprite = cc.Sprite:create("box.png")
        sprite:setPosition(location)
        scene:addChild(sprite)

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

    -- タッチイベントの登録
    local listener = cc.EventListenerTouchOneByOne:create()
    listener:registerScriptHandler(onTouchBegan, cc.Handler.EVENT_TOUCH_BEGAN )
    local eventDispatcher = scene:getEventDispatcher()
    eventDispatcher:addEventListenerWithSceneGraphPriority(listener, scene)
    
    return scene
end

return GameScene
```

四角い画像をbox.pngの名前で作成し、resディレクトリに追加します。

![box.png](https://qiita-image-store.s3.amazonaws.com/0/45447/d88bf0ab-373e-748d-d3cc-324c2a7101c2.png "box.png")box.png

実行して画面をタッチすると、タッチした場所に四角いスプライトが作成され、落下していきます。

![ss.png](https://qiita-image-store.s3.amazonaws.com/0/45447/83167fa6-cb07-9d03-26c9-8ebc91521e30.png "ss.png")

## 解説

### 準備：シーンを物理シミュレーション用に作成

createWithPhysicsメソッドでシーンを作成します。

```lua:
local scene = cc.Scene:createWithPhysics()
```

### デバッグ表示（任意）

```lua:
scene:getPhysicsWorld():setDebugDrawMask(cc.PhysicsWorld.DEBUGDRAW_ALL)
```
設定すると物体の形が表示されます。デバッグ時には表示しておくと設定されている物体の形がわかりやすいです。


### 画面サイズと同じ枠を作る（任意）

必要に応じて、画面サイズと同じ枠を作って、画面から物体が出ないようにします。
もし、下に遮蔽物が無いと物体は永遠に落下し続けます。

```lua:
-- 画面と同じサイズのノードを作ります
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)  
```

### スプライトを作り、物体を割り当てる

スプライトを作り、その形を物体としてスプライトに設定します。

```lua:
-- スプライトを作る
local sprite = cc.Sprite:create("box.png")
sprite:setPosition(location)
scene:addChild(sprite)

-- 同型の物体を割り当てる
local physicsBody = cc.PhysicsBody:createBox(sprite:getContentSize())
sprite:setPhysicsBody(physicsBody)
```
円形の場合はcreateBoxの代わりにcreateCircle(半径)を使います。

### 物体を固定物にする

`body:setDynamic(false)`のように物体に対してsetDynamicを使います。他の物体との衝突や、重力の影響を受けなくなります。


### 無重力にしたり、重力を設定する方法

```lua:
scene:getPhysicsWorld():setGravity(cc.p(0, 0)) -- 無重力
```
初期状態は(0, -98)で、物体は下へ落下します。
右側へ落下したり(98, 0)、上へ落下させたり(0, 98)することもできます。
落下速度を早めるには、数字を大きくします。

### 物体を重力の影響を受けないようにする

PhysicsBody:setGravityEnable(false)を使います。

## 物体の衝突時に関数を呼び出す

<del>長くなりそうなので、別記事で投稿予定です。</del>
こちらに投稿しました。
[物理シミュレーションで物体の衝突時の処理（Cocos Code IDE, Lua言語）](http://qiita.com/senchan05/items/cb04f3354a1a6510caec)

---
修正事項：PhysicsBodyの訳を物理体から物体に変更しています。ただ、PhysicsBodyは物体の形状や材質、その他重力の影響の有無など物理エンジン上での振る舞いを記述するもので、単なる物体の以上の意味を持っています。Cocos2dでは剛体(rigid body,変形しない物体)だけを扱うので剛体でもいいのでしょうが物体の方がわかりやすいかなと思っています。