【スポンサーリンク】

[phina.js] ゲーム内で表示できるオブジェクトの基本

[phina.js] ゲーム内で表示できるオブジェクトの基本

前回は phina.js の土台となるシーン構成を概観しました。
今回は シーンの要素となる基本的なオブジェクトをざっと見ていきます。

参考資料は、「phina.js Tips集 上巻」です。

\記事が役に立ったらシェアしてね/
キーワード
【スポンサーリンク】

1. ゲーム内で表示するオブジェクト

前回の各サンプルで使われていたオブジェクトは
・Label テキストを配置
・Sprite 画像を配置
・Button テキストと枠を配置
でした。

シンプルな項目なら、そのまま生成して配置します。

    var label = Label('Hello, phina.js!').addChildTo(this);

動作も含めて定義するなら、継承してクラスを作ります1

phina.define('Piece', {
  superClass: 'Button',

  /* ... */
});

クラス定義しておけば、それを配置して使えます。

    var numbers = Array.range(1, MAX_NUM+1).shuffle();
    numbers.each(function(index, i) {
      /* ... */
      var p = Piece(index).addChildTo(self.group);
      /* ... */
      p.onpointstart = function() {
        self.check(this);
      };
      p.appear();
    });

2. 基本の図形描画(Shape)

画面の要素の基本は Shapeです。
基本の四角形を表示できます。

Shapeの図形要素があります2

図形の配置・操作
  • Shapeをシーンに表示する3、透明・非表示にする4
  • Shapeの位置5・サイズ6・回転7・拡大縮小8・背景色9を指定する
  • 原点を変更する10

2-1. Shapeクラスのスーパークラス・定義場所

クラスと主なメソッド・プロパティ
  • Shape
    • render
  • DisplayElement
    • visible, show, hide, alpha
  • Object2D
    • position, lotation, scale, origin
    • hitTest, move
  • Element
    • parent, children, addChild, remove, wake, sleep
  • EventDispatcher

2-2. 表示・非表示・位置・サイズ

Shape() で生成して、addChildToでシーンを指定すれば、Shapeは表示されます。
変数で保持しておくと後で操作できます。

var shape = Shape().addChildTo(this);

背景色を指定します。

shape.backgroundColor = '#ffff00';
shape.backgroundColor = `rgb(0, 255, 255)`;

位置は、x, y 座標で指定できます。
moveByやadd(Vector2) で相対位置に移動させることもできます。

var shape = Shape({
  x: 320,
  y: 480
}).addChildTo(this)

shape.x = 320;
shape.y = 480;

var shape = Shape().addChildTo(this).setPosition(320, 480);

shape.setPosition(320, 480).moveBy(100, 200);

var v = Vector2(100, 200);
shape.position.add(v);

サイズは width, heightで指定します。

var shape = Shape({
  x: 320,
  y: 480,
  width: 128,
  height: 256,
}).addChildTo(this);

shape.width = 128;
shape.height = 128;
shape.setSize(128, 256);

ただし、Shapeにはパディング(余白)があるので注意。paddingを0にしておきましょう。

      defaults: {
        width: 64,
        height: 64,
        padding: 8,

透過率を指定したり、非表示にもできます。

shape.alpha = 0.25;
shape.hide();

削除するときはremove()を使います11

    /**
     * @method remove
     * 自身を親要素の子要素から削除します。
     */
    remove: function() {
      if (!this.parent) return ;

      this.parent.removeChild(this);
      this.parent = null;

      return this;
    },

Shapeの色やサイズを途中で変更したら、再描画が必要みたいです。

  this.render(this.canvas);                                         

2-3. 回転・拡大縮小

回転率は、360°で表記されています。

var shape = Shape({
  x: 320,
  y: 720,
  rotation: 60
}).addChildTo(this);

shape.rotation = 45;
var shape = Shape().addChildTo(this).setPosition(320, 600).setRotation(15);

Scaleで倍率。

shape.scaleX = 1.5; // 横方向に拡大
var shape = Shape().addChildTo(this).setPosition(320, 480).setScale(0.5, 0.5);
サイズと拡大率

サイズ変更と拡大・縮小の違いは、実際のサイズが変更されるかどうかです。
拡大・縮小は見た目は変わっても実際のサイズは変更されません。
当たり判定の時などに注意が必要です。

setOriginでは、表示位置の基準を変更できます。
デフォルトでは(0, 0)で画像中央。
-1〜1まで変更できます。

shape.setOrigin(0, 0);

2-4. より複雑な図形要素

四角形の枠以外に、図形要素があります。
図形では、塗りつぶしと縁取りを設定できます。

主な属性(図形によっては さらに)
  • fill 塗りつぶし色
  • stroke 縁取り線色
  • strokeWidth 縁取り線の太さ
  • radius 半径
図形要素
  • Shape
  • RectangleShape(四角形)
  • CircleShape(円)
  • TriangleShape(三角形)
  • StarShape(星型)
  • PolygonShape(多角形)
  • HeartShape(ハート型)
  • PathShape(頂点配置)

2-5. マスによる位置管理(Grid)

ゲームでは位置をマス単位で管理することが多いです。
そのためのオブジェクトが Grid です12

Grid を活用すると、マスと位置座標を相互に参照できます。

Gridは文字通り格子を意味しています。
 phina.jsでは、 Sceneに対してデフォルトでGridが設定されていて、
縦・横がそれぞれ16分割の格子に分けられています(格子の縦横比は正方形ではなく、画面比と同じになります)。

マスによる位置管理(Grid)

Scene::gridXとScene::gridYを利用します。

    var rect = RectangleShape().addChildTo(this);
    rect.setPosition(this.gridX.span(4), this.gridY.span(6));

中央からの相対位置を指定することもできます。

    var rect2 = RectangleShape().addChildTo(this);
    rect2.setPosition(this.gridX.center(-3), this.gridY.center(2));
    rect2.alpha = 0.5;

spancenterの引数には小数値も指定できますので、位置の微調整が可能です。

任意の幅とグリッド数で独自にGridを作成することができます。

Grid({
  width: グリッド全体の幅,
  columns: グリッドの数,
  loop: spanにマイナス値を指定できるかどうか(任意),
  offset: オフセット値(任意)
});

x, y それぞれ用意します。

    var starGridX = Grid({
      width: 320,
      columns: 10,
      offset: 100
    });
    var starGridY = Grid({
      width: 160,
      columns: 5,
      offset: 320
    });

    (10).times(function(spanX) {
      (5).times(function(spanY) {
        var star = StarShape({
          radius: 12,
        }).addChildTo(starGroup);
        star.setPosition(starGridX.span(spanX), starGridY.span(spanY));
      });
    });

2-6. テキスト描画(Label)

文字を配置するには、Labelを使います。

  • Label(文字)を表示する
  • Labelの文字サイズを変更する
  • Labelのフォントを変更する
  • Labelの文字を変更する
  • Labelの文字色を変更する
  • Labelの枠の色を変更する
  • Labelの幅と高さを調べる
// ラベル表示
var label = Label('Time is money').addChildTo(this);
label.setPosition(this.gridX.center(), this.gridY.center());

フォントサイズ・フォント、色も変更できます。

var label2 = Label('Time is money').addChildTo(this);
label2.setPosition(320, 600);
label2.fontFamily = "'sans-serif'";
label2.fontSize = 48;
label2.fill = 'red';

後から文字を変更できます。

// ラベル文字変更
this.onpointstart = function() {
  label.text = 'Money is time';
};

文字列に応じたラベルの大きさを計測することができます。

var height = label.calcCanvasHeight();
var width = label.calcCanvasWidth();

3. 画像データの描画(Sprite)

画像描画の基本は Sprite です13

Sprite は、Shape と同じ基底クラスを継承していますので、共通のプロパティやメソッドを使用することができます。

  • Spriteを表示して位置を指定する
  • Spriteを回転・拡大縮小させる
  • Spriteのサイズを指定する
  • Spriteを透明にする
  • Spriteの向きを反転させる

3-1. 画像データを読み込んで表示する

画像データを表示するには、(1)事前にアセットの定義し、(2)ゲームエンジンで読み込んでから、(3)シーン内で表示します。

アセット定義では、image の連想配列にファイル名を登録します。

// アセット
var ASSETS = {
  // 画像
  image: {
    'tomapiko': 'https://cdn.jsdelivr.net/gh/phinajs/phina.js@develop/assets/images/tomapiko.png',
  },
};

GameAppの生成時に、assets要素に定義したオブジェクトを設定します。

phina.main(function() {
  var app = GameApp({
    startLabel: 'main',
    // アセット読み込み
    assets: ASSETS,
  });
  app.run();
});

シーン内で表示するときには、Spriteのパラメータに設定したラベルを入れるだけで大丈夫です。

Sprite('tomapiko').addChildTo(this).setPosition(320, 480);

3-2. 回転・拡大率・サイズ・透明・反転など

sp2.rotation = 45;
Sprite('tomapiko').addChildTo(this).setPosition(320, 700).setRotation(15);

sp1.width = 128;
Sprite('tomapiko').addChildTo(this).setPosition(320, 480).setSize(128, 128);

向きを反転するには、ScaleX, ScaleY に負の数を入れます。

// 画面タッチ時処理
this.onpointstart = function() {
  // 横向き反転
  sprite.scaleX *= -1;
};

3-3. アニメーションとスプライトシート

Spriteは、スプライトシートを元にアニメーションを設定できます。
スプライトシート画像とは、アニメーション用のコマをシートの様に並べた画像です。

アセットでスプライトシートの情報を登録しておきます。

// アセット
var ASSETS = {
  // 画像
  image: {
    'tomapiko': 'https://cdn.jsdelivr.net/gh/phinajs/phina.js@develop/assets/images/tomapiko_ss.png',
  },
  // スプライトシート
  spritesheet: {
    "tomapiko_ss":
    {
      // フレーム情報
      "frame": {
        "width": 64, // 1フレームの画像サイズ(横)
        "height": 64, // 1フレームの画像サイズ(縦)
        "cols": 6, // フレーム数(横)
        "rows": 3, // フレーム数(縦)
      },
      // アニメーション情報
      "animations" : {
        "walk": { // アニメーション名
          "frames": [12,13,14], // フレーム番号範囲
          "next": "walk", // 次のアニメーション
          "frequency": 6, // アニメーション間隔
        },
      }
    },
  }
};

フレームアニメーション設定は外部ファイルとして定義して、アセットとして読み込むことができます。

// アセット
var ASSETS = {
  // 画像
  image: {
    'tomapiko': 'https://cdn.jsdelivr.net/gh/phinajs/phina.js@develop/assets/images/tomapiko_ss.png',
  },
   // フレームアニメーション情報
  spritesheet: {
    'tomapiko_ss': 'https://cdn.jsdelivr.net/gh/phinajs/phina.js@develop/assets/tmss/tomapiko.tmss',
  },
};

スプライトシートからSpriteを生成するには、width, heightを指定します。

// スプライト画像作成
var sprite = Sprite('tomapiko', 64, 64).addChildTo(this);

登録したフレームアニメーションをアタッチすると、アニメーションを開始できます。

// スプライトにフレームアニメーションをアタッチ
var anim = FrameAnimation('tomapiko_ss').attachTo(sprite);
// アニメーションを指定する
anim.gotoAndPlay('walk');

フレームアニメーションは update で自動で管理されています。

爆発など、アニメーション終了後に消える処理では、anim.finished で判定します14

// 毎フレーム処理
update: function() {
  // アニメーションが終わったら自身を消去
  if (this.anim.finished) { // ←ここで判定
    this.remove();
    console.log('removed');
  }
},

4. 入力を受け付ける(イベント)

ユーザーの入力を受け付ける主な方法として、
update(app) 15

  // 更新
  update: function(app) {
    var p = app.pointer;

    if (p.getPointing()) {
      var diff = this.player.x - p.x;
      if (Math.abs(diff) > SPEED) {
        if (diff < 0) {
          this.player.x += SPEED;
          this.player.scaleX = -1;
        } else {
          this.player.x -= SPEED;
          this.player.scaleX = 1;
        }
/* ... */

onpointstartなどオブジェクトへのイベント16があります。

    this.onpointstart = function(e) {
      var p = e.pointer;
      var wave = Wave().addChildTo(this);
      wave.x = p.x;
      wave.y = p.y;
    };

4-1. タッチイベント

マウス操作は「タッチイベント」として処理されます17

  • タッチイベントを設定する
  • タッチされた座標を調べる
  • タッチイベントの種類を理解する

オブジェクトへのタッチ処理を定義する。

// タッチ可能にする
shape.setInteractive(true);
// タッチイベント登録
// シーンにタッチイベント登録
this.onpointstart = function(e) {
  // タッチされた座標を調べる
  var tx = e.pointer.x;
  var ty = e.pointer.y;
  // タッチされた座標にShapeを移動
  shape.setPosition(tx, ty);
};

パラメータ e にタッチイベントの詳細が入っています。
e.pointer からタッチされた座標を参照できます。

4-2. app.keyboard

update中に、app.keyboardを取得すると、入力中のキーが取得できます。

// 毎フレーム処理
this.update = function(app) {
  var key = app.keyboard;
  // 移動
  if (key.getKey('left')) {
    shape.x -= SPEED;
  }
  // キーダウン

  if (key.getKeyDown('right')) {
    label1.text = 'getKeyDown: right';
  }
  // キーアップ
  }
  if (key.getKeyUp('up')) {
    label2.text = 'getKeyUp: up';
  }
};

矢印キーの入力は、角度やベクトルでも取得できます。

// キーの方向をangleで取得
var angle = key.getKeyAngle();
label4.text = 'angle:' + angle; // left >> 180

// キーの方向を正規化した値eで取得
var direction = key.getKeyDirection();
label5.text = 'direction:' + direction; // left >> {x:-1, y:0}

4-3. キーイベントの処理を追加

オブジェクトにキーイベント時の操作を追加することもできます。

// キーアップイベント
this.onkeyup = function(e) {
  label3.text = 'onkeyup: ' + e.keyCode + ':' + String.fromCharCode(e.keyCode);
};

(補足)

  1. Spriteクラスを継承して独自のクラスを作る|phina.js Tips集 下巻
  2. <シェイプ編>|phina.js Tips集 上巻
  3. Shapeをシーンに表示する|phina.js Tips集 上巻
  4. Shapeを透明・非表示にする|phina.js Tips集 上巻
  5. Shapeの位置を指定する|phina.js Tips集 上巻
  6. Shapeのサイズを指定する|phina.js Tips集 上巻
  7. Shapeを回転させる|phina.js Tips集 上巻
  8. Shapeを拡大・縮小させる|phina.js Tips集 上巻
  9. Shapeの背景色を指定する|phina.js Tips集 上巻
  10. Shapeの原点を変更する|phina.js Tips集 上巻
  11. Element::remove –phina.js/element.js at develop · phinajs/phina.js · GitHub
  12. 【phina.js】Gridクラスを使いこなそう
  13. <スプライト編>|phina.js Tips集 上巻
  14. https://runstant.com/alkn203/projects/6c71743a
  15. Walk Tomapiko – phina.js
  16. Touch Game – phina.js
  17. <イベント編>|phina.js Tips集 上巻
QRコードを読み込むと、関連記事を確認できます。

[phina.js] ゲーム内で表示できるオブジェクトの基本
【スポンサーリンク】
タイトルとURLをコピーしました