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

formation 7

almost nothing added from formation 6. This work is just for refactoring.
Get Adobe Flash player
by codeonwort 28 Jun 2011
/**
 * Copyright codeonwort ( http://wonderfl.net/user/codeonwort )
 * MIT License ( http://www.opensource.org/licenses/mit-license.php )
 * Downloaded from: http://wonderfl.net/c/zyRY
 */

// forked from codeonwort's formation 6
// forked from codefl's formation 5
// forked from codefl's formation 4
// forked from codefl's formation 3
package {
    
    import flash.display.DisplayObject
    import flash.display.Sprite
    import flash.display.MovieClip
    import flash.events.Event
    import flash.events.MouseEvent
    import flash.events.KeyboardEvent
    import flash.ui.Keyboard
    import flash.text.TextField
    
    import com.bit101.components.RadioButton
    
    /* 이번에 하고 있는 작업
    - 대형 함수에서 유닛의 목적지를 직접 정하는 게 아니라 목적지 데이터만 생성해서 반환하고
    호출하는 측에서 그 데이터를 적용하는 방식으로 고쳤다
    - 무작위 분포는 더블 클릭에서 대형 시리즈로 변경.
    */
    
    /* 앞으로 할 작업
    - 나중에 일부 유닛들로만 대형을 이루는 것도 구현할 경우를 대비해서
    현재 유닛들 전체로 대형을 만드는 방식은 삼간다
    - 대형 종류만 추가하는 건 그만두고 슬슬 새로운 기능을 생각해보자
    - 유닛끼리 비켜가는 건 언제 구현하지 -ㄴ-
    - IDestination 떡밥도 처리해야 하는디
    - 동그라미가 슬슬 질리는도다.. 근데 스프라이트 넣으면 정렬도 해야한다 아이고 귀찮아ㅋㅋ
    - 대각선으로 이동하는 것도 좀 바꿀까
    */
    
    /* 설명
    - 화면을 누르면 누른 지점을 기점으로 대형을 이룬다
    - 유닛은 목적지까지 대각선으로 일정 속도로 움직인다
    - ←, → 방향키를 누르면 대형이 바뀐다
    - 노란 텍스트 필드에 숫자를 입력하고 엔터를 눌러 유닛 수를 바꾼다
    - 우상단의 두 라디오 버튼은 입력을 누를 때만 보낼 것인지, 누르고 있으면 계속 보낼 것인지를 결정한다
    */
    
    [SWF(width=500, height=500)]
    
    public class FormationWorld extends Sprite {
        
        private var formationNames:Array = ["rect", "circle", "circular crowd",
                                            "wedge", "helix", "firework", "random"]
        private var formationIndex:int = 0
        private var formationView:TextField
        
        private var numInput:TextField
        private var unitContainer:Sprite
        private var formCaller:FormationCaller
        
        public function FormationWorld() {
            graphics.beginFill(0x0, 1)
            graphics.drawRect(0, 0, stage.stageWidth, stage.stageHeight)
            graphics.endFill()
            
            unitContainer = addChild(new Sprite) as Sprite
            unitContainer.mouseEnabled = false
            unitContainer.mouseChildren = false
            makeUnits(67) // 인자는 유닛 개수
            setKeyboardAction()
            unitContainer.addEventListener("enterFrame", loop)
            
            // 언제 대형 함수를 호출할 지를 결정한다
            formCaller = new FormationCaller(this)
            formCaller.runClickMode(stage)
            
            // makeFormationCallModeInterface
            new RadioButton(this, stage.width-80, 5, "click", true, _setClickMode)
            new RadioButton(this, stage.width-80, 20, "timed click", false, _setTimedClickMode)
            function _setClickMode():void { formCaller.runClickMode(stage) }
            function _setTimedClickMode():void { formCaller.runTimedClickkMode(stage) }
        }
        
        public function makeFormation(centerX:Number, centerY:Number):void {
            var len:uint = numUnits()
            var data:FormationData
                = FormationDataGenerator.gen(formationIndex, len, centerX, centerY)
            for(var i:int=0 ; i<len ; i++){
                unitAt(i).dest.x = data.dests[i].x
                unitAt(i).dest.y = data.dests[i].y
            }
        }
        
        private function makeUnits(num:uint):void {
            var unit:Unit, x0:Number, y0:Number
            for(var i:int=0 ; i<num ; i++){
                x0 = Math.random() * stage.stageWidth
                y0 = Math.random() * stage.stageHeight
                unit = new Unit(x0, y0)
                unitContainer.addChild(unit)
            }
        }
        
        private function loop(e:Event):void {
            // move units
            var speedX:Number = 5, speedY:Number = 5
            var unit:Unit
            for(var i:int=0 ; i<unitContainer.numChildren ; i++){
                unit = unitAt(i)
                if(unit.x < unit.dest.x){
                    if(unit.dest.x - unit.x > speedX) unit.vx = speedX
                    else unit.vx = unit.dest.x - unit.x
                }
                else if(unit.x > unit.dest.x){
                    if(unit.x - unit.dest.x > speedX) unit.vx = -speedX
                    else unit.vx = unit.dest.x - unit.x
                }
                if(unit.y < unit.dest.y){
                    if(unit.dest.y - unit.y > speedY) unit.vy = speedY
                    else unit.vy = unit.dest.y - unit.y
                }
                else if(unit.y > unit.dest.y){
                    if(unit.y - unit.dest.y > speedY) unit.vy = -speedY
                    else unit.vy = unit.dest.y - unit.y
                }
                if(Math.abs(unit.x-unit.dest.x)<0.05) unit.vx = 0
                if(Math.abs(unit.y-unit.dest.y)<0.05) unit.vy = 0
                unit.x += unit.vx
                unit.y += unit.vy
            }
        }

        ///////////////////////////////////////////////////////////////////
        ///////////////////////////////////////////////////////////////////
        // 볼 필요 없는 부분 no need to see
        private function unitAt(idx:int):Unit { return unitContainer.getChildAt(idx) as Unit }
        private function numUnits():uint { return unitContainer.numChildren }
        
        private function setKeyboardAction():void {
            formationView = addChild(new TextField()) as TextField
            formationView.autoSize = "left"
            formationView.selectable = false
            formationView.textColor = 0xffffff
            formationView.text = "formation : " + formationNames[formationIndex]
            formationView.mouseEnabled = false
            stage.addEventListener("keyDown", changeFormation)
            function changeFormation(e:KeyboardEvent):void {
                switch(e.keyCode){
                    case Keyboard.LEFT :
                        formationIndex --
                        if(formationIndex == -1) formationIndex = FormationDataGenerator.length - 1
                        break
                    case Keyboard.RIGHT :
                        formationIndex ++
                        if(formationIndex == FormationDataGenerator.length) formationIndex = 0
                        break
                }
                formationView.text = "formation : " + formationNames[formationIndex]
            }
            
            var cap:TextField = addChild(new TextField()) as TextField
            cap.selectable = false
            cap.autoSize = "left"
            cap.y = 20
            cap.textColor = 0xffffff
            cap.mouseEnabled = false
            cap.text = "write number of units and enter"
            
            numInput = addChild(new TextField) as TextField
            numInput.text = "67"
            numInput.type = "input"
            numInput.autoSize = "left"
            numInput.background = true
            numInput.backgroundColor = 0xffff00
            numInput.textColor = 0x000000
            numInput.x = 160
            numInput.y = 20
            numInput.restrict = "0-9"
            numInput.maxChars = 4
            numInput.addEventListener("keyDown", changeNumUnits)
            function changeNumUnits(e:KeyboardEvent):void {
                if(e.keyCode == Keyboard.ENTER){
                    for(;unitContainer.numChildren;) unitContainer.removeChildAt(0)
                    makeUnits(int(numInput.text))
                }
            }
        } // setKeyboardAction() 끝
        
    }
    
}

//////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////
// 패키지 스코프의 바깥

import flash.display.Shape
internal class Unit extends Shape {
    public static const R:int = 5
    public var dest:IDestination
    public var vx:Number=0, vy:Number=0
    public function Unit(x0:Number, y0:Number){
        x = x0 ; y = y0
        dest = new Location(x0, y0)
        graphics.beginFill(0xff0000, 1)
        graphics.drawCircle(0, 0, R)
        graphics.endFill()
    }
}

internal interface IDestination {
    function get x():Number
    function set x(val:Number):void
    function get y():Number
    function set y(val:Number):void
}
internal class Location implements IDestination {
    private var _x:Number, _y:Number
    public function Location(x0:Number, y0:Number) {
        _x = x0 ; _y = y0
    }
    public function get x():Number { return _x }
    public function set x(val:Number):void { _x = val }
    public function get y():Number { return _y }
    public function set y(val:Number):void { _y = val }
}
internal class UnitLocation implements IDestination {
    private var _u:Unit
    public function UnitLocation(u:Unit) {
        _u = u
    }
    public function get x():Number { return _u.x }
    public function get y():Number { return _u.y }
    public function set x(val:Number):void {}
    public function set y(val:Number):void {}
}

import flash.display.InteractiveObject
import flash.events.MouseEvent
import flash.events.Event
// manages when to call formation function
// 대형 함수를 호출하는 역할을 맡는다
internal class FormationCaller {
    private var world:FormationWorld
    private var clk_io:InteractiveObject
    private var time_io:InteractiveObject
    public function FormationCaller(formationWorld:FormationWorld) {
        world = formationWorld
    }
    public function runClickMode(io:InteractiveObject):void {
        clearMode()
        io.addEventListener("mouseDown", clickMode_mouseDown)
        clk_io = io
    }
    private function clickMode_mouseDown(e:MouseEvent):void {
        if(e.target == clk_io){
            world.makeFormation(e.stageX, e.stageY)
        }
    }
    
    public function runTimedClickkMode(io:InteractiveObject):void {
        clearMode()
        io.addEventListener("mouseDown", timedClickMode_mouseDown)
        time_io = io
    }
    private function timedClickMode_mouseDown(e:MouseEvent):void {
        time_io.addEventListener("enterFrame", timedClickMode_enterFrame)
        time_io.stage.addEventListener("mouseUp", timedClickMode_mouseUp)
        if(e.target == time_io) world.makeFormation(e.stageX, e.stageY)
    }
    private function timedClickMode_enterFrame(e:Event):void {
        world.makeFormation(time_io.mouseX, time_io.mouseY)
    }
    private function timedClickMode_mouseUp(e:MouseEvent):void {
        time_io.removeEventListener("enterFrame", timedClickMode_enterFrame)
        time_io.stage.removeEventListener("mouseUp", timedClickMode_mouseUp)
    }
    
    private function clearMode():void {
        if(clk_io){
            clk_io.removeEventListener("mouseDown", clickMode_mouseDown)
            clk_io = null
        }
        if(time_io){
            time_io.removeEventListener("mouseDown", timedClickMode_mouseDown)
            time_io.removeEventListener("enterFrame", timedClickMode_enterFrame)
            time_io.stage.removeEventListener("mouseUp", timedClickMode_mouseUp)
            time_io = null
        }

    }

}

// 대형 구성 정보
import flash.geom.Point
internal class FormationData {
    public var dests:Vector.<Point>
    private var count:int = 0
    public function FormationData(len:uint) {
        dests = new Vector.<Point>(len, true)
        for(var i:int=0 ; i<dests.length ; i++) dests[i] = new Point
    }
    public function push(dx:Number, dy:Number):void {
        dests[count].x = dx
        dests[count].y = dy
        count ++
    }
    public function get full():Boolean { return count == dests.length }
    public function get extra():Boolean { return count != dests.length }
}

// 대형 발생기
internal class FormationDataGenerator {
    private static var list:Array = [f0, f1, f2, f3, f4, f5, f6]
    private static var numUnits:uint
    private static var data:FormationData
    public static function get length():uint { return list.length }
    public static function gen(idx:int, num:uint, dx:Number, dy:Number):FormationData {
        numUnits = num
        data = new FormationData(num)
        list[idx](dx, dy)
        return data
    }

    // 직사각형
    public static function f0(destX:Number, destY:Number):void {
        var numColumns:int = Math.sqrt(numUnits)
        var numRows:int = numUnits / numColumns
        var numMods:int = numUnits - numColumns*numRows
        var spaceX:Number = Unit.R * 2, spaceY:Number = Unit.R * 2
        var LT_x:Number = destX - numRows*spaceX/2
        var LT_y:Number = destY - numColumns*spaceY/2
        
        var count:int = 0
        for(var column:int=0 ; column<numColumns ; column++){
            for(var row:int=0 ; row<numRows ; row++){
                data.push(LT_x + row*spaceX, LT_y + column*spaceY)
                count ++
            }
        }
        if(count < numUnits){
            var numRest:uint = numUnits - numRows*numColumns
            for(var i:int=0 ; i<numRest ; i++){
                data.push(LT_x + i*spaceX, LT_y + column*spaceY)
                count ++
            }
        }
    }
    
    // 원
    public static function f1(destX:Number, destY:Number):void {
        var R:Number = Math.min(300, numUnits*2)
        var t:Number
        for(var i:int=0 ; i<numUnits ; i++){
            t = 2*Math.PI*i/numUnits
            data.push(destX + R*Math.cos(t), destY + R*Math.sin(t))
        }
    }
    
    // 다층 원
    private static var circularCrowd_angle:Number = 0
    public static function f2(destX:Number, destY:Number):void {
        var rest:int = numUnits
        var need:int = Math.min(3, rest)
        var count:int = 0
        var R:Number = Unit.R * 2
        var t:Number = circularCrowd_angle += 1 * Math.PI/180
        
        var k:Number
        while(true){
            for(var i:int=0 ; i<need ; i++){
                k = 2*Math.PI * i/need
                data.push(destX + R*Math.cos(k+t), destY + R*Math.sin(k+t))
                count ++
            }
            rest -= need
            if(rest <= 0) break
            need = Math.min(rest, need+5)
            R += Unit.R * 3
        }
    }
    
    // 쐐기
    public static function f3(cx:Number, cy:Number):void {
        var rest:uint = numUnits
        var num:uint = 1, num_inc:uint = 8
        var rowSpace:Number = Unit.R * 6
        var spaceX:Number = Unit.R * 2.5
        var spaceY:Number = Unit.R * 2
        
        var i:int, half:uint, other:uint
        while(rest > 0){
            if(rest <= num){ num=rest ; rest=0 }
            else{ rest -= num }
            
            cx -= rowSpace
            half = num / 2
            other = num - half
            if(num & 1) { data.push(cx, cy) ; other-- } 
            for(i = 1 ; i <= half ; i++) data.push(cx + spaceX*i, cy - spaceY*i)
            for(i = 1 ; i <= other ; i++) data.push(cx + spaceX*i, cy + spaceY*i)
            num += num_inc
        }
    }
    
    // 나선
    public static function f4(cx:Number, cy:Number):void {
        var t:Number = 0, r:Number = Unit.R * 2
        var rInc:Number = Unit.R / 4
        
        for(var i:int = 0 ; i < numUnits ; i++){
            data.push( cx + r*Math.cos(t), cy + r*Math.sin(t) )
            t += Math.acos((r*r + (r+rInc)*(r+rInc) - Unit.R*Unit.R*4) / (2*r*(r+rInc)))
            r += rInc
        }
    }
    
    // 불꽃놀이
    private static var fire_angle:Number = 30 * Math.PI/180
    public static function f5(cx:Number, cy:Number):void {
        var rest:uint = numUnits
        var t:Number = 0, r:Number = Unit.R * 2, space:Number = Unit.R * 2
        var numNiddles:uint = 8, tInc:Number = 2*Math.PI / numNiddles
        var limit:uint = numNiddles
        var angle:Number = fire_angle += Math.PI/180
        
        var c:int = 0
        for(var i:int = 0 ; i <= limit ; i++){
            if(i == numNiddles){
                rest -= numNiddles
                if(rest <= 0) break
                else{
                    i = 0
                    r += space
                    t = 0
                    limit = Math.min(rest, numNiddles)
                }
            }
            data.push(cx + r * Math.cos(angle + t), cy + r * Math.sin(angle + t))
            t += tInc
            c++
            if(c == numUnits) break
        }
    }
    
    // 랜덤 (더블클릭으로 하는 거였는데 시리즈에 추가함)
    public static function f6(cx:Number, cy:Number):void {
        for(var i:int=0 ; i<numUnits ; i++){
            data.push(Math.random()*500, Math.random()*500)
        }
    }

}