JavaScript Canvas游戏如何从数组生成多图片不同类型敌人
问题排查与修复方案
核心错误点
- draw方法引用错误:Enemy类的draw方法中直接使用
img变量,未指向实例自身的this.img属性,导致绘制时找不到目标图片对象。 - enemies数组逻辑混乱:
createEnemies的定时器回调中先执行enemies.length = 6,会直接截断数组清空之前生成的有效敌人实例;同时循环内把Image对象直接存入enemies数组,后续遍历执行draw、move方法时,Image对象没有这两个方法,会导致执行异常。 - 图片加载逻辑错误:每次生成敌人时才动态创建Image实例赋值src,图片未完成加载就执行绘制操作,导致图片无法正常渲染。
- 敌人坐标逻辑问题:所有生成的敌人x坐标都固定为300,多个敌人会完全重叠,无法区分显示。
修复后完整代码
/** @type {HTMLCanvasElement} */ const canvas = document.getElementById("canvas"); const ctx = canvas.getContext("2d"); const backgroundImg = document.getElementById("background"); const playerImg = document.getElementById("player"); canvas.width = 800; canvas.height = 500; // 预加载所有敌人图片 const ENEMY_IMG_COUNT = 6; const enemyImages = []; // 预加载完成后再启动游戏逻辑 let imgLoadedCount = 0; for (let i = 1; i <= ENEMY_IMG_COUNT; i++) { const img = new Image(); img.src = `./images/enemy_${i}.png`; img.onload = () => { imgLoadedCount++; if (imgLoadedCount === ENEMY_IMG_COUNT) { // 所有图片加载完成后启动游戏 createGame(); createEnemies(); } } enemyImages.push(img); } let enemies = []; class Enemy { constructor(img, x, y, w, h, speed) { this.img = img; this.x = x; this.y = y; this.w = w; this.h = h; this.speed = speed; } draw() { // 修正为使用实例自身的img属性 ctx.drawImage(this.img, this.x, this.y, this.w, this.h); } move() { this.x = this.x - this.speed; } } function createEnemies() { setInterval(() => { let w = 40; let h = 72; // x坐标改为画布最右侧,和原单图逻辑一致 let x = canvas.width; let y = Math.random() * Math.abs(canvas.height - h); let speed = 5; // 随机选一张敌人图片 const randomImg = enemyImages[Math.floor(Math.random() * ENEMY_IMG_COUNT)]; // 直接往数组里加敌人实例,不要修改数组长度 enemies.push(new Enemy(randomImg, x, y, w, h, speed)); }, 2000); } function createGame() { ctx.clearRect(0, 0, canvas.width, canvas.height); enemies.forEach((enemy) => { enemy.draw(); enemy.move(); }); requestAnimationFrame(createGame); }
内容的提问来源于stack exchange,提问作者BlueJean
相关产品推荐
相关产品推荐

