ブロックチェーンゲーム制作チェーン -Minimal Arcade Medal-

ブロックチェーン技術、ゲーム作成のためのコード、ドット絵やアニメーションの作り方を解説するブログです。最終的に記事の内容を組み合わせることで誰でもブロックチェーンゲームが作れるようにしたいです。Micro Arcade MedalというdApps開発中です。

体力バーを描画する方法ーCocosCreator

f:id:kusakabob:20180710095243p:plain


この記事ではアニメーション付きの丸や四角を描画する方法を解説します。


上の画像はサンプルのものですが、それぞれアニメーションが付いています。

  • 左上の四角は左に向かって幅が小さくなっていきます。
  • 右の四角は下に向かって高さが低くなっていきます。
  • 左下の丸は扇状に丸を描画していきます。


空間を図形で埋めていくアニメーションです。


サンプルプロジェクトのFilledSpriteというSceneの中身を見ていきます。


サンプルプロジェクトはCocosCreatorのNewProjectからExample Collectionでアクセスできます。


場所はここです。
example/assets/cases/01_graphics/01_sprite/FilledSprite

Sceneエディタ


f:id:kusakabob:20180710100403p:plain


Sceneを開くとこのような画面が出てきます。


4つの図形がありますが、全ての親NodeであるCanvasのPropertyパネルを見ると、

  • ScriptがFilledSpriteControll
  • HorzontalにHorizontal
  • 以下省略


f:id:kusakabob:20180710100610p:plain


上の画像のようにComponentとSpriteが紐づけられています。


f:id:kusakabob:20180710100928p:plain


Spriteはassets/res/textures/filled
の中に全て保存されてます。

アニメーションを付与するコード


このSceneの肝であるアニメーションを画像に付与するコードの中身を見てみます。


場所は
example/assets/cases/01_graphics/01_sprite/FilledSprite/FilledSprite.js
です。


FilledSpriteControll.js

cc.Class({
    extends: cc.Component,

    properties: {

        speed: 0.1,

        horizontal: {
            default: null,
            type: cc.Sprite
        },

        vertical: {
            default: null,
            type: cc.Sprite
        },

        radial_round: {
            default: null,
            type: cc.Sprite
        },

        radial_semicircle: {
            default: null,
            type: cc.Sprite
        }
    },

    update: function (dt) {
        // update fill start
        this._updataFillStart(this.horizontal, dt);
        this._updataFillStart(this.vertical, dt);
        // update fill range
        this._updateFillRange(this.radial_round, 1, dt);
        this._updateFillRange(this.radial_semicircle, 0.5, dt);
    },

    _updataFillStart: function (sprite, dt) {
        var fillStart = sprite.fillStart;
        fillStart = fillStart > 0 ? fillStart -= (dt * this.speed) : 1;
        sprite.fillStart = fillStart;
    },

    _updateFillRange: function (sprite, range, dt) {
        var fillRange = sprite.fillRange;
        fillRange = fillRange < range ? fillRange += (dt * this.speed) : 0;
        sprite.fillRange = fillRange;
    }

});

大きく2つのコードからなります。

  • property
  • update


上から順番に見ていきます。

properties: {

        speed: 0.1,

        horizontal: {
            default: null,
            type: cc.Sprite
        },

        vertical: {
            default: null,
            type: cc.Sprite
        },

        radial_round: {
            default: null,
            type: cc.Sprite
        },

        radial_semicircle: {
            default: null,
            type: cc.Sprite
        }
    },


propertiesは以下のpropertyを持ちます。

  • speed:アニメーションの速さ
  • horizontal Spriteへの参照
  • vertical Spriteへの参照
  • radial_roundへの参照
  • radial_semicircleへの参照


f:id:kusakabob:20180710100610p:plain


それぞれこのようにSpriteが突っ込まれてます。

update: function (dt) {
        // update fill start
        this._updataFillStart(this.horizontal, dt);
        this._updataFillStart(this.vertical, dt);
        // update fill range
        this._updateFillRange(this.radial_round, 1, dt);
        this._updateFillRange(this.radial_semicircle, 0.5, dt);
    },

    _updataFillStart: function (sprite, dt) {
        var fillStart = sprite.fillStart;
        fillStart = fillStart > 0 ? fillStart -= (dt * this.speed) : 1;
        sprite.fillStart = fillStart;
    },

    _updateFillRange: function (sprite, range, dt) {
        var fillRange = sprite.fillRange;
        fillRange = fillRange < range ? fillRange += (dt * this.speed) : 0;
        sprite.fillRange = fillRange;
    }


次にupdate関数ですが補助関数が2つ定義されてます。

  • _updateFillStart:
  • updateFillRange


これらは毎フレームupdateから呼び出されます。

dtは1フレームごとの時間で単位は秒です。

ちなみにdtにはこのような数値が入っているようです。


f:id:kusakabob:20180710103148p:plain


1秒=60フレームなので
1/60 = 0.0016あたりの値が入っています。

update: function (dt) {
        // update fill start
        this._updataFillStart(this.horizontal, dt);
        this._updataFillStart(this.vertical, dt);
        // update fill range
        this._updateFillRange(this.radial_round, 1, dt);
        this._updateFillRange(this.radial_semicircle, 0.5, dt);
    },


それぞれ適切な引数を入れて補助関数を呼んでいます。

 _updataFillStart: function (sprite, dt) {
        var fillStart = sprite.fillStart;
        fillStart = fillStart > 0 ? fillStart -= (dt * this.speed) : 1;
        sprite.fillStart = fillStart;
    },


まずsprite.fillStartを呼んでいます。


これはpropertyで保持している長方形です。
spriteクラスであると定義しているのでfillStartが使えます。


このfillStartという関数はcc.Sprite.Type.FILLEDとセットされていないと使えないようです。
このコードの中ではセットされていません。


それではどこでセットされているのかというと


f:id:kusakabob:20180710105029p:plain


ここです。他にも色々とアニメーションに必要な値が設定されています。

ここがポイント

fillStart = fillStart > 0 ? fillStart -= (dt * this.speed) : 1;

この部分はfillStartが0以上ならば、
fillStartからdt*this.speedを引いたものでfillStart更新、
0以下ならばfillStartを1にセットします。


fillStartは-1から1の数字をとります。初期値は1です。
これはPropertyパネルで設定されています。


dt*this.speed = 0.0016*0.1= 0.00016が1から毎フレーム引かれていきます。
つまり、0.00016*60 = 0.0096
毎秒長さが変わります。


その長さが0以上になったとき、1に戻してループさせています。

    _updateFillRange: function (sprite, range, dt) {
        var fillRange = sprite.fillRange;
        fillRange = fillRange < range ? fillRange += (dt * this.speed) : 0;
        sprite.fillRange = fillRange;
    }


こちらも基本一緒です。
代わりにfillRangeを使ってますね。


またfilledRangeの値は半円の場合0から0.5まで
円の場合は0から1まで変わります。

所感


fillStartとfillRangeの使い方が要ですね。


この方法を使えば、簡単に様々なゲージが表現できます。


格ゲーとか良さそうですね。