4

如何在地图上生成对象,而不会占用相同的空间或在 HTML5 画布上重叠?

X坐标在一定程度上是随机生成的。我想检查数组内部是否已经存在,以及之后的 20 个值(以考虑宽度),但没有运气。

var nrOfPlatforms = 14,
platforms = [],
platformWidth = 20,
platformHeight = 20;
var generatePlatforms = function(){
  var positiony = 0, type;
  for (var i = 0; i < nrOfPlatforms; i++) {
    type = ~~(Math.random()*5);
    if (type == 0) type = 1;
    else type = 0;
    var positionx = (Math.random() * 4000) + 500 - (points/100);
    var duplicatetest = 21;
    for (var d = 0; d < duplicatetest; d++) {
      var duplicate = $(jQuery.inArray((positionx + d), platforms));
      if (duplicate > 0) {
        var duplicateconfirmed = true;
      }
    }
    if (duplicateconfirmed) {
      var positionx = positionx + 20;
    }
    var duplicateconfirmed = false;
    platforms[i] = new Platform(positionx,positiony,type);
  }
}();

我最初通过让它们在大约 4000 大的区域中生成来进行作弊修复,降低了几率,但我想随着游戏的进行增加难度,通过让它们看起来更在一起,使其更难。但随后它们重叠。

以粗略的图片形式,我想要这个

....[]....[].....[]..[]..[][]...

不是这个

......[]...[[]]...[[]]....[]....

我希望这是有道理的。

作为参考,这里是数组检查和难度之前的代码,只是便宜的距离黑客。

var nrOfPlatforms = 14,
platforms = [],
platformWidth = 20,
platformHeight = 20;
var generatePlatforms = function(){
  var position = 0, type;
  for (var i = 0; i < nrOfPlatforms; i++) {
    type = ~~(Math.random()*5);
    if (type == 0) type = 1;
    else type = 0;
    platforms[i] = new Platform((Math.random() * 4000) + 500,position,type);
  }
}();

编辑 1

经过一些调试,重复返回为 [object Object] 而不是索引号,但不知道为什么

编辑 2

问题是对象在数组平台中,而 x 在数组对象中,那么我该如何再次搜索呢?,这就是它之前失败的原因。感谢 firebug 和 console.log(platforms);

platforms = [Object { image=img,  x=1128,  y=260,  more...}, Object { image=img,  x=1640,  y=260,  more...} etc
4

4 回答 4

8

您可以实现一个 while 循环,该循环尝试插入一个对象并在它发生碰撞时静默失败。然后添加一个计数器并在放置所需数量的成功对象后退出 while 循环。如果对象靠得很近,则此循环可能会运行更长的时间,因此您可能还想给它一个最长的寿命。或者你可以实现一个'是否甚至可以将 z 对象放在 x 和 y 的地图上'以防止它永远运行。

这是一个示例(演示):

//Fill an array with 20x20 points at random locations without overlap
var platforms = [],
    platformSize = 20,
    platformWidth = 200,
    platformHeight = 200;

function generatePlatforms(k) {
  var placed = 0,
      maxAttempts = k*10;
  while(placed < k && maxAttempts > 0) {
    var x = Math.floor(Math.random()*platformWidth),
        y = Math.floor(Math.random()*platformHeight),
        available = true;
    for(var point in platforms) {
      if(Math.abs(point.x-x) < platformSize && Math.abs(point.y-y) < platformSize) {
        available = false;
        break;
      }
    }
    if(available) {
      platforms.push({
        x: x,
        y: y
      });
      placed += 1;
    }
    maxAttempts -= 1;
  }
}

generatePlatforms(14);
console.log(platforms);
于 2013-01-16T17:32:17.533 回答
2

以下是实现网格捕捉哈希的方法:http: //jsfiddle.net/tqFuy/1/

var can = document.getElementById("can"),
    ctx = can.getContext('2d'),
    wid = can.width,
    hei = can.height,
    numPlatforms = 14,
    platWid = 20,
    platHei = 20,
    platforms = [],
    hash = {};

for(var i = 0; i < numPlatforms; i++){
  // get x/y values snapped to platform width/height increments
  var posX = Math.floor(Math.random()*(wid-platWid)/platWid)*platWid,
    posY = Math.floor(Math.random()*(hei-platHei)/platHei)*platHei;

  while (hash[posX + 'x' + posY]){
    posX = Math.floor(Math.random()*wid/platWid)*platWid;
    posY = Math.floor(Math.random()*hei/platHei)*platHei;
  }

  hash[posX + 'x' + posY] = 1; 
  platforms.push(new Platform(/* your arguments */));
}

请注意,我正在连接 x 和 y 值并将其用作哈希键。这是为了简化检查,并且只是一个可行的解决方案,因为我们将 x/y 坐标捕捉到特定的增量。如果我们不捕捉,碰撞检查会更复杂。

对于大型集合(根据您的标准似乎不太可能),使用排除方法可能会更好:生成所有可能位置的数组,然后对于每个“平台”,从数组中随机选择一个项目,然后将其删除从数组。这类似于你如何洗牌。

编辑——要注意的一件事是numPlatforms <= (wid*hei)/(platWid*platHei)必须评估为真,否则 while 循环将永远不会结束。

于 2013-01-16T20:51:02.257 回答
0

我使用这段代码搜索数组中的对象,找到了另一个问题(在 JavaScript 数组中搜索对象)的答案

function search(array, value){
    var j, k;
    for (j = 0; j < array.length; j++) {
        for (k in array[j]) {  
            if (array[j][k] === value) return j;
        }
    }
}

我最终还重写了一堆代码,以在其他地方加速它并更好地回收平台。

它有效,但缺点是我的平台较少,因为它真的开始变慢了。最后这就是我想要的,但这样做不再可行。

var platforms = new Array();
    var nrOfPlatforms = 7;
    platformWidth = 20,  
    platformHeight = 20;
    var positionx = 0;
    var positiony = 0;
    var arrayneedle = 0;
    var duplicatetest = 21;

    function search(array, value){
        var j, k;
        for (j = 0; j < array.length; j++) {
            for (k in array[j]) {  
                if (array[j][k] === value) return j;
            }
        }
    }

    function generatePlatforms(ind){  
        roughx = Math.round((Math.random() * 2000) + 500);
        type = ~~(Math.random()*5);  
        if (type == 0) type = 1;  
        else type = 0;  

        var duplicate = false;

        for (var d = 0; d < duplicatetest; d++) {
            arrayneedle = roughx + d;
            var result = search(platforms, arrayneedle);
            if (result >= 0) {
                duplicate = true;
            }
        }

        if (duplicate = true) {
            positionx = roughx + 20;
        }
        if (duplicate = false) {
            positionx = roughx;
        }
        platforms[ind] = new Platform(positionx,positiony,type);  
    }  

    var generatedplatforms = function(){
        for (var i = 0; i < nrOfPlatforms; i++) {
            generatePlatforms(i);
        };
    }();
于 2013-01-16T20:57:39.393 回答
-1

您使用大数据,生成所有可能性,将每个可能性存储在一个数组中,打乱数组,修剪前 X 个项目,这是您的非启发式算法。

于 2015-02-19T14:09:11.623 回答