ローグライクマップ 生成
ローグライクマップ
工程の再現アニメーションが途中・・
大きさの制御が適当
/**
* Copyright kenbu ( http://wonderfl.net/user/kenbu )
* MIT License ( http://www.opensource.org/licenses/mit-license.php )
* Downloaded from: http://wonderfl.net/c/1e3V
*/
/**
ローグライクマップ
工程の再現アニメーションが途中・・
大きさの制御が適当
*/
package
{
import flash.display.Bitmap;
import flash.display.BitmapData;
import flash.display.Sprite;
import flash.display.StageAlign;
import flash.display.StageScaleMode;
import flash.events.Event;
import flash.geom.Rectangle;
import flash.geom.Point;
public class Main extends Sprite
{
private var map:RogueLikeMap;
private var bitmap:Bitmap;
private const WIDTH:Number = 90;
private const HEIGHT:Number = 90;
private const SCALE:Number = 5;
public function Main()
{
stage.scaleMode = StageScaleMode.NO_SCALE;
stage.align = StageAlign.TOP_LEFT;
var progressArray:Array = [];
map = new RogueLikeMap(WIDTH,HEIGHT, 4,4,5,progressArray);
var bitmapData:BitmapData = new BitmapData(WIDTH*SCALE, HEIGHT*SCALE);
bitmap = new Bitmap(bitmapData);
addChild(bitmap);
this.addEventListener(Event.ENTER_FRAME, enterFrameHandler);
}
private var cnt:int = 0;
private function enterFrameHandler(event:Event):void
{
var l:int = 100;
for(var i:int = 0; i<l; i++)
{
draw();
}
if(cnt == map.buildProgressArray.length)
{
this.removeEventListener(Event.ENTER_FRAME, enterFrameHandler);
}
}
private var rect:Rectangle = new Rectangle(0,0,0,0);
private function draw():void
{
if(cnt == map.buildProgressArray.length)
{
return;
}
var point:Object= map.buildProgressArray[cnt];
var color:Number;
if(point.value == 0)
{
color = 0xffffffff;
}
else
{
color = 0xff000000;
}
var scale:Number = 3;
var bitmapData:BitmapData = bitmap.bitmapData;
rect.x = point.x * SCALE;
rect.y = point.y * SCALE;
rect.width = SCALE;
rect.height = SCALE;
bitmapData.fillRect(rect, color);
cnt++;
}
}
}
import flash.display.Graphics;
import flash.display.Sprite;
import flash.geom.Point;
import flash.geom.Rectangle;
class RogueLikeMap
{
private var rectArray:Array;
private var roomArray:Array;
private var roadArray:Array;
public var width:uint;
public var height:uint;
private var minRoomWidth:uint;
private var minRoomHeight:uint;
private var maxCouple:uint;
public var data:Array;
public var buildProgressArray:Array;
public function RogueLikeMap(width:uint, height:uint, minRoomWidth:uint, minRoomHieght:uint, maxCouple:uint, buildProgressArray:Array = null)
{
//minRoomWidth 最小の部屋のサイズ width
//minRoomHeight 最小の部屋のサイズ height
//maxCouple 最大分割数。
this.width = width;
this.height = height;
this.minRoomWidth = minRoomWidth;
this.minRoomHeight = minRoomHieght;
this.maxCouple = maxCouple;
this.buildProgressArray = buildProgressArray;
initialize();
}
private function initialize():void
{
data = [];
rectArray = [];
roomArray = [];
roadArray = [];
setRect(new Rect(0,0,width, height, (Math.random()>0.5)));
setRoom();
setRoad();
setDataArray();
}
private var splitCnt:int;
private function setRect(rect:Rect):void
{
if(maxCouple <= splitCnt++)
{
return;
}
var x:uint = rect.x;
var y:uint = rect.y;
var w:uint = rect.width;
var h:uint = rect.height;
rectArray.push(rect);
//分割する
var nowRect:Rect;
if(rect.splitAline)
{
//縦に分割
var _x:uint = uint(w/2);
rect.width = _x;
nowRect = new Rect(x+_x, y, w-_x, h, !rect.splitAline);
setRect(nowRect);
}
else
{
//横に分割
var _y:uint = int(h/2);
rect.height = _y;
nowRect = new Rect(x, y+_y, w, h-_y, !rect.splitAline);
setRect(nowRect);
}
}
private function setRoom():void
{
rectArray.forEach(function(rect:Rect, i:int, array:Array):void{
var room:Rectangle = new Rectangle(rect.x, rect.y, rect.width, rect.height);
var w:uint = ((room.width-2) - minRoomWidth)*Math.random() + minRoomWidth;
var h:uint = ((room.height-2) - minRoomHeight)*Math.random() + minRoomHeight;
room.x = room.x + int((rect.width - w)/2);
room.y = room.y + int((rect.height - h)/2);
room.width = w;
room.height = h;
roomArray.push(room);
});
}
public function setRoad():void
{
//道を引く。
var prevRoomRect:Rectangle;
rectArray.forEach(function(rect:Rect, i:int, arr:Array):void{
//一個目は飛ばす。
if(i > 0)
{
var road:Road;
var prev:Rect = arr[i-1];
var room:Rectangle = roomArray[i];
var prevRoom:Rectangle = roomArray[i-1];
//中継点
var x0:uint;
var x1:uint;
var y0:uint;
var y1:uint;
if(rect.x < prev.x)
{
//ターゲットが右側。
//始点、
//終点
y0 = getRadomPos(room.y, room.height);
y1 = getRadomPos(prevRoom.y, prevRoom.height);
road = new Road(
//始点
new Point(room.x + room.width, y0),
//中継点
new Point(rect.x+rect.width, y0),
new Point(rect.x+rect.width, y1),
new Point(prevRoom.x, y1)
);
}
else if(rect.x > prev.x)
{
//ターゲットが左側
y0 = getRadomPos(room.y, room.height);
y1 = getRadomPos(prevRoom.y, prevRoom.height);
road = new Road(
//始点
new Point(room.x, y0),
//中継点
new Point(rect.x, y0),
new Point(rect.x, y1),
new Point(prevRoom.x+prevRoom.width, y1)
);
}
else if(rect.y > prev.y )
{
//ターゲットが上
x0 = getRadomPos(room.x, room.width);
x1 = getRadomPos(prevRoom.x, prevRoom.width);
road = new Road(
//始点
new Point(x0, room.y),
//中継点
new Point(x0, rect.y),
new Point(x1, rect.y),
new Point(x1, prevRoom.y+prevRoom.height)
);
}
else
{
//ターゲット下
x0 = getRadomPos(room.x, room.width);
x1 = getRadomPos(prevRoom.x, prevRoom.width);
road = new Road(
//始点
new Point(x0, room.y + room.height),
//中継点
new Point(x0,rect.y+rect.height),
new Point(x1, rect.y+rect.height),
new Point(x1, prevRoom.y)
);
}
roadArray.push(road);
}
});
}
private function getRadomPos(x:uint, w:uint):uint
{
//x ~ (x + w) の間のランダムな数値を返す。
var _w:int = int((w-1)*Math.random())
return x + _w + 1;
}
private function setDataArray():void
{
//壁を生成
var l:int = width * height;
for(var i:int = 0; i<l; i++)
{
setData(i%width, int(i/width), 1);
}
//部屋を生成
roomArray.forEach(function(rect:Rectangle, i:int, arr:Array):void
{
var n:int = rect.y + rect.height;
for(var y:int = rect.y; y<n; y++)
{
var l:int = rect.x + rect.width;
for(var x:int = rect.x; x<l; x++)
{
setData(x, y, 0);
}
}
});
//道を生成
roadArray.forEach(function(road:Road,i:int, arr:Array):void{
road.points.forEach(function(p:Point, i:int, array:Array):void{
if(i != 0)
{
setDataRoad(array[i-1], array[i]);
}
});
});
}
private function setDataRoad(point1:Point, point2:Point):void
{
//2点間を線でつなぎます。
if(point1.y == point2.y)
{
var l:int = (point1.x - point2.x);
var dirX:int = (l>0)?1:-1;
l = (l>0)?l:-l;
for(var i:int = 0; i<l; i++)
{
var x:uint = point2.x + dirX*i;
setData(x,point1.y,0);
}
}
else
{
var n:int = (point1.y - point2.y);
var dirY:int = (n>0)?1:-1;
n = (n>0)?n:-n;
for(var j:int = 0; j<n; j++)
{
var y:uint = point2.y + dirY*j;
setData(point1.x,y,0);
}
}
}
private function setData(x:uint, y:uint, value:uint):void
{
data[x+width*y] = value;
if(buildProgressArray)
{
buildProgressArray.push({x:x, y:y, value:value});
}
}
public function dump():Sprite
{
var sprite:Sprite = new Sprite();
return sprite;
var g:Graphics = sprite.graphics;
g.lineStyle(1);
rectArray.forEach(function(rect:Rectangle, i:int, arr:Array):void
{
g.drawRect(rect.x, rect.y, rect.width, rect.height);
});
roomArray.forEach(function(rect:Rectangle, i:int, arr:Array):void
{
g.beginFill(0xff0000);
g.drawRect(rect.x, rect.y, rect.width, rect.height);
});
g.endFill();
//道を引く
g.lineStyle(1, 0xff00ff);
roadArray.forEach(function(road:Road,i:int, arr:Array):void{
g.moveTo(road.points[0].x,road.points[0].y);
g.lineTo(road.points[1].x,road.points[1].y);
g.lineTo(road.points[2].x,road.points[2].y);
g.lineTo(road.points[3].x,road.points[3].y);
});
var traceLine:String = "";
var cnt:int = 0;
data.forEach(function(v:uint, i:int, arr:Array):void{
traceLine += v+""
cnt++;
if(cnt%width == 0)
{
traceLine ="";
cnt = 0;
}
});
return sprite;
}
}
class Rect extends Rectangle
{
public var splitAline:Boolean;
public function Rect(x:Number, y:Number, width:Number, height:Number ,splitAline:Boolean)
{
super(x, y, width, height);
this.splitAline = splitAline;
}
}
class Road
{
public var points:Array;
public function Road(startPoint:Point, jointPoint1:Point, jointPoint2:Point, endPoint:Point)
{
points = [startPoint, jointPoint1, jointPoint2, endPoint];
}
}