forked from: 不思議のダンジョン自動生成
forked from 不思議のダンジョン自動生成 (diff: 1)
ActionScript3 source code
/**
* Copyright takimo ( http://wonderfl.net/user/takimo )
* MIT License ( http://www.opensource.org/licenses/mit-license.php )
* Downloaded from: http://wonderfl.net/c/4Lxf
*/
// forked from takimo's 不思議のダンジョン自動生成
package {
import flash.utils.IDataInput;
import flash.text.TextField;
import flash.text.TextFormat;
import flash.geom.Rectangle;
import flash.display.Sprite;
import flash.geom.Point;
import flash.geom.Rectangle;
//参考:http://d.hatena.ne.jp/Gemma/20070816
public class RogueMap extends Sprite {
private var _debug:TextField;
private var _margin:uint = 8;
private var _dungeonWidth:uint = 60;
private var _dungeonHeight:uint = 30;
private var _fontSize:uint = 12;
private var _rectArray:Array;
private var _dungeon:Array;
private var _format:TextFormat;
public function RogueMap() {
startDebug();
var rect:Rectangle = new Rectangle(0, 0, _dungeonWidth - 1, _dungeonHeight - 1);
_dungeon = new Array(_dungeonHeight);
for (var j:int=0; j<_dungeonHeight; j++)
{
_dungeon[j] =new Array(_dungeonWidth);
for(var i:int=0; i < _dungeonWidth; i++)
{
_dungeon[j][i] =' ';
}
}
var compartments:Array = flatten(split(rect), []);
debug(String(compartments.length));
var rooms:Array = compartments.map(createRoom);
for each (var room:Rectangle in rooms)
{
//debug(String(item.toString()));
drawRect(room);
}
createRoad(compartments, rooms);
for each (var row:Array in _dungeon)
{
for each (var column:String in row)
{
debug(column, false);
}
debug('\n', false);
}
}
private function half(n:int):int
{
return int(n >> 1);
}
private function fill(rect:Rectangle, parts:String ="#"):void
{
//debug("top :" + String(rect.top) + ", bottom:" + String(rect.bottom) + ", left:" + String(rect.left) + ",right: " + String(rect.right));
var min_j:int = Math.min(rect.top, rect.bottom);
var max_j:int = Math.max(rect.top, rect.bottom);
var min_i:int = Math.min(rect.left, rect.right);
var max_i:int = Math.max(rect.left, rect.right);
for (var j:int = min_j; j <= max_j; j++)
for (var i:int = min_i; i <= max_i; i++)
_dungeon[j][i] = parts;
}
private function drawRect(rect:Rectangle, parts:String ="|", parts1:String = "-"):void
{
var min_j:int = Math.min(rect.top, rect.bottom);
var max_j:int = Math.max(rect.top, rect.bottom);
var min_i:int = Math.min(rect.left, rect.right);
var max_i:int = Math.max(rect.left, rect.right);
for (var j:int = min_j; j <= max_j; j++)
{
_dungeon[j][min_i - 1] = parts;
_dungeon[j][max_i + 1] = parts;
}
for (var i:int = min_i; i <= max_i; i++)
{
_dungeon[min_j - 1][i] = parts1;
_dungeon[max_j + 1][i] = parts1;
}
}
private function randomRange(min:int, max:int):int
{
if(min > max) return 0;
else if(min == max) return min;
else return Math.floor(Math.random() * (max - min)) + min;
}
private function createRoad(compartments:Array, rooms:Array):void
{
var connectList:Array = new Array();
for (var i:int = 0; i < compartments.length - 1; i++)
connectList.push([i, i + 1]);
for (var k:int = 0; k < compartments.length; k++)
for (var j:int = k + 1; j < compartments.length; j++)
if (randomRange(0,5) == 0)
if (compartments[k].left == compartments[j].right ||
compartments[k].right == compartments[j].left ||
compartments[k].top == compartments[j].bottom ||
compartments[k].bottom == compartments[j].top)
connectList.push([k,j]);
for each (var connect:Array in connectList)
{
var from:int = connect[0];
var to:int = connect[1];
//debug(String(from) + ":" + String(to));
var parentCompartment:Rectangle = compartments[from];
var childrenCompartment:Rectangle = compartments[to];
var parentRoom:Rectangle = rooms[from];
var childrenRoom:Rectangle = rooms[to];
if (parentCompartment.bottom == childrenCompartment.top)
{
// N
var a:int = randomRange(parentRoom.left, parentRoom.right);
var b:int = randomRange(childrenRoom.left, childrenRoom.right);
//debug(String(a) + "," + String(b));
/**
fillRect(a, half(parentCompartment.top + parentCompartment.bottom), a, parentCompartment.bottom);
fillRect(b, half(childrenCompartment.top + childrenCompartment.bottom), b, childrenCompartment.top);
fillRect(a, parentCompartment.bottom, b, childrenCompartment.top);
*/
fillRect(a, parentRoom.bottom + 1, a, parentCompartment.bottom);
fillRect(b, childrenRoom.top - 1, b, childrenCompartment.top);
fillRect(a, parentCompartment.bottom, b, childrenCompartment.top);
}
else if (parentCompartment.right == childrenCompartment.left)
{
// Z
a = randomRange(parentRoom.top + 1, parentRoom.bottom - 1);
b = randomRange(childrenRoom.top + 1, childrenRoom.bottom - 1);
//debug(String(a) + "," + String(b));
fillRect(parentRoom.right + 1, a, parentCompartment.right, a);
fillRect(childrenRoom.left - 1, b, childrenCompartment.left, b);
fillRect(parentCompartment.right, a, childrenCompartment.left, b);
/**
fillRect(half(parentRoom.left + parentRoom.right), a, parentCompartment.right, a);
fillRect(half(childrenRoom.left + childrenRoom.right), b, childrenCompartment.left, b);
fillRect(parentCompartment.right, a, childrenCompartment.left, b);
*/
}
}
}
private function fillRect(x0:int, y0:int, x1:int, y1:int):void
{
var rect:Rectangle = new Rectangle();
rect.topLeft = new Point(Number(x0), Number(y0));
rect.bottomRight = new Point(Number(x1), Number(y1));
fill(rect);
}
private function createRoom(rect:Rectangle, index:int=0, array:Array=null):Rectangle
{
var room:Rectangle = new Rectangle();
room.left = rect.left + randomRange(2, half(rect.right - rect.left) - 1);
room.top = rect.top + randomRange(2, half(rect.bottom - rect.top) - 1);
room.right = rect.right - randomRange(2, half(rect.right - rect.left) - 1);
room.bottom = rect.bottom - randomRange(2, half(rect.bottom - rect.top) - 1);
return room;
}
private function split(rect:Rectangle, index:int=0, array:Array=null):Array
{
if ((rect.right - rect.left < _margin * 2) || (rect.bottom - rect.top < _margin * 2))
{
return [rect];
}
var rect1:Rectangle = new Rectangle();
var rect2:Rectangle = new Rectangle();
// 縦(0) or 横(1)
var direction:int = Math.floor(Math.random() * 2);
//debug("direction : " + String(direction));
// 分割
var point:Point = new Point();
// 縦分割
if(direction)
{
point.x = randomRange(rect.left + _margin, rect.right - _margin);
rect1.topLeft = rect.topLeft;
rect1.bottomRight = new Point(point.x, rect.bottom);
rect2.topLeft = new Point(point.x, rect.top);
rect2.bottomRight = rect.bottomRight;
}
else
{
point.y =randomRange(rect.top + _margin, rect.bottom - _margin);
rect1.topLeft = rect.topLeft;
rect1.bottomRight = new Point(rect.right, point.y);
rect2.topLeft = new Point(rect.x, point.y);
rect2.bottomRight = rect.bottomRight;
}
return [rect1, rect2].map(split);
}
private function flatten(array:*, tmp:Array):Array
{
//debug("flatten");
for each (var item:* in array)
{
if(item as Array) tmp = flatten(item, tmp);
if(item as Rectangle) tmp.push(item);
}
return tmp;
}
private function debug(message:String, isBreak:Boolean = true):void
{
if (isBreak) message += "\n";
_debug.appendText(message);
}
private function startDebug():void
{
/**
* setting debug
*/
var format:TextFormat = new TextFormat();
format.font = '_等幅';
format.size = _fontSize;
format.color = 0x000000;
_debug = new TextField();
_debug.height = 450;
_debug.width = 400;
_debug.border = true;
_debug.text = '\n';
_debug.setTextFormat(format);
this.addChild(_debug);
}
}
}
