拾 Cocos2d-xでミニゲームの状態変化を実装する

#目次
1 はじめに
2 初期化からゲームオーバーそして再開
4 今後の予定

#はじめに
本記事は、cocos2d-xおよびCocos Code IDEを導入し、絵を表示したり実機で実行してみたりした人で、これからゲームの状態変化を実装したい人向けの、覚書きです。状態定義にはLuaの配列っぽいものを使い、実際にタッチイベントでゲームオーバー、リスタートで絵の位置を戻すという処理を説明します。

#初期化からゲームオーバーそして再開
下のコードを実行すると、タッチした点に絵が移動して、BGMが停止し、ゲームオーバーとなります。ゲームオーバーが表示された後タッチすると、絵が初期位置に戻り、BGMが再生されます。

```GameScene.lua

local MUSIC_BGM         = "background.mp3"
local EFFECT_GAMEOVER   = "effect1.wav"

-- a)ゲーム状態の定義
local State = {Init = 1, Run = 2, Pause = 3, PreGameOver = 4, GameOver = 5}

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

    -- b)ゲーム状態を初期状態にする
    self.state = State.Init
end

function GameScene:playBgMusic()
    -- BGMを再生
    local bgMusicPath = cc.FileUtils:getInstance():fullPathForFilename(MUSIC_BGM) 
    cc.SimpleAudioEngine:getInstance():playMusic(bgMusicPath, true)
    -- 効果音を先読み
    local effectPath = cc.FileUtils:getInstance():fullPathForFilename(EFFECT_GAMEOVER)
    cc.SimpleAudioEngine:getInstance():preloadEffect(effectPath)
end

function GameScene:createLayer()
    local layer = cc.Layer:create()
    -- ここから初期化開始
    
    -- 背景
    local sprite_background = cc.Sprite:create("farm.jpg")
    sprite_background:setPosition(self.visibleSize.width/2, self.visibleSize.height/2)
    sprite_background:setScale(1.2)
    layer:addChild(sprite_background)
    
    -- 絵
    local sprite = cc.Sprite:create("land.png")
    sprite:setPosition(100,100)
    layer:addChild(sprite)
    
    -- ゲームオーバー表示
    local label_gameover = cc.Label:createWithTTF("GAME OVER","fonts/Marker Felt.ttf", 55)
    label_gameover:setPosition(self.visibleSize.width/2,self.visibleSize.height/2)
    label_gameover:setColor(cc.c3b(250, 250, 250))
    label_gameover:enableShadow()
    label_gameover:setOpacity(0)
    layer:addChild(label_gameover)
    
    -- タッチ開始時に呼ばれる
    local function onTouchBegan(touch, event)
        local location = touch:getLocation()
        
        if self.state == State.Run then
        -- ゲームオーバーにする処理
            --DEBUG 絵の位置をタッチ位置に変更
            sprite:setPosition(location)

            -- BGMを止める
            cc.SimpleAudioEngine:getInstance():stopMusic()

            -- ゲーム終了通知音を鳴らす
            local effectPath = cc.FileUtils:getInstance():fullPathForFilename(EFFECT_GAMEOVER)
            cc.SimpleAudioEngine:getInstance():playEffect(effectPath)

            -- d)ゲーム状態をゲーム終了前状態に変更
            self.state = State.PreGameOver

            -- ゲームオーバ表示をフェードインした後ゲームオーバー状態に変更
            local fade = cc.FadeIn:create(2)
            local function funcToGameOver(node)
                -- e)ゲーム状態をゲームオーバーに変更
                self.state = State.GameOver
            end
            local callFunc = cc.CallFunc:create(funcToGameOver)
            label_gameover:runAction(cc.Sequence:create(fade,callFunc))
        end
        
        if self.state == State.GameOver then
        -- ゲームオーバーになった後ゲームを再開する処理
            
            -- BGMを再生
            local bgMusicPath = cc.FileUtils:getInstance():fullPathForFilename(MUSIC_BGM) 
            cc.SimpleAudioEngine:getInstance():playMusic(bgMusicPath, true)
            
            -- ゲームオーバー表示をフェードアウト
            label_gameover:runAction(cc.FadeOut:create(2))
            
            -- 絵の位置を初期化
            sprite:setPosition(100,100)
            
            -- f)ゲーム状態をランへ変更
            self.state = State.Run
        end
        
        return true  -- trueを返す
    end

    -- タッチイベントで呼ばれる関数を登録し、このレイヤーでのタッチイベント取得を有効化
    local listener = cc.EventListenerTouchOneByOne:create()
    listener:registerScriptHandler(onTouchBegan,cc.Handler.EVENT_TOUCH_BEGAN )
    local eventDispatcher = layer:getEventDispatcher()
    eventDispatcher:addEventListenerWithSceneGraphPriority(listener, layer)
    
    -- c)ゲーム状態をランに変更
    self.state = State.Run
    
    return layer
end

return GameScene
```

a)ゲームの状態を定義、Luaの連想配列（定義名と値が組みになった配列）が使えます。
b)変数self.stateにInitを設定
c)同変数にRunを設定
d)同変数にPreGameOverを設定
e)同変数にGameOverを設定
f)同変数にRUNを設定

![10-1.png](https://qiita-image-store.s3.amazonaws.com/0/90495/dc83ada3-3184-85ea-ad5e-d2e719f19731.png)

![10-2.png](https://qiita-image-store.s3.amazonaws.com/0/90495/0bf2eec1-ee20-08b4-3ce7-50490790f8e0.png)


#今後の予定
パラパラ絵を動かす。アニメーションについて説明します。