Actionscript 3 AS3中的碰撞检测和剪裁问题

Actionscript 3 AS3中的碰撞检测和剪裁问题,actionscript-3,collision-detection,game-physics,Actionscript 3,Collision Detection,Game Physics,我最近开始从头开始做一个小的物理模拟,这是我以前从未尝试过的,我遇到了一个问题,关于我在舞台上的物体碰撞之间的相互作用,我认为是我的恒定重力。我不确定200行代码对这里来说是否太大,但这就是我所拥有的 package { import flash.events.*; import flash.display.*; import flash.geom.Rectangle; [SWF (width="1500", height="1000", frameRat

我最近开始从头开始做一个小的物理模拟,这是我以前从未尝试过的,我遇到了一个问题,关于我在舞台上的物体碰撞之间的相互作用,我认为是我的恒定重力。我不确定200行代码对这里来说是否太大,但这就是我所拥有的

package  {

    import flash.events.*;
    import flash.display.*;
    import flash.geom.Rectangle;


    [SWF (width="1500", height="1000", frameRate="24")]
    public class ElasticityV2 extends MovieClip{
        /* Gravity is 9.8 m/s2, which for flash, since it's being applied every frame, needs to be 
        divided out by the frame rate as to not have super fast acceleration. GravMulti is to balance
        out gravity's speed, as it seemed a little slow after the framerate division. Resistance is acting
        like friction for now, and slows down the objects in the air and on the ground at the same rate.
        Elasticity is how bouncy each object is and how the force it recieves is applied*/
        public var gravMulti:Number = 5;
        public var gravity:Number = gravMulti *(9.8/stage.frameRate);
        public var resistance:Number = 0.98;
        public var elasticity:Number = 0.8;
        public var floor:Number = stage.stageHeight - 100;

        public var objectList:Array = new Array();
        public var shadowList:Array = new Array();
        public var yVelocityList:Array = new Array();
        public var xVelocityList:Array = new Array();
        public var massList:Array = new Array();
        public var frictionList:Array = new Array();
        public var lastXList:Array = new Array();
        public var lastYList:Array = new Array();
        public var elasticityList:Array = new Array();
        public var dragList:Array = new Array();

        public var spawnNum:int = 20;

        public var bounding:Rectangle = new Rectangle(0,0,stage.stageWidth - 100,stage.stageHeight);

        public var distantBackground:Background = new Background();
        public var starLight:Light = new Light();


        public function ElasticityV2() {

            addChild(starLight);
            starLight.x = stage.stageWidth/2;
            starLight.y = -400;
            starLight.addEventListener(MouseEvent.MOUSE_DOWN, onLightDrag);
            starLight.addEventListener(MouseEvent.MOUSE_UP, onLightDrag);
            starLight.addEventListener(MouseEvent.MOUSE_OUT, onLightDrag);

            for(var s:int=0;s<spawnNum;s++){
                var ballShadow:Shadow = new Shadow();
                addChild(ballShadow);
                setChildIndex(ballShadow,0);
                ballShadow.y = floor - (ballShadow.height/2);
                ballShadow.x = 100;
                shadowList.push(ballShadow);

                var ball:ElasticBall = new ElasticBall();
                var dragging:Boolean = false;
                addChild(ball);
                ball.y = 100;
                ball.x = s * 200;
                objectList.push(ball);
                yVelocityList.push(randomMe(20,-20));
                xVelocityList.push(randomMe(40,-40));
                massList.push(randomMe(20,5));
                frictionList.push(randomMe(0.6,0.01));
                objectList[s].width = objectList[s].height = massList[s] * 10;
                elasticityList.push(elasticity);
                dragList.push(dragging);
                ball.addEventListener(MouseEvent.MOUSE_DOWN, onDrag);
                ball.addEventListener(MouseEvent.MOUSE_UP, onDrag);
                ball.addEventListener(MouseEvent.MOUSE_OUT, onDrag);
            }

            addChild(distantBackground);
            distantBackground.y = stage.stageHeight - distantBackground.height;
            distantBackground.width = stage.stageWidth;
            setChildIndex(distantBackground,0);

            addEventListener(Event.ENTER_FRAME, onGameLoop);

        }

        public function onGameLoop(e:Event):void{
            //checkCollision();
            for(var i:int=0;i<objectList.length;i++){
                updatePhysics(i);
                updateShadows(i,starLight);
            }
        }

        public function updatePhysics(objRef:int):void{
            if(lastXList[objRef] != undefined){
                if(lastXList[objRef] != objectList[objRef].x){
                    xVelocityList[objRef] = objectList[objRef].x - lastXList[objRef];
                }
            }

            if(lastYList[objRef]!= undefined){
                if(lastYList[objRef] != objectList[objRef].y){
                    yVelocityList[objRef] = 4*(objectList[objRef].y - lastYList[objRef])/stage.frameRate;
                }
            }

            if(objectList[objRef].y>= floor - objectList[objRef].height){
                yVelocityList[objRef] = -(yVelocityList[objRef] * elasticityList[objRef]);  
                objectList[objRef].y = floor - objectList[objRef].height;
            }
            if(objectList[objRef].y<= 0){
                yVelocityList[objRef] = -(yVelocityList[objRef] * elasticityList[objRef]);  
                objectList[objRef].y = 0;
            }
            if(objectList[objRef].x > (stage.stageWidth - objectList[objRef].width)){
                xVelocityList[objRef]=-xVelocityList[objRef];
                objectList[objRef].x = stage.stageWidth - objectList[objRef].width;
            }
            if (objectList[objRef].x <0){
                xVelocityList[objRef]=-xVelocityList[objRef];
                objectList[objRef].x = 0;
            }



            if(!dragList[objRef]){
                yVelocityList[objRef]+=gravity;
                objectList[objRef].y += yVelocityList[objRef];
                xVelocityList[objRef]= (xVelocityList[objRef] * resistance);
                if(-0.5<xVelocityList[objRef] && xVelocityList[objRef]<0.5){
                    xVelocityList[objRef] = 0;
                }
                objectList[objRef].x += xVelocityList[objRef];
            }
            lastXList[objRef] = objectList[objRef].x;
            lastYList[objRef] = objectList[objRef].y;

            if(xVelocityList[objRef] == 0){
                xVelocityList[objRef]=randomMe(90,-90);
                yVelocityList[objRef]=randomMe(90,-90); 
            }
        }

        public function onDrag(e:Event):void{
            if(e.type == "mouseDown"){
                setChildIndex(DisplayObjectContainer(e.target),numChildren - 1)
                e.target.startDrag(false,bounding);
                //xVelocityList[objRef] = yVelocityList[objRef] = 0;
                //dragging = true;
            }else{
                e.target.stopDrag();
                //dragging = false;
            }


        }

        public function onLightDrag(e:Event):void{
            if(e.type == "mouseDown"){
                e.target.startDrag(false,bounding);
            }else{
                e.target.stopDrag();
            }
        }

        public function updateShadows(objRef:int, lightSource:MovieClip):void{

            //-----Cut for convenience------
        }

        public function checkCollision():void{
            for(var v:int=0;v<objectList.length;v++){
                var ball1 = objectList[v];
                for(var w:int=v+1;w<objectList.length;w++){
                    var ball2 = objectList[w];
                    if((ball1.x + getRadius(ball1) + getRadius(ball2) > ball2.x) && (ball1.x < ball2.x + getRadius(ball1) + getRadius(ball2)) && (ball1.y + getRadius(ball1) + getRadius(ball2) > ball2.y) && (ball1.y < ball2.y + getRadius(ball1) + getRadius(ball2))){

                        var dx:Number = ball2.x - ball1.x;
                        var dy:Number = ball2.y - ball1.y;

                        var dist:Number = Math.sqrt((dx * dx) + (dy * dy));

                        if(dist < getRadius(ball1)+getRadius(ball2)){



                            var newX1:Number;
                            var newY1:Number;
                            var newX2:Number;
                            var newY2:Number;

                            trace("Magnitude 1 is : " + (Math.sqrt((xVelocityList[v] * xVelocityList[v]) + (yVelocityList[v] * yVelocityList[v]))));
                            trace("Magnitude 2 is : " + (Math.sqrt((xVelocityList[w] * xVelocityList[w]) + (yVelocityList[w] * yVelocityList[w]))));

                            newX1 = ((massList[v] * xVelocityList[v])+(massList[w] * xVelocityList[w]))/(massList[v] + massList[w]) * 2 - xVelocityList[v];
                            newY1 = ((massList[v] * yVelocityList[v])+(massList[w] * yVelocityList[w]))/(massList[v] + massList[w]) * 2 - yVelocityList[v];
                            newX2 = ((massList[v] * xVelocityList[v])+(massList[w] * xVelocityList[w]))/(massList[v] + massList[w]) * 2 - xVelocityList[w];
                            newY2 = ((massList[v] * yVelocityList[v])+(massList[w] * yVelocityList[w]))/(massList[v] + massList[w]) * 2 - yVelocityList[w];

                            xVelocityList[v] = newX1;
                            yVelocityList[v] = newY1;
                            xVelocityList[w] = newX2;
                            yVelocityList[w] = newY2;

                            ball1.x += newX1;
                            ball1.y += newY1;
                            ball2.x += newX2;
                            ball2.y += newY2;

                        }

                    }
                }
            }
        }

        public function randomMe(high:Number, low:Number = 0):Number{
            return Math.random() * (high - low) + low;
        }

        public function getRadius(obj:MovieClip):Number{
            return obj.width/2;
        }

        public function centerX(obj:MovieClip):Number{
            return obj.x + getRadius(obj);
        }

        public function centerY(obj:MovieClip):Number{
            return obj.y + getRadius(obj);
        }

    }

}
包{
导入flash.events.*;
导入flash.display.*;
导入flash.geom.Rectangle;
[SWF(width=“1500”,height=“1000”,frameRate=“24”)]
公共类ElasticityV2扩展了MovieClip{
/*重力为9.8 m/s2,这对于闪光来说,因为它在每一帧都被应用,所以需要
以帧速率划分为不具有超快加速度。多是为了平衡
计算重力的速度,因为在帧速率分割后它似乎有点慢。阻力正在起作用
就像现在的摩擦一样,以同样的速度减慢空中和地面上的物体。
弹性是指每个物体的弹性以及它所受的力是如何施加的*/
公共变量:数字=5;
公共var重力:数字=gravMulti*(9.8/阶段帧率);
公共无功电阻:数值=0.98;
公共风险价值弹性:数字=0.8;
公共var楼层:编号=stage.stageHeight-100;
public-var-objectList:Array=new-Array();
public var shadowList:Array=new Array();
public var yVelocityList:Array=new Array();
public var xVelocityList:Array=new Array();
public var massList:Array=new Array();
公共变量摩擦列表:数组=新数组();
public var lastXList:Array=new Array();
public var lastYList:Array=new Array();
公共变量弹性列表:数组=新数组();
public var dragList:Array=new Array();
公共变量spawnNum:int=20;
公共变量边界:矩形=新矩形(0,0,stage.stageWidth-100,stage.stageHeight);
public var distantBackground:Background=new Background();
公共变量星光:灯光=新灯光();
公共功能弹性v2(){
addChild(星光);
星光.x=舞台宽度/2;
星光.y=-400;
starLight.addEventListener(MouseEvent.MOUSE_DOWN,onLightDrag);
starLight.addEventListener(MouseEvent.MOUSE_UP,onLightDrag);
starLight.addEventListener(MouseEvent.MOUSE_OUT,onLightDrag);

对于(var s:int=0;s我希望你的球的行为是这样的:当一个球落在另一个球的上面时,它实际上躺在地上,另一个球被推到地上,然后你在updatePhysics()中对它做出反应因此,通过将其放置在其起源的位置,这些球就变成了一个接一个的球。可以解决这一问题的建议之一是将每个球的最后一个碰撞物体保持一个物理周期,如下所示:

if(dist < getRadius(ball1)+getRadius(ball2)){
    // process collision
    ball1.lastCollided=ball2;
    ball2.lastCollided=ball1;
}
if(dist

然后,当您在updatePhysics()中更新坐标时,检查lastCollided是否为null,如果不是,则以相同的方式更新球的坐标和速度,本质上模拟另一次碰撞。在检查更新物理周期内的所有事件后,将null分配给所有球的lastCollided。

也许您应该将代码减少到感兴趣的部分。尽管能够复制很酷对于您的应用程序行为,我不确定是否有人会阅读针对此类特定问题的所有这些行。请通过
trace
函数检查此条件的执行情况
if(dist