本気でダンジョンRPG作る step4-(主人公のモーションを作る)
LIVE CODING 2010/04/27 20:27-23:27
wonderflでがんばってダンジョンRPGを作ってます。
主人公モーションひとまず完成
絵は24枚
操作方法
移動:方向キー
足踏み: A
攻撃: Z
びっくり: Y
階段を下りる: 階段上でSpace
マップ
緑:部屋 または 通路
赤:敵
ピンク:主人公
水色:階段
通ったことのない場所の階段,敵は見えません
English
I make a RPG.
step2: move charactors
walk: arrow keys
step in place: A
attack: Z
go down stairs: Space
map
green: room or passage
red: Enemy
pink: player
light blue: staire
制作過程を残していきたいのでforkを重ねて制作してます。
PREVIOUS http://wonderfl.net/c/t3qt
NEXT http://wonderfl.net/c/rhcZ/
前のステップの差分は,上の[diff()]をクリックするとみることができます
/**
* Copyright shohei909 ( http://wonderfl.net/user/shohei909 )
* MIT License ( http://www.opensource.org/licenses/mit-license.php )
* Downloaded from: http://wonderfl.net/c/oDmN
*/
// forked from shohei909's 本気でダンジョンRPG作る step3-(マップを立体化する)
package{
//LIVE CODING 2010/04/27 20:27-23:27
//wonderflでがんばってダンジョンRPGを作ってます。
//主人公モーションひとまず完成
//絵は24枚
//操作方法
//移動:方向キー
//足踏み: A
//攻撃: Z
//びっくり: Y
//階段を下りる: 階段上でSpace
//マップ
// 緑:部屋 または 通路
// 赤:敵
// ピンク:主人公
// 水色:階段
//通ったことのない場所の階段,敵は見えません
//English
// I make a RPG.
//
// step2: move charactors
// walk: arrow keys
// step in place: A
// attack: Z
// go down stairs: Space
// map
// green: room or passage
// red: Enemy
// pink: player
// light blue: staire
//制作過程を残していきたいのでforkを重ねて制作してます。
//PREVIOUS http://wonderfl.net/c/t3qt
//NEXT http://wonderfl.net/c/rhcZ/
//前のステップの差分は,上の[diff()]をクリックするとみることができます
import flash.display.*;
import net.hires.debug.Stats;
[SWF(backgroundColor="#000000", frameRate="30",width="465",height="465" )]
public class Game extends Sprite{
public function Game() {
var back:Bitmap = new Bitmap(new BitmapData( 465, 465, true, 0xFF000033 ) );
stage.addChild(back);
stage.addChild( new RPG() );
stage.addChild( new Stats() );
}
}
}
import flash.display.*;
import flash.events.*;
import flash.ui.*;
import flash.utils.*;
import flash.text.TextField;
import flash.net.URLRequest;
import flash.system.*;
import flash.geom.*;
import org.papervision3d.objects.*;
import org.papervision3d.view.*;
import org.papervision3d.materials.*;
import org.papervision3d.objects.primitives.*;
class RPG extends Sprite{
private var map:Map;
public function RPG(){ addEventListener( Event.ADDED_TO_STAGE, init );}
public function init(e:Event):void{
removeEventListener( Event.ADDED_TO_STAGE, init );
map = new Map(30,30);
while(this.numChildren>0){ this.removeChildAt(0); }
map.bitmap.scaleX = 3;
map.bitmap.scaleY = -3;
map.bitmap.x = 340;
map.bitmap.y = 440;
addChild(map.view);
addChild( new Shadow(GameData.SWF_WIDTH,GameData.SWF_HEIGHT));
addChild(map.bitmap);
//stage.addChild(map.textField);
stage.addEventListener( "enterFrame", map.man.onFrame );
stage.addEventListener( "keyDown", map.man.onKeyDown );
}
}
class MapView extends BasicView{
public var map:Map;
private var plane:Plane;
private var loader:Loader;
public var load:Boolean =false;
public var sourceImg:BitmapData;
public var floorPlanes:Vector.<Vector.<Plane>>;
public var hWallPlanes:Vector.<Vector.<Plane>>;
public var vWallPlanes:Vector.<Vector.<Plane>>;
public var manShadow:Plane;
public var enemyShadows:Vector.<Plane>;
public var manPlane:Plane;
public var enemyPlanes:Vector.<Plane>;
public var cameraTarget:DisplayObject3D;
public var viewW:int = 11;
public var viewH:int = 11;
public var centerX:int = 5;
public var centerY:int = 4;
public var cameraX:Number = 0;
public var cameraY:Number = 0;
public var images:Array;
public function MapView(m:Map):void{
super(465,465,false);
map = m;
loader = new Loader();
loader.contentLoaderInfo.addEventListener(Event.COMPLETE, loadComplete);
loader.load(new URLRequest(GameData.IMAGE_URL),new LoaderContext(true));
}
private function loadComplete(e:Event):void{
loader.contentLoaderInfo.removeEventListener(Event.COMPLETE, loadComplete);
sourceImg = new BitmapData(loader.height,loader.width,true);
sourceImg = Bitmap(e.currentTarget.loader.content).bitmapData;
images = new Array();
for each(var i:Object in GameData.IMAGE_ARRAY){
images[i.name] = new BitmapData(i.w,i.h,true,0x00000000);
images[i.name].draw( sourceImg, new Matrix(1,0,0,1,-i.x,-i.y), new ColorTransform(), BlendMode.NORMAL, new Rectangle(0,0,i.w,i.h) );
}
init();
}
public function init():void{
floorPlanes = new Vector.<Vector.<Plane>>(viewW);
for(var i:int=0; i< viewW ;i++){
floorPlanes[i] = new Vector.<Plane>(viewH);
for(var j:int=0; j < viewH; j++){
var material:BitmapMaterial = new BitmapMaterial(new BitmapData(50,50,false,0x000000));
var fp:Plane = new Plane(material ,50,50);
floorPlanes[i][j] = fp;
fp.useOwnContainer = true;
fp.x = 50 * i - 50 * centerX;
fp.y = 50 * j - 50 * centerY;
scene.addChild( fp );
}
}
hWallPlanes = new Vector.<Vector.<Plane>>(viewW);
for(i=0; i< viewW ;i++){
hWallPlanes[i] = new Vector.<Plane>(viewH+1);
for(j=0; j < viewH+1; j++){
material = new BitmapMaterial(images["wall"]);
material.oneSide = false;
var hwp:Plane = new Plane(material ,50,50);
hWallPlanes[i][j] = hwp;
hwp.useOwnContainer = true;
hwp.x = 50 * i - 50 * centerX;
hwp.y = 50 * j - 50 * centerY -25;
hwp.z = -25;
hwp.rotationX = -90;
scene.addChild( hwp );
}
}
vWallPlanes = new Vector.<Vector.<Plane>>(viewW+1);
for(i=0; i< viewW+1 ;i++){
vWallPlanes[i] = new Vector.<Plane>(viewH);
for(j=0; j < viewH; j++){
material = new BitmapMaterial(images["wall"]);
material.oneSide = false;
var vwp:Plane = new Plane(material ,50,50, 1, 1);
vWallPlanes[i][j] = vwp;
vwp.useOwnContainer = true;
vwp.x = 50 * i - 50 * centerX-25;
vwp.y = 50 * j - 50 * centerY;
vwp.z = -25;
vwp.rotationZ = -90;
vwp.rotationX = -90;
scene.addChild( vwp );
}
}
enemyShadows = new Vector.<Plane>();
manShadow = map.man.shadow;
manShadow.useOwnContainer = true;
manShadow.z = -12;
scene.addChild( manShadow );
manPlane = map.man.plane;
manPlane.material = new BitmapMaterial(images["man_left_walk0"]);
manPlane.useOwnContainer = true;
manPlane.rotationX = -20;
manPlane.z = -40;
scene.addChild( manPlane );
cameraTarget = new DisplayObject3D();
camera.target = cameraTarget;
cameraX = 0;
cameraY = -200;
camera.z = -400;
camera.zoom = 70;
load = true;
floorUpdate();
addEventListener(Event.ENTER_FRAME, onFrame);
}
public function onFrame(evt:Event):void{
map.man.action(); //このイベントの呼び出しに合わせて主人公を動かす
map.man.motion.nextFrame();
for each(var e:Enemy in map.enemys){
if(e.shadow.visible){
e.motion.nextFrame();
e.shadow.x = 50 * ( e.motion.x - map.man.x );
e.shadow.y = 50 * ( e.motion.y - map.man.y )-7;
}
}
manShadow.x = 50 * ( map.man.motion.x - map.man.x );
manShadow.y = 50 * ( map.man.motion.y - map.man.y )-7;
manPlane.x = 50 * ( map.man.motion.x - map.man.x );
manPlane.y = 50 * ( map.man.motion.y - map.man.y )-7;
cameraTarget.x = 50 * ( map.man.motion.x - map.man.x );
cameraTarget.y = 50 * ( map.man.motion.y - map.man.y );
if(map.man.motion.change){
manPlane.material = new BitmapMaterial(images[ map.man.motion.toImageName() ]);
map.textField.text = map.man.motion.page+"";
}
camera.x=cameraX+manShadow.x;
camera.y=cameraY+manShadow.y;
renderer.renderScene(scene, camera, viewport);
}
public function floorUpdate():void{
for each(var shadow:Plane in enemyShadows){
scene.removeChild( shadow );
}
for each(var e:Enemy in map.enemys){
enemyShadows.push( e.shadow );
e.shadow.visible = false;
e.shadow.useOwnContainer = true;
e.shadow.z = -12;
scene.addChild( e.shadow );
}
update();
}
public function update():void{
for each(var e:Enemy in map.enemys){
if( e.x-map.man.x < viewW-centerX && map.man.x-e.x < centerX &&
e.y-map.man.y < viewH-centerY && map.man.y-e.y < centerY){
e.shadow.visible = true;
}else{e.shadow.visible = false;}
}
for(var i:int=0; i< viewW ;i++){
for(var j:int=0; j < viewH; j++){
var mapI:int = i - centerX + map.man.x;
var mapJ:int = j - centerY + map.man.y;
var fp:Plane = floorPlanes[i][j];
if(mapI < 0 || map.width <= mapI || mapJ < 0 || map.height <= mapJ ){
fp.material.bitmap = images["roof"];
fp.z = -50;
}else{
var f:Floor = map.floors[mapI][mapJ];
switch(f.name){
case "route" : case "room":
if(f.isStair){ fp.material.bitmap = images["staire"];}
else{ fp.material.bitmap = images["floor"]; }
fp.z = 0;
break;
default:
fp.material.bitmap = images["roof"];
fp.z = -50;
break;
}
}
}
}
for(i=0; i< viewW ;i++){
for(j =0; j < viewH+1; j++){
mapI = i - centerX + map.man.x;
mapJ = j - centerY + map.man.y-1;
var hwp:Plane = hWallPlanes[i][j];
hwp.visible = false;
if( (mapI < 0 || map.width <= mapI || mapJ < 0 || map.height <= mapJ)==false ){
f = map.floors[mapI][mapJ];
switch(f.name){
case "route" : case "room":
if( map.floors[mapI][mapJ+1].name == "wall"){ hwp.visible = true; }
break;
}
}
mapJ = j - centerY + map.man.y;
if( (mapI < 0 || map.width <= mapI || mapJ < 0 || map.height <= mapJ)==false ){
f = map.floors[mapI][mapJ];
switch(f.name){
case "route" : case "room":
if( map.floors[mapI][mapJ-1].name == "wall"){ hwp.visible = true; }
break;
}
}
}
}
for(i=0; i< viewW+1 ;i++){
for(j =0; j < viewH; j++){
mapI = i - centerX + map.man.x-1;
mapJ = j - centerY + map.man.y;
var vwp:Plane = vWallPlanes[i][j];
vwp.visible = false;
if( (mapI < 0 || map.width <= mapI || mapJ < 0 || map.height <= mapJ)==false ){
f = map.floors[mapI][mapJ];
switch(f.name){
case "route" : case "room":
if( map.floors[mapI+1][mapJ].name == "wall"){ vwp.visible = true; }
else{ vwp.visible = false;}
break;
}
}
mapI = i - centerX + map.man.x;
if( (mapI < 0 || map.width <= mapI || mapJ < 0 || map.height <= mapJ)==false ){
f = map.floors[mapI][mapJ];
switch(f.name){
case "route" : case "room":
if( map.floors[mapI-1][mapJ].name == "wall"){ vwp.visible = true; }
break;
}
}
}
}
}
}
class Shadow extends Bitmap{
public function Shadow(w:int,h:int){
var bmd:BitmapData = new BitmapData( w,h,true );
bmd.lock();
var cx:int = w/2;
var r:int = 150;
var cy:int = h/2;
for(var i:int = 0;i<w;i++){
for(var j:int = 0;j<h;j++){
var rx:int = i-cx;
var ry:int = j-cy;
var r2:int = rx*rx+ry*ry;
if(r2 > r*r){
var d:int = ( Math.sqrt(r2) - r )*1;
if( 0xFF < d){d=0xFF}
var color:uint = 0x01000000 * d;
}else{ color = 0x00000000; }
bmd.setPixel32(i,j,color);
}
}
bmd.unlock();
super(bmd);
}
}
class DropShadow extends BitmapData{
public function DropShadow(){
super( 50,50,true );
var cx:int =25;var r:int = 20;var cy:int = 25;
lock();
for(var i:int = 0;i<50;i++){
for(var j:int = 0;j<50;j++){
var rx:int = i-cx;var ry:int = j-cy;
var r2:int = rx*rx+ry*ry;
if(r2 < r*r){
var d:int = r2 * 0xA0/(r*r);
if( 0xA0 < d){d = 0xA0}
d = 0xA0 - d;
var color:uint = 0x01000000 * d;
}else{ color = 0x00000000; }
setPixel32(i,j,color);
}
}
unlock();
}
}
//マップデータのクラス
class Map{
public var bitmap:Bitmap;
public var view:MapView
public var textField:TextField = new TextField();
public var rank:int = 0; //階層
public var width:int;
public var height:int;
//マップの内容 0:壁、1:部屋 2:通路 3:アイテム 4:敵 5:自分 6:階段
public var data:Vector.<Vector.<int>>;
//マップに関する詳細なデータ
public var floors:Vector.<Vector.<Floor>>;
//部屋のサイズは6×6固定になります
public static var ROOM_SIZE:int = 6;
public var rooms:Vector.<Room>;//部屋のデータ
public var routes:Vector.<Route>;
public var enemys:Vector.<Enemy>;
public var items:Vector.<DropItem>;//床に落ちているアイテム
public var man:Man = new Man();
//wとhには21以上を指定してください。
public function Map(w:int = 50,h:int = 50){
if(w < ROOM_SIZE *3 +2){w = ROOM_SIZE *3 +2;}
if(h < ROOM_SIZE *3 +2){h = ROOM_SIZE *3 +2;}
width = w;
height = h;
init();
}
//現在のサイズでマップを初期化
public function init():void{
bitmap = new Bitmap(new BitmapData( width, height, true, 0x00000000 ) );
rank = 0;
makeFloor();
view = new MapView(this);
}
public function makeFloor():void{
rooms=new Vector.<Room>(); routes=new Vector.<Route>(); enemys=new Vector.<Enemy>(); items=new Vector.<DropItem>();
data = new Vector.<Vector.<int>>(width);
data.fixed = true;
floors = new Vector.<Vector.<Floor>>(width);
floors.fixed = true;
for(var i:int=0; i<width; i++ ){
data[i] = new Vector.<int>(height);
data[i].fixed = true;
floors[i] = new Vector.<Floor>(height);
floors[i].fixed = true;
for(var j:int=0; j<height; j++ ){
data[i][j] = 0;
floors[i][j] = new Floor(i,j,this);
floors[i][j].wall(0);
if( i==0 || j==0 || i==width-1 || j==height-1 ){
floors[i][j].routeable = false;
floors[i][j].roomable = false;
}
}
}
if( generate() ){ update(); }
else{ makeFloor(); }
}
//ランダムマップの生成をします
public function generate():Boolean{
var missCount:int = 0;
while(missCount<10){
if( requestRoom( 1+Math.random()*(width-ROOM_SIZE-2), 1+Math.random()*(height-ROOM_SIZE-2) ) == false){ missCount++;
}else{ missCount = 0; }
}
if(rooms.length<2){
if(width >= ROOM_SIZE*2+3 && height >= ROOM_SIZE*2+3){ return false; }
}else{
var c:int = 0;
while(connect() == false){
var i:int = c%rooms.length;
exit( rooms[i] );c++;
if(c>rooms.length*100){return false;}
}
}
for each(var route:Route in routes){ cutRoute(route); }
setParts();
return true;
}
//指定された位置に部屋を作成を試みます
//成功したかどうかをbooleanで返します。
private function requestRoom(x:int,y:int):Boolean{
if(width < ROOM_SIZE*2+3 || height < ROOM_SIZE*2+3){ return false; }
var miss:Boolean = false;
for(var i:int = x; i< x+ROOM_SIZE; i++){
for(var j:int = y; j< y+ROOM_SIZE; j++){
if( floors[i][j].roomable == false ){
miss = true;
}
}
}
if(miss){ return false; }
else{ makeRoom(x,y); }
return false;
}
//部屋を作成します。requestRoom以外から呼び出さないでください。
private function makeRoom(x:int,y:int):void{
rooms.push(new Room(x,y,ROOM_SIZE,ROOM_SIZE,rooms.length,this));
for(var i:int = x-1; i< x+ROOM_SIZE+1; i++){
for(var j:int = y-1; j< y+ROOM_SIZE+1; j++){
if(x <= i && i< x+ROOM_SIZE && y <= j && j < y+ROOM_SIZE ){
data[i][j] = 1;
floors[i][j].room(rooms.length-1);
}else if( (x+1<=i && i<x+ROOM_SIZE-1) || (y+1<=j && j<y+ROOM_SIZE-1) ){
floors[i][j].roomable=false;
}else{
floors[i][j].roomable=false;
floors[i][j].routeable=false;
}
}
}
}
//すべての部屋がつながってるか調べます
private function connect():Boolean{
var ok:Boolean = true;
var v:Vector.<int> = rooms[0].getConnect();
for(var i:int=0; i<rooms.length; i++){ if(v.indexOf(i)==-1){ok=false;} }
return ok;
}
//rに出口となる部屋をまっすぐ伸ばします。
private function exit(r:Room):Boolean{
var a:int = Math.random()*4;
var c:int; var x:int; var y:int; var dx:int=0; var dy:int=0;
switch(a){
case 0://上に道を伸ばす
x = r.x+1 + Math.random()*(ROOM_SIZE-2); y = r.y-1; dy = -1;
break;
case 1://下に道を伸ばす
x = r.x+1 + Math.random()*(ROOM_SIZE-2); y = r.y+r.height; dy = 1;
break;
case 2://左に道を伸ばす
x = r.x-1; y = r.y+1 + Math.random()*(ROOM_SIZE-2); dx = -1;
break;
case 3://右に道を伸ばす
x = r.x+r.width; y = r.y+1 + Math.random()*(ROOM_SIZE-2); dx = 1;
break;
}
if(floors[x][y].routeable == true){
var route:Route = new Route(routes.length);
route.rooms.push(r);
c = 0;
while(c<height){
if(floors[x][y].routeable == true){
data[x][y] = 2;
floors[x][y].route(route.index);
route.floors.push(floors[x][y]);
x += dx;
y += dy;
}else if(data[x][y]==1){
close(dx,dy,r);
close(-dx,-dy,rooms[floors[x][y].index]);
rooms[ floors[x][y].index ].exits.push( route );
r.exits.push( route );
route.rooms.push( rooms[floors[x][y].index] );
routes.push(route);
break;
}else if(data[x][y]==2){
close(dx,dy,r);
r.exits.push(route);
routes[ floors[x][y].index ].connect(route);
break;
}else if(c>0){
close(dx,dy,r);
r.exits.push(route);
routes.push(route);
break;
}else{
break;
}
c++;
}
}else{
return false;
}
return true;
}
//rの一面を出口にできなくする。
private function close(dx:int,dy:int,r:Room):void{
for(var i:int = r.x+dx; i< r.x+r.width+dx; i++){
for(var j:int = r.y+dy; j< r.y+r.height+dy; j++){
floors[i][j].routeable=false;
}
}
}
//行き止まりを消す。
public function cutRoute(r:Route):void{
var loop:Boolean = true;
while(loop){
loop = false;
for each(var f:Floor in r.floors){
var c:int = 0;
var side:Floor = floors[f.x + 1][f.y];
if( ( side.name == "route" && side.index == r.index ) || side.name == "room"){c++;}
side = floors[f.x - 1][f.y];
if( ( side.name == "route" && side.index == r.index ) || side.name == "room"){c++;}
side = floors[f.x][f.y - 1];
if( ( side.name == "route" && side.index == r.index ) || side.name == "room"){c++;}
side = floors[f.x][f.y + 1];
if( ( side.name == "route" && side.index == r.index ) || side.name == "room"){c++;}
if(c == 1){
loop = true;
data[f.x][f.y] = 0;
floors[f.x][f.y].wall(0);
r.floors.splice(r.floors.indexOf(f),1);
}
}
}
}
//人、敵、階段、アイテムなどを設置
private function setParts():void{
GameUtil.setItems(this,rank);
GameUtil.setEnemys(this,rank);
//主人公は0番の部屋に配置
var x:int = rooms[0].x + rooms[0].width * Math.random();
var y:int = rooms[0].y + rooms[0].height * Math.random();
data[x][y] = 5;
man.init( x, y, this);
//階段は最後のの部屋に配置
var l:int = rooms.length-1;
x = rooms[l].x + rooms[l].width * Math.random();
y = rooms[l].y + rooms[l].height * Math.random();
data[x][y] = 6;
floors[x][y].stair();
}
//階段を下りる
public function down():void{
rank++;
if(rank > GameData.DEPTH ){ rank = 0; }
makeFloor();
view.floorUpdate();
}
//敵の行動などを1つ進める
public function step():void{
for each( var enemy:Enemy in enemys ){ enemy.walk(); }
if(view.load){view.update();}
update();
}
//textFieldから現在の状態を出力
public function output():void{
var str:String = "";
var f:Floor = floors[man.x][man.y];
str += "現在地: B" + (rank+1) + "階";
str += " x," + man.x;
str += " y," + man.y;
str += " " + f.name + f.index +"\n";
str += "\n近くの敵:\n";
for each(var e:Enemy in enemys){
var ef:Floor = floors[e.x][e.y];
if(ef.name == f.name && ef.index == f.index){
str += e.data.name;
str += " life:" + e.life + "/" + e.maxLife;
str += " walkType:" + e.data.walkType +"\n";
}
}
textField.width = 400;
textField.text = str;
}
//bitmapを更新します。
public function update():void{
output();
var bitmapData:BitmapData = bitmap.bitmapData;
bitmapData.lock();
for(var i:int=0; i<width; i++ ){
for(var j:int=0; j<height; j++ ){
var color:uint = 0x3300FF00;
switch(data[i][j]){
case 0:
color = 0x00000000; break;
case 1:
if(floors[i][j].visit){color = 0xFF00FF00;}
break;
case 2:
if(floors[i][j].visit){color = 0xFF00FF00;}
break;
case 3:
if(floors[i][j].visit){color = 0xFF0000FF;}
break;
case 4:
if(floors[i][j].visit){color = 0xFFFF0000;}
break;
case 5:
color = 0xFFFF00FF; break;
case 6:
if(floors[i][j].visit){color = 0xFF00FFFF;}
break;
}
bitmapData.setPixel32(i,j,color);
}
}
bitmapData.unlock();
}
}
//部屋のクラス
class Room{
public var x:int;
public var y:int;
public var width:int;
public var height:int;
public var index:int;
public var map:Map;
public var exits:Vector.<Route> = new Vector.<Route>();
public function Room(xx:int,yy:int,w:int,h:int,i:int,m:Map):void{
x=xx;
y=yy;
width=w;
height=h;
index=i;
map=m;
}
//この部屋とつながっている部屋を返します
public function getConnect( v:Vector.<int> = null ):Vector.<int>{
if(v == null){v = new Vector.<int>();}
if(v.indexOf(index)== -1){ v.push(index);}
for each(var route:Route in exits){
v = route.getConnect(v);
}
return v;
}
//この部屋を通ったことがあるところとして設定
public function visit():void{
for (var i:int = x; i<x+width; i++){
for (var j:int = y; j<y+height; j++){
map.floors[i][j].visit = true ;
}
}
}
}
//道のクラス
class Route{
//通り道{x,y,visit}
public var floors:Vector.<Floor> = new Vector.<Floor>();
//つながっている部屋のリスト。
public var rooms:Vector.<Room> = new Vector.<Room>();
public var index:int;
public function Route(i:int){
index = i;
}
//Routeを接続します。
public function connect(r:Route):void{
floors.concat(r.floors);
rooms.concat(r.rooms);
for each(var room:Room in r.rooms){
room.exits.push(this);
}
for each(var floor:Floor in r.floors){
floor.index = index;
}
}
public function getConnect( v:Vector.<int> = null ):Vector.<int>{
for each(var room:Room in rooms){
if(v.indexOf(room.index) == -1){ v= room.getConnect(v) }
}
return v;
}
}
class Floor{
public var x:int;
public var y:int;
public var map:Map;
public var name:String="undefined";
public var data:int=0;
public var index:int = 0;
public var visit:Boolean=false;
public var routeable:Boolean=true;
public var roomable:Boolean=true;
public var isStair:Boolean=false;
public function Floor(xx:int,yy:int,m:Map){
x = xx;
y = yy;
map = m;
}
//この床を壁として初期化
public function wall(i:int):void{
name = "wall";
index = i;
data = 0;
routeable = true;
roomable = true;
}
//この床を部屋として初期化
public function room(i:int):void{
name = "room";
index = i;
data = 1;
routeable = false;
roomable = false;
}
//この床を道として初期化
public function route(i:int):void{
name = "route";
index = i;
data = 2;
routeable = false;
roomable = false;
}
//この床を階段にする
public function stair():void{
isStair = true;
data = 6;
}
//この床を通ったことがある場所として設定.
public function over():void{
if(visit == false){
if(name == "room"){
map.rooms[index].visit();
}else{
visit = true;
}
}
}
}
//床に落ちているアイテムのクラス
class DropItem{
public var x:int = 0;
public var y:int = 0;
public var name:String = "item";//itemのクラス
}
//キャラクターのクラス
//キャラクターには敵や自分が含まれます。
class Charactor{
public var alive:Boolean = true;
public var x:int = 0;
public var y:int = 0;
public var map:Map; //このキャラクターが配置されているマップ
public var life:int = 100;
public var maxLife:int = 100;
public var name:String = "chara";
public var motion:Motion;
public var shadow:Plane = new Plane( new BitmapMaterial( new DropShadow() ) ,50,50, 1, 1);
public var plane:Plane = new Plane( new BitmapMaterial() ,48,48, 1, 1);
}
//主人公のクラス
import flash.accessibility.Accessibility;
class Man extends Charactor{
public var dx:int = 0;
public var dy:int = 0;
public var camera:Boolean = false; //カメラの中心に置くか?
public var moving:Boolean = false;
private var keyEvents:Vector.<KeyboardEvent>;
public function init(xx:int, yy:int, m:Map):void{
x=xx; y=yy; map=m;
name = "man";
camera = true;
motion = new Motion(name,x,y);
keyEvents = new Vector.<KeyboardEvent>();
map.floors[x][y].over();
}
public function onFrame(e:Event):void{
if(moving){move(dx,dy)}
}
public function onKeyDown(e:KeyboardEvent):void{
keyEvents.push(e);
}
public function action():void{
for each(var e:KeyboardEvent in keyEvents){
if(e.keyCode == Keyboard.DOWN){ move(0,-1); }
else if(e.keyCode == Keyboard.UP){ move(0,1); }
else if(e.keyCode == Keyboard.LEFT){ move(-1,0); }
else if(e.keyCode == Keyboard.RIGHT){ move(1,0); }
else if(e.keyCode == 65){ move(0,0); }
else if(e.keyCode == 90){ attack(); }
else if(e.keyCode == 88){ surprised(); }
else if(e.keyCode == Keyboard.SPACE && map.floors[x][y].isStair){ move(0,0);map.down(); }
}
keyEvents = new Vector.<KeyboardEvent>();
}
public function move(ddx:int,ddy:int):Boolean{
if(motion.moving){
moving = false;
}else{
camera = true;
dx = ddx; dy=ddy;
moving = true;
var data:int = map.data[x+dx][y+dy];
if( data == 0 || data == 4 ){
motion.walk(x,y,x,y,2,4);
motion.setDir(ddx,ddy);
return false;
}else{
motion.walk(x,y,x+dx,y+dy,2,4);
map.data[x][y] = map.floors[x][y].data;
x+=dx; y+=dy;
map.data[x][y] = 5;
map.floors[x][y].over();
map.step();
}
}
return moving == false;
}
public function attack():void{
//toDo 攻撃モーション
motion.attack(x,y,6,14);
}
public function surprised():void{
//toDo 攻撃モーション
motion.surprised(x,y,6,14);
}
}
class Enemy extends Charactor{
public var data:Object;
public function Enemy(xx:int, yy:int, m:Map,n:String){
x=xx; y=yy; map=m;
name = n;
data = GameData.ENEMY_DATA[n];
life = data.life;
maxLife = life;
motion = new Motion(name,x,y);
}
public function walk():void{
var c:int = 0;
while(c < 6){
switch(data.walkType){
case "chase":
if(map.floors[map.man.x][map.man.y].name == "room" && map.floors[map.man.x][map.man.y].index == map.floors[x][y].index){
if( chase() ){break;}
}else{ if( walkRandom() ){break;} }
break;
case "random":
if( walkRandom() ){break;}
break;
}
c++;
}
}
public function walkRandom():Boolean{
var d:int = Math.random()*2;
var dx:int;var dy:int;
if(d==0){
dx = 0;
d = Math.random()*2;
dy = d*2-1;
}else{
dy = 0;
d = Math.random()*2;
dx = d*2-1;
}
return move(dx,dy);
}
public function chase():Boolean{
var d:int = Math.random()*2;
var dx:int;var dy:int;
if(d==0){ if(map.man.x == x){d=1;} }
else{ if(map.man.y == y){d=0;} }
if(d==1){
dx = 0;
if(map.man.y > y){dy=1;}
else{dy=-1}
}else{
dy = 0;
if(map.man.x > x){dx=1;}
else{dx=-1}
}
return move(dx,dy);
}
public function move(dx:int,dy:int):Boolean{
if(motion.moving){
return false;
}else{
var d:int = map.data[x+dx][y+dy];
if( d == 0 || d == 2 || d == 4 || d == 5){
return false;
}else{
motion.walk(x,y,x+dx,y+dy,2,2);
map.data[x][y] = map.floors[x][y].data;
x+=dx; y+=dy;
map.data[x][y] = 4;
}
}
return true;
}
}
class Motion extends EventDispatcher{
//モーションが稼働しているか
public var moving:Boolean = false;
//モーションの名前
public var name:String = "stop" ;
public var change:Boolean = true; //前回の表示から画像の変化があったか?
public var page:int = 0; //モーション画像の番号
public var numPage:int = 1; //モーション画像の数
public var interval:int = 2; //モーション画像の変更間隔
//動作主の名前
public var parent:String;
public var x:Number = 0;
public var y:Number = 0;
//モーションの始点
public var startX:Number = 0;
public var startY:Number = 0;
//モーションの終点
public var endX:Number = 0;
public var endY:Number = 0;
public var frameLength:int=-1; //モーションの継続時間(フレーム)
public var frame:int=0; //モーション開始からの経過時間
public var dir:String = "down";
public function Motion(p:String,xx:Number,yy:Number){
x=xx; y=yy; parent = p;
}
//モーションを開始します
public function start():void{
moving = true;
x=startX;
y=startY;
frame = 0;
}
//モーションを終了します
public function stop():void{
moving = false;
change = true;
frameLength = 200000;
name = "stop";
numPage = 1;
frame = 0;
x=endX;
y=endY;
}
public function walk( sx:Number,sy:Number,ex:Number,ey:Number,p:int,l:int):void{
startX = sx; startY = sy;
endX = ex; endY = ey;
setDir(ex - sx,ey - sy);
name = "walk";
interval = p; //4枚絵
numPage = 4; //4枚絵
frameLength = l; //モーション時間 0.16s
change = true;
if(page%2 == 0){nextPage();}
start();
}
public function attack( sx:Number,sy:Number,p:int,l:int):void{
startX = sx; startY = sy;
endX = sx; endY = sy;
name = "attack";
interval = p;
numPage = 2; //2枚絵
frameLength = l; //モーション時間 0.16s
change = true;
start();
page=0;
frame=4;
}
public function surprised( sx:Number,sy:Number,p:int,l:int):void{
startX = sx; startY = sy;
endX = sx; endY = sy;
name = "surprised";
interval = p;
numPage = 1; //1枚絵
frameLength = l; //モーション時間 0.16s
change = true;
start();
page=0;
frame=0;
}
public function toImageName():String{
change = false;
var str:String = "";
var p:int = page%numPage;
if(parent == "man"){
if(name == "walk" && (p==1||p==3) ){str = parent +"_"+ dir + "_stop0"; }
else{str = parent +"_"+ dir +"_"+ name + p; }
}
return str;
}
public function setDir( cx:Number,cy:Number):void{
var d:Number = Math.atan2(cx, cy);
if(cx==0 && cy==0){ }
else if(-3/4*Math.PI<=d && d<=-1/4*Math.PI && 0>=cx){ dir="left"; }
else if(-1/4*Math.PI<d && d<1/4*Math.PI) { dir="up"; }
else if(1/4*Math.PI<=d && d<=3/4*Math.PI){ dir="right"; }
else { dir="down"; };
}
public function nextFrame():void{
if(frame % interval == 0){ nextPage(); }
frame++;
if(moving){
if(frame == frameLength){
stop();
}else{
var f:int = frame%frameLength;
var def:Number = frameLength - f;
x = ( startX*def + endX*f )/ frameLength ;
y = ( startY*def + endY*f )/ frameLength ;
}
}
}
//nextPage
public function nextPage():void{
page++;
change = true;
}
//x,yを更新する
public function update():void{
page++;
change = true;
}
}
//敵、画像、アイテム、技、などのデータが収められている静的クラス
class GameData{
public static const SWF_WIDTH:int = 465;
public static const SWF_HEIGHT:int = 465;
public static const ROOM_WIDTH:int = 5;
public static const ROOM_HEIGHT:int = 5;
public static const DEPTH:int = 1;
public static const IMAGE_URL:String = "http://assets.wonderfl.net/images/related_images/6/6d/6d9c/6d9cc63c6b7fcfd0d81ce6915dadb1e444317d38";
//画像の位置データ===========================================
public static var IMAGE_ARRAY:Array = [
{name:"floor",x:50,y:0,w:50,h:50},
{name:"wall",x:0,y:0,w:50,h:50},
{name:"staire",x:100,y:0,w:50,h:50},
{name:"roof",x:150,y:0,w:50,h:50},
{name:"man_left_walk0", y:50,x:0,w:24,h:24},
{name:"man_left_walk2", y:50,x:25,w:24,h:24},
{name:"man_right_walk0",y:50,x:50,w:24,h:24},
{name:"man_right_walk2",y:50,x:75,w:24,h:24},
{name:"man_down_walk0", y:50,x:100,w:24,h:24},
{name:"man_down_walk2", y:50,x:125,w:24,h:24},
{name:"man_up_walk0", y:50,x:150,w:24,h:24},
{name:"man_up_walk2", y:50,x:175,w:24,h:24},
{name:"man_left_stop0", y:75,x:0,w:24,h:24},
{name:"man_right_stop0",y:75,x:25,w:24,h:24},
{name:"man_down_stop0", y:75,x:50,w:24,h:24},
{name:"man_up_stop0", y:75,x:75,w:24,h:24},
{name:"man_left_attack1", y:75,x:100,w:24,h:24},
{name:"man_right_attack1", y:75,x:125,w:24,h:24},
{name:"man_down_attack1", y:75,x:150,w:24,h:24},
{name:"man_up_attack1", y:75,x:175,w:24,h:24},
{name:"man_left_attack0", y:100,x:100,w:24,h:24},
{name:"man_right_attack0", y:100,x:125,w:24,h:24},
{name:"man_down_attack0", y:100,x:150,w:24,h:24},
{name:"man_up_attack0", y:100,x:175,w:24,h:24},
{name:"man_left_surprised0", y:100,x:0,w:24,h:24},
{name:"man_right_surprised0", y:100,x:25,w:24,h:24},
{name:"man_down_surprised0", y:100,x:50,w:24,h:24},
{name:"man_up_surprised0", y:100,x:75,w:24,h:24}
];
//(画像の位置データ)=============================================
//各階のデータ=============================================
public static var RANK_ARRAY:Array =[
{//0階
minEnemy:1,
maxEnemy:2,
enemy:["mosamosa","fusafusa"]
},
{//1階
minEnemy:1,
maxEnemy:2,
enemy:["mosamosa","fusafusa"]
}
];
//(各階のデータここまで)=============================================
//敵のデータ==============================================
public static var ENEMY_DATA:Object = {
mosamosa:{//もさもさ
name:"もさもさ",
life:60,
walkType:"chase"
},
fusafusa:{
name:"ふさふさ",
life:50,
walkType:"random"
}
}
//(敵のデータここまで)====================================
}
class GameUtil{
//その階層に見合ったアイテムを配置
public static function setItems(map:Map,rank:int):void{}
//その階層に見合った敵を配置
public static function setEnemys(map:Map,rank:int):void{
for (var i:int=1;i<map.rooms.length;i++){
var room:Room = map.rooms[i];
var max:int = GameData.RANK_ARRAY[rank].maxEnemy;
var min:int = GameData.RANK_ARRAY[rank].minEnemy;
var c:int = min + (max-min+1) * Math.random();
while(c>0){
var x:int = room.x + room.width * Math.random();
var y:int = room.y + room.height * Math.random();
var e:Array = GameData.RANK_ARRAY[rank].enemy;
var l:int = e.length*Math.random();
var name:String = e[l];
map.data[x][y] = 4;
map.enemys.push( new Enemy(x,y,map,name) );
c--;
}
}
}
}