マリオみたいなゲームを作ろうその4(p5.js)

p5.js

今回は敵を動かします。
ちゃちゃっと作るつもりが、敵に落下判定も付けることになったので、時間が掛かってしまいました。
それでは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;
  }
}

次回はカメラを調整して見やすくします。
それではまた次回。

コメント


タイトルとURLをコピーしました