舞台上多个物体的碰撞测试

发布于 2024-12-18 09:52:57 字数 2737 浏览 2 评论 0原文

我正在尝试创建一种树形图,这样,如果您单击其中一个圆圈,它的子圆圈就会以某种程度的随机性从原始圆圈向外扩展,并通过线条连接。我已经完成了这项工作,但现在我想做的是确保没有任何圆圈相互碰撞,也没有任何线条交叉。您可以查看当前正在发生的情况的屏幕截图。我的代码如下。如何更改此代码以便检查冲突并避免冲突?我已经阅读了 flash 的 hitTestObject 命令,但这仅适用于一个对象到另一个对象的上下文。我想测试一个对象是否接触任何显示对象。

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

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

聽兲甴掵 2024-12-25 09:52:57

有两种方法可以做到这一点:

  1. 重构代码以使用 Actionscript 物理库(即 Box2D 或您喜欢的任何一个)。然后,将您的“圆”和“线”视为会相互碰撞的物理对象,可能与您在此处尝试执行的操作具有相同的效果。这样做的优点是该库附带了各种扩展类来处理物理交互。 CON 是实施过程中的开销。
  2. 执行此操作的手动/自定义方法是在舞台或初始圆圈上为 ENTER_FRAME 添加事件侦听器,该监听器将循环其子项,并与每个其他“子项”相比,在每个“子项”圆圈上调用 hitTestObject 方法圆圈。这些线在儿童圈内,所以应该没问题。

我注意到您实际上并未将 childCircles 添加到初始圆圈中,而是将它们添加到舞台中。您可能希望将这些圆圈推入数组中,以便稍后引用此“collisionDetection”方法。

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.

凌乱心跳 2024-12-25 09:52:57

从根本上讲,您需要维护屏幕上所有圆圈的列表,然后每次有物体移动(或每一帧)时,您都需要检查移动的圆圈与所有其他圆圈,看看它们是否发生碰撞。

数组 应该可以很好地跟踪所有圆圈。

然后,每次有东西移动时,只要它在移动,你就应该遍历数组并检查它是否击中了任何其他圆圈。使用类似以下内容:

function drawLine (...) 
{

    // Your code here

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

或者,您可以指定一个 onEnterFrame 函数,该函数每帧检查每个圆与其他每个圆的关系,尽管这会使用更多资源。我猜此时资源对您来说不是问题,因此请采用更简单的路线并在以后需要时进行优化。

Fundamentally you'll need to maintain a list of all the circles on the screen, and then every time something moves (or every frame) you'll need to check the moving circle against all the other circles to see if they are colliding.

An Array should work nicely for keeping track of all the circles.

Then, every time something moves, as long as it's moving, you should iterate through the array and check if it has hit any of the other circles. Use something like:

function drawLine (...) 
{

    // Your code here

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

Alternatively, you can specify an onEnterFrame function that checks every circle against every other circle every frame, although this uses more resources. I'm guessing resources aren't an issue for you at this point, so go with the simpler route and optimize if you need it later.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文