且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

碰撞测试与舞台上的多个对象

更新时间:2022-10-18 07:52:00

有2种方式,你可以这样做:

  1. 重新因素的code到使用ActionScript物理库(比如Box2D的或任何你preFER)。然后,请考虑您的圈子和行,因为他们会相互碰撞,很可能有同样的效果,你想在这里做什么物体。临去,这是该库自带的扩展类的分类来处理物理相互作用。 con是在执行的开销。
  2. 在手动/自定义的方式来做到这一点是通过它的孩子在每个孩子圈添加一个事件监听器为ENTER_FRAME,在舞台上或初始圈,这将循环,并调用hitTestObject方法,每隔比较孩子圈。该行是孩子们的圈子之内,所以应该没事。

我注意到你没有实际添加childCircles最初的圈子,而不是将其添加到舞台上。您可能希望这些圈子推入一个数组以后引用这个collisionDetection的方法。

I'm trying to create a sort of tree diagram such that, if you click on one of the circles, its child circles spread outward with some degree of randomness from the original circle, connected by lines. I have this working, but now what I want to do is make sure that none of the circles collide with each other and none of the lines criss cross. You can see the screenshot for what is currently happening. My code is below. How do I change this code so that it checks for collisions and avoids them? I've read up on flash's hitTestObject command, but that only works in the context one object to another. I want to test for one object contacting any display object.

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

//Want to check if either the line or the circle is contacting anything here. If it is, I want to kill the tween to the circle (thus also stopping the drawing of the line).

}

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

There's 2 ways you could do this:

  1. Re-factor your code to use an Actionscript Physics Library (i.e. Box2D or whichever you prefer). Then, consider your "circles" and "lines" as physical objects that will collide with each other, probably having the same effect as what you're trying to do here. The PRO to this is that the library comes with an assortment of extended classes to handle physical interaction. The CON is the overhead in implementation.
  2. The manual/custom way to do this is to add an eventlistener for ENTER_FRAME, on the stage OR the initial circle, that will loop through it's children, and call the hitTestObject method on each "child" circle, compared with every other "child" circle. The lines are within the children circles, so should be fine.

I notice you're not actually adding the childCircles to the initial circle, and instead adding them to the stage. You might want to push these circles into an Array to reference later for this "collisionDetection" method.