RogueLikeSimulator
ローグライクのダンジョンを自動生成して、エネミーを動かしてみる。
無理やりコードを一つにまとめたらとんでもなくひどいものになったけど
せっかくなので公開しました。
Enter:ダンジョン再構築
スマホ向けローグライクを作り始めました https://twitter.com/rogue_inu
/**
* Copyright inu ( http://wonderfl.net/user/inu )
* MIT License ( http://www.opensource.org/licenses/mit-license.php )
* Downloaded from: http://wonderfl.net/c/tEAA
*/
package
{
import flash.display.Sprite;
import flash.events.Event;
import flash.events.KeyboardEvent;
import flash.ui.Keyboard;
[SWF(width="465",height="465",frameRate="60")]
/**
* ...
* @author inu
ローグライクのダンジョンを自動生成して、エネミーを動かしてみる。
無理やりコードを一つにまとめたらとんでもなくひどいものになったけど
せっかくなので公開しました。
Enter:ダンジョン再構築
スマホ向けローグライクを作り始めました https://twitter.com/rogue_inu
*/
public class Main extends Sprite
{
private var floor:Floor;
private var ef:EnemyFactory;
private var minimap:MiniMap;
private var debug:Debug;
public function Main():void
{
if (stage) init();
else addEventListener(Event.ADDED_TO_STAGE, init);
}
private function init(e:Event = null):void
{
removeEventListener(Event.ADDED_TO_STAGE, init);
// entry point
newFloor();
addEventListener(Event.ENTER_FRAME, ent);
stage.addEventListener(KeyboardEvent.KEY_DOWN, keyDownEvent);
}
private function keyDownEvent(e:KeyboardEvent):void
{
if (e.keyCode == Keyboard.ENTER) {
newFloor();
}
}
private function newFloor():void {
removeChildren();
floor = null;
ef = null;
minimap = null;
debug = null;
if (int(Math.random() * 2)) floor = new FloorNormal();
else floor = new FloorUnion();
ef = new EnemyFactory(floor);
for(var i:int = 0; i < 1; i++){
ef.create();
}
minimap = new MiniMap(floor, ef);
minimap.newMiniMap();
debug = new Debug(floor, ef);
addChild(minimap);
addChild(debug);
}
private function ent(e:Event):void {
ef.update();
minimap.draw();
debug.update();
if (ef.ready()) ef.turnUpdate();
}
}
}
import flash.display.Bitmap;
import flash.display.BitmapData;
import flash.display.Sprite;
import flash.geom.Point;
import flash.geom.Rectangle;
import flash.text.TextField;
import flash.utils.getTimer;
class Floor //フロア
{
protected var vec2Grid:Vector.<Vector.<Grid>>;
protected var vecRoom:Vector.<Room>;
public var turn:int = 0;
public function Floor():void {
turn = 0;
create();
}
public function getGrid(gridX:int, gridY:int ):Grid {
if (gridX < 0 || gridY < 0 || gridX >= 59 || gridY >= 35) return Grid.dummy;
return vec2Grid[gridY][gridX];
}
public function getGridByPoint(point:Point):Grid {
if (point.x < 0 || point.y < 0 || point.x >= 59 || point.y >= 35) return Grid.dummy;
return vec2Grid[point.y][point.x];
}
public function getRoom(roomN:int):Room {
var i:int;
for(i = 0; i < vecRoom.length; i++){
if (vecRoom[i].roomN == roomN) return vecRoom[i];
}
return null;
}
public function getRandomRoom():Room {
var i:int;
return vecRoom[Rand.getInt(vecRoom.length)];
}
public function getRandomRoomGrid():Grid {
var room:Room = getRandomRoom();
var point:Point = room.getRandomPoint();
return vec2Grid[room.gridY + point.y][room.gridX + point.x];
}
public function setChar(char:Character):void {
vec2Grid[char.gridY][char.gridX].char = char;
}
public function removeChar(char:Character):void {
vec2Grid[char.gridY][char.gridX].char = null;
}
public function setExitPointToRoom():void {
var i:int, j:int, k:int;
var room:Room;
var grid:Grid;
var rx:int, ry:int;
var len:int = vecRoom.length;
for(k = 0; k < len; k++){
room = vecRoom[k];
rx = room.gridX;
ry = room.gridY;
room.vecExitPoint = null;
room.vecExitPoint = new Vector.<Point>();
for (i = -1; i < room.gridH + 1; i++) for (j = - 1; j < room.gridW + 1; j++) {
grid = vec2Grid[ry + i][rx + j];
if (grid.type == 1) {
grid.roomExitN = room.roomN;
room.vecExitPoint.push(new Point(rx + j, ry + i));
}
}
if (room.vecExitPoint.length == 0) trace("t");//どこにもつながってない部屋
}
}
//移動チェック -1:壁 -2:キャラ
public function moveCheck(char:Character, d:int):int {
var point:Point = Move.point(d);
var grid2:Grid = getGrid(char.gridX + point.x, char.gridY + point.y);
if (d % 2 == 1) {
var grid3:Grid;
var grid4:Grid;
point = Move.point(d + 1);
grid3 = getGrid(char.gridX + point.x, char.gridY + point.y);
point = Move.point(d - 1);
grid4 = getGrid(char.gridX + point.x, char.gridY + point.y);
if (grid2.type == 0 || grid3.type == 0 || grid4.type == 0) {
return -1;
}
if (grid2.char != null) {
return -2;
}
}else {
if (grid2.type == 0) return -1;
if (grid2.char != null) return -2;
}
return 0;
}
//フロア作成中しか使わない**********************************************************************************
protected var divW:int, divH:int;
protected var rectW:int, rectH:int;
protected var vec2Rect:Vector.<Vector.<Rect>>;
protected var vec2RoadH:Vector.<Vector.<Road>>;
protected var vec2RoadV:Vector.<Vector.<Road>>;
protected function create():void {
trace("virtual");
}
//フロア作成中しか使わない
protected function initGrid():void {
var i:int, j:int;
//初期化
vec2Grid = new Vector.<Vector.<Grid>>();
for (i = 0; i < 35; i++) {
vec2Grid.push(new Vector.<Grid>());
for (j = 0; j < 59; j++) {
vec2Grid[i][j] = new Grid(j, i);
}
}
}
//フロア作成中しか使わない
protected function initRect():void {
//区画設定
var i:int, j:int;
//マップを区画分け
divW = Rand.minmax(3, 6);
divH = Rand.minmax(3, 4);
rectW = (59 - divW + 1) / divW;
rectH = (35 - divH + 1) / divH;
//初期化
vec2Rect = new Vector.<Vector.<Rect>>();
for (i = 0; i < divH; i++) {
vec2Rect.push(new Vector.<Rect>());
for (j = 0; j < divW; j++) {
vec2Rect[i][j] = new Rect(j * (rectW + 1), i * (rectH + 1), rectW, rectH);
vec2Rect[i][j].room = new Room(0, 0, 0, 0);
vec2Rect[i][j].room.roomN = i * divW + j;
}
}
}
//connectRect();
//フロア作成中しか使わない
protected function initRoad():void {
//通路設定
var i:int, j:int;
vec2RoadH = new Vector.<Vector.<Road>>();
vec2RoadV = new Vector.<Vector.<Road>>();
for (i = 0; i < divH; i++) {
vec2RoadH.push(new Vector.<Road>());
for (j = 0; j < divW - 1; j++) {
if (vec2Rect[i][j] == vec2Rect[i][j + 1]) { vec2RoadH[i][j] = null; continue;}
vec2RoadH[i][j] = new Road(j * (rectW + 1) + rectW, i * (rectH + 1), 1, rectH );
vec2RoadH[i][j].room1 = vec2Rect[i][j].room;//左の部屋
vec2RoadH[i][j].room2 = vec2Rect[i][j + 1].room;//右の部屋
}
}
for (i = 0; i < divH - 1; i++) {
vec2RoadV.push(new Vector.<Road>());
for (j = 0; j < divW; j++) {
if (vec2Rect[i][j] == vec2Rect[i + 1][j]) {vec2RoadV[i][j] = null; continue;}
vec2RoadV[i][j] = new Road(j * (rectW + 1), i * (rectH + 1) + rectH, rectW, 1);
vec2RoadV[i][j].room1 = vec2Rect[i][j].room;//上の部屋
vec2RoadV[i][j].room2 = vec2Rect[i + 1][j].room;//下の部屋
}
}
}
//フロア作成中しか使わない
protected function createMaze():void {
//棒倒し的に
var i:int, j:int;
for (i = 0; i < divH - 1; i++) for (j = 0; j < divW - 1; j++) {
//上下左右に棒倒し 通路を消して上下、左右の区画を拡張
switch(Rand.getInt(6)*2) {
case 0:
if (vec2RoadH[i][j] == null) continue;
vec2RoadH[i][j] = null;
if (!vec2Rect[i][j].room.isConnectedV) vec2Rect[i][j].gridW++;
if (!vec2Rect[i][j + 1].room.isConnectedV) {
vec2Rect[i][j + 1].gridW++;
vec2Rect[i][j + 1].gridX--;
}
break;
case 2:
if (vec2RoadV[i][j + 1] == null) continue;
vec2RoadV[i][j + 1] = null;
if (!vec2Rect[i][j + 1].room.isConnectedH) vec2Rect[i][j + 1].gridH++;
if (!vec2Rect[i + 1][j + 1].room.isConnectedH) {
vec2Rect[i + 1][j + 1].gridH++;
vec2Rect[i + 1][j + 1].gridY--;
}
break;
case 4:
if (vec2RoadH[i + 1][j] == null) continue;
vec2RoadH[i + 1][j] = null;
if (!vec2Rect[i + 1][j].room.isConnectedV) vec2Rect[i + 1][j].gridW++;
if (!vec2Rect[i + 1][j + 1].room.isConnectedV) {
vec2Rect[i + 1][j + 1].gridW++;
vec2Rect[i + 1][j + 1].gridX--;
}
break;
case 6:
if (vec2RoadV[i][j] == null) continue;
vec2RoadV[i][j] = null;
if (!vec2Rect[i][j].room.isConnectedH) vec2Rect[i][j].gridH++;
if (!vec2Rect[i + 1][j].room.isConnectedH) {
vec2Rect[i + 1][j].gridH++;
vec2Rect[i + 1][j].gridY--;
}
break;
}
}
var loopCnt:int;//無限ループ防ぎ
var loopLength:int = Rand.minmax(divH*divW/5,divH*divW/4)
for (i = 0; i < loopLength; i++) {//通路部屋の作成
loopCnt++; if (loopCnt > 100) break;
var rx:int = Rand.getInt(divW);
var ry:int = Rand.getInt(divH);
if (vec2Rect[ry][rx].room.roomN == -1 || vec2Rect[ry][rx].room.isConnected()) {
i--; continue; //被ったらコンティニュー
}else {//部屋の大きさを1グリッドにする
vec2Rect[ry][rx].room.roomN = -1;
vec2Rect[ry][rx].room.gridW = 1;
vec2Rect[ry][rx].room.gridH = 1;
}
}
}
//フロア作成中しか使わない
protected function createRoom():void {
//区画に部屋を作成
var i:int, j:int;
var roomX:int, roomY:int, roomH:int, roomW:int;
vecRoom = new Vector.<Room>();
for (i = 0; i < divH; i++) for (j = 0; j < divW; j++) {
var rect:Rect = vec2Rect[i][j];
var room:Room = rect.room;
if (room.gridX != 0) continue;
if (room.roomN != -1) {//通常の部屋だったら
if (room.isConnectedH) roomW = Rand.minmax(rectW + rect.gridW % rectW + 1, rect.gridW - 2);
else roomW = Rand.minmax(rect.gridW / 2, rect.gridW - 2);
if (room.isConnectedV) roomH = Rand.minmax(rectH + rect.gridH % rectH + 1, rect.gridH - 2);
else roomH = Rand.minmax(rect.gridH / 2, rect.gridH - 2);
room.gridW = roomW;
room.gridH = roomH;
}
roomX = rect.gridX + Rand.minmax(1, rect.gridW - room.gridW - 1);
roomY = rect.gridY + Rand.minmax(1, rect.gridH - room.gridH - 1);
//min 1,1
room.gridX = roomX;
room.gridY = roomY;
vecRoom.push(room);
}
}
//フロア作成中しか使わない
protected function createRoad():void {
var i:int, j:int;
var road:Road;
for (i = 0; i < divH; i++) for (j = 0; j < divW - 1; j++) {
road = vec2RoadH[i][j];
if (road == null) continue;
var room1nodeY:int = Rand.minmax(Math.max(i * (rectH + 1), road.room1.gridY + 1) , Math.min( (i + 1) * (rectH + 1) - 2, road.room1.getBottomGridY() - 1));
var room2nodeY:int = Rand.minmax(Math.max(i * (rectH + 1), road.room2.gridY + 1) , Math.min( (i + 1) * (rectH + 1) - 2, road.room2.getBottomGridY() - 1));
if (road.room1.roomN == -1) room1nodeY = road.room1.gridY;
if (road.room2.roomN == -1) room2nodeY = road.room2.gridY;
road.gridH = Math.abs(room1nodeY - room2nodeY) + 1;
road.gridY = Math.min(room1nodeY, room2nodeY);
road.gridX = Rand.minmax(road.room1.getRightGridX() + 2, road.room2.gridX - 2);
if (road.gridY == room1nodeY) road.nodeType = 0;
else road.nodeType = 1;
}
for (i = 0; i < divH - 1; i++) for (j = 0; j < divW; j++) {
road = vec2RoadV[i][j];
if (road == null) continue;
var room1nodeX:int = Rand.minmax(Math.max(j * (rectW + 1), road.room1.gridX + 1) , Math.min( (j + 1) * (rectW + 1) - 2, road.room1.getRightGridX() - 1));
var room2nodeX:int = Rand.minmax(Math.max(j * (rectW + 1), road.room2.gridX + 1) , Math.min( (j + 1) * (rectW + 1) - 2, road.room2.getRightGridX() - 1));
if (road.room1.roomN == -1) room1nodeX = road.room1.gridX;
if (road.room2.roomN == -1) room2nodeX = road.room2.gridX;
road.gridW = Math.abs(room1nodeX - room2nodeX) + 1;
road.gridX = Math.min(room1nodeX, room2nodeX);
road.gridY = Rand.minmax(road.room1.getBottomGridY() + 2, road.room2.gridY - 2);
if (road.gridX == room1nodeX) road.nodeType = 0;
else road.nodeType = 1;
}
}
//フロア作成中しか使わない
protected function insertToGrid():void {
var i:int, j:int, k:int, l:int;
var room:Room;
var road:Road;
for (k = 0; k < vecRoom.length; k++) {//部屋を反映
room = vecRoom[k];
if (room.roomN == -1) {
//通路部屋だったら通路と判定し、vecRoomから除外
vec2Grid[room.gridY][room.gridX].type = 1;
vecRoom.splice(k--, 1);
continue;
}
for(i = 0; i < room.gridH; i++)for(j = 0; j < room.gridW; j++){
vec2Grid[room.gridY + i][room.gridX + j].type = 2;
vec2Grid[room.gridY + i][room.gridX + j].roomN = room.roomN;
}
}
for(k = 0; k < divH; k++)for(l = 0; l < divW - 1; l++){//通路を反映
road = vec2RoadH[k][l];
if (road == null) continue;
for(i = 0; i < road.gridH; i++)for(j = 0; j < road.gridW; j++){
vec2Grid[road.gridY + i][road.gridX + j].type = 1;
}
for (i = 1; 1;i++ ) {
if (road.nodeType == 0) {
if (vec2Grid[road.gridY][road.gridX - i].type == 0) {
vec2Grid[road.gridY][road.gridX - i].type = 1;
}else break;
}else {
if (vec2Grid[road.gridY][road.gridX + i].type == 0) {
vec2Grid[road.gridY][road.gridX + i].type = 1;
}else break;
}
}
for (i = 1; 1;i++ ) {
if (road.nodeType == 0) {
if (vec2Grid[road.getBottomGridY()][road.gridX + i].type == 0) {
vec2Grid[road.getBottomGridY()][road.gridX + i].type = 1;
}else break;
}else {
if (vec2Grid[road.getBottomGridY()][road.gridX - i].type == 0) {
vec2Grid[road.getBottomGridY()][road.gridX - i].type = 1;
}else break;
}
}
}
for(k = 0; k < divH - 1; k++)for(l = 0; l < divW; l++){//通路を反映
road = vec2RoadV[k][l];
if (road == null) continue;
for(i = 0; i < road.gridH; i++)for(j = 0; j < road.gridW; j++){
vec2Grid[road.gridY + i][road.gridX + j].type = 1;
}
for (i = 1; 1;i++ ) {
if (road.nodeType == 0) {
if (vec2Grid[road.gridY - i][road.gridX].type == 0) {
vec2Grid[road.gridY - i][road.gridX].type = 1;
}else break;
}else {
if (vec2Grid[road.gridY + i][road.gridX].type == 0) {
vec2Grid[road.gridY + i][road.gridX].type = 1;
}else break;
}
}
for (i = 1; 1;i++ ) {
if (road.nodeType == 0) {
if (vec2Grid[road.gridY + i][road.getRightGridX()].type == 0) {
vec2Grid[road.gridY + i][road.getRightGridX()].type = 1;
}else break;
}else {
if (vec2Grid[road.gridY - i][road.getRightGridX()].type == 0) {
vec2Grid[road.gridY - i][road.getRightGridX()].type = 1;
}else break;
}
}
}
}
}
class FloorNormal extends Floor
{
override protected function create():void {
initGrid();//グリッド初期化
initRect();//区画の初期化
initRoad();//通路の初期化
createMaze();//区画を迷路化
createRoom();//部屋を作成
createRoad();//通路を作成
insertToGrid();//作った部屋などをvec2Gridに反映
setExitPointToRoom();//部屋に出口を設定
}
}
class FloorUnion extends Floor
{
override protected function create():void {
initGrid();//グリッド初期化
initRect();//区画の初期化
connectRect();//区画を繋げる********
initRoad();//通路の初期化
createMaze();//区画を迷路化
createRoom();//部屋を作成
createRoad();//通路を作成
insertToGrid();//作った部屋などをvec2Gridに反映
setExitPointToRoom();//部屋に出口を設定
}
private function connectRect():void{
var i:int, j:int;
for(i = 0; i < divH - 1; i++)for(j = 0; j < divW - 1; j++){//区画を繋げる
switch(Rand.getInt(5)) {
case 0://左上と右上の区画をつなげる
if (vec2Rect[i][j].room.isConnected()|| vec2Rect[i][j + 1].room.isConnected()) continue;
//if (vec2Rect[i][j] == vec2Rect[i][j + 1]) continue;
vec2Rect[i][j + 1] = null;
vec2Rect[i][j + 1] = vec2Rect[i][j];
vec2Rect[i][j].gridW += rectW + 1;
vec2Rect[i][j].room.isConnectedH = true;
break;
case 1://右上と右下
if (vec2Rect[i][j + 1].room.isConnected() || vec2Rect[i + 1][j + 1].room.isConnected()) continue;
//if (vec2Rect[i + 1][j + 1] == vec2Rect[i][j + 1]) continue;
vec2Rect[i + 1][j + 1] = null;
vec2Rect[i + 1][j + 1] = vec2Rect[i][j + 1];
vec2Rect[i][j + 1].gridH += rectH + 1;
vec2Rect[i][j + 1].room.isConnectedV = true;
break;
case 2://右下と左下
if (vec2Rect[i + 1][j].room.isConnected() || vec2Rect[i + 1][j + 1].room.isConnected()) continue;
//if (vec2Rect[i + 1][j + 1] == vec2Rect[i + 1][j]) continue;
vec2Rect[i + 1][j + 1] = null;
vec2Rect[i + 1][j + 1] = vec2Rect[i + 1][j];
vec2Rect[i + 1][j].gridW += rectW + 1;
vec2Rect[i + 1][j].room.isConnectedH = true;
break;
case 3://左下と左上
if (vec2Rect[i][j].room.isConnected() || vec2Rect[i + 1][j].room.isConnected()) continue;
if (vec2Rect[i + 1][j] == vec2Rect[i][j]) continue;
vec2Rect[i + 1][j] = null;
vec2Rect[i + 1][j] = vec2Rect[i][j];
vec2Rect[i][j].gridH += rectH + 1;
vec2Rect[i][j].room.isConnectedV = true;
break;
case 4://4つくっつける
if (vec2Rect[i][j].room.isConnected() || vec2Rect[i][j + 1].room.isConnected() || vec2Rect[i + 1][j].room.isConnected()) continue;
if (vec2Rect[i][j] == vec2Rect[i][j + 1] || vec2Rect[i][j] == vec2Rect[i + 1][j] || vec2Rect[i][j] == vec2Rect[i + 1][j + 1]) continue;
vec2Rect[i + 1][j] = null;
vec2Rect[i + 1][j] = vec2Rect[i][j];
vec2Rect[i][j + 1] = null;
vec2Rect[i][j + 1] = vec2Rect[i][j];
vec2Rect[i + 1][j + 1] = null;
vec2Rect[i + 1][j + 1] = vec2Rect[i][j];
vec2Rect[i][j].gridW += rectW + 1;
vec2Rect[i][j].gridH += rectH + 1;
vec2Rect[i][j].room.isConnectedH = true;
vec2Rect[i][j].room.isConnectedV = true;
break;
}
}
}
}
class Grid
{
public static const dummy:Grid = new (Grid)(0, 0);
public var gridX:int;
public var gridY:int;
public var type:int;
public var roomN:int = -1;
public var roomExitN:int = -1;
public var char:Character;
public function Grid(gridX:int, gridY:int)
{
this.gridX = gridX;
this.gridY = gridY;
}
public function getGridPoint():Point{
return new Point(gridX, gridY);
}
}
class Rect //区画
{
public var gridX:int;
public var gridY:int;
public var gridW:int;
public var gridH:int;
public var room:Room;
public function Rect(gridX:int, gridY:int, gridW:int, gridH:int)
{
this.gridX = gridX;
this.gridY = gridY;
this.gridW = gridW;
this.gridH = gridH;
}
}
class Road //通路
{
public var gridX:int;
public var gridY:int;
public var gridW:int;
public var gridH:int;
public var room1:Room;
public var room2:Room;
public var nodeType:int;
public function Road(gridX:int, gridY:int, gridW:int, gridH:int)
{
this.gridX = gridX;
this.gridY = gridY;
this.gridW = gridW;
this.gridH = gridH;
}
public function getBottomGridY():int {
return gridY + gridH - 1;
}
public function getRightGridX():int {
return gridX + gridW - 1;
}
}
class Room //部屋
{
public var gridX:int;
public var gridY:int;
public var gridW:int;
public var gridH:int;
public var isConnectedH:Boolean;
public var isConnectedV:Boolean;
public var vecExitPoint:Vector.<Point>;
public var roomN:int = 0;
public function Room(gridX:int, gridY:int, gridW:int, gridH:int)
{
this.gridX = gridX;
this.gridY = gridY;
this.gridW = gridW;
this.gridH = gridH;
}
public function isConnected():Boolean {
if (isConnectedH || isConnectedV) return true;
return false;
}
public function getBottomGridY():int {
return gridY + gridH - 1;
}
public function getRightGridX():int {
return gridX + gridW - 1;
}
public function getRandomPoint():Point {
return new Point(Rand.getInt(gridW), Rand.getInt(gridH));
}
public function getRandomExitPoint(moveEnemy:Enemy):Point {//ランダムな出口を返す。距離1は除外
if (vecExitPoint.length == 1) return vecExitPoint[0];
var exitPoint:Point;
while(true){
exitPoint = vecExitPoint[Rand.getInt(vecExitPoint.length)];
if (Point.distance(exitPoint, moveEnemy.getGridPoint()) != 1) return exitPoint;
}
return null;
}
}
class Character extends Sprite
{
public var gridX:int;
public var gridY:int;
public var pastGridX:int;
public var pastGridY:int;
//ステータス
public var speed:int;
public var direction:int;
//アクション
protected var action:Action;
public var moveSpeed:int = 6;//移動スピード
public var vecAction:Vector.<Action>;
public var floor:Floor;
public function Character(floor:Floor)
{
this.floor = floor;
vecAction = new Vector.<Action>();
}
public function update():void {
//アクション
if (vecAction.length != 0) {
action = vecAction[0];
if (action.startFunc != null) { action.startFunc(); action.startFunc = null; }
action.frame--;
x += action.moveX;
y += action.moveY;
if (action.frame == 0) {
if (action.callback != null) action.callback();
vecAction.shift();
}
}
}
public function draw():void {
trace("virtual");
}
public function getPoint():Point{
return new Point(x, y);
}
public function getGridPoint():Point{
return new Point(gridX, gridY);
}
public function getPastGridPoint():Point {
return new Point(pastGridX, pastGridY);
}
//現在の部屋番号を取得
public function getRoomN():int {
return floor.getGrid(gridX, gridY).roomN;
}
//現在の部屋を取得
public function getRoom():Room {
return floor.getRoom(floor.getGrid(gridX, gridY).roomN);
}
//現在のグリッドを取得
public function getGrid():Grid {
return floor.getGrid(gridX, gridY);
}
public function getPastGrid():Grid {
return floor.getGrid(pastGridX, pastGridY);
}
public function init():void {
gridX = 0;
gridY = 0;
pastGridX = 0;
pastGridY = 0;
warp();
}
public function move(d:int):Boolean {
trace("virtual");
return false;
}
//グリッドの移動
public function moveGrid(gridX:int, gridY:int):void {
floor.removeChar(this);//消す
pastGridX = this.gridX;
pastGridY = this.gridY;
this.gridX = gridX;
this.gridY = gridY;
floor.setChar(this);//反映
}
//向き変更
public function changeDirection(d:int):Boolean {
if (d < 0 ) d += 8;
if (d > 7) d -= 8;
direction = d;
return true;
}
//準備チェック
public function ready():Boolean {
if (vecAction.length == 0) return true;
return false;
}
public function warp():void {
var grid:Grid;
for (var i:int = 0; i < 100; i++ ) {
grid = floor.getRandomRoomGrid();
if (grid.char == null) break;
}
if (i == 100) grid = floor.getGrid(gridX, gridY);
moveGrid(grid.gridX, grid.gridY);
x = grid.gridX * 48;
y = grid.gridY * 48;
}
public function addAction(action:Action):void {
vecAction.push(action);
}
}
class Enemy extends Character
{
public var actionPoint:int;
public var targetPointTurn:int;
public var targetPoint:Point;
public var vecCandidate:Vector.<int>;
public var moveEnd:Boolean = true;
public function Enemy(floor:Floor)
{
super(floor);
speed = 2//(int(Math.random() * 3) + 1) * 2;
vecCandidate = new Vector.<int>();
}
public function turnUpdate():void {
actionPoint += speed;
while(actionPoint >= 2){
actionPoint -= 2;
moveEnd = false;
updateTargetPoint();
if (moveEnd) continue;
setCandidate();
tryCandidte();
}
}
//ターゲットポイントを更新
public function updateTargetPoint():void {
var i:int;
var roomN:int = getRoomN();
var roomExitN:int = getGrid().roomExitN;
var room:Room;
var vecNear:Vector.<Point>;
var nowGridPoint:Point = getGridPoint();
targetPointTurn--;
if (targetPoint != null) {
if (targetPointTurn <= 0 || targetPoint.equals(nowGridPoint)) {
targetPoint = null;
}
else if(getRoomN() != -1)return;
}
if (roomN == -1) {//通路にいたら
vecNear = new Vector.<Point>();
var point:Point;
if (floor.getGridByPoint(point = nowGridPoint.add(Move.point(direction))).type != 0) {
vecNear.push(point);
}
if (floor.getGridByPoint(point = nowGridPoint.add(Move.point(direction + 2))).type != 0) {
vecNear.push(point);
}
if (floor.getGridByPoint(point = nowGridPoint.add(Move.point(direction - 2))).type != 0) {
vecNear.push(point);
}
if (vecNear.length != 0) targetPoint = vecNear[Rand.getInt(vecNear.length)];
if(targetPoint == null || floor.getGridByPoint(targetPoint).char != null){
changeDirection(direction + 4);
targetPoint = null;
moveEnd = true;
}
}else {//部屋にいたら
room = getRoom();
targetPoint = room.getRandomExitPoint(this);
targetPointTurn = Point.distance(targetPoint, nowGridPoint) + 10;
}
}
//移動候補を設定
public function setCandidate():void {
var d:int = Move.direction(targetPoint.subtract(getGridPoint()));
if (Rand.getInt(2)) vecCandidate.push(Move.fixDirection(d + 1), Move.fixDirection(d - 1));
else vecCandidate.push(Move.fixDirection(d - 1), Move.fixDirection(d + 1));
if (Rand.getInt(2)) vecCandidate.push(Move.fixDirection(d + 2), Move.fixDirection(d - 2));
else vecCandidate.push(Move.fixDirection(d - 2), Move.fixDirection(d + 2));
//ターゲットポイントに近い順にソート
if (d % 2 == 1) vecCandidate.sort(distanceSort);
vecCandidate.unshift(d);
//ソート関数
function distanceSort(a:int, b:int):Number{
return Point.distance(getGridPoint().add(Move.point(a)), targetPoint) - Point.distance(getGridPoint().add(Move.point(b)), targetPoint);
}
}
public function tryCandidte():void {
if (vecCandidate.length == 0) return;
if (!move(vecCandidate[0])) tryCandidte();
}
override public function move(d:int):Boolean {
var point:Point = Move.point(d);
switch(floor.moveCheck(this, d)) {
case -1:
vecCandidate.shift();
return false;
break;
case -2://アタック
vecCandidate.shift();
return false;
break;
}
//移動
vecCandidate.splice(0, vecCandidate.length);
addAction(new Action(2, point.x * 48, point.y * 48, 8 / speed, function():void { changeDirection(d) } ));
moveGrid(gridX + point.x, gridY + point.y);//グリッドの移動
return true;
}
}
class Action
{
public var phase:int;
public var moveX:int;
public var moveY:int;
public var frame:int;
public var startFunc:Function;
public var callback:Function;
public function Action(phase:int, moveX:int, moveY:int, frame:int, startFunc:Function = null, callback:Function = null)
{
this.phase = phase;
this.moveX = moveX / frame;
this.moveY = moveY / frame;
this.frame = frame;
this.startFunc = startFunc;
this.callback = callback;
}
}
class Move
{
static private var vecPoint:Vector.<Point> = Vector.<Point>([new Point(0, -1), new Point(1, -1), new Point(1, 0), new Point(1, 1), new Point(0, 1), new Point( -1, 1), new Point( -1, 0), new Point( -1, -1)]);
static public function point(d:int):Point {
d = fixDirection(d);
switch(d) {
case 0:return vecPoint[0]; break;
case 1:return vecPoint[1]; break;
case 2:return vecPoint[2]; break;
case 3:return vecPoint[3]; break;
case 4:return vecPoint[4]; break;
case 5:return vecPoint[5]; break;
case 6:return vecPoint[6]; break;
case 7:return vecPoint[7]; break;
}
return null;
}
static public function direction(point:Point):int {
var i:int;
if (point.x < 0) point.x = -1;
else if (point.x > 0) point.x = 1;
else point.x = 0;
if (point.y < 0) point.y = -1;
else if (point.y > 0) point.y = 1;
else point.y = 0;
for(i = 0; i < 8; i++){
if (point.x == vecPoint[i].x && point.y == vecPoint[i].y) return i;
}
return -1;
}
static public function fixDirection(d:int):int {
if (d > 7) d -= 8;
if (d < 0) d += 8;
return d;
}
}
class Rand
{
static public function getInt(n:int, min:int = 0):int {
if (n < 0) n = 0;
return Math.random() * n + min;
}
static public function minmax(min:int, max:int):int {
return int(Math.random() * (max - min + 1)) + min;
}
}
class MiniMap extends Bitmap
{
private var size:int = 8;
private const roomColor:uint = 0x669999ff
private var floor:Floor;
private var ef:EnemyFactory;
public function MiniMap(floor:Floor,ef:EnemyFactory)
{
this.floor = floor;
this.ef = ef;
super(new BitmapData(472,280))
y = 50;
}
public function newMiniMap():void {
bitmapData.lock();
drawFloor();
drawEnemy();
bitmapData.unlock();
}
public function update():void {
}
public function draw():void {
bitmapData.lock();
drawFloor();
drawEnemy();
bitmapData.unlock();
}
private function drawFloor():void {
var i:int, j:int;
for(i = 0; i < 35; i++)for(j = 0; j < 59; j++){
var grid:Grid = floor.getGrid(j, i);
switch(grid.type) {
case 1:
case 2:
drawRect(j * size, i * size, size, size, roomColor);
break;
}
}
}
private function drawEnemy():void {
var i:int;
var enemy:Enemy;
var len:int;
if (ef.vecEnemy.length != 0) len = ef.vecEnemy.length;
for(i = 0; i < len; i++){
enemy = ef.vecEnemy[i];
drawRect(enemy.x / 48 * size + 1, enemy.y / 48 * size + 1, size - 2, size - 2, 0xffff0000);
}
}
public function drawRect(x:int, y:int, w:int, h:int, fillColor:uint):void {
bitmapData.fillRect(new Rectangle(x, y, w, h), fillColor);
}
}
class EnemyFactory
{
public var vecEnemy:Vector.<Enemy>;
private var floor:Floor;
public function EnemyFactory(floor:Floor)
{
this.floor = floor;
vecEnemy = new Vector.<Enemy>();
}
public function update():void {
var i:int;
var len:int = vecEnemy.length;
for(i = 0; i < len; i++){
vecEnemy[i].update();
}
}
public function turnUpdate():void {
var i:int;
var len:int = vecEnemy.length;
floor.turn++;
for (i = 0; i < len; i++) {
vecEnemy[i].turnUpdate();
}
if (floor.turn % 20 == 1) {
create();
}
}
public function init():void {
vecEnemy = null;
vecEnemy = new Vector.<Enemy>();
}
public function create():void {
var enemy:Enemy = new Enemy(floor);
enemy.draw();
enemy.warp();
vecEnemy.push(enemy);
}
public function ready():Boolean {
var i:int;
for(i = 0; i < vecEnemy.length; i++){
if (!vecEnemy[i].ready()) return false;
}
return true;
}
public function removeEnemy(enemy:Enemy):void {
var i:int;
var len:int = vecEnemy.length;
for(i = 0; i < len; i++){
if (vecEnemy[i] == enemy) {
vecEnemy.splice(i, 1);
break;
}
}
}
}
class Debug extends Sprite
{
private var tf:TextField;
private var time:Number = 0;
private var cnt:int;
private var fps:Number = 30;
private var floor:Floor;
private var ef:EnemyFactory;
public function Debug(floor:Floor,ef:EnemyFactory)
{
this.floor = floor;
this.ef = ef;
addChild(tf = new TextField());
//tf.background = true;
//tf.backgroundColor = 0xffffff;
//tf.alpha = 0.5;
}
public function update():void {
cnt++;
getTimer();
if (getTimer() - time >= 1000) {
fps = cnt / (getTimer() - time) * 1000;
cnt = 0;
time = getTimer();
}
tf.text = "";
tf.appendText("fps:" + int(fps) + "\n");
tf.appendText("turn " + floor.turn + "\n");
tf.appendText("enemyNum " + ef.vecEnemy.length + "\n");
}
}