PlayCanvasでサンディちゃんを歩かせるゲームを作るぞ☆（第２回）

# こんなん作ってます。
https://playcanv.as/b/6yisdCs4/
※本解説よりも開発が進んでいることもございますのでご了承ください。

# 今回の目標
前回はサンディちゃんを配置してみました。
今回はキーボードのカーソルキーで操作するところまで。

# サンディを操作する。
JavaScriptで動作について書いてきます。
アセットに「src」フォルダを作成し、「ctrlSandy」というJavaScriptを作ります。（拡張子は自動でつく）
![N1_3.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/110583/53f1ae04-d47d-0e7e-1627-3e522299b27f.jpeg)

作成したJSファイルのインスペクタからEditをクリック。JSファイルの編集をします。
![N1_4.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/110583/6f1e235b-0441-31e2-a707-666ca5849b75.jpeg)


デフォ状態

```ctrlSandy.js
var CtrlSandy = pc.createScript('ctrlSandy');

// initialize code called once per entity
CtrlSandy.prototype.initialize = function() {
    
};

// update code called every frame
CtrlSandy.prototype.update = function(dt) {
    
};

// swap method called for script hot-reloading
// inherit your script state here
// CtrlSandy.prototype.swap = function(old) { };

// to learn more about script anatomy, please read:
// http://developer.playcanvas.com/en/user-manual/scripting/
```

書き換える

```ctrlSandy.js
// update code called every frame
CtrlSandy.prototype.update = function(dt) {
     //z軸方向に1ずつ移動する
    this.entity.translate(0,0,0.1);
};
```

JSファイルの動作をモデルに適用します。

サンディちゃんのインスペクタでADD COMPONENTでScriptを追加。
![N1_5.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/110583/78160829-21c3-6550-b08e-b691a1f5435e.jpeg)

追加されたSCRIPTSでNewScriptで「ctrlSandy」を追加する。
![N1_6.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/110583/2c9b7052-a12f-302c-965b-9e43c3431cea.jpeg)

Launchしてみましょう。

ただスライド移動するだけです。


ちなみに、座標変換のメソッドを書き換えてみる。

```ctrlSandy.js
// update code called every frame
CtrlSandy.prototype.update = function(dt) {
     //z軸方向に1ずつ移動する
    this.entity.translateLocal(0,0,0.1);
};
```

先述のコードでは横方向にスライドしてしまいましたが、書き換えたコードではサンディちゃんの向いている方向へ移動しました。
ワールド座標でのZ軸方向か、オブジェクトのローカル上でのZ軸方向か、違いはそれだけです。
ローカルでの変換はちゃんと変換されてワールドに影響されます。

不思議に思う人もいるかもしれませんが、不思議なままでもなんとかなります。
まあ、いずれわかればいいのです（笑）


# ついでで
BoxオブジェクトにもctrlSandy.jsを適用してみましょう。

サンディちゃんも箱もおんなじ方向に移動しますね。

モデルにスクリプトファイルを適用するということは、オブジェクト志向的には後付けでクラスにスーパークラスを充てているようなものなのかもしれませんね。

- サブクラス＝ビューワ上の各オブジェクト
- スーパークラス＝JSファイル内のオブジェクト

実際のところは違うのかもしれませんが、こういうのを利用すればプログラムの再利用を設計に盛り込めますね。



# キーボード入力で歩かせてみよう
以下のようにソースを改修してみました。

```ctrlSandy.js

// update code called every frame
CtrlSandy.prototype.update = function(dt) {
    var ctrl=0;
    
    if(this.app.keyboard.isPressed(pc.KEY_UP))
        ctrl += C_KEY_UP;
    if(this.app.keyboard.isPressed(pc.KEY_DOWN))
        ctrl += C_KEY_DOWN;
    if(this.app.keyboard.isPressed(pc.KEY_LEFT))
        ctrl += C_KEY_LEFT;
    if(this.app.keyboard.isPressed(pc.KEY_RIGHT))
        ctrl += C_KEY_RIGHT;
    if(this.app.keyboard.isPressed(pc.KEY_Z))
        ctrl += C_KEY_Z;
    if(this.app.keyboard.isPressed(pc.KEY_X))
        ctrl += C_KEY_X;

    //カーソルキーの上が押されていたら
    if(ctrl & C_KEY_UP){
        this.entity.translateLocal(0,0,0.1);
    }
    //カーソルキーの下が押されていたら
    if(ctrl & C_KEY_DOWN){
        this.entity.translateLocal(0,0,-0.1);
    }
    //カーソルキーの左が押されていたら
    if(ctrl & C_KEY_LEFT){
        this.entity.rotateLocal(0, 15, 0);
    }
    //カーソルキーの右が押されていたら
    if(ctrl & C_KEY_RIGHT){
        this.entity.rotateLocal(0, -15, 0);
    }
    
     //z軸方向に1ずつ移動する
    //this.entity.translate(-0.2,0,0.2);
    //this.entity.translateLocal(0,0,0.1);
};
```

これでカーソルキーでサンディちゃんを自在に動かせるようになります。

（カメラの真前まで移動させてみたらちょっと怖かった・・・）
![スクリーンショット 2019-12-23 0.16.53.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/110583/8ef78914-33c8-6f4a-f43e-6eed76361d70.png)

しかしLAUNCHしてみればわかるのですが、このままではいわゆるホバー移動でキャラを動かしている感じがしません。

次はアニメーションと絡めていきます。


# 移動時にアニメーションさせる。
Playerオブジェクトのインスペクタ、ANIMATIONでAdd Assetsします。（赤枠）
walk.jsonとrun.json、それとkick.jsonも追加しましょう。（緑枠）
ADD SELECTIONで各jsonファイルを選択しDONEです。
![N1_7.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/110583/6cba1a73-35b6-3e29-4461-fde9f4632440.jpeg)

これでエディタ側のアニメーションの準備はできました。
あとはプログラムで入力（または状態）にあわせてオブジェクトをアニメーションさせましょう。

簡単な仕様

- カーソルキー上：歩く
- カーソルキー下：後ろへ歩く
- カーソルキー右：右へ回る
- カーソルキー左：左へ回る
- カーソルキー上＋Zキー：走る



まずは定数を追加します。

```ctrlSandy.js
//コントロール用定数
var C_KEY_UP = 1;
var C_KEY_DOWN = 2;
var C_KEY_LEFT = 4;
var C_KEY_RIGHT = 8;
var C_KEY_Z = 16;
var C_KEY_X = 32;

//歩くスピード
var DIS_WALK = 0.06;

//ダッシュスピード
var DIS_RUN = 0.12;

//歩くスピード
var TURN = 15;

```

initializeイベントを改修。

```ctrlSandy.js
// initialize code called once per entity
CtrlSandy.prototype.initialize = function() {
    //アニメーションブレンディング変数
    this.blendTime = 0.2;
    
    //現在のアニメーション
    this.animation = "idle.json";
    
    //WALK状態変数
    this.countWalk = 0;
    
    //RUN状態変数
    this.countRun = 0;
    
};
```

updateイベントを改修。

```ctrlSandy.js
// update code called every frame
CtrlSandy.prototype.update = function(dt) {
    
    //（現在の）キー入力を一つの変数にまとめる
    var ctrl=0;
    if(this.app.keyboard.isPressed(pc.KEY_UP))
        ctrl += C_KEY_UP;
    if(this.app.keyboard.isPressed(pc.KEY_DOWN))
        ctrl += C_KEY_DOWN;
    if(this.app.keyboard.isPressed(pc.KEY_LEFT))
        ctrl += C_KEY_LEFT;
    if(this.app.keyboard.isPressed(pc.KEY_RIGHT))
        ctrl += C_KEY_RIGHT;
    if(this.app.keyboard.isPressed(pc.KEY_Z))
        ctrl += C_KEY_Z;
    if(this.app.keyboard.isPressed(pc.KEY_X))
        ctrl += C_KEY_X;

    //*** サンディちゃんの移動と状態変数の制御 ***
    //カーソルキーの上が押されていたら
    if(ctrl & C_KEY_UP){
        if(ctrl & C_KEY_Z){
            this.entity.translateLocal(0,0,DIS_RUN);
            this.countWalk=0;
            this.countRun++;
        }else{
            this.entity.translateLocal(0,0,DIS_WALK);
            this.countWalk++;
            this.countRun=0;
        }
    }
    
    //カーソルキーの下が押されていたら
    if(ctrl & C_KEY_DOWN){
        this.entity.translateLocal(0,0,-1*DIS_WALK);
        this.countWalk++;
        this.countRun=0;
    }
    
    //カーソルキーの左が押されていたら
    if(ctrl & C_KEY_LEFT){
        this.entity.rotateLocal(0, TURN, 0);
        this.countWalk++;
        this.countRun=0;
    }
    
    //カーソルキーの右が押されていたら
    if(ctrl & C_KEY_RIGHT){
        this.entity.rotateLocal(0, -1*TURN, 0);
        this.countWalk++;
        this.countRun=0;
    }
    
    //アニメーション切り替え
    //入力がなくなったらアイドリングに戻す
    if(this.animation !== "idle.json" && ctrl === 0){
        this.setAnimation("idle.json");
        this.countWalk=0;
        this.countRun=0;
    }else{
        if(this.countWalk===1){
            this.setAnimation("walk.json");
        }
        
        if(this.countRun===1){
            this.setAnimation("run.json");
        }
    }
    
     //z軸方向に1ずつ移動する
    //this.entity.translate(-0.2,0,0.2);
    //this.entity.translateLocal(0,0,0.1);
};
```

関数の追加

```ctrlSandy.js
CtrlSandy.prototype.setAnimation = function (anime) {
    this.animation = anime;
    this.entity.animation.play(anime, this.blendTime);
};
```

これで歩き回れます！走れます！

スクリーンショット、走り去ってます（笑）
![スクリーンショット 2019-12-25 23.31.10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/110583/f99e0ee8-1ad5-2640-8f7c-58893fff6ddd.png)


プログラムはもっとうまく書けたよう気がしますが、いきあたりばったりなプログラミングをしてればこんなもんかな？（＾＾；

次はマップをちゃんと作って、障害物などで衝突判定でも入れましょうか。