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

如何基于玩家位置加载数组特定区域?(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开始循环,自然加载不到出生点外的区域。

正确实现方案

思路步骤

  1. 将玩家的屏幕坐标转换为网格索引(对应levels数组的i、j):
    • 网格行索引:playerGridY = floor(player.y / blockheight)
    • 网格列索引:playerGridX = floor(player.x / blockwidth)
  2. 定义加载范围(比如玩家上下各15行、左右各20列,可按需调整),同时确保不超出数组边界:
    • 起始行:startRow = max(0, playerGridY - 加载行数)
    • 结束行:endRow = min(levels[level].length - 1, playerGridY + 加载行数)
    • 起始列:startCol = max(0, playerGridX - 加载列数)
    • 结束列:endCol = min(当前行长度 - 1, playerGridX + 加载列数)
  3. 仅遍历计算好的范围内的网格,生成对应方块。

修正后的代码

// 计算玩家所在的网格位置
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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.05 18:45:00