肆 Cocos2d-xで表示した絵を消してキラッとする


#目次
1 はじめに
2 表示した絵を消す
3 絵を消した所をキラッとする
4 今後の予定
　開始時にBGMを鳴らす、絵を消す時に効果音を鳴らす、得点を表示する

#はじめに
本記事は、cocos2d-xおよびCocos Code IDEを導入し、絵(スプライト)を表示し、タッチに反応して絵を動かした人で、今度はタッチした絵を消したい、またそこにキラッとした視覚効果を表示したい人向けの、覚書です。表示した絵を削除するにはアクションを使います。また、キラッとした視覚効果はパーティクルと呼ばれる粒子視覚効果を使って実現します。そこで、まずタッチした絵をゆっくり消し、その後、そこに粒子視覚効果を表示するコードを追加するという順番で説明していきます。

#表示した絵を消す
今回は、タッチされた絵を移動する下記コードを使って説明します。

```GameScene.lua

local GameScene = class("GameScene",function()
    return cc.Scene:create()
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()
    --[[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()

    -- スプライトを追加
    local sprite = cc.Sprite:create("land.png")
    sprite:setPosition(100,100)
    layer:addChild(sprite)

    -- b)タッチイベントで呼ばれる関数
    local function onTouchBegan(touch, event)
        local location = touch:getLocation()
        
        -- e)タッチ点に絵があるか確認
        if cc.rectContainsPoint(sprite:getBoundingBox(), location) then
            -- a)スプライトを移動
            local x = math.random(100,400) -- 100から400の乱数
            local y = math.random(100,600) -- 100から600の乱数
            local move = cc.MoveTo:create(0.3, cc.p(x,y))
            sprite:runAction(move)
        end
        
        return true
    end

    -- c)タッチイベントで呼ばれる関数を登録
    local listener = cc.EventListenerTouchOneByOne:create()
    listener:registerScriptHandler(onTouchBegan, cc.Handler.EVENT_TOUCH_BEGAN )

    -- d)このレイヤーでのタッチイベント取得を有効化
    local eventDispatcher = layer:getEventDispatcher()
    eventDispatcher:addEventListenerWithSceneGraphPriority(listener, layer)
    
    return layer
end

return GameScene
```

a)の部分を下記のように書き換えます。これにより、タッチされた絵は、ゆっくりと見えなくなり最終的に消えます。

```
...
            -- a)スプライトをフェードアウトしてから削除
            local fade = cc.FadeOut:create(1)
            local remove = cc.RemoveSelf:create()
            local sequence = cc.Sequence:create(fade,remove)
            sprite:runAction(sequence)
...
```

`cc.FadeOut:create(1)`は、1秒で見た目をフェードアウトするアクション命令です。
`cc.RemoveSelf:create()`は、スプライト等を削除するアクション命令です。
`cc.Sequence:create(fade,remove)`は、引数のアクションを順番に実行するアクション命令です。
最後の`sprite:runAction(sequence)`で、絵(sprite)に対し、1秒かけて見た目をフェードアウトさせた後、描画対象のレイヤーから削除、というアクション命令を実行することになります。
変更を保存した後実行し、絵をタップすると、ゆっくりと見えなくなって消えます。

![4-4 before fade.png](https://qiita-image-store.s3.amazonaws.com/0/90495/2858549d-2a55-a252-46e3-80e038523113.png)

![4-5 fade.png](https://qiita-image-store.s3.amazonaws.com/0/90495/6401c70d-4307-dd0e-c571-ffa8c41d8bb7.png)

スプライト等のレイヤーに追加された描画対象物は、フェードアウトしただけではまだそこに存在しており、RemoveSelfアクションを実行することで、ようやく描画対象から削除されます。

アクションを必要としない場合は、sprite:removeFromParent()でも対象の絵を削除できます。これは、例えばゲームオーバー後のリセット処理等でよく使います。

見えないけど削除されていないものが残っていると、意図しないクラッシュが発生することがあります。自分が意図的に見えないようにした絵については、その削除まで意識して開発を行う必要があります。これは、今後説明予定のゲーム開始→ゲームオーバー→リトライの流れを作るときに再度説明します。

#絵を消した所をキラッとする
では、今絵を消したところをキラッとさせます。これにはパーティクルという粒子視覚効果を使います。パーティクル自体は、ゲームエンジンでよく提供される機能ですが、粒子の発生頻度や大きさ方向勢い継続時間等、設定しなければいけない項目が多いため、使い始め苦労します。cocos2d-xの場合、パーティクルの出力結果を確認しながら設定内容をGUIで編集し、その設定ファイルの出力までできるウェブアプリparticle2dx.comが利用できます。

ブラウザでparticle2dx.comを開き、画面右のTemplateをクリックした後、

![4-1 particle2dx.png](https://qiita-image-store.s3.amazonaws.com/0/90495/7f42a391-299b-b536-0f3a-ee2cd42bdb79.png)

真ん中下のほうにあるdamage3をクリックすると、画面左の表示が星のキラキラになります。その後、画面右上のExportをクリックします、

![4-2 particle2dx export.png](https://qiita-image-store.s3.amazonaws.com/0/90495/76660d7b-742f-48b7-0d62-56d64a2c2904.png)

さらに、画面真ん中あたりにあるCOCOS2DX PNG Containedのあたりをクリックします。
すると、particle_texture.plistという名前のファイルがダウンロードできます。

このファイルparticle_texture.plistを、Cocos Code IDEのプロジェクトExplorerのresフォルダにドラッグアンドドロップし、下のようにresフォルダ下に追加されていればOKです。

![4-3 particle_texture added.png](https://qiita-image-store.s3.amazonaws.com/0/90495/ecbe0c25-f8f2-44cc-123d-808a7889ba73.png)

Luaコードa)の部分を次のように変更します。

```GameScene.lua
...
            -- a)スプライトをフェードアウトしてから削除
            local fade = cc.FadeOut:create(1)
            -- f)キラッとする
            local x,y = sprite:getPosition()
            local function func(node)
                local particle = cc.ParticleSystemQuad:create("particle_texture.plist")
                particle:setPosition(x,y)
                layer:addChild(particle)
            end
            local callFunc = cc.CallFunc:create(func)
            local remove = cc.RemoveSelf:create()
            local sequence = cc.Sequence:create(fade,callFunc,remove)
            sprite:runAction(sequence)
...
```

f)キラッとする〜callFuncまでを追加し、さらにsequenceの引数にcallFuncを追加しました。
`local x,y = sprite:getPosition()`は、削除前の絵の位置を取得しています。
次に絵を削除した後に呼ばれる関数funcを定義し、その中で、
　`cc.ParticleSystemQuad:create("particle_texture.plist")`により、先ほどダウンロードした設定値ファイルを使ってパーティクルを生成し、
　`particle:setPosition(x,y)`および`layer:addChild(particle)`により、削除前の絵の位置を指定して、このパーティクルを描画対象のレイヤーに追加しています。
ここで、`cc.CallFunc:create(func)`は関数を呼び出すアクション命令です。このアクションをsequenceの引数の最後に追加することで、絵をフェードアウト、削除、func関数の呼び出しという流れが作れます。

![4-4 before fade.png](https://qiita-image-store.s3.amazonaws.com/0/90495/2858549d-2a55-a252-46e3-80e038523113.png)

![4-5 fade.png](https://qiita-image-store.s3.amazonaws.com/0/90495/6401c70d-4307-dd0e-c571-ffa8c41d8bb7.png)

![4-6 after fade particle.png](https://qiita-image-store.s3.amazonaws.com/0/90495/03831930-d459-03d3-4445-fb0d5fa29359.png)


ところで、particleも使わなくなった時点で削除したほうが良いです。今回のパーティクルは0.3秒で放出が終了する設定だったので、下記コードを`layer:addChild(particle)`の下に追加すれば、描画レイヤーにパーティクル追加後、0.3秒待ち、パーティクルを描画レイヤーから削除することができます。

```
                local delay = cc.DelayTime:create(0.3)
                local remove = cc.RemoveSelf:create()
                local sequence = cc.Sequence:create(delay,remove)
                particle:runAction(sequence)
```

今回は星の粒子でしたが、particle2dxにはほかにも雛形となる設定例があります。また、particle2dxのメニューにあるColor&ShapeやMotionをクリックすると、さまざまな設定値を出力結果を見ながら編集できます。

以上が、タッチした絵を消して、一瞬キラッとさせるためのアクションとパーティクルの簡単な説明になります。

#今後の予定
ゲーム開発では、ゲーム開始時にはBGMを再生し、絵を消すときに効果音を鳴らし、絵を消すと同時に得点表示を更新する、という振る舞いがよく用いられます。

次回は、cocos2d-xでのBGMおよび効果音の鳴らし方と、得点表示の仕方について説明する予定です。