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

L-SYSTEMによる自己相似図形の描画

L-SYSTEMによる自己相似図形の描画
マウスクリックで成長
カーソルキー上下で違う図形を描画
参考:http://www14.ocn.ne.jp/~kk62526/Lsys/index.html
http://www.hl.pc.uec.ac.jp/hays/computer/turtle.htm
Get Adobe Flash player
by Nao_u 23 Apr 2009
//
// L-SYSTEMによる自己相似図形の描画
//
// マウスクリックで成長
// カーソルキー上下で違う図形を描画
//
// 参考:http://www14.ocn.ne.jp/~kk62526/Lsys/index.html
//      http://www.hl.pc.uec.ac.jp/hays/computer/turtle.htm
//
package {    
    import flash.display.Sprite;    
    import flash.events.*;    
    [SWF(width="465", height="465", backgroundColor="0xFFFFFF", frameRate="60")]     
    public class FlashTest extends Sprite {    
        public function FlashTest() {    
            Main = this;    
            initialize();    
            stage.addEventListener(Event.ENTER_FRAME,update);     
            stage.addEventListener(KeyboardEvent.KEY_DOWN, keyCheckDown);      
            stage.addEventListener(MouseEvent.MOUSE_DOWN,  onClick);      
        }    
    }    
}            

import flash.display.Sprite;    
import flash.text.*;
import flash.events.*;    
import flash.geom.*; 
import flash.ui.Keyboard;      
var SCREEN_W:Number = 465, SCREEN_H:Number = 465;   
var Main:Sprite;    
var Text:TextField;
var Text2:TextField;

var Ls:LSystem;
var Name:String = "";
var LsNo:int = 0;
var LsNoMax:int = 9;

function initialize():void{    
    Text = new TextField();    
    Text.text = "";  
    Text.autoSize = "left";  
    Main.addChild(Text);     
 
    Text2 = new TextField();    
    Text2.y = 16;
    Text2.text = "";  
    Text2.autoSize = "left";  
    Main.addChild(Text2);     

    Ls = createLs( LsNo );
}

function createLs( type:int ):LSystem{
    var l:LSystem;
    switch( type ){
    case 0: 
        Name = "コッホ曲線";
        l = new LSystem( "F", 4, 60 );
        l.CntMax  = 5;
        l.addRule( new Rule("F","F-F++F-F") );
        l.draw();
        break;

    case 1: 
        Name = "シェルビンスキーのガスケット";
        l = new LSystem( "F", 5, 120 );
        l.addRule( new Rule("F","F-F-F-GG") );
        l.addRule( new Rule("G","GG") );
        l.draw();
        break;

    case 2: 
        Name = "シェルビンスキーの Arrowhead";
        l = new LSystem( "LF", 5, 60  );
        l.addRule( new Rule("L","-RF+LF+RF-") );
        l.addRule( new Rule("R","+LF-RF-LF+") );
        l.addRule( new Rule("F","") );
        l.draw();
        break;

    case 3: 
        Name = "樹木1";
        l = new LSystem( "F", 10, 15 );
        l.XInit   = 200;
        l.RotInit = -90;
        l.CntMax  = 4;
        l.addRule( new Rule("F","F[+F-F-F]F[--F+F+F]") );
        l.draw();
        break;

    case 4: 
        Name = "樹木2";
        l = new LSystem( "F", 2, 25 );
        l.XInit = 200;
        l.RotInit = -90;
        l.CntMax  = 5;
        l.addRule( new Rule("F","F[-FF]F[++F]F") );
        l.draw();
        break;

    case 5: 
        Name = "樹木3";
        l = new LSystem( "F", 22, 21 );
        l.XInit = 200;
        l.RotInit = -90;
        l.CntMax  = 7;
        l.addRule( new Rule("F","F[-F[F+++F]]") );
        l.draw();
        break;

    case 6: 
        Name = "樹木4";
        l = new LSystem( "F", 40, 17 );
        l.XInit = 200;
        l.RotInit = -90;
        l.CntMax  = 8;
        l.addRule( new Rule("F","F[+F][-F]") );
        l.draw();
        break;

    case 7: 
        Name = "ドラコン曲線";
        l = new LSystem( "F+FA-F", 1, 45 );
        l.XInit = 150;
        l.YInit = 350;
        l.CntMax  = 14;
        l.addRule( new Rule("A","A+F+FB") );
        l.addRule( new Rule("B","A-F-FB") );
        l.draw();
        break;

    case 8: 
        Name = "平面充填曲線";
        l = new LSystem( "XF+F+XF+F+XF+F", 3, 60 );
        l.XInit = 10;
        l.YInit = 40;
        l.CntMax  = 5;
        l.addRule( new Rule("X","XF+F+XF-F-F-XF-F+F+F-F+F+F-X") );
        l.draw();
        break;


    }
    Text.text = (type+1) +":"+ Name + " " + l.getRuleText();
    Text2.text = l.Str;  

    return l;
}    


function onClick(event:MouseEvent):void{
    graphicClear();  
    Ls.update();
    Ls.draw();
}

function keyCheckDown(event:KeyboardEvent):void {      
    switch (event.keyCode){      
        case Keyboard.UP:    LsNo--; break;    
        case Keyboard.DOWN:  LsNo++; break;
    }     
    if( LsNo < 0 )        LsNo = LsNoMax-1;
    if( LsNo >= LsNoMax ) LsNo = 0;

    graphicClear();  
    Ls = createLs( LsNo );
    Ls.draw();
} 

function update(e :Event):void{    
//    graphicClear();  
} 

// 生成ルールクラス
class Rule {
    public var Src:String;
    public var Dst:String;

    public function Rule( src:String, dst:String ){
        Src = src;
        Dst = dst;
    }
}

// 描画用タートルグラフィッククラス
class Turtle {
    public var X:Number, prevX:Number;
    public var Y:Number, prevY:Number;
    public var Rot:Number;
    public var Speed:Number;
    public var RotAdd:Number;
    public var Stack:Array = new Array;
    public var StackPos:int = 0;
  
    public function Turtle( x:Number, y:Number, rot:Number, speed:Number, rotAdd:Number ){
        X = prevX = x;
        Y = prevY = y;
        Rot = rot;
        Speed = speed;
        RotAdd = rotAdd;
    }

    public function update( c:String ):void{
        switch( c ){
        case "G": // 前進
              moveForward();
            break;

        case "F": // 前進して線を引く
            moveForward();
            drawLine( prevX, prevY, X, Y, 1.0, 0xff0000 );
            break;

        case "+": // プラス方向に回転
              Rot += RotAdd;
            break;

        case "-": // マイナス方向に回転
              Rot -= RotAdd;
            break;

        case "[": // スタックに保存
              var t:Turtle = new Turtle( X, Y, Rot, Speed, RotAdd );
            Stack[StackPos] = t;
            StackPos++;
            break;

        case "]": // スタックから復帰
              StackPos--;
            X = Stack[StackPos].X;
            Y = Stack[StackPos].Y;
            prevX = Stack[StackPos].prevX;
            prevY = Stack[StackPos].prevY;
            Rot = Stack[StackPos].Rot;
            break;
        }
    }

    // 前進
    public function moveForward():void{
        prevX = X;
        prevY = Y;
        X += Speed * Math.cos( Rot * 2.0*Math.PI / 360.0 );
        Y += Speed * Math.sin( Rot * 2.0*Math.PI / 360.0  );
    }
}

// L-SYSTEMクラス
class LSystem {
    public var Str:String;
    public var RuleAry:Vector.<Rule> = new Vector.<Rule>;
    public var Speed:Number;
    public var RotAdd:Number;
    public var XInit:Number = 10;
    public var YInit:Number = 400;
    public var RotInit:Number = 0;
    public var Cnt:int = 0;
    public var CntMax:int = 8;

    public function LSystem( s:String, speed:Number, rotAdd:Number ){
        Str = s;
        Speed = speed;
        RotAdd = rotAdd;
    }
    
    public function update():Boolean{
        if( ++Cnt > CntMax ) return false;
        var out:String = "";
        var len:int = Str.length;
        for( var i:int=0; i<len; i++ ){
            var c:String = Str.charAt(i);
            var find:Boolean = false;
            for each( var r:Rule in RuleAry ){
                if( c == r.Src ){
                    out += r.Dst;
                    find = true;
                }
            }
            if( find == false ) out += c;
        }
        Str = out;
        Text2.text = Str;  
        
        return true;
    }

    public function addRule( r:Rule ):void{
        RuleAry.push( r );
    }

    public function getRuleText():String{
        var ret:String = "";
        for each( var r:Rule in RuleAry ){
            ret += "[" + r.Src + "→" + r.Dst + "]";
        }
        return ret;
    }

    public function draw():void{
        var t:Turtle = new Turtle( XInit, YInit, RotInit, Speed, RotAdd );

        var len:int = Str.length;
        for( var i:int=0; i<len; i++ ){
            var c:String = Str.charAt(i);
            t.update( c );
        }
    }
}


function graphicClear():void{  
    Main.graphics.clear();   
}  

function drawLine( sx:Number, sy:Number, ex:Number, ey:Number, size:Number, col:int ):void{      
    Main.graphics.lineStyle(size,col); 
    Main.graphics.moveTo( sx, sy );         
    Main.graphics.lineTo( ex, ey);            
}