キャンバスにさまざまなサイズの 100 個の円を描いていますが、重なってはいけません。これらの円も右から左にアニメーション化され (画面から消えると、キャンバスの右端にループして戻ります)、垂直方向の「ボブ」もいくつかありますが、これも他の円と重なることはありません。
以下は私が現在試みているもので、ブラウザをロックしているようです。円のコレクションをループしてdetectOverlap()
関数を実行し、円のコレクションに渡します。
次に、detectOverlap()
関数は円をループし、次のチェックを実行します。
detectOverlap: function (bubblesArr) {
while (true) {
var hit = 0;
for (var i=0; i<bubblesArr.length; i++) {
var circle = bubblesArr[i];
var dx = this._x - circle._x;
var dy = this._y - circle._y;
var rr = this._radius + circle._radius;
if (dx * dx + dy * dy < rr * rr) {
hit++;
}
}
if (hit == 0) {
break; // didn't overlap, break out of while loop
}
// if we didn't break then there was an overlap somewhere. calc again.
this._x = Math.round(Math.random() * this.stage.getWidth());
this._y = Math.round(Math.random() * this.stage.getHeight());
}
},
の場合hit == 0
、ループが中断され、オーバーラップがないと見なされます。それ以外の場合は、新しい X/Y 位置をランダムに計算し、プロセスを再開します。
これは効率が悪いようです。これを行うためのパフォーマンスのヒントはありますか?
キャンバス クラス (エントリ ポイント) : このクラスは「ステージ」であり、バブル オブジェクトを構築してキャンバスに追加します。
var $container;
var listData;
var bubbles = [];
function init(l, c) {
$container = c;
listData = l;
// this just draws the canvas. full-width + 500px tall.
var stage = new Konva.Stage({
container: $container.selector,
width: window.innerWidth,
height: 500
});
// this creates the drawing layer where the bubbles will live
layer = new Konva.Layer();
// create an instance of the Bubble class for each element in the list.
for (var i=0; i<listData.length; i++) {
bubbles[i] = new celebApp.Bubble.Bubble(listData[i], stage);
}
/** TODO:::: FIGURE OUT COLLISION DETECTION */
for (var i=0; i<bubbles.length; i++) {
bubbles[i].detectOverlap(bubbles);
}
// create the Konva representation for our generated objects
for (var i=0; i<bubbles.length; i++) {
var b = bubbles[i];
layer.add(new Konva.Circle({
x: b._x,
y: b._y,
radius: b._radius,
fill: b._fill,
stroke: b._stroke,
strokeWidth: b._strokeWidth,
}));
}
// add the layer to the stage
stage.add(layer);
}
バブル クラス: 画面に描画されるデータを表すクラスです。これらのオブジェクトが互いに重ならないようにする必要があります。
var Bubble = function (listData, stage) {
this.stage = stage;
this._x = Math.round(Math.random() * stage.getWidth()),
this._y = Math.round(Math.random() * stage.getHeight()),
this._radius = Math.round(Math.random() * 80);
this._fill = 'red';
this._stroke = 'black';
this._strokeWidth = 4;
this._speed = 3;
};
Bubble.prototype = {
detectOverlap: function (bubblesArr) {
while (true) {
var hit = 0;
for (var i=0; i<bubblesArr.length; i++) {
var circle = bubblesArr[i];
var dx = this._x - circle._x;
var dy = this._y - circle._y;
var rr = this._radius + circle._radius;
if (dx * dx + dy * dy < rr * rr) {
hit++;
}
}
if (hit == 0) {
break; // didn't overlap
}
this._x = Math.round(Math.random() * this.stage.getWidth());
this._y = Math.round(Math.random() * this.stage.getHeight());
}
},
};
EDIT : @MarcB からのコメントに基づいてこれを試してみましたが、ブラウザはまだロックしているようです。パフォーマンスのボトルネックが発生していますが、100 個の項目がすべて独自のwhile()
ループを実行していますか?
for (var i=0; i<bubblesArr.length; i++) {
var circle = bubblesArr[i];
var combinedRadius = Math.abs(circle._radius + this._radius);
var distance = Math.abs(this._x - circle._x);
if (distance <= combinedRadius) {
hit++;
}
}