forked from: RPGぽいもの(作りかけ)
forked from RPGぽいもの(作りかけ) (diff: 182)
RPGっぽいもの(作りかけ) 上下左右キーで歩きます。 Enterでメッセージが出ます。
♥0 |
Line 399 |
Modified 2011-03-06 02:00:32 |
MIT License
archived:2017-03-20 06:53:26
| (replaced)
ActionScript3 source code
/**
* Copyright nishink ( http://wonderfl.net/user/nishink )
* MIT License ( http://www.opensource.org/licenses/mit-license.php )
* Downloaded from: http://wonderfl.net/c/cIUd
*/
// RPGっぽいもの(作りかけ)
// 上下左右キーで歩きます。
// Enterでメッセージが出ます。
package {
import flash.display.Sprite;
public class RpgTest extends Sprite {
public function RpgTest() {
addChild(new Main());
}
}
}
import flash.display.Bitmap;
import flash.display.BitmapData;
import flash.display.Loader;
import flash.display.Sprite;
import flash.events.Event;
import flash.events.KeyboardEvent;
import flash.events.MouseEvent;
import flash.geom.Point;
import flash.geom.Rectangle;
import flash.net.URLRequest;
import flash.system.LoaderContext;
import flash.text.TextField;
import flash.text.TextFieldAutoSize;
import flash.text.TextFormat;
import flash.ui.Keyboard;
class Main extends Sprite {
public static const SCR_W:Number = 464;
public static const SCR_H:Number = 464;
// 画像のURL
private const IMAGE_URL:String = "http://assets.wonderfl.net/images/related_images/9/97/9736/9736dc4cd84618ae2aa85797765ebb779c3432ca";
private var loader:Loader = new Loader();
private var canvas:Bitmap = new Bitmap(new BitmapData(SCR_W/2, SCR_H/2, false, 0));
private var key:Key = new Key();
private var field:Field;
public function Main() {
// 画像を読み込みます
loader.contentLoaderInfo.addEventListener(Event.COMPLETE, onComplete);
loader.load(new URLRequest(IMAGE_URL), new LoaderContext(true));
// 描画領域を登録
canvas.scaleX = 2;
canvas.scaleY = 2;
addChild(canvas);
}
// 読み込み完了を待つ
private function onComplete(ev:Event):void {
// 読み込み完了待ちイベントリスナーの破棄
loaderInfo.removeEventListener(Event.COMPLETE, onComplete);
// 入力イベントの登録
addEventListener(Event.ENTER_FRAME, onEnterFrame);
stage.addEventListener(KeyboardEvent.KEY_DOWN, onKeyDown);
stage.addEventListener(KeyboardEvent.KEY_UP, onKeyUp);
addEventListener(MouseEvent.CLICK, onClick);
// 初期化
field = new Field(this, loader.content as Bitmap);
}
// フレーム更新
private function onEnterFrame(ev:Event):void {
key.onEnterFrame();
field.onEnterFrame(key);
field.draw(canvas);
}
// キー押下
private function onKeyDown(ev:KeyboardEvent):void {
key.press(ev.keyCode);
}
// キー離す
private function onKeyUp(ev:KeyboardEvent):void {
key.release(ev.keyCode);
}
// クリック
private function onClick(ev:MouseEvent):void {
field.onClick();
}
}
class Field {
private static const READY:int = 0;
private static const PLAY:int = 1;
private static const TALK:int = 2;
private var image:Bitmap;
private var map:Map = new Map(Main.SCR_W, Main.SCR_H);
private var player:Player = new Player(map, new Rectangle(0, 16, 16, 16), new Point(0, 0));
private var charas:Array;
private var messageWindow:MessageWindow = new MessageWindow(104, 256, 256, 128);
private var caption:Window = new Window(170, 200, 120, 30);
private var state:int;
private var view:Point = new Point(0, 0);
public function Field(base:Sprite, image:Bitmap) {
this.image = image;
// キャラ情報の初期化
charas = [player,
createNpc(map, "NPC1号です。"),
createNpc(map, "NPC2号ですよ。"),
createNpc(map, "NPC3号でございます。"),
createNpc(map, "NPC4号だってばよ。"),
createNpc(map, "NPC5号ざます。"),
createNpc(map, "NPC6号さんです。")];
// マップにキャラ情報を追加
map.setCharas = charas;
// 画像が読み込まれたので描画OK
map.onLoad(image);
// メッセージウィンドウ
messageWindow.visible = false;
base.addChild(messageWindow);
// キャプション
caption.text = "Click to Start!";
base.addChild(caption);
}
private function createNpc(map:Map, message:String):Npc {
var npc:Npc = new Npc(map, new Rectangle(0, 32, 16, 16), new Point(
((uint)(Math.random() * 464 / 16)) * 16,
((uint)(Math.random() * 464 / 16)) * 16
));
npc.message = message;
return npc;
}
// フレーム更新
public function onEnterFrame(key:Key):void {
switch(state) {
case PLAY:
// キー入力による更新
for each(var chara:Chara in charas) {
chara.onEnterFrame(key);
}
// メッセージウィンドウ
if (key.isPress(Keyboard.ENTER)) {
var front:Point = player.getFront();
var message:String = "そのほうこうには だれもいない。";
for each(var c:Chara in charas) {
if (front.x == c.getMapPos.x && front.y == c.getMapPos.y) {
message = (c as Npc).message;
}
}
messageWindow.setMessage(message);
messageWindow.visible = true;
state = TALK;
}
break;
case TALK:
if (key.isPress(Keyboard.ENTER)) {
if (!messageWindow.isMessaging()) {
messageWindow.visible = false;
state = PLAY;
}
}
break;
}
}
// マップとキャラの描画
private const CENTER:int = 464 / 4 - 8;
public function draw(canvas:Bitmap):void {
canvas.bitmapData.lock();
view.x = player.getPos.x - CENTER < 0 ? 0 : player.getPos.x - CENTER;
view.x = view.x > (464 / 2) ? 464 / 2 : view.x;
view.y = player.getPos.y - CENTER < 0 ? 0 : player.getPos.y - CENTER;
view.y = view.y > (464 / 2) ? 464 / 2 : view.y;
map.draw(canvas, view);
for each(var chara:Chara in charas) {
chara.draw(image, canvas, view);
}
canvas.bitmapData.unlock();
}
// クリック
public function onClick():void {
// Clicck to Startを消す
if (caption.visible) {
caption.visible = false;
state = PLAY;
}
}
}
class Map {
private var width:int;
private var height:int;
private var charas:Array;
private var backBuffer:Bitmap;
private var srcRect:Rectangle;
private var dstPos:Point;
private var data:Array = [
"00000000000000000000000000000",
"01010101010101010101010101010",
"01111111111111111111111111110",
"01212121212121212121212121210",
"02222222222222222222222222220", // 5
"02323232323232323232323232320",
"03333333333333333333333333330",
"03434343434343434343434343430",
"04444444444444444444444444440",
"04545454545454545454545454540", // 10
"05555555555555555555555555550",
"05656565656565656565656565650",
"06666666666666666666666666660",
"06060606060606060606060606060",
"00000000000000700000000000000", // 15
"06060606060606060606060606060",
"06666666666666666666666666660",
"05656565656565656565656565650",
"05555555555555555555555555550",
"04545454545454545454545454540", // 20
"04444444444444444444444444440",
"03434343434343434343434343430",
"03333333333333333333333333330",
"02323232323232323232323232320",
"02222222222222222222222222220", // 25
"01212121212121212121212121210",
"01111111111111111111111111110",
"01010101010101010101010101010",
"00000000000000000000000000000",
];
// マップの初期化:サイズはpixel単位
public function Map(w:int, h:int) {
this.width = w;
this.height = h;
srcRect = new Rectangle(0, 0, width/2, height/2);
dstPos = new Point(0, 0);
}
// マップ上にキャラを配置
public function set setCharas(charas:Array):void {
this.charas = charas;
}
// 画像ロード完了時に呼び出す:マップをバックバッファに描画しておく
public function onLoad(src:Bitmap):void {
var srcRect:Rectangle = new Rectangle(0, 0, 16, 16);
var dstPos:Point = new Point();
backBuffer = new Bitmap(new BitmapData(width, height, false, 0));
for (var y:int=0; y<width; y+=16) {
for (var x:int=0; x<height; x+=16) {
var line:String = data[y/16];
srcRect.x = getMapChip(x/16, y/16) * 16;
dstPos.x = x;
dstPos.y = y;
backBuffer.bitmapData.copyPixels(src.bitmapData, srcRect, dstPos);
}
}
}
// マップの描画
public function draw(dst:Bitmap, view:Point):void {
srcRect.x = view.x;
srcRect.y = view.y;
dst.bitmapData.copyPixels(backBuffer.bitmapData, srcRect, dstPos);
}
// マップチップの種類を取得
public function getMapChip(x:int, y:int):Number {
var line:String = data[y];
return line.charCodeAt(x) - '0'.charCodeAt(0);
}
// 指定した座標が通行可能かどうか判定
public function isObstacle(x:int, y:int):Boolean {
// マップ外は障害物と判定
if (x < 0 || y < 0 || x >= width/16 || y >= height/16)
return true;
var chip:Number = getMapChip(x, y);
// 高い山と水を障害物と判定
if (chip == 4 || chip == 6) return true;
// キャラがいる場所は障害物と判定
for each(var chara:Chara in charas) {
var pos:Point = chara.getMapPos;
if (pos.x == x && pos.y == y) {
return true;
}
}
return false;
}
}
class Chara {
public static const DOWN:uint = 0;
public static const UP:uint = 1;
public static const LEFT:uint = 2;
public static const RIGHT:uint = 3;
private var dir:uint = 0;
private var count:int = 0;
private var pos:Point;
private var rect:Rectangle;
private var vx:int = 0;
private var vy:int = 0;
private var map:Map;
private var drawPos:Point = new Point(0, 0);
public function Chara(map:Map, rect:Rectangle, pos:Point) {
this.map = map;
this.rect = rect;
this.pos = pos;
}
protected function move(key:Key):int {
return (int)(Math.random() * 32);
}
public function onEnterFrame(key:Key):void {
if (pos.x % 16 == 0 && pos.y % 16 == 0) {
// 移動速度
var moveState:int = move(key);
vy = vx = 0;
if (moveState == DOWN) {
dir = DOWN;
if (!map.isObstacle(pos.x/16,pos.y/16+1)) vy = 2;
} else if (moveState == UP) {
dir = UP;
if (!map.isObstacle(pos.x/16,pos.y/16-1)) vy = -2;
} else if (moveState == LEFT) {
dir = LEFT;
if (!map.isObstacle(pos.x/16-1,pos.y/16)) vx = -2;
} else if (moveState == RIGHT) {
dir = RIGHT;
if (!map.isObstacle(pos.x/16+1,pos.y/16)) vx = 2;
}
}
// 描画位置の更新
pos.x += vx;
pos.y += vy;
changeImage();
}
// 描画
public function draw(src:Bitmap, canvas:Bitmap, view:Point):void {
drawPos.x = pos.x - view.x;
drawPos.y = pos.y - view.y;
canvas.bitmapData.copyPixels(src.bitmapData, rect, drawPos);
}
private function changeImage():void {
// 描画する絵をどれにするかカウント
count++;
if (count >= 30) count = 0;
// 描画する絵の判定
rect.x = dir * 32;
if (count >= 15) {
rect.x += 16;
}
}
public function get getPos():Point {
return pos;
}
public function get getMapPos():Point {
var x:int = (int)(pos.x/16);
var y:int = (int)(pos.y/16);
if (!(pos.x%16==0 && pos.y%16==0)) {
if (dir == DOWN) y++;
if (dir == RIGHT) x++;
}
return new Point(x, y);
}
protected function get getDir():uint {
return dir;
}
}
class Player extends Chara {
public function Player(map:Map, rect:Rectangle, pos:Point) {
super(map, rect, pos);
}
protected override function move(key:Key):int {
if (key.isPressed(Keyboard.DOWN)) {
return DOWN;
} else if (key.isPressed(Keyboard.UP)) {
return UP;
} else if (key.isPressed(Keyboard.LEFT)) {
return LEFT;
} else if (key.isPressed(Keyboard.RIGHT)) {
return RIGHT;
} else {
return -1;
}
}
public function getFront():Point {
var front:Point = new Point(getMapPos.x, getMapPos.y);
if (getDir == DOWN) front.y++;
if (getDir == UP) front.y--;
if (getDir == RIGHT) front.x++;
if (getDir == LEFT) front.x--;
return front;
}
}
class Npc extends Chara {
public var message:String;
public function Npc(map:Map, rect:Rectangle, pos:Point) {
super(map, rect, pos);
}
}
class Window extends TextField {
public function Window(
x:Number, y:Number, width:Number, height:Number) {
this.border = true;
this.borderColor = 0xffffff;
this.background = true;
this.backgroundColor = 0;
this.wordWrap = true;
this.text = "";
this.textColor = 0xffffff;
this.width = width;
this.height = height;
this.x = x;
this.y = y;
var tf:TextFormat = new TextFormat();
tf.size = 18;
this.defaultTextFormat = tf;
}
}
class MessageWindow extends Window {
private var msg:String;
private var cnt:int;
public function MessageWindow(
x:Number, y:Number, width:Number, height:Number) {
super(x, y, width, height);
msg = "";
cnt = 0;
addEventListener(Event.ENTER_FRAME, onEnterFrame);
}
private function onEnterFrame(ev:Event):void {
if (msg.length > cnt) {
this.appendText(msg.charAt(cnt));
cnt++;
}
}
public function setMessage(msg:String):void {
this.msg = msg;
this.cnt = 0;
this.text = "";
}
public function isMessaging():Boolean {
return (msg.length > cnt);
}
}
class Key {
private var state:Array = new Array();
private var nowState:Array = new Array();
private var oldState:Array = new Array();
public function press(keyCode:uint):void {
state[keyCode] = true;
}
public function release(keyCode:uint):void {
state[keyCode] = false;
}
// 押した瞬間のみtrue
public function isPress(keyCode:uint):Boolean {
return nowState[keyCode] && !oldState[keyCode];
}
// キーが押されていればtrue
public function isPressed(keyCode:uint):Boolean {
return nowState[keyCode];
}
public function onEnterFrame():void {
oldState = nowState.concat();
nowState = state.concat();
}
}
