読者です 読者をやめる 読者になる 読者になる

凹みTips

C++、JavaScript、Unity、ガジェット等の Tips について雑多に書いています。

Canvas を使ってみんなもお手軽に弾幕作ろうぜ!! - 其の弐 -

JavaScript HTML5

はじめに

前回、N-way 弾を発射するところまでやりました。今回は敵を表示するところを書いてみたいと思います。

用意する画像

オリジナルサイズ

拡大


こんな敵の画像を用意しておきます。横方向は時間経過によるアニメーション、縦方向が向きです。
ではこのドット絵をよしなに動かしてみましょう。
更新のある場所だけ以下に抜粋します。

// direction
const DIRECTION = {
	LEFT        : 0,
	LEFT_FRONT  : 1,
	FRONT       : 2,
	RIGHT_FRONT : 3,
	RIGHT       : 4,
};

/* ------------------------------------------------------------------------- */
//  Containers
/* ------------------------------------------------------------------------- */
var Bullets        = new Container();
var BulletCurtains = new Container();
var Enemies        = new Container(); // 追加

/* ------------------------------------------------------------------------- */
//  Enemy
/* ------------------------------------------------------------------------- */
var Enemy = function(enemy) {
	Mover.call(this, enemy);
};
Enemy.prototype = $.extend({}, Mover.prototype, {
	move : function() {
		Mover.prototype.move.apply(this);
		this.shot();
	},
	draw : function() {
		// direction
		var vx = this.vx, vy = Math.abs(this.vy);
		if      ( vx/vy < -2   ) this.sy = this.h * DIRECTION.LEFT;
		else if ( vx/vy < -0.5 ) this.sy = this.h * DIRECTION.LEFT_FRONT;
		else if ( vx/vy >  2   ) this.sy = this.h * DIRECTION.RIGHT;
		else if ( vx/vy >  0.5 ) this.sy = this.h * DIRECTION.RIGHT_FRONT;
		else                     this.sy = this.h * DIRECTION.FRONT;

		// animation
		this.sx = this.w * (((this.cnt/5)|0) % 3);

		Mover.prototype.draw.apply(this);
	},
	shot : function() {},
});

/* ------------------------------------------------------------------------- */
//  Main
/* ------------------------------------------------------------------------- */
function main() {
	var frame = 0;
	setInterval(function(){
		if (frame%60 === 0) {
			//...(略)
			Enemies.add(
				new Enemy({
					x   : WIDTH/2,
					y   : -MARGIN,
					vx  : -2.5 + Math.random()*5,
					vy  : 1,
					key : 'enemy.red',
				})
			);
		}

		var containers = [BulletCurtains, Enemies, Bullets];
		for (var i in containers) containers[i].move();
		Canvas.clear();
		for (var i in containers) containers[i].draw();

		++frame;
	}, 1000/FPS);
}


速度に応じて向きが変わるようになります。
ただ、このままでは敵と弾がバラバラなので敵から弾が発射されるようにしてみましょう。3-Way 弾を発射する敵クラス Enemy3Way を作成してみます。

/* ------------------------------------------------------------------------- */
//  Enemy Variations
/* ------------------------------------------------------------------------- */
// shooting 3-way bullets curtain
var Enemy3Way = function(enemy) {
	Enemy.call(this, enemy);
}
Enemy3Way.prototype = $.extend({}, Enemy.prototype, {
	move : function() {
		this.vx = 5*Math.sin(Math.PI/30 * this.cnt);
		Enemy.prototype.move.call(this);
	},
	shot : function() {
		if (this.cnt%60 === 1) {
			BulletCurtains.add(
				new BC_NWay({
					nway   : 3,
					x      : this.x,
					y      : this.y,
					v      : 5,
					ang0   : Math.PI/2,
					dang   : Math.PI/10,
					num    : 8,
					period : 5,
					color  : COLOR.RED,
					key    : 'bullet.normal',
				})
			);
		}
	},
});

/* ------------------------------------------------------------------------- */
//  Main
/* ------------------------------------------------------------------------- */
function main() {
	var frame = 0;
	setInterval(function(){
		if (frame%60 === 0) {
			Enemies.add(
				new Enemy3Way({
					x   : (Math.random() + 0.5)*WIDTH/2,
					y   : -MARGIN,
					vx  : -2 + Math.random()*5,
					vy  : 2,
					key : 'enemy.red',
				})
			);
		}

		var containers = [BulletCurtains, Enemies, Bullets];
		for (var i in containers) containers[i].move();
		Canvas.clear();
		for (var i in containers) containers[i].draw();

		++frame;
	}, 1000/FPS);
}

});

BC_NWay の生成場所を Enemy.x、Enemy.y にしました。あとついでに敵をゆらゆら動かすようにしてみました。さてさてどうでしょう。

あれ、なんか違う。敵から発射されてるように見えないです。さて、なんででしょう?
これは、BC_NWay を作った瞬間の Enemy.x と Enemy.y の位置から全弾発射するようになっているからです。こうではなくて、敵のいる場所から常に発射されるようにしたいですね。ということで以下のように変更します。

Enemy3Way.prototype = $.extend({}, Enemy.prototype, {
	//...(略)
	shot : function() {
		var cnt = this.cnt%180;
		if (cnt < 90 && cnt%5 === 0) {
			BulletCurtains.add(
				new BC_NWay({
					nway   : 3,
					x      : this.x,
					y      : this.y,
					v      : 5,
					ang0   : Math.PI/2,
					dang   : Math.PI/10,
					num    : 1,
					period : 0,
					color  : COLOR.RED,
					key    : 'bullet.normal',
				})
			);
		}
	},
});


N-Way 弾を単発で打つように変更しました。これで敵の動きに合わせて sin カーブを1周期きれいに描くようになりました!

ここまでのコード

だんまくさんぷる5

おわりに

次は自機を表示して操作するところを紹介したいと思います。