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

HTML5 Canvas游戏地面不显示问题排查求助

HTML5 Canvas游戏地面瓦片无法渲染问题排查

问题描述

正在开发一款基于JavaScript的HTML5 Canvas游戏,地面瓦片无法显示。已创建Ground类表示地面瓦片,在start循环中调用渲染方法,但地面未渲染到Canvas上。Canvas背景及其他游戏元素显示正常,检查过构造函数、位置计算和渲染循环后仍未找到原因。

关键代码片段:

class Ground {
    constructor(x, num, src) {
        this.canvas = canvas;
        this.context = this.canvas.getContext('2d');
        this.ground = new Image();
        this.ground.src = src;
        this.width = this.ground.width;
        this.height = this.ground.height;
        this.position = {
            x: (x + this.width) * num,
            y: this.canvas.height - this.width,
        };
    }

    create() {
        let context = this.context;
        context.drawImage(this.ground, this.position.x, this.position.y, this.width, this.height);
    }
}

const canvas = document.querySelector('#canvas');
canvas.style.background = "#f9f9f9";
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;

const ground = [];
for (let i = 0; i < 100; i++) {
    let src = 'src/Tiles/Tile (2).png';
    ground[i] = new Ground(0, i, src);
}

let start = () => {
    requestAnimationFrame(start);

    ground.forEach(ground => {
        ground.create();
        if (player.position.y + player.height <= ground.position.y && player.position.y + player.height + player.velocity.y >= ground.position.y && player.position.x + player.width >= ground.position.x && player.position.x <= ground.position.x + ground.width) {
            player.velocity.y = 0;
            doJump = true;
        }
        zombies.forEach(zombie => {
            if (zombie.position.y + zombie.height <= ground.position.y && zombie.position.y + zombie.height + zombie.velocity.y >= ground.position.y && zombie.position.x + zombie.width >= ground.position.x && zombie.position.x <= ground.position.x + ground.width) {
                zombie.velocity.y = 0;
            }
        });
    });
}

start();

排查与解决方案

1. 图片异步加载导致渲染无效

new Image()设置src后是异步加载的,构造函数中直接获取this.ground.width和this.ground.height时,图片尚未加载完成,这两个值为0,后续绘制宽高为0的元素自然看不到。同时调用create()时图片可能还没加载好,drawImage不会执行。

修复方式:
给图片添加load事件监听,确保加载完成后再初始化宽高、位置,并标记加载状态,绘制前检查状态:

class Ground {
    constructor(x, num, src) {
        this.canvas = canvas;
        this.context = this.canvas.getContext('2d');
        this.ground = new Image();
        this.isLoaded = false;
        // 图片加载完成后初始化参数
        this.ground.onload = () => {
            this.width = this.ground.width;
            this.height = this.ground.height;
            this.position = {
                x: (x + this.width) * num,
                y: this.canvas.height - this.height,
            };
            this.isLoaded = true;
        };
        this.ground.src = src;
    }

    create() {
        // 未加载完成则跳过绘制
        if (!this.isLoaded) return;
        this.context.drawImage(this.ground, this.position.x, this.position.y, this.width, this.height);
    }
}

2. 地面Y轴位置计算错误

原构造函数中y: this.canvas.height - this.width,这里误用了width代替height,如果瓦片宽高不一致,地面会被绘制到Canvas可视区域之外(比如宽大于高时,y值会超出底部),修改为this.canvas.height - this.height即可。

3. 额外检查点

  • 确认图片路径src/Tiles/Tile (2).png是否正确,可在浏览器控制台查看是否有404错误;
  • 若渲染循环未清除画布,后续帧会叠加,但这不是本次不显示的核心原因,可按需在start函数开头添加context.clearRect(0, 0, canvas.width, canvas.height)。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.06 11:32:04