Forked from: takimo's 不思議のダンジョン自動生成 diff:1039 不思議のダンジョン(ダンジョン自動生成&移動&戦闘) 参考:http://d.hatena.ne.jp/Gemma/20070816 takimo forked:1favorite:8lines:793license : MIT License modified : 2010-01-07 19:00:24 Embed Tweet // forked from takimo's 不思議のダンジョン自動生成 package { import flash.display.Bitmap; import flash.utils.IDataInput; import flash.events.Event; import flash.events.KeyboardEvent; import flash.text.TextField; import flash.text.TextFormat; import flash.geom.Rectangle; import flash.display.Sprite; import flash.geom.Point; import flash.geom.Rectangle; import flash.text.AntiAliasType; //参考:http://d.hatena.ne.jp/Gemma/20070816 [SWF(backgroundColor="#000000")] public class Rogue extends Sprite { private var _debug:TextField; private var _mapText:TextField; private var _status:TextField; private var _fontSize:uint = 12; private var _rectArray:Array; private var _dungeon:Array; private var _map:Array; private var _format:TextFormat; private var _commandManager:CommandManager; private var _user:User; private var _players:Array; private var _floor:Floor; private var _enemies:Array; public function Rogue() { super(); _debug = new TextField(); createTextField(_debug, 400, 40, 0, 0, 12, 0xffffff, 'h,j,k,lで移動。@がPlayer。アルファベットは敵'); _mapText = new TextField(); // game 用 //createTextField(_mapText, 300, 300, 100, 100, 20, 0xffffff); // debug 用 createTextField(_mapText, 400, 400, 0, 0, 10, 0xffffff); _status = new TextField(); createTextField(_status, 100, 400, 350, 0, 12, 0xffffff); _user = new User(); _user.symbol = "@"; _user.hitpoint = 10; _commandManager = new CommandManager(); _commandManager.addEventListener(CommandEvent.COMPLETE, commandManager_completeHandler); stage.addEventListener(KeyboardEvent.KEY_UP, stage_keyUpHandler); _floor = new Floor(this); _floor.addEventListener(DungeonEvent.NEXT_FLOOR, dungeon_nextfloorHandler); nextFloor(); renderMap(); _status.appendText("\n"); displayStatus(); } private function displayStatus():void { _status.text = ""; _status.appendText("Floor : " + String(_floor.count) + "\n"); _status.appendText("HP : " + String(_user.hitpoint) + "\n"); _status.appendText("LEVEL : " + String(_user.level) + "\n"); _status.appendText("EXP : " + String(_user.exp) + "\n"); } private function nextFloor():void { _floor.generate(); //render(floor.map.toString()); _enemies = new Array(); _floor.dungeon = _floor.map; _user.position = _floor.randomPosition(); generateEnemies(["A", "B", "C", "D"]); setEnemies(); _floor.dungeon[_user.position.y][_user.position.x] = _user; _map = generateMap(_floor.dungeon); } private function generateEnemies(enemySymbols:Array):void { var enemy:Enemy; for each(var enemySymbol:String in enemySymbols) { enemy = new Enemy(); enemy.position = _floor.randomPosition(); enemy.symbol = enemySymbol; enemy.hitpoint = 3; _enemies.push(enemy); } } private function setEnemies():void { for each(var enemy:Enemy in _enemies) { if(enemy.hitpoint > 0) _floor.dungeon[enemy.position.y][enemy.position.x] = enemy; else //debug(_floor.map[enemy.position.y][enemy.position.x]); _floor.dungeon[enemy.position.y][enemy.position.x] = _floor.map[enemy.position.y][enemy.position.x]; } } private function workEnemies():void { _enemies.map(moveEnemy); /** for each(var enemy:Enemy in _enemies) { } */ } private function moveEnemy(enemy:Enemy, index:int, array:Array):void { if(enemy.hitpoint > 0) { var position:Point = enemy.position.clone(); var way:uint = randomRange(0, 4); switch(way) { case 0: enemy.position = _floor.move(enemy, Command.MOVE_RIGHT); break; case 1: enemy.position = _floor.move(enemy, Command.MOVE_LEFT); break; case 2: enemy.position = _floor.move(enemy, Command.MOVE_UP); break; case 3: enemy.position = _floor.move(enemy, Command.MOVE_DOWN); break; default: break; } _floor.dungeon[enemy.position.y][enemy.position.x] = enemy; } else { //debug(_floor.map[enemy.position.y][enemy.position.x]); } } private function generateMap(map:Array, position:Point = null):Array { var dungeon:Array = new Array(); var tmp:Array; for each (var row:Array in map) { tmp = new Array(); for each (var column:* in row) { if (column is Wall) tmp.push(column.symbol); else if (column is Ground) tmp.push("."); else if (column is Road) tmp.push("#"); else if (column is Door) tmp.push(column.symbol); else if (column is Stairs) tmp.push(column.symbol); else if (column is User) tmp.push(column.symbol); else if (column is Enemy) tmp.push(column.symbol); else //debug(String(column)); tmp.push(" "); } dungeon.push(tmp); } return dungeon; } public function debug(message:String, isBreak:Boolean = true):void { if (isBreak) message += "\n"; //_debug.appendText(message); _debug.text = message; } private function render(message:String, isBreak:Boolean = true):void { if (isBreak) message += "\n"; _mapText.appendText(message); } private function renderMap():void { var rect:Rectangle = new Rectangle(0, 0, 60, 30); //var rect:Rectangle = new Rectangle(_user.position.x - 10 , _user.position.y - 5, 20, 10); render(""); _mapText.text = ""; for (var i:int = rect.top; i < rect.bottom; i++) { for (var j:int = rect.left; j < rect.right; j++) { if(i < 0 || j < 0 || i > _floor.height || j > _floor.width || !_map[i][j]) render(" ", false); else render(_map[i][j], false); } render('\n', false); } } private function createTextField(textField:TextField, width:int, height:int, x:int = 0, y:int = 0, fontsize:int=12, color:int = 0xffffff, text:String = " "):void { var format:TextFormat = new TextFormat(); format.font = '_等幅'; format.size = fontsize; format.color = color; textField.height = height; textField.width = width; textField.x = x; textField.y = y; //textField.border = true; textField.text = text; textField.setTextFormat(format); this.addChild(textField); } private function stage_keyUpHandler(event:KeyboardEvent):void { _commandManager.input(event.keyCode); //debug(String(event.keyCode)); } private function commandManager_completeHandler(event:CommandEvent):void { _user.position = _floor.move(_user, event.action); _floor.dungeon = new Array(); _floor.dungeon = _floor.map; setEnemies(); _floor.dungeon[_user.position.y][_user.position.x] = _user; _map = generateMap(_floor.dungeon); renderMap(); displayStatus(); workEnemies(); } private function dungeon_nextfloorHandler(event:DungeonEvent):void { nextFloor(); } 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; } } } import flash.events.EventDispatcher; class CommandManager extends EventDispatcher { private var _command:String; public function CommandManager():void { _command = ""; } public function input(command:int):void { _command += String(command); switch(_command) { case "27": _command = ""; break; case "72": dispatch(Command.MOVE_LEFT); break; case "74": dispatch(Command.MOVE_DOWN); break; case "75": dispatch(Command.MOVE_UP); break; case "76": dispatch(Command.MOVE_RIGHT); break; default: dispatch("error"); } } private function dispatch(action:String):void { var event:CommandEvent = new CommandEvent(CommandEvent.COMPLETE); event.action = action; dispatchEvent(event); _command = ""; } } import flash.geom.Point; import flash.geom.Rectangle; class Dungeon { public function get floor():Floor { return _floor; } private var _floor:Floor; public function set floor(floor:Floor):void { _floor = floor; } public function get enemies():Array { return _enemies; } private var _enemies:Array; public function set enemies(enemies:Array):void { _enemies = enemies; } public function Dungeon():void { } public function generateFloor():void { } public function generateEnemies():void { } public function renderFloor():String { return ""; } public function setPlayer():void { } public function setItems(items:Array):void { } public function move():void { } } import flash.geom.Rectangle; import flash.utils.ByteArray; import flash.events.EventDispatcher; class Floor extends EventDispatcher { private var _dungeonWidth:uint = 60; private var _dungeonHeight:uint = 30; private var _margin:uint = 8; private var _self:*; public function get count():uint { return _count; } private var _count:uint; public function set count(count:uint):void { _count = count; } public function get width():uint { return _dungeonWidth; } public function get height():uint { return _dungeonHeight; } public function get rooms():Array { return _rooms; } private var _rooms:Array; public function set rooms(rooms:Array):void { _rooms = rooms; } public function get map():Array { var tmp:Array = new Array(); for each(var colmun:Array in _map) tmp.push(colmun.concat()); return tmp; //return _map; } private var _map:Array; public function set map(map:Array):void { _map = map; } public function get dungeon():Array { /** var tmp:Array = new Array(); for each(var colmun:Array in _dungeon) tmp.push(colmun.concat()); return tmp; */ return _dungeon; } private var _dungeon:Array; public function set dungeon(dungeon:Array):void { _dungeon = dungeon; } public function Floor(self:*):void { _self = self; _count = 0; } public function generate():void { var rect:Rectangle = new Rectangle(0, 0, _dungeonWidth - 1, _dungeonHeight - 1); _map = new Array(_dungeonHeight); for (var j:int=0; j<_dungeonHeight; j++) { _map[j] =new Array(_dungeonWidth); for(var i:int=0; i < _dungeonWidth; i++) { _map[j][i] = null; } } var compartments:Array = flatten(split(rect), []); _rooms = compartments.map(createRoom); for each (var room:Rectangle in _rooms) { setRoom(room); } createRoad(compartments, _rooms); setStairs(_rooms); _count++; } public function move(character:*, way:String):Point { var point:Point = character.position.clone(); switch(way) { case Command.MOVE_RIGHT: point.x++; break; case Command.MOVE_LEFT: point.x--; break; case Command.MOVE_UP: point.y--; break; case Command.MOVE_DOWN: point.y++; break; default: break; } var dungeon:* = _dungeon[point.y][point.x]; //_self.debug(dungeon.toString()); if ((dungeon is Ground) || (dungeon is Road) || (dungeon is Door)) { return point; } else if(!(character is Enemy)) { if ((dungeon is Enemy)) { dungeon.protec(); } else if (dungeon is Stairs) { var event:DungeonEvent = new DungeonEvent(DungeonEvent.NEXT_FLOOR); dispatchEvent(event); } return character.position; } else { if ((dungeon is User)) { dungeon.protec(); } return character.position; } } public function attack(enemy:Enemy):void { enemy.hitpoint--; } private function half(n:int):int { return int(n >> 1); } private function setRoad(rect:Rectangle):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++) for (var i:int = min_i; i <= max_i; i++) _map[j][i] = new Road(); } private function setRoom(rect:Rectangle):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++) for (var i:int = min_i; i <= max_i; i++) _map[j][i] = new Ground(); for (j = min_j; j <= max_j; j++) { _map[j][min_i] = new Wall(Wall.LEFT); _map[j][max_i] = new Wall(Wall.RIGHT); } for (i = min_i; i <= max_i; i++) { _map[min_j][i] = new Wall(Wall.TOP); _map[max_j][i] = new Wall(Wall.BOTTOM); } } private function setDoor(rect:Rectangle):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++) for (var i:int = min_i; i <= max_i; i++) _map[j][i] = new Door(); } private function setStairs(rects:Array):void { var position:Point = randomPosition(); _map[position.y][position.x] = new Stairs(); } 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]; 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 + 1, parentRoom.right - 1); var b:int = randomRange(childrenRoom.left + 1, childrenRoom.right - 1); setDoor(point2Rect(a, parentRoom.bottom, a, parentRoom.bottom)); setRoad(point2Rect(a, parentRoom.bottom + 1, a, parentCompartment.bottom)); setRoad(point2Rect(b, childrenRoom.top - 1, b, childrenCompartment.top)); setDoor(point2Rect(b, childrenRoom.top, b, childrenRoom.top)); setRoad(point2Rect(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); setDoor(point2Rect(parentRoom.right, a, parentRoom.right, a)); setRoad(point2Rect(parentRoom.right + 1, a, parentCompartment.right, a)); setRoad(point2Rect(childrenRoom.left - 1, b, childrenCompartment.left, b)); setDoor(point2Rect(childrenRoom.left, b, childrenRoom.left, b)); setRoad(point2Rect(parentCompartment.right, a, childrenCompartment.left, b)); } } } private function point2Rect(x0:int, y0:int, x1:int, y1:int):Rectangle { var rect:Rectangle = new Rectangle(); rect.topLeft = new Point(Number(x0), Number(y0)); rect.bottomRight = new Point(Number(x1), Number(y1)); return 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; } public function randomPosition():Point { var target:int = randomRange(0, _rooms.length); var rect:Rectangle = _rooms[target]; var point:Point = new Point(); point.x = randomRange(rect.left + 1, rect.right - 1); point.y = randomRange(rect.top + 1, rect.bottom - 1); return point; } public function clone(source:Object):* { var tmp:ByteArray = new ByteArray(); tmp.writeObject(source); tmp.position = 0; return(tmp.readObject()); } } import flash.events.Event; class CommandEvent extends Event { public static const COMPLETE:String = "complete"; /** * action */ public function get action():String { return _action; } private var _action:String; public function set action(action:String):void { _action = action; } public function CommandEvent(type:String, bubbles:Boolean=false, cancelable:Boolean=false):void { super(type, bubbles, cancelable); } public override function clone():Event { return new CommandEvent(type, bubbles, cancelable); } } class Command { public static const MOVE_LEFT:String = "move_left"; public static const MOVE_RIGHT:String = "move_right"; public static const MOVE_UP:String = "move_up"; public static const MOVE_DOWN:String = "move_down"; public function Command():void { } } import flash.events.Event; class DungeonEvent extends Event { public static const NEXT_FLOOR:String = "next_floor"; public function DungeonEvent(type:String, bubbles:Boolean=false, cancelable:Boolean=false):void { super(type, bubbles, cancelable); } } class DungeonObject { public function get symbol():String { return _symbol; } protected var _symbol:String; public function set symbol(symbol:String):void { _symbol = symbol; } public function DungeoObject():void { } } class Wall extends DungeonObject { public static const TOP:String = "top"; public static const BOTTOM:String = "bottom"; public static const LEFT:String = "left"; public static const RIGHT:String = "right"; public function get type():String { return _type; } private var _type:String; public function set type(type:String):void { _type = type; } override public function get symbol():String { if(_type == TOP || _type == BOTTOM) return "-"; else if(_type == LEFT || _type == RIGHT) return "|"; else return " "; } public function Wall(type:String):void { _type = type; } } class Road extends DungeonObject { public function Road():void { } } class Door extends DungeonObject { public function Door():void { _symbol = "+"; } } class Ground extends DungeonObject { public function Ground():void { } } import flash.geom.Point; class Character extends DungeonObject { public function get position():Point { return _position; } protected var _position:Point; public function set position(position:Point):void { _position = position; } public function get hitpoint():int { return _hitpoint; } protected var _hitpoint:int public function set hitpoint(hitpoint:int):void { _hitpoint = hitpoint; } public function get items():Array { return _items; } protected var _items:Array public function set items(items:Array):void { _items = items; } public function get level():int { return _level; } protected var _level:int public function get exp():int { return _exp; } protected var _exp:int; public function addExp(exp:int):void { _exp += exp; } public function Character():void { } public function protec():void { _hitpoint--; } } import flash.geom.Point; class User extends Character { public function User():void { _level = 1; _exp = 0; _items = [":", ")", "[", "!", "?", "="] } } import flash.geom.Point; class Enemy extends Character { public function Enemy():void { _level = 0; _exp = 0; _items = []; } } class Stairs extends DungeonObject { public function Stairs():void { _symbol = "%"; } } Code Fullscreen Preview Fullscreen takuyas chidax_pleas.. Hio818214 hacker_ba4jh.. hacker_vun6d.. digitrick bearholic toby : gamerogueroguelikerogueっぽい! game rogue roguelike type cancelable bubbles message String Array Math.min Math.max Math.exp Point split dispatchEvent position height source Boolean target Math.floor writeObject readObject sort new page view favorite forked pv0 forked from: 不思議のダンジョン(ダンジョン自動.. bricklayer.digital forked:0 favorite:0lines:793 (diff:1)