тестирование столкновений с несколькими объектами на сцене - PullRequest
0 голосов
/ 27 ноября 2011

Я пытаюсь создать своего рода древовидную диаграмму, чтобы при нажатии на один из кругов его дочерние круги распространялись наружу с некоторой степенью случайности от исходного круга, соединенного линиями. У меня это работает, но теперь я хочу убедиться, что ни одна из окружностей не сталкивается друг с другом и ни одна из линий не пересекается. Вы можете увидеть скриншот для того, что происходит в настоящее время. Мой код ниже. Как мне изменить этот код, чтобы он проверял наличие коллизий и избегал их? Я прочитал о команде FlashTestObject, но она работает только в контексте одного объекта к другому. Я хочу проверить один объект, контактирующий с любым экранным объектом.

import com.greensock.TweenMax;

var sw = stage.stageWidth;
var sh = stage.stageHeight;
var cr = 3; //circle radius
var moveRange = 25;
var circleColor = 0xcccccc;
var numCircles = 4;
var lineCanvas:Sprite = new Sprite();
addChild(lineCanvas);
var lineColor = 0xe9e9e9;
var lineWeight = 1;

function init(){
    firstCircle();
}

function firstCircle(){
    var xPos = randomRange(cr, sw-cr);
    var yPos = randomRange(cr, sh-cr);
    var newCircle:Shape = new Shape();
    newCircle.graphics.beginFill(circleColor);
    newCircle.graphics.drawCircle(0,0,cr);
    newCircle.graphics.endFill();

    var circleClip:MovieClip = new MovieClip();
    circleClip.childCircles = 2;
    circleClip.x = xPos;
    circleClip.y = yPos;
    circleClip.addChild(newCircle);

    addChild(circleClip);
    circleClip.addEventListener(MouseEvent.CLICK,clickCircle);
}

function clickCircle(e:MouseEvent):void {
    var thisCircle = e.target;
    for (var i=0; i<thisCircle.childCircles;i++){
        drawCircle(thisCircle);
    }
}

function drawCircle(parentCircle){
    var xPos = parentCircle.x;
    var yPos = parentCircle.y
    //var xPos = randomRange(cr, sw-cr);
    //var yPos = randomRange(cr, sh-cr);
    var newCircle:Shape = new Shape();
    newCircle.graphics.beginFill(circleColor);
    newCircle.graphics.drawCircle(0,0,cr);
    newCircle.graphics.endFill();

    var circleClip:MovieClip = new MovieClip();
    circleClip.childCircles = 2;
    circleClip.x = xPos;
    circleClip.y = yPos;
    circleClip.addChild(newCircle);
    addChild(circleClip);
    circleClip.addEventListener(MouseEvent.CLICK,clickCircle);
    moveCircle(circleClip,xPos,yPos);
}

function drawLine(childCircle,parentX,parentY){
        lineCanvas.graphics.lineStyle(lineWeight,lineColor);
        lineCanvas.graphics.moveTo(parentX,parentY);
        lineCanvas.graphics.lineTo(childCircle.x,childCircle.y);

// Хотите проверить, соприкасается ли здесь линия или круг. Если это так, я хочу убить анимацию в круге (таким образом, также останавливая рисование линии).

}

function moveCircle(childCircle,parentX,parentY){
    var curX = childCircle.x;
    var curY = childCircle.y;
    var moveX = randomRange(curX-moveRange,curX+moveRange);
    var moveY = randomRange(curY-moveRange-cr,curY+moveRange+cr);
    TweenMax.to(childCircle,.5, { x: moveX, y: moveY, onUpdate:drawLine, onUpdateParams:[childCircle,parentX,parentY]});
}

function randomRange(minNum:Number, maxNum:Number):Number {  
    return (Math.floor(Math.random() * (maxNum - minNum + 1)) + minNum);  
}

init();

Ответы [ 2 ]

1 голос
/ 28 ноября 2011

По сути, вам нужно вести список всех окружностей на экране, а затем каждый раз, когда что-то перемещается (или каждый кадр), вам нужно проверять движущийся круг по всем другим кружкам, чтобы увидеть, являются ли они встречные.

Массив должен хорошо работать для отслеживания всех кругов.

Затем, каждый раз, когда что-то движется, пока оно движется, вы должны перебирать массив и проверять, попало ли оно в какие-либо другие круги. Используйте что-то вроде:

function drawLine (...) 
{

    // Your code here

    for (var i:int = 0; i < Array.length; i++)
    {  
        childCircle.hitTestObject(Array[i]);  
    }
}

В качестве альтернативы, вы можете указать функцию onEnterFrame, которая проверяет каждый круг на каждом круге в каждом кадре, хотя при этом используется больше ресурсов. Я предполагаю, что ресурсы не являются проблемой для вас на данный момент, поэтому следуйте более простому маршруту и ​​оптимизируйте его, если он понадобится вам позже.

1 голос
/ 28 ноября 2011

Есть 2 способа сделать это:

  1. Перефакторинг вашего кода для использования библиотеки физики Actionscript (т. Е. Box2D или по вашему выбору). Затем рассмотрите ваши «круги» и «линии» как физические объекты, которые будут сталкиваться друг с другом, вероятно, с тем же эффектом, что вы пытаетесь сделать здесь. ПРО в этом заключается в том, что библиотека поставляется с набором расширенных классов для обработки физического взаимодействия. CON - накладные расходы при реализации.
  2. Ручной / нестандартный способ сделать это - добавить список событий для ENTER_FRAME на сцене ИЛИ начальном круге, который будет проходить по его дочерним элементам, и вызывать метод hitTestObject для каждого «дочернего» круга по сравнению со всеми остальными. «детский» круг. Линии находятся внутри детских кругов, поэтому должно быть в порядке.

Я заметил, что вы на самом деле не добавляете childCircles в начальный круг, а вместо этого добавляете их на сцену. Возможно, вы захотите вставить эти круги в массив, чтобы ссылаться позже для этого метода "collisionDetection".

...