Flashでゲームキャラを動してみる2。オンラインゲームが作りたい(4)

前回に引き続きキャラクターを動かす。
前回の記事はこっち(そろそろ同一ウィンドウ内でリンクしたい)

今回はちょっと変わってます。ポイントは以下の3つ。

  • RPGツクール2000用のキャラクターチップを読込む
  • 一枚の画像からキャラクターアニメーションを作成
  • キャラクターが止まってるときは、ちゃんと足をそろえる。

RPGツクール2000用のキャラクターチップを読込むってのが特にポイント。
ドット絵描けない自分にとって、フリーでゲーム用素材を提供してくれる職人様は神様です。
でも、ネット上で配布されているフリーのゲーム素材のほとんどがRPGツクール2000ベースで作成されています。
たまに、XP用などもありますが、2000の方が「RPGツクール以外のゲームでも使って良いよ」素材が多いので今回は2000のキャラクターチップからロード出来るように作成しました。
こういう画像を読込みます。
素材はあらかじめ透過色を指定しておいてください。
配布元によっては複数のキャラクターが一枚の画像にまとめられている場合があります。
その場合はフォトショでアクションでも組んでください。

サンプル
プロジェクトファイル

3つのクラスで構成されています。
NetworkGame.as

package {
	import flash.display.*;
	import flash.events.*;
	import flash.utils.*;

	public class NetworkGame extends Sprite
	{

		// プレイヤー
		private var player:Character;

		// キーコード
		private var keyCode:Number;
		
		public function NetworkGame()
		{	
			// プレイヤー作成
			player = new Character();
			addChild( player.getMovieClip() );

			// イベントリスナーの追加
			stage.addEventListener(KeyboardEvent.KEY_DOWN,keyDownEvent);
			stage.addEventListener(KeyboardEvent.KEY_UP,keyUpEvent);

			// タイマーの追加(100m秒間隔、無制限)
			var timer:Timer = new Timer(100,0);
			
			// イベントリスナーの追加(発生時に)
			timer.addEventListener(TimerEvent.TIMER,timerEvent);
			
			// タイマーの開始
			timer.start();	
			
		}
		// キーダウンイベント
		private function keyDownEvent(event:KeyboardEvent):void {

			// 	キーコードを代入
			keyCode = event.keyCode;

		}
		
		// キーアップイベント
		private function keyUpEvent(event:KeyboardEvent):void {

			// 静止アニメーション
			if (keyCode == 37) {
				player.stopLeft();
			} else if (keyCode == 38) {
				player.stopUp();
			} else if (keyCode == 39) {
				player.stopRight();
			} else if (keyCode == 40) {
				player.stopDown();
			}

			// 	キーコードを空にする
			keyCode = 0;

		}

		// タイマーイベント
		private function timerEvent(event:TimerEvent):void{

			// 移動 ←↑→↓
			if (keyCode == 37) {
				player.moveLeft();
			} else if (keyCode == 38) {
				player.moveUp();
			} else if (keyCode == 39) {
				player.moveRight();
			} else if (keyCode == 40) {
				player.moveDown();
			}

			// 攻撃 space
			if (keyCode == 32) {
				player.actionAttack();
			}

		}
	}
}

Character.as

package {

	import flash.display.*;
	import flash.events.*;
	import flash.utils.Timer;
	import mx.core.ButtonAsset;

	public class Character extends Sprite {

		// 素材クラスの定義
		[Embed(source='images/character/player/0202.png')]
		private var char0202:Class;

		// MovieClip
		private var mc:MovieClip;

		// 移動スピード
		private var x_speed:Number;//X座標
		private var y_speed:Number;//Y座標
		
		private var reverse_flg:Boolean;
		
		// 

		// RPG2kConverter
		public var converter:RPG2kConverter;

		//コンストラクタ
		public function Character() {

			// 変数の初期化
			x_speed = 7;//X座標移動スピード
			y_speed = 7;//Y座標移動スピード


			// RPG2k用画像からプレイヤーMCの作成
			converter = new RPG2kConverter(char0202);
			mc = converter.getMovieClip();

			// 配置位置の初期化
			mc.x = 0;
			mc.y = 0;


		}

		public function moveUp():void {
			var position:Number = converter.getPosition();
			if(position == 12){
				if(reverse_flg){
					converter.changeMovieClip(13);
					reverse_flg = false;
				}else{
					converter.changeMovieClip(11);
					reverse_flg = true;
				}
			}else{
				converter.changeMovieClip(12);
			}
			mc.y -= y_speed;
		}
		
		public function moveRight():void {
			var position:Number = converter.getPosition();
			if(position == 22){
				if(reverse_flg){
					converter.changeMovieClip(23);
					reverse_flg = false;
				}else{
					converter.changeMovieClip(21);
					reverse_flg = true;
				}
			}else{
				converter.changeMovieClip(22);
			}
			mc.x += x_speed;
		}
		
		public function moveDown():void {
			var position:Number = converter.getPosition();
			if(position == 32){
				if(reverse_flg){
					converter.changeMovieClip(33);
					reverse_flg = false;
				}else{
					converter.changeMovieClip(31);
					reverse_flg = true;
				}
			}else{
				converter.changeMovieClip(32);
			}
			mc.y += y_speed;
		}
		
		public function moveLeft():void {
			var position:Number = converter.getPosition();
			if(position == 42){
				if(reverse_flg){
					converter.changeMovieClip(43);
					reverse_flg = false;
				}else{
					converter.changeMovieClip(41);
					reverse_flg = true;
				}
			}else{
				converter.changeMovieClip(42);
			}
			mc.x -= x_speed;
		}
		
		public function stopUp():void{
			converter.changeMovieClip(12);
		}

		public function stopRight():void{
			converter.changeMovieClip(22);
		}
		
		public function stopDown():void{
			converter.changeMovieClip(32);
		}

		public function stopLeft():void{
			converter.changeMovieClip(42);
		}
		
		public function actionAttack():void
		{
			trace("攻撃");
		}

		public function getMovieClip():MovieClip{
			return mc;
		}

	}
}

RPG2kConverter.as

package
{
	import flash.display.*;
	public class RPG2kConverter extends Sprite
	{

		private var mc:MovieClip;
		private var position:Number;
		
		public function RPG2kConverter(source:Class){			

			// 元画像MC生成
			var image:MovieClip = new MovieClip();
			image.addChild(new source());
			image.name = "image";

			// マスク生成
			var mask:MovieClip = new MovieClip();
			mask.graphics.beginFill(0x000000);
			mask.graphics.drawRect(0,0,24,32);
			mask.graphics.endFill();
			mask.name = "mask_mc";
			mask.alpha = 0.5;

			// 合体!!
			mc = new MovieClip();
			mc.addChild(image);
			mc.addChild(mask);
			mc.mask = mask;
			mc._x = 0;
			mc._y = 0;
			
			//初期画像
			mc.getChildByName("image").x = -24;
			mc.getChildByName("image").y = -64;
		}
		
		public function getMovieClip():MovieClip{
			return mc;
		}
		
		public function getPosition():Number{
			return position;
		}
		
		public function changeMovieClip(n:Number):void{
			// 位置を記憶
			position = n;
			
			switch (n){
				case 11:
					mc.getChildByName("image").x = 0;
					mc.getChildByName("image").y = 0;
					break;
				case 12:
					mc.getChildByName("image").x = -24;
					mc.getChildByName("image").y = 0;
					break;
				case 13:
					mc.getChildByName("image").x = -48;
					mc.getChildByName("image").y = 0;
					break;
				case 21:
					mc.getChildByName("image").x = 0;
					mc.getChildByName("image").y = -32;
					break;
				case 22:
					mc.getChildByName("image").x = -24;
					mc.getChildByName("image").y = -32;
					break;
				case 23:
					mc.getChildByName("image").x = -48;
					mc.getChildByName("image").y = -32;
					break;
				case 31:
					mc.getChildByName("image").x = 0;
					mc.getChildByName("image").y = -64;
					break;
				case 32:
					mc.getChildByName("image").x = -24;
					mc.getChildByName("image").y = -65;
					break;
				case 33:
					mc.getChildByName("image").x = -48;
					mc.getChildByName("image").y = -64;
					break;
				case 41:
					mc.getChildByName("image").x = 0;
					mc.getChildByName("image").y = -96;
					break;
				case 42:
					mc.getChildByName("image").x = -24;
					mc.getChildByName("image").y = -96;
					break;
				case 43:
					mc.getChildByName("image").x = -48;
					mc.getChildByName("image").y = -96;
					break;
				default:
					mc.getChildByName("image").x = -24;
					mc.getChildByName("image").y = -66;
					position = 32;
					break;
			}
		}
		
		
	}
}

まったく関係ないけどRPGツクールアドバンスは名作だと思う。
次回はそろそろサーバーと連携。
今回使用しているドット絵はREFMAP様が配布しているフリー画像素材を使用してます。ゲームからデータを取り出しての2次使用は禁止されています。詳しくはこちらを参考ください。