如何基于玩家位置加载数组特定区域?(Khan Academy开发)
问题:围绕玩家加载特定区域方块优化性能
我在Khan Academy开发项目时,一次性加载约12000个方块导致性能拉胯,想改成只加载玩家周围区域的方块。
原全量加载代码
for (var i = 0; i < levels[level].length; i++) { for (var j = 0; j < levels[level][i].length; j++) { switch (levels[level][i][j]) { // 其他方块类型处理逻辑 case "b": blocks.push(new Block(j * blockwidth, i * blockheight, "block")); break; // 其他方块类型处理逻辑 } }
错误的尝试代码
我试过用constrain函数限制循环范围,但移动玩家后,出生点以外的区域根本加载不出来:
for (var i = 0; i < constrain(levels[level].length,player.y-player.y,player.y+player.y+30); i++) { for (var j = 0; j < constrain(levels[level][i].length,player.x-player.x,player.x+player.x+30); j++) { switch (levels[level][i][j]) { // 生成逻辑 } }
问题根源
你的constrain用法完全错误:player.y - player.y等于0,player.y + player.y +30是两倍玩家Y坐标加30,这根本不是玩家周围的网格范围。而且你只是限制了循环的上限,没有调整循环的起始索引,等于还是从0开始循环,自然加载不到出生点外的区域。
正确实现方案
思路步骤
- 将玩家的屏幕坐标转换为网格索引(对应levels数组的i、j):
- 网格行索引:
playerGridY = floor(player.y / blockheight) - 网格列索引:
playerGridX = floor(player.x / blockwidth)
- 网格行索引:
- 定义加载范围(比如玩家上下各15行、左右各20列,可按需调整),同时确保不超出数组边界:
- 起始行:
startRow = max(0, playerGridY - 加载行数) - 结束行:
endRow = min(levels[level].length - 1, playerGridY + 加载行数) - 起始列:
startCol = max(0, playerGridX - 加载列数) - 结束列:
endCol = min(当前行长度 - 1, playerGridX + 加载列数)
- 起始行:
- 仅遍历计算好的范围内的网格,生成对应方块。
修正后的代码
// 计算玩家所在的网格位置 var playerGridY = floor(player.y / blockheight); var playerGridX = floor(player.x / blockwidth); // 定义加载范围,可根据性能和视野需求调整 var loadRangeY = 15; // 上下各加载15行 var loadRangeX = 20; // 左右各加载20列 // 计算行的循环边界,防止超出数组范围 var startRow = max(0, playerGridY - loadRangeY); var endRow = min(levels[level].length - 1, playerGridY + loadRangeY); for (var i = startRow; i <= endRow; i++) { var currentRow = levels[level][i]; // 计算当前行的列边界 var startCol = max(0, playerGridX - loadRangeX); var endCol = min(currentRow.length - 1, playerGridX + loadRangeX); for (var j = startCol; j <= endCol; j++) { switch (currentRow[j]) { case "b": blocks.push(new Block(j * blockwidth, i * blockheight, "block")); break; // 处理其他方块类型的逻辑 } } }
额外优化建议
- 每次玩家移动时,先清空
blocks数组再重新加载,避免重复生成方块导致内存占用过高 - 可以添加距离判断:只有当玩家移动超过半个方块的距离时,才触发重新加载,减少不必要的计算
内容的提问来源于stack exchange,提问作者PhazeDrop
相关产品推荐
相关产品推荐

