シューティングゲームの弾幕って素敵ですよね。
画面いっぱいに広がる弾。
どこに行けば避けられるのか、はたまた無理ゲーなのか。
デモはこちらです。
記事はデモの抜粋なので、コピペだけでは動きません。
弾の移動には、デルタタイムを掛けると滑らかに動いて見えます。
今回はやっていません(ゴメンネ)。
処理の流れ
main.js
// メインループ
const id = setInterval(() => {
try {
// 弾管理クラスのメインループ
shotClass.forEach(e => e.roop(Canvas.getCanvasSize()));
// キャンバスのメインループ
Canvas.roop(Bullets);
} catch(error) {
console.error(error);
clearInterval(id);
}
}, 30 / 1000);
弾を管理するクラスのメインループで弾の生成・移動処理をし、キャンバスのループ内で描画処理をしています。
フロント画面の弾のオプション値を参照し、押下されたボタンの弾を生成するようにしています。
Line.js
createBullet(canvasSize) {
const directions = this.getDirection(this.directionValue);
directions.forEach(direction => {
// 弾の生成
const Bullet = new BulletClass();
// キャンバスの中心から生成する
Bullet.setPos({x: canvasSize / 2, y: canvasSize / 2});
Bullet.setSize(canvasSize / 20);
Bullet.setDirection(direction);
Bullet.setSpeed(this.speedValue);
this.Bullets.push(Bullet);
});
}
弾を直線的に飛ばすクラスです。
フロント画面のオプション値(弾の方向)から得られた値によって方向を変えています。
弾の生成位置、大きさ、進行方向、進行速度を決め、配列に追加しています。
Swirl.js
createBullet(canvasSize) {
const directions = this.getDirection(this.directionValue);
directions.forEach((direction, i) => {
// 弾の生成
const Bullet = new BulletClass();
// キャンバスの中心から生成する
Bullet.setPos({x: canvasSize / 2, y: canvasSize / 2});
Bullet.setSize(canvasSize / 20);
// 進行方向を1度づつずらす
this.rad += 1;
if(360 <= this.rad) this.rad = 0;
// 射出方向の数だけずらす
const r = this.rad + 360 / directions.length * i;
const radian = r * Math.PI / 180;
direction.x = Math.cos(radian);
direction.y = Math.sin(radian);
Bullet.setDirection(direction);
Bullet.setSpeed(this.speedValue);
this.Bullets.push(Bullet);
});
}
弾を渦巻き状に飛ばすクラスです。
弾の進行方向を少しづつ変えることで渦巻き状にいます。
自機狙い弾で似たようなことをしています。
実際は、弾は直線的に飛んでいるので、Line.js 内の処理も Swirl.js でできます。
進行方向をずらす際(10行目)、角度に足していくと右回りになり、角度から引いていくと左回りになります。(JavaScript の場合)
Canvas.js
// キャンバスの初期化
this.ctx.fillStyle = '#ffffffff';
this.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height);
this.ctx.fillStyle = '#22ee22ff';
this.ctx.strokeStyle = '#000000ff';
ShotBullet.forEach(Bullet => {
// 弾の描画
this.ctx.beginPath();
this.ctx.arc(Bullet.getPos().x, Bullet.getPos().y, Bullet.getSize(), 0, Math.PI * 2, true);
this.ctx.fill();
this.ctx.stroke();
});
弾クラスを描画する処理です。
弾クラスから位置や大きさを取得して描画しています。
Bullet.js
class BulletClass {
constructor() {
// 大きさ
this.size = 10;
// 位置
this.pos = { x: 0, y: 0 };
// 速さ
this.speed = { x:0, y: 0 };
// 方向
this.direction = { x: 0, y: 0 };
}
getSize() {
return this.size;
}
setSize(s) {
this.size;
}
getPos() {
return this.pos;
}
setPos(p) {
this.pos = p;
}
getSpeed() {
return this.speed;
}
setSpeed(s) {
if(s.hasOwnProperty('x') && s.hasOwnProperty('y')) this.speed = s;
else this.speed = {x: s, y: s};
}
getDirection() {
return this.direction;
}
setDirection(d) {
this.direction = d;
}
move(p = {x: 1, y: 1}) {
this.pos.x += this.speed.x * this.direction.x * p.x;
this.pos.y += this.speed.y * this.direction.y * p.y;
}
}
弾のクラスです。
弾の大きさや位置情報、飛んでいく速さや飛んでいく方向などを持っています。
情報を利用して、Canvas.js で描画します。
弾の移動は、【速さ * 向き】を利用しています。
Direction.js
class DirectionClass {
getDirection(d) {
switch(d) {
case 0:
return [{ x:0, y:1 }];
case 1:
return [{ x:0, y:1 }, { x:0, y:-1 }];
case 2:
return [{ x:1, y:0 }, { x: -1, y:0 }];
case 3:
return [{ x:0, y:1 }, { x:0, y:-1 }, { x:1, y:0 }, { x:-1, y:0 }];
case 4:
return [
{ x:0, y:1 }, { x:0, y:-1 }, { x:1, y:0 }, { x:-1, y:0 },
{ x:1, y:1 }, { x:-1, y:-1 }, { x:1, y:-1 }, { x:-1, y:1 }
];
default:
console.log('定義されていない方向です。とりあえず下方向に飛ばします。');
return [{ x:0, y: 1}];
}
}
}
弾の移動する向きを決めるクラスです。
canvas は通常左上を原点なので、右・下に向かうと+方向となります。