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...
Awsome seeing you doing things working :)
(almost midnight here)
You're the first guy i saw live coding :]
.. but i dont understand what u write ^^
good luck!
/**
* 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--;
}
}
}
}