モーリーのメモ

アプリ開発等(プログラミング、CG作成)、興味を持ったことを実践してまとめるブログです。

モーリーのメモ

マリオみたいな2Dアクションゲームを作る! その3 プレイヤーをキー操作する:Cocos Creator

 ◆ Cocos Creatorスーパーマリオみたいな2Dアクションゲームを作ります。◆
 ◆ このシリーズの他の記事を見るには『PlatformerGame』タグをクリックして下さい。◆
 ◆ 最初から読みたい場合はココをクリックして下さい。◆
 
 こちらの記事の続きです。

 
 今回はプレイヤーをキーボードで操作出来るようにします。
 左右の移動とジャンプを実装します。
 
【 注意 】この記事で使用しているCocos Creator v2.3.3は、VS Codeデバッグ実行でブレークポイントが機能しないバグがあので、v.2.3.2を使用して下さい。
 v.2.3.2は、Cocos DashboardのEditorのDownloadボタンからインストール出来ます。
 既存のプロジェクトのEditor Versionは、下図のように切り替えます。一度確認のメッセージが表示されます。
    f:id:mmorley:20200422191834p:plain

使用環境

 私が使用している環境です。

キーボードイベントを登録する

 キーボードイベントには下記の2つがあります。

  • KeyDownイベント:キーを押した時に発生します。
  • KeyUpイベント:キーを離した時に発生します。
 それぞれのイベント発生時に呼び出す関数を作成して登録します。
 またノードを破棄する時にイベントを解除するようにします。
 

    Cocos Creatorで作業

  1. 『Assets』パネルで『assets/script/player』をダブルクリックします。
    VS Codeが起動します。

    VS Codeで作業

  2. 『onKeyDown()』と『onKeyUp()』を追加します。
    それぞれKeyDownイベントとKeyUpイベントの発生時に呼び出す関数です。
    現時点では関数の中身は空です。
    引数のevent(cc.Event.EventKeyboard型)で、どのキーが押されたか等の情報を受け取ります。

        onLoad () {
            /* 省略 */
        }
    
        onKeyDown (event: cc.Event.EventKeyboard) {  // キーを押した時の処理
    
        }
    
        onKeyUp (event: cc.Event.EventKeyboard) { // キーを離した時の処理
    
        }
    

  3. 『onLoad()』に、キーボードイベントを登録するコードを追加します。

        onLoad () {
            /* 省略 */
    
            cc.systemEvent.on(cc.SystemEvent.EventType.KEY_DOWN, this.onKeyDown, this); // KeyDownイベントを登録
            cc.systemEvent.on(cc.SystemEvent.EventType.KEY_UP, this.onKeyUp, this); // KeyUpイベントを登録
        }
    

  4. 『onDestroy()』で、キーボードイベントを削除します。
    『onDestroy()』はノードが破棄される時に実行されます。

        onLoad () {
            /* 省略 */
        }
    
        onDestroy () { // ノードが破棄される時の処理
            cc.systemEvent.off(cc.SystemEvent.EventType.KEY_DOWN, this.onKeyDown, this); // KeyDownイベントを登録
            cc.systemEvent.off(cc.SystemEvent.EventType.KEY_UP, this.onKeyUp, this); // KeyUpイベントを登録
        }
    

キーボード操作を設定する

  • キーの割り当ては下図のようにします。
    PCゲームでよく使われる『WDA』と『←↑→』のどちらでも操作出来るようにします。
    f:id:mmorley:20200331104246p:plain
  • 移動方向を計算します。
    • inputRight :右移動のキー入力状態、押されたら1、離したら0
    • inputLeft:左移動のキー入力状態、押されたら1、離したら0
    • direction:X方向の移動方向、右移動の時は1、左移動の時は-1、停止時は0
      次の式で計算します。direction = inputRight - inputLeft
      左右の移動キーが同時に押された時は0なので停止します。
      f:id:mmorley:20200402122223p:plain
  • ジャンプ操作の入力を受け付けます。
    • inputJump :ジャンプのキー入力状態、押されたら1、離したら0
 

    VS Codeで作業

  1. 『onKeyDown()』にコードを追加します。

        direction: number = 0; // プレイヤーの移動方向
        inputRight: number = 0; // 右移動の入力状態
        inputLeft: number = 0; // 左移動の入力状態
        inputJump: number = 0; // ジャンプの入力状態
        onKeyDown (event: cc.Event.EventKeyboard) {  // キーを押した時の処理
            switch(event.keyCode) { // 押されたキーの種類で分岐
                case cc.macro.KEY.d: // 『d』キーの場合
                case cc.macro.KEY.right: // 『→』キーの場合
                    this.inputRight = 1; // 『右』の入力を1にする
                    this.direction = this.inputRight - this.inputLeft; // プレイヤーの移動方向 右=1、左=-1
                    break;
                case cc.macro.KEY.a: // 『a』キーの場合
                case cc.macro.KEY.left: //  『←』キーの場合
                    this.inputLeft = 1; //『左』の入力を1にする
                    this.direction = this.inputRight - this.inputLeft; // プレイヤーの移動方向 右=1、左=-1
                    break;
                case cc.macro.KEY.w: // 『w』キーの場合
                case cc.macro.KEY.up: // 『↑』キーの場合
                case cc.macro.KEY.space: // 『スペース』キーの場合
                     this.inputJump = 1; //『ジャンプ』の入力を1にする
                    break;
            }
        }
    

  2. 『onKeyUp()』にコードを追加します。

        onKeyUp (event: cc.Event.EventKeyboard) { // キーを離した時の処理
            switch(event.keyCode) { // 押されたキーの種類で分岐
                case cc.macro.KEY.d: // 『d』キーの場合
                case cc.macro.KEY.right: // 『→』キーの場合
                    this.inputRight = 0; // 『右』の入力を1にする
                    this.direction = this.inputRight - this.inputLeft; // プレイヤーの移動方向 右=1、左=-1
                    break;
                case cc.macro.KEY.a: // 『a』キーの場合
                case cc.macro.KEY.left: //  『←』キーの場合
                    this.inputLeft = 0; //『左』の入力を0にする
                    this.direction = this.inputRight - this.inputLeft; // プレイヤーの移動方向 右=1、左=-1
                    break;
                case cc.macro.KEY.w: // 『w』キーの場合
                case cc.macro.KEY.up: // 『↑』キーの場合
                case cc.macro.KEY.space: // 『スペース』キーの場合
                     this.inputJump = 0; //『ジャンプ』の入力を0にする
                    break;
            }
        }
    

左右の移動処理を実装する

 ゲーム画面はアニメのコマ送りのように描画することで動きを見せています。
 ゲームでアニメのコマに当たるのがフレームです。
 今回使用する『update(dt)』は毎フレームの描画の前に呼び出される関数です。
 左右の移動キーが押されている間、プレイヤーが加減速を持って移動するように、毎フレームのプレイヤーの速度を『update(dt)』で計算します。
 
 下記のように実装します。

  • プレイヤーの絵の向きを移動方向にします。
    ノードのX方向のスケールを”-1”にすると、左右反転します。
  • X方向の加速度(減速)と最大速度を設定します。
  • プレイヤーの速度をフレームごとに次の式によって計算します。
    プレイヤーの速度= 前フレームの速度 + 加速度 × 移動方向
  • 移動方向(direction)が0の場合は、減速して停止します。
 

    VS Codeで作業

  1. 『update()』を追加します。

        onKeyUp () {
            /* 省略 */
        }
    
        acceleration: number = 2000; // プレイヤーの加速度
        maxSpeed: number = 400; // プレイヤーの最大速度
        update (dt: number) { // 毎フレームの描画前の処理(dt:前フレームからの経過時間)
            let velocity: cc.Vec2 = this.getComponent(cc.RigidBody).linearVelocity; // 現在の速度を取得
    
            // 左右の移動処理
            if(this.direction != 0) { // 移動する場合
                this.node.scaleX = Math.abs(this.node.scaleX) * this.direction; // 絵の向きを進行方向にする
                velocity.x += this.acceleration * dt * this.direction; // 次の速度を計算する
                if(velocity.x < -this.maxSpeed) velocity.x = -this.maxSpeed; // 最大速度に制限する(左移動)
                else if(velocity.x > this.maxSpeed) velocity.x = this.maxSpeed; // 最大速度に制限する(右移動)
            } else { // 停止する場合
                if (velocity.x != 0) { // 速度が0でない場合
                    let d: number = this.acceleration * dt; // 1フレーム当たりの減速量
                    if (velocity.x < -d) velocity.x += d; // 減速処理(左移動)
                    else if (velocity.x > d) velocity.x -= d; // 減速処理(右移動)
                    else velocity.x = 0; // 速度が減速量以下の場合は停止する
                }
            }
    
            this.getComponent(cc.RigidBody).linearVelocity = velocity; // 速度を更新する
        }
    

コライダーの摩擦を0にする

 摩擦があると着地の際に減速します。動きのスムーズさを優先したいので摩擦を0にします。
 

    Cocos Creatorで作業

  1. 『Node Tree』パネルで『player』を選択して、『Properties』パネルで『PhysicsPolygonCollider』の『Friction』を”0"にします。
    f:id:mmorley:20200418081004p:plain
  2. 『ctrl + p』キー(またはプレビューボタン)を押して、プレビューを実行します。
    ゲーム画面を一度クリックした後、プレイヤーをキー操作で移動出来ます。
    【 注意 】クリックでゲーム画面をフォーカスしていないとキー操作出来ません。
     
    *下図はgifです。クリックで再生します。(ブログの仕様でgifがループします。)
    *キーボードとマウスの操作を表示するソフトを使っています。

ジャンプ処理を実装する

 ジャンプは一度上向きの速度を与えるだけです。
 重力の影響によるY方向の加減速は物理エンジンが行います。
 
 下記のように実装します。

  • ジャンプキーを一度押したら、一度だけジャンプ処理をするようにします。
    キーを押しっぱなしの時に連続で処理しないように、inputJumpが0の時だけ処理します。
  • 着地している時に、ジャンプキーの操作があれば上向きの速度を与えます。
    今回は簡単に、Y方向の速度=0の時に着地しているものとします。
    ただし、これだとジャンプの頂点や天井に頭をぶつけた時に着地とみなしてしまう場合があります。
    次回、接触イベントで着地を判定する処理を追加する予定です。
  • 重力スケール(Gravity Scale)を大きくして、ジャンプの動きを機敏にします。
 

    VS Codeで作業

  1. 『onKeyDown()』にジャンプ処理を追加します。

        /* 省略 */
        jumpSpeed: number = 900; // プレイヤーのジャンプ速度
        onKeyDown (event: cc.Event.EventKeyboard) {  // キーを押した時の処理
            switch(event.keyCode) { // 押されたキーの種類で分岐
                /* 省略 */
                case cc.macro.KEY.w: // 『w』キーの場合
                case cc.macro.KEY.up: // 『↑』キーの場合
                case cc.macro.KEY.space: // 『スペース』キーの場合
                    // ジャンプ処理
                    if (!this.inputJump) { // 『ジャンプ』の入力が0の場合
                        this.inputJump = 1; //『ジャンプ』の入力を1にする
                        let velocity: cc.Vec2 = this.getComponent(cc.RigidBody).linearVelocity; // 現在の速度を取得
                        if (velocity.y == 0) { // y方向の速度が0の場合
                            velocity.y = this.jumpSpeed; // ジャンプする(y+方向にジャンプ速度を与える)
                        }
                        this.getComponent(cc.RigidBody).linearVelocity = velocity; // 速度を更新する
                    }
                    break;
            }
        }
    

    Cocos Creatorで作業

  2. 『ctrl + p』キー(またはプレビューボタン)を押して、プレビューを実行します。
    ゲーム画面を一度クリックした後、プレイヤーをキー操作で移動出来ます。
     
    *下図はgifです。クリックで再生します。(ブログの仕様でgifがループします。)

今回作成したファイル

 今回の作業によって下記のファイルのようになります。

 
 今回はここまでです。お疲れさまでした。
 
 続きは、こちらの記事です。