ローグライクマップ 生成 ローグライクマップ 工程の再現アニメーションが途中・・ 大きさの制御が適当 kenbu forked:0favorite:9lines:329license : MIT License modified : 2009-06-16 00:28:24 Embed Tweet /** ローグライクマップ 工程の再現アニメーションが途中・・ 大きさの制御が適当 */ 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]; } } Code Fullscreen Preview Fullscreen natak_2010 hacker_x60gg.. osamX digitrick Hiiragi massy22 : ローグ siouxcitizen.. : ローグ tenchiwang2 : 迷宮 zahir : 不思議のダンジョン ローグ 迷宮 width Rectangle height map Array forEach graphics removeEventListener Boolean length addEventListener Object push Event.ENTER_FRAME addChild uint String Math.random Event Sprite