今回は敵を動かします。
ちゃちゃっと作るつもりが、敵に落下判定も付けることになったので、時間が掛かってしまいました。
それではsprite.jsから見ていきます。
あまり変わってないように見えますが、敵クラスにspeed、directionを追加しました。
speedは敵の動く速度、directionは動く方向です。
class Mine {
constructor(x, y, vy, gridSize) {
this.x = x;
this.y = y;
this.w = gridSize;
this.h = gridSize;
this.vy = vy;
this.isJumping = false;
this.isAlive = true;
this.speed = 2;
this.direction = 1;
}
show() {
fill(255, 0, 0);
rect(this.x, this.y, this.w, this.h);
}
move() {
if (keyIsDown(LEFT_ARROW)) {
this.x -= 5;
}
// 右の矢印キーが押されている場合
if (keyIsDown(RIGHT_ARROW)) {
this.x += 5;
}
}
}
// 敵クラス
class Enemy {
constructor(x, y, vy, gridSize) {
this.x = x;
this.y = y;
this.w = gridSize;
this.h = gridSize;
this.vy = vy;
this.isAlive = true;
this.speed = 2;
this.direction = 1;
}
// 敵を描画
show() {
fill(0, 0, 255);
rect(this.x, this.y, this.w, this.h);
}
move() {
this.x += this.speed * this.direction;
if (this.x <= 0 || this.x + this.w >= width) {
this.direction *= -1;
}
}
}
class Block {
constructor(x, y, w, h) {
this.x = x;
this.y = y;
this.w = w;
this.h = h;
}
show() {
fill(139, 69, 19);
rect(this.x, this.y, this.w, this.h);
}
}
続いてsketch.jsです。
主に書き換えたのは敵の描画の所です。
enemyFutureYは敵の将来のy座標です。
画面を更新するごとに子の変数の値でy座標を更新します。(自機と同じ処理ですが)
directionはー1を掛けると方向転換する仕組みになっています。
let player;
let blocks = [];
let enemies = [];
let gridSize = 40;
function setup() {
createCanvas(800, 400);
// プレイヤー初期設定
player = new Mine(50, 300, 0, gridSize);
// ブロック(地面を含む)を配置
blocks = [
new Block(200, 250, 100, 20),// 通常ブロック
new Block(400, 200, 100, 20),// 通常ブロック
new Block(600, 300, 100, 20),// 通常ブロック
new Block(0, height - 50, width, 50),// 地面
];
// 敵を追加
enemies = [
new Enemy(300, 210, 0, gridSize),
new Enemy(500, height - 90, 0, gridSize),
];
}
function draw() {
background(135, 206, 250);
// プレイヤーの重力処理
if (player.isAlive) {
player.show();
player.move();
}
player.vy += 1; // 重力
let futureY = player.y + player.vy; // 次のフレームのY位置
// 衝突判定
for (let block of blocks) {
if (
player.x < block.x + block.w && // 水平方向の重なり
player.x + player.w > block.x && // 水平方向の重なり
player.y + player.h <= block.y && // プレイヤーがブロックの上面にいる
futureY + player.h >= block.y // 次のフレームでブロックを通過しない
) {
futureY = block.y - player.h; // プレイヤーをブロックの上に移動
player.vy = 0; // 縦方向の速度をリセット
player.isJumping = false; // ジャンプ状態を解除
}
}
// プレイヤー位置を更新
player.y = futureY;
// 敵との衝突判定
for (let enemy of enemies) {
if (
enemy.isAlive && // 敵が生存中
player.x < enemy.x + enemy.w && // 水平方向の重なり
player.x + player.w > enemy.x && // 水平方向の重なり
player.y + player.h <= enemy.y && // プレイヤーが敵の上面にいる
player.y + player.h + player.vy >= enemy.y // 次のフレームで敵を踏む
) {
// 敵を倒す
enemy.isAlive = false;
player.vy = -10; // プレイヤーを跳ね返す
} else if (
enemy.isAlive && // 敵が生存中
player.x < enemy.x + enemy.w && // 水平方向の重なり
player.x + player.w > enemy.x && // 水平方向の重なり
player.y + player.h > enemy.y // プレイヤーが敵の上面以外に触れる
) {
player.isAlive = false;
}
}
// ブロックの描画
for (let block of blocks) {
block.show();
}
// 敵の描画
for (let enemy of enemies) {
if (enemy.isAlive) {
enemy.vy += 1; // 重力
let enemyFutureY = enemy.y + enemy.vy;
// 敵のブロックとの衝突判定
for (let block of blocks){
if (
enemy.x < block.x + block.w && // 水平方向の重なり
enemy.x + enemy.w > block.x && // 水平方向の重なり
enemy.y + enemy.h <= block.y && // 敵がブロックの上面にいる
enemyFutureY + enemy.h >= block.y // 次のフレームでブロックを通過しない
) {
enemyFutureY = block.y - enemy.h; // 敵をブロックの上に移動
enemy.vy = 0; // 縦方向の速度をリセット
}
if (
enemy.x < block.x + block.w && // 水平方向の重なり
enemy.x + enemy.w > block.x && // 水平方向の重なり
enemy.y + enemy.h > block.y && // 敵がブロックに接触
enemy.y < block.y + block.h // 敵がブロック内にいる
) {
enemy.direction *= -1; // 方向を反転
enemy.x += enemy.speed * enemy.direction; // 衝突を避ける
}
}
enemy.y = enemyFutureY;
enemy.show();
enemy.move();
}
}
}
function keyPressed() {
if (keyCode === 32 && !player.isJumping) { // スペースキーでジャンプ
player.vy = -15;
player.isJumping = true;
}
}
次回はカメラを調整して見やすくします。
それではまた次回。
コメント