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

Canvas游戏开发:草块Tile无法正常渲染的问题求助

Canvas游戏草块Tile无法显示的修复方案

问题根源

你的代码存在两个核心问题导致草块无法绘制:

  1. Map类未正确引用全局变量:Map类的grassLand方法中使用了this.tiley、this.tilex、this.tileSize、this.tiles,但这些变量是全局定义的,并非Map实例的属性,导致循环条件不成立,根本没执行绘制逻辑。
  2. 图片异步加载未处理:Image对象加载是异步的,游戏循环启动时草块图片可能还没加载完成,调用drawImage时图片资源无效,自然无法显示。

修复步骤

  1. 修正Map类的变量引用:将this.xxx改为直接访问全局变量,或者把这些变量作为参数传入Map类(后者更符合封装原则)。
  2. 等待图片加载完成再启动游戏:监听所有图片的load事件,等全部加载完毕后再启动游戏循环。

修复后的完整代码

var canvas = document.getElementById("canvas");
var ctx = canvas.getContext('2d');

canvas.width = window.innerWidth;
canvas.height = window.innerHeight;

// Variables
var tileSize = 32;
var tilex = Math.ceil(canvas.width / tileSize);
var tiley = Math.ceil(canvas.height / tileSize);
var tiles = [];
var player = [];
var playerState = 'idle';
var keyPresses = {};
var userSize = 128;
var loadedImagesCount = 0;
var totalImages = 156 + 40; // 156个tile图 + 40个玩家图

// Event Listeners
window.addEventListener('keydown', keyDownListener, false);
function keyDownListener(event) {
  keyPresses[event.key] = true;
};

window.addEventListener('keyup', keyUpListener, false);
function keyUpListener(event) {
  keyPresses[event.key] = false;
  playerState = 'idle';
};

// 图片加载完成计数函数
function checkAllImagesLoaded() {
  loadedImagesCount++;
  if (loadedImagesCount === totalImages) {
    // 所有图片加载完成后启动游戏循环
    setInterval(gameLoop, 1000/24);
  }
}

//TileImages grass, stone, and structure
for (let i = 0; i < 156; i++) {
    tiles[i] = new Image();
    tiles[i].src = 'performanceTask Assets/tiles/tile' + i.toString() + '.png';
    tiles[i].onload = checkAllImagesLoaded;
};

//Player Images idle and movement
for (let i = 0; i < 40; i++) {
    player[i] = new Image();
    player[i].src = 'performanceTask Assets/player/player' + i.toString() + '.png';
    player[i].onload = checkAllImagesLoaded;
};

class Map {
    xTileLocation = 0;
    yTileLocation = 0;
    grassLand() {
        // 直接使用全局变量,或者可以在构造函数传入这些参数
        for (let i = 0; i < tiley; i++) {
            for (let j = 0; j < tilex; j++) {
                ctx.drawImage(tiles[0], this.xTileLocation, this.yTileLocation, tileSize, tileSize);
                this.xTileLocation += tileSize;
            };
            this.xTileLocation = 0;
            this.yTileLocation += tileSize;
        };
        this.xTileLocation = 0;
        this.yTileLocation = 0;
    };
};

class Player {
    x = canvas.width/2;
    y = canvas.height/2;

    tick = 0;
    playerImage = player;
    state = playerState;

    movementSpeed = 5;
    draw() {
        this.state = playerState

        // Movement
        if (keyPresses.w) {
            this.y -= this.movementSpeed;
            playerState = 'moving';
        }
        if (keyPresses.s) {
            this.y += this.movementSpeed;
            playerState = 'moving';
        }
        if (keyPresses.a) {
            this.x -= this.movementSpeed;
            playerState = 'moving';
        }
        if (keyPresses.d) {
            this.x += this.movementSpeed;
            playerState = 'moving';
        }

        // IDLE STATE
        if (this.state == 'idle') {
            if(this.tick==20 || this.tick > 20) {
                this.tick = 0;
            };
            ctx.drawImage(this.playerImage[this.tick], this.x - 64, this.y + 64, 128, 128);
        }
        else {
            if (this.state == 'moving') {
                if(this.tick < 21 || this.tick == 39) {
                    this.tick = 21;
                };
                ctx.drawImage(this.playerImage[this.tick], this.x -64, this.y + 64, 128, 128);
            }
        }
        this.tick = this.tick + 1;
    };
};

let user = new Player();
let map = new Map();
function gameLoop() {
    ctx.clearRect(0, 0, canvas.width, canvas.height);
    map.grassLand();
    user.draw();
};

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.25 17:47:08