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

本気でダンジョンRPG作る step1 -(ランダムマップ生成)

LIVE CODING 2010/04/22 17:33-0:41
LIVE CODING 2010/04/23 9:00-11:44
next step:  http://wonderfl.net/c/tFGr
wonderflでがんばってダンジョンRPGを作ってみます。
途中で挫折したりしたらごめんなさい。
とりあえず第一段階としてランダムマップの生成をします。
黒:壁
白:部屋
うすい灰色:通路
黄色:敵
赤:主人公
緑:階段
まだ操作はできません。
step1はこれで終了です。
制作過程を残しておきたいので、
step2以降は、forkしてつくっていきます。
早くもソースがごちゃごちゃ。
先が思いやられる。
English
I make a RPG.

step1: Generate a random map
black:wall
white:room or passage
yellow:Enemy
red:player
green:staire

This can't be controlled yet...
Get Adobe Flash player
by shohei909 04 Jul 2010
/**
 * Copyright shohei909 ( http://wonderfl.net/user/shohei909 )
 * MIT License ( http://www.opensource.org/licenses/mit-license.php )
 * Downloaded from: http://wonderfl.net/c/eamf
 */

package{
    //LIVE CODING 2010/04/22 17:33-0:41
    //LIVE CODING 2010/04/23 9:00-11:44
    
    
    //next step:  http://wonderfl.net/c/tFGr
    
    
    
    
    
    //wonderflでがんばってダンジョンRPGを作ってみます。
    //途中で挫折したりしたらごめんなさい。
    
    //とりあえず第一段階としてランダムマップの生成をします。
    //    黒:壁
    //    白:部屋
    //    うすい灰色:通路
    //    黄色:敵
    //    赤:主人公
    //    緑:階段
    //まだ操作はできません。
    
    //step1はこれで終了です。
    //制作過程を残しておきたいので、
    //step2以降は、forkしてつくっていきます。
    
    

    
    
    
    
    //早くもソースがごちゃごちゃ。
    //先が思いやられる。
    
    
    
    
    //English
    
    // I make a RPG.
    // 
    // step1: Generate a random map
    //     black:wall
    //    white:room or passage
    //    yellow:Enemy
    //    red:player
    //    green:staire
    //
    // This can't be controlled yet...
    
    
    
    
    
    

    
    import flash.display.*;
    public class Game extends Sprite{
        public function Game() {
               stage.addChild( new RPG() );
        }
    }
}

import flash.display.*;
    
class RPG extends Sprite {
    private var map:Map;
    public function RPG() {
        init();
    }
    public function init():void{
        map = new Map(35,35);
        while(this.numChildren>0){
            this.removeChildAt(0);
        }
        
        map.bitmap.scaleX = 8;
        map.bitmap.scaleY = 8;
        addChild(map.bitmap);
    }
}






//マップデータのクラス
class Map{
    public var bitmap:Bitmap;
    public var rank:int = 1; //階層
    public var width:int;
    public var height:int;
    
    
    
    //マップの内容 0:壁、1:部屋 2:通路 3:アイテム 4:敵 5:自分 6:階段
    public var data:Vector.<Vector.<int>>;
    //マップに関する詳細なデータ
    public var detail:Vector.<Vector.<Floor>>;
    
    
    //部屋のサイズは6×6固定になります
    public static var ROOM_SIZE:int = 6;
    
    
    
    public var rooms:Vector.<Room>;//部屋のデータ
    public var routes:Vector.<Route>;
    public var enemys:Vector.<Enemy>;
    public var items:Vector.<DropItem>;//床に落ちているアイテム
    
    public var man:Man;
    
    //wとhには21以上を指定してください。
    public function Map(w:int = 50,h:int = 50){
        if(w < ROOM_SIZE *3 +2){w = ROOM_SIZE *3 +2;}
        if(h < ROOM_SIZE *3 +2){h = ROOM_SIZE *3 +2;}
        width = w;
        height = h;
        init();
    }
    
    //現在のサイズでマップを初期化
    public function init():void{
        bitmap = new Bitmap(new BitmapData( width, height, false, 0x000000 ) );
        
        rooms = new Vector.<Room>();
        routes = new Vector.<Route>();
        enemys = new Vector.<Enemy>();
        items = new Vector.<DropItem>();
        
        data = new Vector.<Vector.<int>>(width);
        data.fixed;
        
        detail = new Vector.<Vector.<Floor>>(width);
        detail.fixed;
        
        for(var i:int=0; i<width; i++ ){
            data[i] = new Vector.<int>(height);
            data[i].fixed;
            
            detail[i] = new Vector.<Floor>(height);
            detail[i].fixed;
            
            for(var j:int=0; j<height; j++ ){
                data[i][j] = 0;
                var placable:Boolean = true;
                
                
                detail[i][j] = new Floor(i,j);
                detail[i][j].wall(0);
                if( i==0 || j==0 || i==width-1 || j==height-1 ){
                    detail[i][j].routeable = false;
                    detail[i][j].roomable = false;
                }
            }    
        }
        
        if( generate() ){
            update();
        }else{
            init();
        }
    }
    
    //ランダムマップの生成をします
    public function generate():Boolean{
        var missCount:int = 0;
        while(missCount<10){
            if( requestRoom( 1+Math.random()*(width-ROOM_SIZE-2), 1+Math.random()*(height-ROOM_SIZE-2) ) == false){
                missCount++;
            }else{
                missCount = 0;
            }
        }
        if(rooms.length<2){
            if(width >= ROOM_SIZE*2+3 && height >= ROOM_SIZE*2+3){
                return false;
            }
        }else{
            var c:int = 0;
            while(connect() == false){
                var i:int = c%rooms.length;
                exit( rooms[i] );c++;
                if(c>rooms.length*100){return false;}
            }
        }
        for each(var route:Route in routes){
            cutRoute(route);
        }
        setParts();
        
        return true;
    }
    
    //指定された位置に部屋を作成を試みます
    //成功したかどうかをbooleanで返します。
    private function requestRoom(x:int,y:int):Boolean{
        if(width < ROOM_SIZE*2+3 || height < ROOM_SIZE*2+3){return false;}
        var miss:Boolean = false;
        for(var i:int = x; i< x+ROOM_SIZE; i++){
            for(var j:int = y; j< y+ROOM_SIZE; j++){
                if( detail[i][j].roomable == false ){
                    miss = true;
                }
            }
        }
        if(miss){ return false; }
        else{ makeRoom(x,y); }
        return false;
    }
    //部屋を作成します。requestRoom以外から呼び出さないでください。
    private function makeRoom(x:int,y:int):void{
        rooms.push(new Room(x,y,ROOM_SIZE,ROOM_SIZE,rooms.length));
        for(var i:int = x-1; i< x+ROOM_SIZE+1; i++){
            for(var j:int = y-1; j< y+ROOM_SIZE+1; j++){
                if(x <= i && i< x+ROOM_SIZE && y <= j && j < y+ROOM_SIZE ){
                    data[i][j] = 1;
                    detail[i][j].name = "room";
                    detail[i][j].index = rooms.length-1;
                    detail[i][j].roomable=false;
                    detail[i][j].routeable=false;
                }else if( (x+1<=i && i<x+ROOM_SIZE-1) || (y+1<=j && j<y+ROOM_SIZE-1) ){
                    detail[i][j].roomable=false;
                }else{
                    detail[i][j].roomable=false;
                    detail[i][j].routeable=false;
                }
            }
        }
    }
    //すべての部屋がつながってるか調べます
    private function connect():Boolean{
        var ok:Boolean = true;
        var v:Vector.<int> = rooms[0].getConnect();
        for(var i:int=0; i<rooms.length; i++){
            if(v.indexOf(i)==-1){ok=false;}
        }
        return ok;
    }
    //rに出口となる部屋をまっすぐ伸ばします。
    private function exit(r:Room):Boolean{
        var a:int = Math.random()*4;
        var c:int;
        var x:int;
        var y:int;
        var dx:int=0;
        var dy:int=0;
        switch(a){
            case 0://上に道を伸ばす
                x = r.x+1 + Math.random()*(ROOM_SIZE-2);
                y = r.y-1;
                dy = -1; 
                break;
            case 1://下に道を伸ばす
                x = r.x+1 + Math.random()*(ROOM_SIZE-2);
                y = r.y+r.height;
                dy = 1; 
                break;
            case 2://左に道を伸ばす
                x = r.x-1;
                y = r.y+1 + Math.random()*(ROOM_SIZE-2);
                dx = -1; 
                break;
            case 3://右に道を伸ばす
                x = r.x+r.width;
                y = r.y+1 + Math.random()*(ROOM_SIZE-2);
                dx = 1; 
                break;
        }
        if(detail[x][y].routeable == true){
            var route:Route = new Route(routes.length);
            route.rooms.push(r);
            
            c = 0; 
            while(c<height){
                if(detail[x][y].routeable == true){
                    data[x][y] = 2;
                    detail[x][y].route(route.index);
                    route.floors.push(detail[x][y]);
                    x += dx;
                    y += dy;
                }else if(data[x][y]==1){
                    close(dx,dy,r);
                    close(-dx,-dy,rooms[detail[x][y].index]);
                    rooms[ detail[x][y].index ].exits.push( route );
                    r.exits.push( route );
                    route.rooms.push( rooms[detail[x][y].index] );
                    routes.push(route);
                    break;
                }else if(data[x][y]==2){
                    close(dx,dy,r);
                    r.exits.push(route);
                    routes[ detail[x][y].index ].connect(route);
                    break;
                }else if(c>0){
                    close(dx,dy,r);
                    r.exits.push(route);
                    routes.push(route);
                    break;
                }else{
                    break;
                }
                c++;
            }
        }else{
            return false;
        }
        return true;
    }
    //rの一面を出口にできなくする。
    private function close(dx:int,dy:int,r:Room):void{
        for(var i:int = r.x+dx; i< r.x+r.width+dx; i++){
            for(var j:int = r.y+dy; j< r.y+r.height+dy; j++){
                detail[i][j].routeable=false;
            }
        }
    }
    //行き止まりを消す。
    public function cutRoute(r:Route):void{
        var loop:Boolean = true;
        while(loop){
            loop = false;
            for each(var f:Floor in r.floors){
                var c:int = 0;
                var side:Floor = detail[f.x + 1][f.y];
                if( ( side.name == "route"  && side.index == r.index ) || side.name == "room"){c++;}
                side = detail[f.x - 1][f.y];
                if( ( side.name == "route"  && side.index == r.index ) || side.name == "room"){c++;}
                side = detail[f.x][f.y - 1];
                if( ( side.name == "route"  && side.index == r.index ) || side.name == "room"){c++;}
                side = detail[f.x][f.y + 1];
                if( ( side.name == "route"  && side.index == r.index ) || side.name == "room"){c++;}
                if(c == 1){
                    loop = true;
                    data[f.x][f.y] = 0;
                    detail[f.x][f.y].wall(0);
                    r.floors.splice(r.floors.indexOf(f),1);
                }
            }
        }
    } 
    //人、敵、階段、アイテムなどを設置
    private function setParts():void{
        //
        
        GameUtil.setItems(this,rank);
        GameUtil.setEnemys(this,rank);
        
        //主人公は0番の部屋に配置
        var x:int = rooms[0].x + rooms[0].width * Math.random(); 
        var y:int = rooms[0].y + rooms[0].height * Math.random(); 
        data[x][y] =  5;
        man = new Man( x, y, this);
        
        //階段は最後のの部屋に配置
        var l:int = rooms.length-1;
        x = rooms[l].x + rooms[l].width * Math.random(); 
        y = rooms[l].y + rooms[l].height * Math.random(); 
        data[x][y] =  6;
    }
    
    
    
    
    
    
    //bitmapを更新します。
    public function update():void{
        var bitmapData:BitmapData = bitmap.bitmapData;
        bitmapData.lock();
        for(var i:int=0; i<width; i++ ){
            for(var j:int=0; j<height; j++ ){
                var color:uint; 
                switch(data[i][j]){
                    case 0:
                        color = 0x000000; 
                        break;
                    case 1:
                        color = 0xFFFFFF; 
                        break;
                    case 2:
                        color = 0xEEEEEE; 
                        break;
                    case 3:
                        color = 0x0000FF; 
                        break;
                    case 4:
                        color = 0xFFFF00; 
                        break;
                    case 5:
                        color = 0xFF0000; 
                        break;
                    case 6:
                        color = 0x00FF00; 
                        break;
                }
                bitmapData.setPixel(i,j,color);
            }
        }
        bitmapData.unlock();
    }
}



//部屋のクラス
class Room{
    public var x:int;
    public var y:int;
    public var width:int;
    public var height:int;
    public var index:int;
    public var visit:Boolean = false;//この部屋を通ったことがあるか?
    
    
    public var exits:Vector.<Route> = new Vector.<Route>();

    
    public function Room(xx:int,yy:int,w:int,h:int,i:int):void{
        x=xx;
        y=yy;
        width=w;
        height=h;
        index=i;
    }
    
    
    //この部屋とつながっている部屋を返します
    public function getConnect( v:Vector.<int> = null ):Vector.<int>{
        if(v == null){v = new Vector.<int>();}
        if(v.indexOf(index)== -1){ v.push(index);}
        for each(var route:Route in exits){
            v = route.getConnect(v);
        }
        return v;
    }
}





//道のクラス
class Route{
    //通り道{x,y,visit}
    public var floors:Vector.<Floor> = new Vector.<Floor>();
    //つながっている部屋のリスト。
    public var rooms:Vector.<Room> = new Vector.<Room>();
    public var index:int;
    public function Route(i:int){
        index = i;
    }
    
    
    
    //Routeを接続します。
    public function connect(r:Route):void{
        floors.concat(r.floors);
        rooms.concat(r.rooms);
        for each(var room:Room in r.rooms){
            room.exits.push(this);
        }
        for each(var floor:Floor in r.floors){
            floor.index = index;
        } 
    }
    
    
    
    public function getConnect( v:Vector.<int> = null ):Vector.<int>{
        for each(var room:Room in rooms){
            if(v.indexOf(room.index) == -1){ v= room.getConnect(v) }
        }    
        return v;
    }
    
    

}
class Floor{
    public var x:int;
    public var y:int;
    public var name:String="wall";
    public var index:int = 0;
    public var visit:Boolean=false;
    public var routeable:Boolean=true;
    public var roomable:Boolean=true;
    
    public function Floor(xx:int,yy:int){
        x = xx;
        y = yy;
    }
    
    //この床を壁として初期化
    public function wall(i:int):void{
        name = "wall";
        index = i;
        routeable = true;
        roomable = true;
    } 
    //この床を部屋として初期化
    public function room(i:int):void{
        name = "room";
        index = i;
        routeable = false;
        roomable = false;
    } 
    //この床を道として初期化
    public function route(i:int):void{
        name = "route";
        index = i;
        routeable = false;
        roomable = false;
    } 
}
//床に落ちているアイテムのクラス
class DropItem{
    public var x:int = 0;
    public var y:int = 0;
    public var name:String = "item";//itemのクラス
}
//キャラクターのクラス
//キャラクターには敵や自分が含まれます。
class Charactor{
    public var x:int = 0;
    public var y:int = 0;
    public var map:Map;        //このキャラクターが配置されているマップ
    public var life:int = 100;
    public var maxLife:int = 100;
    public var name:String = "chara";
}
class Man extends Charactor{
    public function Man(xx:int, yy:int, m:Map){
        x=xx; y=yy; map=m;
        name = "man";
    }
}
class Enemy extends Charactor{
    public function Enemy(xx:int, yy:int, m:Map,n:String){
        x=xx; y=yy; map=m;
        name = n;
    }
}









//敵、画像、アイテム、技、などのデータが収められている静的クラス
class GameData{
    public static var ROOM_WIDTH:int = 6;
    public static var ROOM_HEIGHT:int = 6;
    public static var ROOM_DEPTH:int = 6;
    
    
    
    
    
    //各階のデータ=============================================
    public static var RANK_ARRAY:Array =[
        {//0階
        },
        {//1階
            minEnemy:1,
            maxEnemy:2,
            enemy:["mosamosa","fusafusa"]
        }
    ];
    //(各階のデータここまで)=============================================
    
    
    
    
    
    
    
    
    
    //敵のデータ==============================================
    public static var ENEMY_DATA:Object = {
        mosamosa:{//もさもさ
            name:"もさもさ"
        },
        fusafusa:{
            name:"ふさふさ"
        }
    }
    //(敵のデータここまで)====================================
}

class GameUtil{
    //その階層に見合ったアイテムを配置
    public static function setItems(map:Map,rank:int):void{}
    
    
    public static function setEnemys(map:Map,rank:int):void{
        for (var i:int=1;i<map.rooms.length;i++){
            var room:Room = map.rooms[i];
            var max:int = GameData.RANK_ARRAY[rank].maxEnemy;
            var min:int = GameData.RANK_ARRAY[rank].minEnemy;
            var c:int = min + (max-min+1) * Math.random();
            while(c>0){
                var x:int = room.x + room.width * Math.random(); 
                var y:int = room.y + room.height * Math.random(); 
                var e:Array = GameData.RANK_ARRAY[rank].enemy;
                var l:int = e.lenght*Math.random();
                var name:String = e[l];
                
                map.data[x][y] = 4;
                map.enemys.push( new Enemy(x,y,map,name) )
                c--;
            }
        }
    }
    
    
}