In case Flash no longer exists; a copy of this site is included in the Flashpoint archive's "ultimate" collection.

Dead Code Preservation :: Archived AS3 works from wonderfl.net

不思議のダンジョン(ダンジョン自動生成&移動&戦闘)

参考:http://d.hatena.ne.jp/Gemma/20070816
Get Adobe Flash player
by takimo 07 Jan 2010
/**
 * Copyright takimo ( http://wonderfl.net/user/takimo )
 * MIT License ( http://www.opensource.org/licenses/mit-license.php )
 * Downloaded from: http://wonderfl.net/c/lcMA
 */

// 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 = "%";
	}	

}