You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

面向对象JavaScript:如何创建并运行同一对象的多个实例?

面向对象JavaScript躲避方块游戏开发指南

嘿,很高兴看到你用做游戏来学习OOP JavaScript,这绝对是最有趣的学习方式之一!既然你的Player对象已经正常运行,主循环的定时器也搭好了,那我们一步步把剩下的核心功能补全,让游戏真正跑起来吧。

1. 敌人方块的OOP实现

先给敌人也创建一个类,和你的Player保持一致的面向对象风格,代码结构会更清晰:

class Enemy {
  constructor(x, y, width, height, speed) {
    this.x = x;
    this.y = y;
    this.width = width;
    this.height = height;
    this.speed = speed;
  }

  // 敌人从右向左移动的逻辑
  update() {
    this.x -= this.speed;
  }

  // 绘制敌人方块
  draw(ctx) {
    ctx.fillStyle = '#ff4444'; // 用红色区分玩家方块
    ctx.fillRect(this.x, this.y, this.width, this.height);
  }
}

2. 敌人的生成与管理

在主循环外创建一个数组来存储所有敌人,再定时生成新的敌人(避免一次性生成太多,影响游戏体验):

const enemies = [];
// 每1.5秒生成一个随机位置的敌人
const enemySpawnInterval = setInterval(() => {
  // 随机生成y坐标,确保敌人在画布范围内
  const randomY = Math.random() * (canvas.height - 50);
  enemies.push(new Enemy(canvas.width, randomY, 50, 50, 3));
}, 1500);

3. 主循环的核心逻辑完善

把敌人的更新、绘制,以及关键的碰撞检测逻辑,都整合到你的主循环里:

// 启动主循环(建议用requestAnimationFrame替代setInterval,更流畅)
function mainLoop() {
  // 先清空画布,避免方块移动留下残影
  ctx.clearRect(0, 0, canvas.width, canvas.height);

  // 更新并绘制玩家
  player.update();
  player.draw(ctx);

  // 遍历敌人列表:更新位置、绘制、清理超出屏幕的敌人
  for (let i = enemies.length - 1; i >= 0; i--) {
    const enemy = enemies[i];
    enemy.update();
    enemy.draw(ctx);

    // 移除左侧超出屏幕的敌人,节省性能
    if (enemy.x + enemy.width < 0) {
      enemies.splice(i, 1);
    }

    // 检测玩家与敌人是否碰撞
    if (checkCollision(player, enemy)) {
      gameOver();
      return; // 碰撞后直接终止当前循环
    }
  }

  // 持续调用循环,和浏览器刷新同步
  requestAnimationFrame(mainLoop);
}

// 矩形碰撞检测函数(通用逻辑,适用于玩家和敌人)
function checkCollision(rect1, rect2) {
  return rect1.x < rect2.x + rect2.width &&
         rect1.x + rect1.width > rect2.x &&
         rect1.y < rect2.y + rect2.height &&
         rect1.y + rect1.height > rect2.y;
}

// 游戏结束处理函数
function gameOver() {
  clearInterval(enemySpawnInterval); // 停止生成敌人
  ctx.fillStyle = '#000';
  ctx.font = '48px Arial';
  ctx.textAlign = 'center';
  ctx.fillText('Game Over!', canvas.width / 2, canvas.height / 2);
}

// 启动游戏
mainLoop();

4. 玩家移动的完善(如果还没实现的话)

给你的Player类加上键盘控制逻辑,让玩家能上下移动躲避敌人:

class Player {
  constructor(x, y, width, height, speed) {
    this.x = x;
    this.y = y;
    this.width = width;
    this.height = height;
    this.speed = speed;
    // 记录按键状态,避免按住按键时移动不连贯
    this.keys = { up: false, down: false };
    
    // 绑定键盘事件
    document.addEventListener('keydown', (e) => this.handleKeyDown(e));
    document.addEventListener('keyup', (e) => this.handleKeyUp(e));
  }

  handleKeyDown(e) {
    if (e.key === 'ArrowUp') this.keys.up = true;
    if (e.key === 'ArrowDown') this.keys.down = true;
  }

  handleKeyUp(e) {
    if (e.key === 'ArrowUp') this.keys.up = false;
    if (e.key === 'ArrowDown') this.keys.down = false;
  }

  update() {
    // 上下移动,同时限制玩家不出画布边界
    if (this.keys.up && this.y > 0) {
      this.y -= this.speed;
    }
    if (this.keys.down && this.y + this.height < canvas.height) {
      this.y += this.speed;
    }
  }

  draw(ctx) {
    ctx.fillStyle = '#4285f4'; // 蓝色玩家方块
    ctx.fillRect(this.x, this.y, this.width, this.height);
  }
}

// 初始化玩家(比如放在画布左侧中间位置)
const player = new Player(50, canvas.height/2 - 25, 50, 50, 5);

一些进阶小提示

  • 可以给敌人设置随机速度,让游戏难度随时间递增;
  • 加入分数系统,每躲过一个敌人加1分,增强游戏趣味性;
  • 用requestAnimationFrame替代setInterval做主循环,它会和浏览器刷新节奏同步,游戏更流畅,也更节省系统资源。

内容的提问来源于stack exchange,提问作者Jakub Chaloupka

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.19 09:10:36