****でゴニョゴニョしてみたログ

ブログタイトルは仮。興味のある技術などのメモ書きを行う方針。まずはtmlib.jsを触っていきます。

tmlib.jsでシューティング風なクソゲーを作る02 - 敵を実装

今回やったこと

前回の続きです。今回は的(敵)を出現させる部分を作りたいと思います。

まずは動くものを

敵がひたすら湧いてくるだけ。当たり判定はまだ付けていません。

追加したEnemyオブジェクト

全体は以下のとおり。

var ENEMY_DELAY_GROUP = [0, 30, 15, 8, 45];

var GO_LEFT = -1;
var GO_RIGHT = 1;

var OFFS_Y = ENEMY_HEIGHT + 4;// マージンを持たせる

tm.define("Enemy", {
  superClass: "tm.display.AnimationSprite",

  init: function () {
    
    var enemySS = tm.asset.SpriteSheet({
      image: "enemy",
      frame: {
        width: 32,
        height: 32,
        count: 18
      },
      animations: {
        "walkLeft": [13, 15, "walkLeft", 8],
        "walkRight": [16, 18, "walkRight", 8]
      }
    });

    this.superInit(enemySS, ENEMY_WIDTH, ENEMY_HEIGHT);

    //this.blendMode = 'lighter';
    this.cnt_delay = 0;

    // 移動方向を決定
    var dir = tm.util.Random.randint(0, 65535);
    // とりあえず単純に50%で
    var go_dir = GO_RIGHT;
    if (dir <= 32767) {
      go_dir = GO_LEFT;
    }
    var speed = tm.util.Random.randint(1, 3) * 2.6 + 4;
    this.v = tm.geom.Vector2(speed * go_dir, 0);

    // オフセットを決めて的が重ならないようにする
    this.position.y = tm.util.Random.randint(0, 8) * OFFS_Y + ENEMY_TOP_LIMIT;
    if (GO_LEFT == go_dir) {
      this.gotoAndPlay("walkLeft");
      this.position.x = SCREEN_WIDTH + ENEMY_WIDTH;
    } else {
      this.gotoAndPlay("walkRight");
      this.position.x = -ENEMY_WIDTH;
    }

    // 出現のディレイを決定(めんどいのでまんま乱数を使う。テーブルを使うかは後で検討)
    var idx = tm.util.Random.randint(0, 4);
    this.cnt_delay = ENEMY_DELAY_GROUP[idx];


  },

  update: function () {
    // 出現時間まで待機
    if (this.cnt_delay <= 0) {
      if (0 == this.checkMoveArea()) {
        this.position.add(this.v);
      }else {
        this.cnt_delay = 200000;
        this.remove();
        this.flare("onRemove");
      }
    } else {
      this.cnt_delay--;
    }
  },

  checkMoveArea: function () {
    var is_kill = 0;
    if (this.v.x > 0) {
      if (this.position.x > SCREEN_WIDTH + ENEMY_WIDTH) {
        is_kill = 1;
      }
    } else {
      if (this.position.x < -ENEMY_WIDTH) {
        is_kill = 1;
      }
    }

    return is_kill;
  }

});

スプライトシートを使って表示させています。 挙動としては左方向、右方向に直進し続けるだけのものです。色々と手抜きしているので全体が完成したら動きの部分は検討する余地がありますね。

これといって複雑なことはしていません。画面外に出たら"onRemove"というイベントを発火させています。

追加したコードの概要

コードで言うと、この箇所です。

this.enemyPool = new tm.display.CanvasElement().addChildTo(this);
for(var i=0; i<NUMBER_OF_ENEMY; i++) {
  this.createEnemy();
}

出現させる敵の数だけループを回してEnemyオブジェクトを生成します。createEnemyの実装は以下のとおりです。

createEnemy: function() {
  var self = this;

  var enemy = new Enemy().addChildTo(self.enemyPool)
    .on("onRemove", function(e){
      self.renewEnemy();
    });
  this.cntEnemy++;
},

Enemyオブジェクトを作ってenemyPoolというCanvasEelementに追加します。そのままメソッドチェーンで"onRemove"イベントのハンドラを実装しています。その後は敵カウンタをインクリメントしているだけです。renewEnemyはこんな感じに実装しています。

renewEnemy: function () {
  var self = this;

  this.cntEnemy--;

  if (this.cntEnemy === 0) {
    for(var i=0; i<NUMBER_OF_ENEMY; i++) {
      this.createEnemy();
    }
  }
},

呼び出されると敵カウンタをデクリメントし、1体も敵がいなくなったら、また敵を一括で生成します。

次回

当たり判定を付けて行きたいと思います。まずは敵と機雷あたりから。