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

デバッグ後、duplicateがインデックス番号ではなく[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ループを終了します。オブジェクトが互いに接近している場合、このループはより長く実行される可能性があるため、最大の寿命を与えることもできます。または、'を実装して、xとyのマップにzオブジェクトを配置して、永久に実行されないようにすることもできます。

これの例を次に示します(デモ):

//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座標を特定の増分にスナップしているため、実行可能な解決策にすぎません。スナップしなかった場合、衝突チェックはより複雑になります。

大規模なセット(基準からはありそうもない)の場合は、除外方法を使用することをお勧めします。すべての可能な位置の配列を生成し、「プラットフォーム」ごとに、配列からランダムにアイテムを選択してから削除します。アレイから。これは、カードのデッキをシャッフルする方法と似ています。

編集—注意すべきことの1つは、numPlatforms <= (wid*hei)/(platWid*platHei)trueと評価する必要があることです。そうしないと、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 に答える