P5.js使用createGraphics合并组件图片生成游戏背景失败如何解决?
问题根因
p5.js的preload()函数仅会自动等待直接在preload作用域内调用的loadJSON/loadImage等加载方法完成,再进入setup()。你当前把createComponents()放在loadJSON的回调里执行,里面的loadImage属于异步回调内的嵌套加载,preload不会等待这些图片加载完成,导致你提前调用createGameMapImg时组件图片还未加载完成,绘制到离屏画布就会失效。
修复方案
方案1:调整加载时序,确保所有图片加载完成后再生成地图
修改createComponents方法,统计图片加载进度,所有资源加载完毕后再触发地图生成逻辑:
// createComponents方法调整 createComponents() { let totalImgs = this.componentsJSON.length; let loadedImgs = 0; this.components = this.componentsJSON.map(item => { let component = {...item}; component.img = loadImage(item.imgUrl, () => { loadedImgs++; // 所有图片加载完成后生成地图 if (loadedImgs === totalImgs) { this.gameMapImg = this.createGameMapImg(); } }); return component; }) } // preload逻辑保持不变 preload() { this.componentsJSON = loadJSON(componentsJSON, () => this.createComponents()); }
方案2:延迟调用地图生成方法
不在setup阶段直接调用生成地图的方法,移到draw()里加判断触发,生成后标记避免重复执行:
draw() { // 确认组件初始化完成、所有图片加载完成、还未生成过地图时执行生成逻辑 if (this.components && this.components.every(c => c.img && c.img.width) && !this.gameMapImg) { this.gameMapImg = this.createGameMapImg(); } // 直接绘制已生成的地图即可 if (this.gameMapImg) { image(this.gameMapImg, 0, 0); } }
冗余代码优化
你原createGameMapImg里的全局image()调用是直接画到主画布的冗余逻辑,不需要的话可以删掉:
createGameMapImg() { let gameImg = createGraphics(this.width * this.boxSize, this.height * this.boxSize); gameImg.background('white'); for (let component of this.components) { if (component.img) { gameImg.image( component.img, component.x * this.boxSize, component.y * this.boxSize, component.width * this.boxSize, component.height * this.boxSize ); } } return gameImg; }
内容的提问来源于stack exchange,提问作者Sonya
相关产品推荐
相关产品推荐

