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

ReflectLaser

ReflectLaser.as
Laser and mirrors.
[Control]
Movement: [WASD] keys.
Laser:    Hold [IJKL] or arrow keys.
Get Adobe Flash player
by ABA 02 Jan 2009
/**
 * Copyright ABA ( http://wonderfl.net/user/ABA )
 * MIT License ( http://www.opensource.org/licenses/mit-license.php )
 * Downloaded from: http://wonderfl.net/c/kMc8
 */

// ReflectLaser.as
//  Laser and mirrors.
//  [Control]
//   Movement: [WASD] keys.
//   Laser:    Hold [IJKL] or arrow keys.
package
{
    import flash.display.Sprite;
    import flash.display.BitmapData;
    import flash.display.Bitmap;
    import flash.geom.Rectangle;
    import flash.events.Event;
    import flash.events.KeyboardEvent;

    [SWF(width="465", height="465", backgroundColor="0x000000", frameRate="30")]
    public class ReflectLaser extends Sprite
    {
        public static const SCREEN_WIDTH:int = 465;
        public static const SCREEN_HEIGHT:int = 465;
        private const LASER_MAX_COUNT:int = 4;
        private const MIRROR_MAX_COUNT:int = 4;
        private const BLUR_MAX_COUNT:int = 512;
        private const BLUR_HISTORY_COUNT:int = 6;
        private var player:Player = new Player;
        private var lasers:Vector.<Laser> = new Vector.<Laser>(LASER_MAX_COUNT, true);
        private var mirrors:Vector.<Mirror> = new Vector.<Mirror>(MIRROR_MAX_COUNT, true);
        private var blurs:Vector.<Vector.<Blur>> = new Vector.<Vector.<Blur>>(BLUR_HISTORY_COUNT, true);
        private var blurCounts:Vector.<int> = new Vector.<int>(BLUR_HISTORY_COUNT, true);
        private var blurIndex:int;
        private var buffer:BitmapData = new BitmapData(SCREEN_WIDTH, SCREEN_HEIGHT, false, 0);
        private var rect:Rectangle = new Rectangle;
        private var pos:Vector2 = new Vector2;
        private var offset:Vector2 = new Vector2;
        private var ticks:int;

        public function ReflectLaser()
        {
            var i:int;
            Field.initialize();
            for (i = 0; i < LASER_MAX_COUNT; i++) lasers[i] = new Laser;
            for (i = 0; i < MIRROR_MAX_COUNT; i++) mirrors[i] = new Mirror;
            initializeBlurs();
            ticks = 120;
            stage.scaleMode = "noScale";
            addChild(new Bitmap(buffer));
            stage.addEventListener(KeyboardEvent.KEY_DOWN, Key.onKeyDown);
            stage.addEventListener(KeyboardEvent.KEY_UP, Key.onKeyUp);
            addEventListener(Event.ENTER_FRAME, onEnterFrame);
        }

        private function onEnterFrame(event:Event):void
        {
            buffer.fillRect(buffer.rect, 0);
            buffer.lock();
            updateBlurs();
            drawMirrors();
            player.update(this);
            for each (var l:Laser in lasers) l.update(this);
            buffer.unlock();
            ticks++;
            if (ticks % 150 == 0) setMirrors();
        }

        private function drawMirrors():void
        {
            for each (var m:Mirror in mirrors)
            {
                if (!m.exists) continue;
                offset.x = m.pos2.x - m.pos1.x;
                offset.y = m.pos2.y - m.pos1.y;
                var c:int = offset.length / 10;
                offset.div(c);
                pos.x = m.pos1.x; pos.y = m.pos1.y;
                for (var i:int = 0; i <= c; i++)
                {
                    drawBox(pos.x, pos.y, 7, 0x22ee22, 9, 100, 200, 100);
                    pos.add(offset);
                }
            }
        }

        public function drawBox(x:Number, y:Number, size:int, color:int,
                                 bsize:int, br:int, bg:int, bb:int):void
        {
            rect.x = x - size / 2 + SCREEN_WIDTH / 2;
            rect.y = y - size / 2 + SCREEN_HEIGHT / 2;
            rect.width = rect.height = size;
            buffer.fillRect(rect, color);
            addBlur(x, y, bsize, bsize, br, bg, bb);
        }

        public function checkHitMirrors(p:Vector2):Mirror
        {
            for each (var m:Mirror in mirrors)
            {
                if (!m.exists) continue;
                if (p.checkHit(m.pos1, m.pos2, 30.0)) return m;
            }
            return null;
        }

        private function setMirrors():void
        {
            for (var i:int = 0; i < MIRROR_MAX_COUNT; i++)
            {
                var x:Number = (Math.random() * 2 - 1) * Field.size.x * 0.8;
                var y:Number = (Math.random() * 2 - 1) * Field.size.y * 0.8;
                var l:Number = 40 + Math.random() * 20;
                var m:Mirror = mirrors[i];
                m.exists = true;
                m.angle = Math.random() * Math.PI;
                var sv:Number = Math.sin(m.angle), cv:Number = Math.cos(m.angle);
                m.pos1.x = x - sv * l; m.pos1.y = y - cv * l;
                m.pos2.x = x + sv * l; m.pos2.y = y + cv * l;
            }
        }

        private function updateBlurs():void
        {
            var bi:int = blurIndex + 1;
            for (var i:int = 0; i < BLUR_HISTORY_COUNT; i++)
            {
                if (bi >= BLUR_HISTORY_COUNT) bi = 0;
                for (var j:int = 0; j < blurCounts[bi]; j++)
                {
                    updateBlur(blurs[bi][j]);
                }
                bi++;
            }
            blurIndex++;
            if (blurIndex >= BLUR_HISTORY_COUNT) blurIndex = 0;
            blurCounts[blurIndex] = 0;
        }

        private function addBlur(x:Number, y:Number, w:Number, h:Number,
                                 r:int, g:int, b:int):void
        {
            if (blurCounts[blurIndex] >= BLUR_MAX_COUNT) return;
            var bl:Blur = blurs[blurIndex][blurCounts[blurIndex]];
            bl.pos.x = x + SCREEN_WIDTH / 2; bl.pos.y = y + SCREEN_HEIGHT / 2;
            bl.width = w; bl.height = h;
            bl.r = r; bl.g = g; bl.b = b;
            blurCounts[blurIndex]++;
        }

        private function updateBlur(b:Blur):void
        {
            rect.x = b.pos.x - b.width / 2;
            rect.y = b.pos.y - b.height / 2;
            rect.width = b.width;
            rect.height = b.height;
            buffer.fillRect(rect, b.r * 0x10000 + b.g * 0x100 + b.b);
            b.width *= 1.2; b.height *= 1.2;
            var a:int = (b.r + b.g + b.b) / 3;
            b.r += (a - b.r) * 0.2;
            b.g += (a - b.g) * 0.2;
            b.b += (a - b.b) * 0.2;
            b.r *= 0.7; b.g *= 0.7; b.b *= 0.7;
        }

        private function initializeBlurs():void
        {
            for (var i:int = 0; i < BLUR_HISTORY_COUNT; i++)
            {
                var bs:Vector.<Blur> = new Vector.<Blur>(BLUR_MAX_COUNT, true);
                for (var j:int = 0; j < BLUR_MAX_COUNT; j++)
                {
                    bs[j] = new Blur;
                }
                blurs[i] = bs;
                blurCounts[i] = 0;
            }
            blurIndex = 0;
        }

        public function getLaserInstance():Laser
        {
            return getActorInstance(Vector.<Actor>(lasers));
        }

        private function getActorInstance(actors:Vector.<Actor>):*
        {
            var al:int = actors.length
            for (var i:int = 0; i < al; i++)
            {
                if (!actors[i].exists)
                {
                    actors[i].exists = true;
                    return actors[i];
                }
            }
            return null;
        }
    }
}

import flash.events.KeyboardEvent;

interface IPosition
{
    function get position():Vector2;
}

class Player implements IPosition
{
    private const SCREEN_WIDTH:int = ReflectLaser.SCREEN_WIDTH;
    private const SCREEN_HEIGHT:int = ReflectLaser.SCREEN_HEIGHT;
    private const SPEED:Number = 7.0;
    private const LASER_SPEED:Number = 12.0;
    public var pos:Vector2 = new Vector2;
    public var isFirePressed:Boolean;
    public var laser:Laser = null;
    private var offset:Vector2 = new Vector2;
    private var ticks:int = 0;

    public function update(main:ReflectLaser):void
    {
        var vx:Number = 0, vy:Number = 0;
        if (Key.left)  vx = -1;
        if (Key.right) vx = 1;
        if (Key.up)    vy = -1;
        if (Key.down)  vy = 1;
        if (vx != 0 && vy != 0)
        {
            vx *= 0.7; vy *= 0.7;
        }
        pos.x += vx * SPEED; pos.y += vy * SPEED;
        if (pos.x < -SCREEN_WIDTH  / 2) pos.x = -SCREEN_WIDTH / 2;
        if (pos.x >  SCREEN_WIDTH  / 2) pos.x =  SCREEN_WIDTH / 2;
        if (pos.y < -SCREEN_HEIGHT / 2) pos.y = -SCREEN_HEIGHT / 2;
        if (pos.y >  SCREEN_HEIGHT / 2) pos.y =  SCREEN_HEIGHT / 2;
        var fx:Number = 0, fy:Number = 0;
        if (Key.left2)  fx = -1;
        if (Key.right2) fx = 1;
        if (Key.up2)    fy = -1;
        if (Key.down2)  fy = 1;
        if (fx != 0 || fy != 0)
        {
            var fa:Number = Math.atan2(fx, fy);
            if (isFirePressed && laser != null)
            {
                laser.angle += Util.normalizeAngle(fa - laser.angle) * 0.1;
                laser.angle = Util.normalizeAngle(laser.angle);
            }
            else
            {
                isFirePressed = true;
                laser = main.getLaserInstance();
                if (laser != null) laser.initialize(this, fa, LASER_SPEED);
            }
        }
        else
        {
            if (isFirePressed)
            {
                isFirePressed = false;
                if (laser != null)
                {
                    laser.source = null;
                    laser = null;
                }
            }
        }
        offset.x = 0; offset.y = 7.0 + Math.sin(ticks * 0.25) * 2.0;
        offset.rotation(ticks * 0.15);
        for (var i:int = 0; i < 3; i++)
        {
            main.drawBox(pos.x + offset.x, pos.y + offset.y, 11, 0xee6666, 15, 255, 200, 200);
            offset.rotation(Math.PI * 2 / 3);
        }
        ticks++;
    }

    public function get position():Vector2
    {
        return pos;
    }
}

class Actor
{
    public var exists:Boolean = false;
}

class Laser extends Actor
{
    private const SPEED:Number = 5.0;
    private const SPACING:Number = 10.0;
    public var source:IPosition;
    public var sourcePos:Vector2 = new Vector2;
    public var angle:Number;
    public var speed:Number;
    public var startDist:Number, endDist:Number;
    public var ticks:int;
    private var pos:Vector2 = new Vector2;
    private var offset:Vector2 = new Vector2;

    public function initialize(s:IPosition, a:Number, sp:Number):void
    {
        exists = true;
        source = s;
        angle = a;
        speed = sp;
        startDist = endDist = 0;
        ticks = 0;
    }

    public function update(main:ReflectLaser):void
    {
        if (!exists) return;
        if (source != null)
        {
            sourcePos.x = source.position.x; sourcePos.y = source.position.y;
        }
        else
        {
            endDist += speed;
        }
        startDist += speed;
        pos.x = sourcePos.x; pos.y = sourcePos.y;
        var a:Number = angle;
        offset.x = Math.sin(a); offset.y = Math.cos(a);
        offset.mul(SPACING);
        var d:Number = 0;
        var df:Boolean = false;
        var i:Number = -startDist * 0.05;
        for (;;)
        {
            var m:Mirror = main.checkHitMirrors(pos);
            if (m != null)
            {
                a -= Util.normalizeAngle(a - m.angle) * 2;
                a = Util.normalizeAngle(a);
                offset.x = Math.sin(a); offset.y = Math.cos(a);
                offset.mul(SPACING);
            }
            if (d > endDist)
            {
                main.drawBox(pos.x, pos.y, 5, 0x8888ee, 20,
                             50, 50, 180 + Math.sin(i) * 70);
                i += 0.3;
                df = true;
            }
            if (d >= startDist || !Field.contains(pos)) break;
            pos.add(offset);
            d += SPACING;
        }
        if (!df) exists = false;
    }
}

class Mirror extends Actor
{
    public var pos1:Vector2 = new Vector2;
    public var pos2:Vector2 = new Vector2;
    public var angle:Number;
}

class Field
{
    public static var size:Vector2;

    public static function initialize():void
    {
        size = new Vector2;
        size.x = ReflectLaser.SCREEN_WIDTH * 1.1 / 2; size.y = ReflectLaser.SCREEN_HEIGHT * 1.1 / 2;
    }

    public static function contains(p:Vector2):Boolean
    {
        return (p.x >= -size.x && p.x <= size.x && p.y >= -size.y && p.y <= size.y);
    }
}

class Blur
{
    public var pos:Vector2 = new Vector2;
    public var width:Number, height:Number;
    public var r:int, g:int, b:int;
}


// Utility classes.

class Vector2
{
    public var x:Number = 0;
    public var y:Number = 0;

    public function add(v:Vector2):void
    {
        x += v.x;
        y += v.y;
    }

    public function addMultiplied(v:Vector2, m:Number):void
    {
        x += v.x * m;
        y += v.y * m;
    }

    public function sub(v:Vector2):void
    {
        x -= v.x;
        y -= v.y;
    }

    public function mul(v:Number):void
    {
        x *= v;
        y *= v;
    }

    public function div(v:Number):void
    {
        x /= v;
        y /= v;
    }

    public function normalize():void
    {
        div(length);
    }

    public function getRoughDistance(p:Vector2):Number
    {
        var ox:Number = Math.abs(p.x - x);
        var oy:Number = Math.abs(p.y - y);
        if (ox > oy) return ox + oy / 2;
        else         return oy + ox / 2;
    }

    public function rotation(v:Number):void
    {
        var sv:Number = Math.sin(v);
        var cv:Number = Math.cos(v);
        var rx:Number = cv * x - sv * y;
        y = sv * x + cv * y;
        x = rx;
    }

    public function checkHit(p:Vector2, pp:Vector2, dist:Number):Boolean
    {
      var bmvx:Number, bmvy:Number;
      bmvx = pp.x; bmvy = pp.y;
      bmvx -= p.x; bmvy -= p.y;
      var inaa:Number = bmvx * bmvx + bmvy * bmvy;
      if (inaa > 0.00001)
      {
        var sofsx:Number, sofsy:Number,inab:Number, hd:Number;
        sofsx = x - p.x; sofsy = y - p.y;
        inab = bmvx * sofsx + bmvy * sofsy;
        if (inab >= 0 && inab <= inaa)
        {
          hd = sofsx * sofsx + sofsy * sofsy - inab * inab / inaa;
          if (hd >= 0 && hd <= dist) return true;
        }
      }
      return false;
    }

    public function get length():Number
    {
        return Math.sqrt(x * x + y * y);
    }
}

class Key
{
    public static var left:Boolean, up:Boolean, right:Boolean, down:Boolean;
    public static var left2:Boolean, up2:Boolean, right2:Boolean, down2:Boolean;

    public static function onKeyDown(event:KeyboardEvent):void
    {
        switch (event.keyCode)
        {
            case 0x41:
            {
                left = true;
                break;
            }
            case 0x57:
            {
                up = true;
                break;
            }
            case 0x44:
            {
                right = true;
                break;
            }
            case 0x53:
            {
                down = true;
                break;
            }
            case 0x25:
            case 0x4a:
            {
                left2 = true;
                break;
            }
            case 0x26:
            case 0x49:
            {
                up2 = true;
                break;
            }
            case 0x27:
            case 0x4c:
            {
                right2 = true;
                break;
            }
            case 0x28:
            case 0x4b:
            {
                down2 = true;
                break;
            }
        }
    }

    public static function onKeyUp(event:KeyboardEvent):void
    {
        switch (event.keyCode)
        {
            case 0x41:
            {
                left = false;
                break;
            }
            case 0x57:
            {
                up = false;
                break;
            }
            case 0x44:
            {
                right = false;
                break;
            }
            case 0x53:
            {
                down = false;
                break;
            }
            case 0x25:
            case 0x4a:
            {
                left2 = false;
                break;
            }
            case 0x26:
            case 0x49:
            {
                up2 = false;
                break;
            }
            case 0x27:
            case 0x4c:
            {
                right2 = false;
                break;
            }
            case 0x28:
            case 0x4b:
            {
                down2 = false;
                break;
            }
        }
    }
}

class Util
{
    public static function normalizeAngle(v:Number):Number
    {
        if (v > Math.PI)       return v - Math.PI * 2;
        else if (v < -Math.PI) return v + Math.PI * 2;
        else                   return v;
    }
}