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

pixel perfect collisions

click to create a hole
Terrain generation, pixel perfect collisions and physics

UPDATE:
Fast PPC with lots of objects!!
http://fav.me/d63gqlv
/**
 * Copyright Jacky.Riawan ( http://wonderfl.net/user/Jacky.Riawan )
 * MIT License ( http://www.opensource.org/licenses/mit-license.php )
 * Downloaded from: http://wonderfl.net/c/9WHW
 */

package 

{

    import flash.display.Bitmap;

    import flash.display.BitmapData;
    import flash.display.Sprite;
    import flash.events.Event;
    import flash.events.MouseEvent;

    /**

     * ...

     * @author Jacky Riawan

     */

    public class Main extends Sprite 
    {
        public var collisionBitmap:BitmapData;
        private const objects:Vector.<physicObject> = new Vector.<physicObject>();
        private var display:Sprite = new Sprite();
        public function Main():void 
        {
            if (stage) init();
            else addEventListener(Event.ADDED_TO_STAGE, init);
        }
        private function init(e:Event = null):void 
        {

            removeEventListener(Event.ADDED_TO_STAGE, init);
            addEventListener(Event.ENTER_FRAME, update);
            stage.addEventListener(MouseEvent.CLICK, clickHandler);
            generateGroundBitmap();
            addChild(display);
            for (var i:int = 0; i <200;i++){
                addObject(stage.stageWidth*Math.random(),stage.stageHeight*Math.random()*.1);
            }
        }        
        private function clickHandler(e:MouseEvent):void 
        {
            makeHole(mouseX, mouseY, 30);
        }
        private function addObject(posx:Number, posy:Number):void {
            objects.push(new physicObject(posx, posy,this));
        }
        private function update(e:Event):void 
        {
            updateForces();
        }
        private function updateForces():void 
        {   
            display.graphics.clear();
            var le:int = objects.length;
            for (var i:int = 0; i < le; i++) {
                objects[i].updateForce();
                objects[i].updatePosition();
                display.graphics.beginFill(0xFF0000);
                display.graphics.drawCircle(objects[i]._x, objects[i]._y, 2);
                display.graphics.endFill();        
            }
        }
        private function makeHole(x0:int, y0:int, radius:int):void {
            if (radius == 0) {
                collisionBitmap.setPixel(x0, y0, 0xFFFFFF);
            }else{
                var error:int = 0;
                var x:int = radius;
                var y:int = 0;
                var xChange:int = 1 - (radius << 1);
                var yChange:int = 0;
                while (x >= y) {
                    for (var i:int = x0 - x; i <= x0 + x; i++) {
                        collisionBitmap.setPixel(i, y0 + y,0);
                        collisionBitmap.setPixel(i, y0 - y, 0);
                    }
                    for (i = x0 - y; i <= x0 + y; i++) {
                        collisionBitmap.setPixel(i, y0 + x,0);
                        collisionBitmap.setPixel(i, y0 - x, 0);
                    }
                    y++;
                    error += yChange;
                    yChange += 2;
                    if (((error << 1) + xChange) > 0) {
                        x--;
                        error += xChange;
                        xChange += 2;
                    }
                }
            }
        }
        private function generateGroundBitmap():void 
        {
            collisionBitmap = new BitmapData(stage.stageWidth, stage.stageHeight, false, 0);
            var currentPoint:Number = collisionBitmap.height * .4;
            var topLimit:int = collisionBitmap.height * .35;
            var bottomLimit:int = collisionBitmap.height*.9;
            var timer:int = 0;
            var smoothing:Number = 30;
            var range:Number = 8;
            var speedClimbTarget:Number = (Math.random() - .5) * range;
            var speedClimb:Number = speedClimbTarget
            for (var _x:int = 0; _x < collisionBitmap.width; _x++) {
                var depth:Number = collisionBitmap.height - currentPoint;
                for (var _y:int = currentPoint; _y < collisionBitmap.height; _y++) {
                    var color:uint;
                    var depth_percent:Number = (_y-currentPoint) / depth;
                    if (depth_percent < .005) {
                        color = 0x80FF00
                    }else if (depth_percent < .01) {
                        color = 0x00FF00;
                    }else if (depth_percent < .03) {
                        color = 0x008400;
                    }else if (depth_percent < .04) {
                        color = 0x804000;
                    }else if (depth_percent < .1) {
                        color = 0x623100;
                    }else if (depth_percent < .15) {
                        color = 0x824100;
                    }else if (depth_percent < .35) {
                        color = 0x4A2500;
                    }else if (depth_percent < .36) {
                        color = 0xCEFFC1;
                    }else if (depth_percent < .57) {
                        color = 0x000000;
                    }else if (depth_percent < .59) {
                        color = 0x80FFFF;
                    }else if (depth_percent < .62) {
                        color = 0xC0C0C0;
                    }else if (depth_percent < .68) {
                        color = 0x707070;
                    }else if (depth_percent < .75) {
                        color = 0x3B3B3B;
                    }else if (depth_percent < .76) {
                        color=0xFFFF00
                    }else if (depth_percent < .85) {
                        color = 0xFF0000;
                    }else {
                        color=0x1D1D1D
                    }
                    collisionBitmap.setPixel(_x, _y, color);
                }
                currentPoint += speedClimb;
                speedClimb += (speedClimbTarget - speedClimb) / smoothing;
                if (currentPoint <= topLimit) {
                    currentPoint = topLimit;
                    speedClimbTarget = Math.abs(speedClimbTarget);
                    speedClimb = Math.abs(speedClimb);
                }else if (currentPoint >= bottomLimit) {
                    currentPoint = bottomLimit;
                    speedClimbTarget = -Math.abs(speedClimbTarget);
                    speedClimb = -Math.abs(speedClimb);
                }
                if (timer == 0) {
                    speedClimbTarget = (Math.random() - .5) * range;
                    timer = 3 + Math.random() * 5;
                }else {
                    timer--;
                }
            }
            addChild(new Bitmap(collisionBitmap));
        }        
    }    
}

class physicObject {
    public static const GRAV:Number =.5;
    private var px:int;
    private var py:int;
    private var vx:Number=(Math.random()-.5)*5;
    private var vy:Number=10;
    private var main:Main;
    public var _x:int;
    public var _y:int;
    private var applyGravTimer:int = 0;
    public function physicObject(_x:Number,_y:Number,main:Main) 
    {
            this.main = main;
            this._y = py=_y;
            this._x = px=_x;
    }
    public function updateForce():void {
            var nx:Number = _x + vx;
            var ny:Number = _y + vy;
            px = _x;
            py = _y;
            _x = nx;
            _y = ny;
    }
    public function updatePosition():void {
        var dist:int = Math.max(Math.abs(vx), Math.abs(vy));
        var stepDone:int = 1+Math.min(dist,4);
            var divx:Number = vx / stepDone;
            var divy:Number = vy / stepDone;
            for (var i:int = 1; i < stepDone; i++) {
                var checkX:int = px + i * divx;
                var checkY:int = py + i * divy;
                var col:uint = main.collisionBitmap.getPixel(checkX,checkY);
                if (col !== 0x000000) {
                   // if (main.collisionBitmap.getPixel(checkX, checkY) !== 0x000000) {

                        var force:int = Math.sqrt(Math.pow(vx, 2) + Math.pow(vy, 2));

                        var forceX:int = 0;

                        var forceY:int = 0;

                        if (main.collisionBitmap.getPixel(checkX-2, checkY) !== 0x000000) {

                            forceX = 1;

                        }else if (main.collisionBitmap.getPixel(checkX + 2, checkY) !== 0x000000) {

                            forceX = -1;

                        }

                        if (main.collisionBitmap.getPixel(checkX, checkY-2) !== 0x000000) {

                            forceY = 1;

                        }else if (main.collisionBitmap.getPixel(checkX, checkY + 2) !== 0x000000) {

                            forceY = -1;

                        }

                        if (i == 1) {

                            force *= .9;

                        }

                        var angle:Number = Math.atan2(forceY, forceX);

                        vx = Math.cos(angle) * force * i / stepDone;

                        vy = Math.sin(angle) * force*i/stepDone;

                        _x = checkX;

                        _y = checkY;

                        break;

                    }            

                //}

            }

            vx *= .94;

            vy *= .94;

            vy += GRAV * i / stepDone;

        }

    }