【PlayCanvas(JavaScript)】ランダムな値をTweenに渡してループさせる


PlayCanvas

PlayCanvasは、デスクトップとモバイルブラウザ向けに作られた
WebGL/HTML5ゲームエンジンです。豊富な機能を揃えた3Dエンジンと
クラウドホスティングされた開発環境およびツールセットを備えています。

引用元:PLAYCANVAS

超初歩的な使い方は下記にまとめました。
【参考リンク】:【PlayCanvas(JavaScript)】PlayCanvasを触ってみた

今回はTweenを試すのでtween.jsを下記リンクから頂戴します。
playcanvas-tween

デモ

ライトのレンジをランダムな間隔でランダムな大きさに変化させています。
踊っている人はまったく関係ないです。

Tweenでランダムな値を渡してループさせることに少々苦労したのでメモ残します。

JavaScript初心者なので酷いこと書いてるかもしれません。
どうか優しくしてやってください。

コード

下記全文です。

適当なEntityにアタッチ
//宣言
var LightTween = pc.createScript('lightTween');

//アトリビュート Editor画面にGUIで参照を設定可能に
LightTween.attributes.add('pointLightEntity', {type: 'entity', title: 'Point Light Entity'});

LightTween.prototype.initialize = function() {
    //初期化時Tweenの処理を担うメソッド呼び出す
    this.lightRandomFlash();
};

//ライトのレンジをランダムに変化
LightTween.prototype.lightRandomFlash = function(){
    //"this"を別の変数に持っておく
    var self = this;

    //==================
    // ライトの範囲をTweenで変化させる
    //==================

    //実行中のTween停止
    if(tweenLightRange){
        tweenLightRange.stop();
    }

    //単発でTween実行
    var tweenLightRange = this.app
    .tween(this.pointLightEntity.light).to({range: getRandomInt(3,8)},  getRandomInt(1,3), pc.SineOut)
    .yoyo(true)
    .on('complete', function () {
        //完了時、再帰的にメソッド呼び出し
        self.lightRandomFlash();
    })
    .start();
};

//ランダムな値生成
function getRandomInt(min, max) {
  min = Math.ceil(min);
  max = Math.floor(max);
  return (Math.floor(Math.random() * (max-min)) + min);
}

結論から言うと、Tweenをループさせず再帰的に何度も呼び出しています。
疑似的にループに見せているだけです。

というのも、tween.jsのループ処理は最初に定義したtween以降の処理をループさせるからです。
ランダムな値を渡そうとしても最初に渡した値で二回目以降の処理は固定されます。
(認識間違っていたらコメントください、、)

ですので、下記手順で実行しています。
①HogeTweenを動かす処理を記述したメソッドを呼び出す
②HogeTweenが動いているかチェックし、動いていたら止める
③HogeTweenにランダムな値を渡して動かす
④HogeTweenの完了時に再度HogeTweenを動かす処理を記述したメソッドを呼び出す
⑤ ②に戻る

this

JavaScriptthisが自分の予想したthisを指していなかったようでかなり混乱しました。

【参考リンク】:JavaScriptの「this」は「4種類」??

tweenのメソッドチェーンの中でコールバックに処理を登録できる
.on('hoge',function)というのがあります。

このコールバックの中でthisを使用した場合、thisの中身はtweenになります。

その直前のメソッドチェーンの中で呼び出した際の
thisの中身はlightTweenというScriptのインスタンス
です。

問題の箇所
 var tweenLightRange = this.app
    .tween(this.pointLightEntity.light).to({range: getRandomInt(3,8)},  getRandomInt(1,3), pc.SineOut)
    .yoyo(true)
    .on('complete', function () {
        //このthisは中身がtweenなのでエラーとなる
        this.lightRandomFlash();
    })
    .start();

ですので、tweenの中でlightTweenのインスタンスを使用するには
一度変数にインスタンスを保持させる必要がありました。

    //"this"を別の変数に持っておく
    var self = this; 

    var tweenLightRange = this.app
    .tween(this.pointLightEntity.light).to({range: getRandomInt(3,8)},  getRandomInt(1,3), pc.SineOut)
    .yoyo(true)
    .on('complete', function () {
        //selfは`lightTween`のインスタンスを指す
        self.lightRandomFlash();
    })
    .start();

【参考リンク】:What is the purpose of writing “self = this”?

おわりに

もう少しJavaScriptと仲良くならないとPlayCanvas使うのは大変だなと思いました。

体系的に基礎から学べるサイトとかご存じの方教えてください。


ユーザーコミュニティにてご回答いただいた方ありがとうございました!

参考リンク

Math.random()