在画布中随机生成对象,不会重复或重叠

时间:2013-01-16 17:25:48

标签: javascript arrays html5 canvas

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

在一定程度上随机生成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

经过一些调试后,复制品将作为[对象对象]而不是索引号返回,但不确定为什么

编辑2

问题是对象是在数组平台中,而x是在数组对象中,那么我怎样才能再次在里面搜索? ,这就是它之前失败的原因。 感谢firebug和console.log(平台);

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

4 个答案:

答案 0 :(得分:7)

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

以下是此示例(demo):

//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);

答案 1 :(得分: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)必须评估为true,否则while循环将永远不会结束。

答案 2 :(得分:0)

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

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);
        };
    }();

答案 3 :(得分:0)

你去大数据,生成所有可能性,将每个存储在一个数组中,随机播放数组, 修剪前X项,这是你的非启发式算法。