在画布上随机放置物品而不重叠

Random placement of items on canvas without overlap

提问人:TommyBs 提问时间:11/9/2023 更新时间:11/9/2023 访问量:31

问:

我正在尝试将许多项目(精灵)随机放置在画布元素上,而不会有任何重叠。我使用的是种子随机数,这样我就可以获得一致的位置。但是,我遇到了一些问题。首先,我使用递归逻辑非常快速地达到最大调用堆栈大小,以避免任何冲突(仅 15 个实体),所以我不知道是否有办法优化它。其次,当它成功运行时,我的实体都倾向于沿着画布的顶部和左侧,因此可能会有大量的碰撞。

谁能看到这有什么问题?我尝试只使用 Math.random() 而不是看看这是否是问题所在,但我得到了相同的结果。myrng()

//80 is the width of a single sprite
const getLocation = () => {
    let x = Math.floor(myrng() * (canvas.width - 80));
    let y = Math.floor(myrng() * (canvas.height - 80));

    x = x < 0 ? 0 : x;
    y = y < 0 ? 0 : y;

    const overlap = entities.some((entity) => {
      return (x - entity.position.x < 80 || y - entity.position.y < 80);
    });

    if (!overlap) {
      return [x, y];
    } else {
      return getLocation();
    }
  };

myrng()是以下包中的种子随机数生成器 https://www.npmjs.com/package/seedrandom

在开始调用我的方法之前,我先调用它。update

for (let i = 0; i < 15; i++) {
      const [x, y] = getLocation();
      entities.push({ position: { x, y } });
    }
JavaScript 循环 递归 游戏开发 调用堆栈

评论

0赞 CBroe 11/9/2023
调用堆栈问题可以通过递归执行此操作来避免。而是在循环中进行,直到没有冲突。(这也使得实现限制变得容易,这样,如果它在 x 次尝试后仍然没有找到空闲位置,您可以中断该过程。
0赞 Elvis Adomnica 11/9/2023
@CBroe这是这种代码的问题,但它是不确定的。如果你在画布上放置了足够多的物品,找到一个新点可能需要不同的时间,有时甚至是几分钟。我宁愿将画布视为一个可能位置的数组,并使用随机数来消耗该数组中的元素。

答:

0赞 traktor 11/9/2023 #1

计算似乎不正确。尝试overlap

const overlap = entities.some((entity) => {
      return Math.abs(x - entity.position.x) < 80 
          && Math.abs(y - entity.position.y) < 80);
    });

理由是,如果两个实体的 or 值中的任何一个不在 80px 以内,它们就不会重叠。xy

堆栈空间不足可能是在画布上没有 80 x 80 像素的画布空间未占用时递归调用的结果。需要更多的设计,但可能需要检查某些现有实体在 x 和 y 方向上是否与其他实体相差不少于 80px。如果没有剩余的解决方案,递归应该在递归调用之前弹出 entiies 数组的实体。getLocation

评论

0赞 TommyBs 11/9/2023
认为,我应该注意到这一点,它还解决了将项目固定在左侧和顶部的问题