RPGぽいもの(作りかけ)

by nishink
RPGっぽいもの(作りかけ)
上下左右キーで歩きます。
Enterでメッセージが出ます。
♥0 | Line 339 | Modified 2010-12-13 11:18:11 | MIT License | (replaced)
play

Related images

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/bWh0
 */

// 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.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, SCR_H, false, 0));
    private var key:Key = new Key();
    private var map:Map = new Map(SCR_W, SCR_H);
    private var player:Player = new Player(map);
    private var charas:Array;
    private var statusWindow:Window = new Window(16, 16, 64, 64);
    private var messageWindow:MessageWindow = new MessageWindow(120, 250, 230, 100);
    private var caption:Window = new Window(180, 200, 100, 20);

    public function Main() {
        // 画像を読み込みます
        loader.contentLoaderInfo.addEventListener(Event.COMPLETE, onComplete);
        loader.load(new URLRequest(IMAGE_URL), new LoaderContext(true));
        // 描画領域を登録
        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);
        // キャラ情報の初期化
        charas = [player, new Npc(map), new Npc(map), new Npc(map),
            new Npc(map), new Npc(map), new Npc(map)];
        // マップにキャラ情報を追加
        map.setCharas = charas;
        // 画像が読み込まれたので描画OK
        map.onLoad(loader.content as Bitmap);
        // ステータスウィンドウ
        statusWindow.text = "ああああ\nLV:1\nHP:10\nMP:0";
        addChild(statusWindow);
        // メッセージウィンドウ
        messageWindow.visible = false;
        addChild(messageWindow);
        // キャプション
        caption.text = "Click to Start";
        addChild(caption);
    }
    // 描画更新
    private function onEnterFrame(ev:Event):void {
        key.onEnterFrame();
        for each(var chara:Chara in charas) {
            chara.onEnterFrame(key);
        }
        replaceWindow();
        // メッセージウィンドウ
        if (key.isPress(Keyboard.ENTER)) {
            if (messageWindow.visible) {
                if (!messageWindow.isMessaging()) {
                    messageWindow.visible = false;
                }
            } else {
                messageWindow.setMessage("そのほうこうには だれもいない。");
                messageWindow.visible = true;
            }
        }

        draw();
    }
    private function draw():void {
        var image:Bitmap = loader.content as Bitmap;
        canvas.bitmapData.lock();
        map.draw(canvas);
        for each(var chara:Chara in charas) {
            chara.draw(image, canvas);
        }
        canvas.bitmapData.unlock();
    }

    // ウィンドウ位置の調整
    private function replaceWindow():void {
        var pos:Point = player.getPos;
        if (pos.x < SCR_W/2) {
            statusWindow.x = SCR_W - 80;
        } else {
            statusWindow.x = 16;
        }
        if (pos.y < SCR_H/2) {
            statusWindow.y = SCR_H - 80;
        } else {
            statusWindow.y = 16;
        }
    }

    // キー押下
    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 {
        // Clicck to Startを消す
        if (caption.visible) caption.visible = false;
    }
}
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",
    ];

    public function Map(w:int, h:int) {
        this.width = w;
        this.height = h;
        srcRect = new Rectangle(0, 0, width, height);
        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):void {
        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;
    
    protected var dir:uint = 0;
    protected var count:int = 0;
    protected var pos:Point = new Point(0, 0);
    protected var rect:Rectangle = new Rectangle(0, 16, 16, 16);
    protected var vx:int = 0;
    protected var vy:int = 0;
    protected var map:Map;
    
    public function Chara(map:Map=null) {
        this.map = map;
    }

    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):void {
        canvas.bitmapData.copyPixels(src.bitmapData, rect, pos);
    }
    protected 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);
    }
}
class Player extends Chara {
    public function Player(map:Map) {
        super(map);
    }
    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;
        }
    }
}
class Npc extends Chara {
    public function Npc(map:Map) {
        super(map);
        rect = new Rectangle(0, 32, 16, 16);
    }
}
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;
    }
}
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();
    }

}

Forked