In case Flash no longer exists; a copy of this site is included in the Flashpoint archive's "ultimate" collection.

Dead Code Preservation :: Archived AS3 works from wonderfl.net

Very stable collision resolver

try to drag the squares over eachother
Get Adobe Flash player
by owenray 03 Jun 2011
  • Related works: 1
  • Talk

    makc3d at 04 Jun 2011 03:51
    lol, it teleports rectangles through :) if you drag A toward BCDE you can end up with BCDEA, no?
    wonderwhyer at 04 Jun 2011 13:30
    Hmm on what notion its called stable I wonder :) Stability mostly comes in question when many objects collide together like near ground because of gravity.
    owenray at 04 Jun 2011 16:21
    stable as in, it prevents from objects going into each other no matter what you throw at it, it seeks the closest point nearby, by checking around the desired location in circles, first it does a raw scan, followed by a finner one, and the finest one.. you can modify the precision, this will make it check more points in the circle.

    Tags

    Embed
/**
 * Copyright owenray ( http://wonderfl.net/user/owenray )
 * MIT License ( http://www.opensource.org/licenses/mit-license.php )
 * Downloaded from: http://wonderfl.net/c/lAZV
 */

package {
    import flash.geom.Point;
    import flash.events.Event;
    import flash.display.Sprite;
    import flash.display.StageScaleMode;
    import flash.events.MouseEvent;
    
    public class CollisionResolver extends Sprite{
        private var objects:Array = new Array();
        private var dragging:CollisionObject = null;
        private var grab:Point = new Point();
        
        public function CollisionResolver() {
            for(var c:int = 0; c<10; c++){
                var o:CollisionObject = new CollisionObject();
                addChild(o);
                objects.push(o);
                for(var key:String in objects){
                    objects[key].checkCollision(objects);
                }
                o.addEventListener(MouseEvent.MOUSE_DOWN, startDragging);
            }
        }
        
        private function startDragging(e:MouseEvent):void
        {
            dragging = CollisionObject(e.target);
            grab.x = dragging.mouseX;
            grab.y = dragging.mouseY;
            stage.addEventListener(MouseEvent.MOUSE_UP, stopDragging);
            stage.addEventListener(MouseEvent.MOUSE_MOVE, doDrag);
        }
        
        private function doDrag(e:MouseEvent):void
        {
            dragging.x = mouseX-grab.x;
            dragging.y = mouseY-grab.y;
            dragging.checkCollision(objects);
        }
        
        private function stopDragging(e:MouseEvent):void
        {
            stage.removeEventListener(MouseEvent.MOUSE_UP, stopDragging);
            stage.removeEventListener(MouseEvent.MOUSE_MOVE, doDrag);
        }
    }
}
import flash.display.Sprite;
import flash.geom.Point;
import flash.utils.Proxy;
import flash.geom.Rectangle;

class CollisionObject extends Sprite{
    public function CollisionObject()
    {
        graphics.beginFill(0xFFFFFF*Math.random());
        graphics.drawRect(0, 0, 50+100*Math.random(), 50+100*Math.random());
        x = 400*Math.random();
        y = 400*Math.random();
    }
    
    private function hitTestAll(others:Array):CollisionObject
    {
        for(var key:String in others){
            var rt:Rectangle = others[key].getCollisionRect();
            var r:Rectangle = getCollisionRect();
            var t:CollisionObject = others[key];
            if(t!=this&&
               rt.right>r.left&&
               rt.bottom>r.top&&
               rt.left<r.right&&
               rt.top<r.bottom){
                return others[key];
            }
        }
        return null;
    }

    public function checkCollision(others:Array):void
    {

        var p:Point = new Point(x, y);
        var rad:int = 1;
        var end:Boolean = false;
        var sensivity:int = 20;
        var precision:int = 20;
        
        //in case there is really no way out..
        var safeEscape:int = 0;
        
        if(hitTestAll(others))
            while(!end){
                rad+=sensivity;
                var Y:Number = rad;

                var pos:Array = new Array();

                for(var X:Number = 0; X<=Y; X+=rad/precision){
                    Y = Math.sqrt(Math.pow(rad, 2)-Math.pow(X, 2));
                    pos.push(new Point(p.x+X, p.y+Y));
                    pos.push(new Point(p.x-X, p.y-Y));
                    pos.push(new Point(p.x+X, p.y-Y));
                    pos.push(new Point(p.x-X, p.y+Y));

                    pos.push(new Point(p.x+Y, p.y+X));
                    pos.push(new Point(p.x-Y, p.y-X));
                    pos.push(new Point(p.x-Y, p.y+X));
                    pos.push(new Point(p.x+Y, p.y-X));
                }
                safeEscape++;
                if(safeEscape==1000) end = true;
                for(var key:String in pos){
                    x = pos[key].x;
                    y = pos[key].y;
                    if(!hitTestAll(others)){
                        if(sensivity==20){
                            rad-=20;
                            sensivity = 10;
                        }else if(sensivity==10){
                            rad-=11;
                            sensivity = 1;
                        }else
                            end = true;
                        break;
                    }
                }
            }
    }

    public function getCollisionRect():Rectangle
    {
        return new Rectangle(x,
                             y,
                             width,
                             height);
    }
}