- SHIORI - チュートリアル

ステップ04 移動配列を使ってキャラを動かす


0.テーマ設定

 今回は、前にちょろっと出てきた「特性配列」と「配列ポインタ」を使って、キャラを動かしてみます。 こんな感じで。

ZOUNDSの敵キャラを、ちょろっと登場させてみました。
どうよ。


1.特性配列と配列ポインタに関する詳細

 まずは、今回取り扱う「特性配列」と「配列ポインタ」について、詳細を解説します。

 前にも述べたように、キャラクタの位置や速度は、「ベクタ」と呼ばれるもので管理されています。 そのベクタを複数並べてまとめて取り扱うのが、特性配列配列です。

 この特性配列上の、ひとつのベクタを指し示すのが、配列ポインタです。
 ちなみにこの配列ポインタは、ひとつのベクタを指し示す以外に、『そのベクタが何を意味するのか』という情報も持っています。

 ・・・さて。

 では、そんなことをふまえつつ、キャラクタの移動を表現する方法を考えてみましょう。

 たとえば、キャラクタを右方向にしばらく動かして、そのあと少し下方向に動かして、、、なんて動きを作るには、こんな風に考えていきます。

 まず、こんな配列を作ります。

(64, 0),(64, 0),(64, 0),(64, 0),(64, 0),(64, 0),(64, 0),(64, 0),(64, 0),(64, 0),
( 0,64),( 0,64),( 0,64),( 0,64),( 0,64),( 0,64),( 0,64),( 0,64),( 0,64),( 0,64)

 右方向を向いた相対移動量 (64,0) を10個、そのあとに、下方向を向いた相対移動量 (0,64)を10個並べてみました。

 こいつに、配列ポインタを載せてやります。

[配列ポインタ](現在0番目を指してる。ちなみにこのベクタは、移動量を表す)
  
(64, 0),(64, 0),(64, 0),(64, 0),(64, 0),(64, 0),(64, 0),(64, 0),(64, 0),(64, 0),
( 0,64),( 0,64),( 0,64),( 0,64),( 0,64),( 0,64),( 0,64),( 0,64),( 0,64),( 0,64)

 画面上に現れたキャラクタは、各フレームの最初に、配列ポインタが指し示しているベクタを取得します。
 で、そのベクタが意味するところを確認して、その意味に従って、なんらかの処理をします。

 この場合、配列ポインタが取ってくるベクタは「相対移動量」を表すワケです。 キャラクタは、それに対してアクションを起こすワケですから、、、たとえば最初の位置では、(64,0) のだけの移動をすることになるワケですね。

 配列ポインタは、各フレームでひとつずつ、右方向に移動させていくことにします。

第0frame 第1frame 第2frame  ...以下略
   ↓      ↓      ↓
(64, 0),(64, 0),(64, 0),(64, 0),(64, 0),(64, 0),(64, 0),(64, 0),(64, 0),(64, 0),
( 0,64),( 0,64),( 0,64),( 0,64),( 0,64),( 0,64),( 0,64),( 0,64),( 0,64),( 0,64)

 このようにすると、結局キャラクタの動きはどうなるかというと、、、最初の10フレームは (64,0) の方向に動き、そのあとの10フレームは(0,64)の方向に動く、ということになるワケです。

 キャラクタの移動を表現するには、まぁだいたいこんな流れでやってやればOKです。

 ところで。

 説明が前後しますが、『配列ポインタが、配列上でどのように移動するか』という情報は、特性配列が、その付加情報として持っています。
 上の例では、『配列ポインタは、毎フレーム1ずつ右に動く』ということでした。 これは、特性配列が、『この配列上にいるポインタは、毎フレーム1ずつ右に動いていきます』という付加情報を持っているということなワケです。


2.じゃ、書いてみよっか。

 とりあえず、チュートリアル ステップ03の、最初の状態のデータを持ってきてください。
 こいつに改変を加えていくとしましょう。

 ステップ03の最初の状態は、

これです。
真ん中に自機がいるだけ。 こいつを動かすとしましょう。

 特性配列を使うので、編集するのは、特性定義ファイルです。 こんな風に書いてみましょう。

# ================================================================================
#   自機
# ================================================================================
&DefineJiki( JIKI , 1,0,2 ){

	# -----< 属性 >-----
	#
	&Axis			( X , Y )					# オブジェクトの座標系

	# -----< 移動パターン指定 >-----
	#
	&Move( 0 ){
		DEPENDS		= ( INCREMENT , 1 , + )

		# 配列指定
		VALUES		= {
			  MARK( TOP )
			, (    64*1 ,       0 , 60 )
			, (       0 ,    64*1 , 60 )
			, ( 64*(-1) ,       0 , 60 )
			, (       0 , 64*(-1) , 60 )
			, JUMP( TOP )
		}
	}

	# -----< 描画レイヤー指定 >-----
	#
	&Draw( 0 ){
		# 配列指定
		DIMENSION	= 1
		VALUES		= {
			( 1 , 1 )
		}
	}

	# -----< 描画パターン指定 >-----
	#
	&Draw( 1 ){
		# 配列指定
		VALUES		= {
			( BMP( JIKI ) , 1 , 1 )
		}
	}

	# -----< ポインタ関連 >-----
	#
	&MovePointer	( 0 , VEL )			# 0 番目のラインを移動パターンとして認識するポインタ
	&DrawPointer	( 0 , LAYER )		# 0 番目のラインを描画レイヤーとして認識するポインタ
	&DrawPointer	( 1 , PATTERN )		# 1 番目のラインをパターンとして認識するポインタ
}

赤く書いたところが、変更を加えるところです。

 

&DefineJiki( JIKI , 1,0,2 )

 移動配列をひとつ作るので、ふたつ目の引数が1になります。

 

DEPENDS = ( INCREMENT , 1 , + )

 ここで、特性配列の付加情報を設定しています。
 この設定は、以下のようなことを意味しています。

 『配列ポインタが指し示す位置は、毎回1ずつ進んでいきます。』

 つまり、配列ポインタの位置は、0,1,2,3,4....となっていくワケです。

 

&MovePointer( 0 , VEL )

 これで、移動配列ポインタを、特性配列上に載せています。
 0 番目の特性配列に、ポインタを配置します。 そのポインタが指し示すベクタは、移動速度を意味します。

 

MARK( TOP ) , JUMP( TOP )

 特性配列上には、MARK , JUMP , CHANGELINE , DISAPPEAR といったような、マクロのようなものを配置することができます。 これらは、配列ポインタの制御や、キャラクタの制御に使用することができます。 ちなみに、これを『配列コマンド』と言います。

 ここで使っているのは、MARK と JUMP ですね。
 MARK は文字通り、配列上にマークを設定します。
  JUMP コマンドは、配列ポインタに対して効くコマンドです。 配列ポインタはここにさしかかると、強制的に指定したマーク位置まで移動させられます。
 この場合は、配列情報の最後に JUMP コマンドがついています。 ポインタはここに来ると、先頭に戻りますので、つまり、ポインタは永遠に先頭から最後まで辿るという動きを繰り返すということになるワケですね。


3.動かしてみよう。

 じゃ、うごかしてみましょう。
 自機が、右→下→左→上→右 の順に動いたでしょうか。 動かなければ、なんか間違ってます。


4.例題その2〜その4

説明すべきことは、だいたい説明しました。
あとは、いくらか具体例を挙げてみます。 内容は、自分で考えてみてください。

 

※同じ動きを、別の方法でやってみる例

# ================================================================================
#   自機
# ================================================================================
&DefineJiki( JIKI , 1,0,2 ){

	# -----< 属性 >-----
	#
	&Axis			( X , Y )					# オブジェクトの座標系

	# -----< 移動パターン指定 >-----
	#
	&Move( 0 ){
		DEPENDS	= ( INCREMENT , 1 , + )
		MODE		= VECTOR

		# 配列指定
		VALUES		= {
			  MARK( TOP )
			, (    64*1 ,       0 , 60 )
			, (       0 ,    64*1 , 60 )
			, ( 64*(-1) ,       0 , 60 )
			, (       0 , 64*(-1) , 60 )
			, JUMP( TOP )
		}
	}

	# -----< 描画レイヤー指定 >-----
	#
	&Draw( 0 ){
		# 配列指定
		DIMENSION	= 1
		VALUES		= {
			( 1 , 1 )
		}
	}

	# -----< 描画パターン指定 >-----
	#
	&Draw( 1 ){
		# 配列指定
		VALUES		= {
			( BMP( JIKI ) , 1 , 1 )
		}
	}

	# -----< ポインタ関連 >-----
	#
	&MovePointer	( 0 , POS )			# 0 番目のラインを移動パターンとして認識するポインタ
	&DrawPointer	( 0 , LAYER )		# 0 番目のラインを描画レイヤーとして認識するポインタ
	&DrawPointer	( 1 , PATTERN )		# 1 番目のラインをパターンとして認識するポインタ
}

 特性配列の付加情報 MODE を使って、&MovePointer の意味指定を POS にしてみた例。
 前の例が「速度を設定する」というアプローチだったのに対して、こっちは「キャラクタの位置をすこしずつずらす」という方法で動かしたりとかしてるワケです。

 

※特性配列上の、MARK とか JUMP を使う他に、CHANGELINE を使ってみた例。

# ================================================================================
#   自機
# ================================================================================
&DefineJiki( JIKI , 2,0,2 ){

	# -----< 属性 >-----
	#
	&Axis			( X , Y )					# オブジェクトの座標系

	# -----< 移動パターン指定 >-----
	#
	&Move( 0 ){
		DEPENDS		= ( INCREMENT , 1 , + )
		MODE		= VECTOR

		# 配列指定
		VALUES		= {
			  (    64*1 ,       0 , 60 )
			, (       0 ,    64*1 , 60 )
			, ( 64*(-1) ,       0 , 60 )
			, (       0 , 64*(-1) , 60 )
			, CHANGELINE( 1 , TRUE )
		}
	}

	# -----< 移動パターン指定 >-----
	#
	&Move( 1 ){
		DEPENDS		= ( INCREMENT , 1 , + )
		MODE		= VECTOR

		# 配列指定
		VALUES		= {
			  (    64*1 , 64*(-1) , 60 )
			, ( 64*(-1) , 64*(-1) , 60 )
			, ( 64*(-1) ,    64*1 , 60 )
			, (    64*1 ,    64*1 , 60 )
			, CHANGELINE( 0 , TRUE )
		}
	}

	# -----< 描画レイヤー指定 >-----
	#
	&Draw( 0 ){
		# 配列指定
		DIMENSION	= 1
		VALUES		= {
			( 1 , 1 )
		}
	}

	# -----< 描画パターン指定 >-----
	#
	&Draw( 1 ){
		# 配列指定
		VALUES		= {
			( BMP( JIKI ) , 1 , 1 )
		}
	}

	# -----< ポインタ関連 >-----
	#
	&MovePointer	( 0 , POS )			# 0 番目のラインを移動パターンとして認識するポインタ
	&DrawPointer	( 0 , LAYER )		# 0 番目のラインを描画レイヤーとして認識するポインタ
	&DrawPointer	( 1 , PATTERN )		# 1 番目のラインをパターンとして認識するポインタ
}

 0番目の移動特性配列では、「右→下→左→上」という動きを定義しています。
 1番目の移動特性配列では、「右上→左上→左下→右下」という動きを定義しています。

 それぞれの移動配列の最後で、CHANGELINE( 1,TRUE )とか、CHANGELINE( 0,TRUE )とかやってます。これで、配列ポインタが乗っているライン番号を切り替えています。

 ちうことで、0番目の移動配列→1番目の移動配列→0番目の移動配列→ の順に、配列ポインタが特性配列を飛び移って動いていくワケです。
 これを使うと、なにげにいろいろ表現できます。

 

※ちょっと本番っぽい敵を出す例

 このページの最初に、画像で紹介した例です。
 こいつは、この絵の

赤で囲った部分を使って、敵を定義してます。 そのへんの抜粋は、まぁ省略します。

で。

# ================================================================================
#   雑魚 01
# ================================================================================
&DefineEnemy( ZAKO01 , 2,0,2 ){
	# -----< 属性 >-----
	#
	&Axis			( X , Y )					# オブジェクトの座標系
	&SetClipArea	( -64*64 , -64*64 ) , ( 64*(640+64) , 64*(480+64) )

	# -----< 移動パターン指定 >-----
	#
	&DefInt	Speed	= 64 * 8
	&Move( 0 ){
		DEPENDS		= ( INCREMENT , 1 , + )
		MODE		= VECTOR

		# 配列指定
		VALUES		= {
			  ( 0 + (0*$Speed/4) ,  -$Speed+(0*($Speed/4) ) , 40 )
			, ( 0 + (1*$Speed/4) ,  -$Speed+(1*($Speed/4) ) , 10 )
			, ( 0 + (2*$Speed/4) ,  -$Speed+(2*($Speed/4) ) , 10 )
			, ( 0 + (3*$Speed/4) ,  -$Speed+(3*($Speed/4) ) , 10 )
			, ( 0 + (4*$Speed/4) ,  -$Speed+(4*($Speed/4) ) , 200 )
			, DISAPPEAR
		}
	}

	# -----< 描画レイヤー指定 >-----
	#
	&Draw( 0 ){
		# 配列指定
		DIMENSION	= 1
		VALUES		= {
			( 1 , 1 )
		}
	}

	# -----< 描画パターン指定 >-----
	#
	&Draw( 1 ){
		# 配列指定
		DEPENDS		= ( INCREMENT , 1 , + )
		VALUES		= {
			  MARK( TOP )
			, ( BMP( ZAKO ) , 0 , 1 ) , ( BMP( ZAKO ) , 1 , 1 )
			, ( BMP( ZAKO ) , 2 , 1 ) , ( BMP( ZAKO ) , 3 , 1 )
			, ( BMP( ZAKO ) , 4 , 1 ) , ( BMP( ZAKO ) , 5 , 1 )
			, JUMP( TOP )
		}
	}

	# -----< ポインタ関連 >-----
	#
	&MovePointer	( 0 , POS )			# 0 番目のラインを移動パターンとして認識するポインタ
	&DrawPointer	( 0 , LAYER )		# 0 番目のラインを描画レイヤーとして認識するポインタ
	&DrawPointer	( 1 , PATTERN )		# 1 番目のラインをパターンとして認識するポインタ
}


# ================================================================================
#   雑魚 02
# ================================================================================
&DefineEnemy( ZAKO02 , 2,0,2 ){
	# -----< 属性 >-----
	#
	&Axis			( X , Y )					# オブジェクトの座標系
	&SetClipArea	( -64*64 , -64*64 ) , ( 64*(640+64) , 64*(480+64) )

	# -----< 移動パターン指定 >-----
	#
	&DefInt	Speed	= 64 * 8
	&Move( 0 ){
		DEPENDS		= ( INCREMENT , 1 , + )
		MODE		= VECTOR

		# 配列指定
		VALUES		= {
			  ( 0 - (0*$Speed/4) ,  -$Speed+(0*($Speed/4) ) , 40 )
			, ( 0 - (1*$Speed/4) ,  -$Speed+(1*($Speed/4) ) , 10 )
			, ( 0 - (2*$Speed/4) ,  -$Speed+(2*($Speed/4) ) , 10 )
			, ( 0 - (3*$Speed/4) ,  -$Speed+(3*($Speed/4) ) , 10 )
			, ( 0 - (4*$Speed/4) ,  -$Speed+(4*($Speed/4) ) , 200 )
			, DISAPPEAR
		}
	}

	# -----< 描画レイヤー指定 >-----
	#
	&Draw( 0 ){
		# 配列指定
		DIMENSION	= 1
		VALUES		= {
			( 1 , 1 )
		}
	}

	# -----< 描画パターン指定 >-----
	#
	&Draw( 1 ){
		# 配列指定
		DEPENDS		= ( INCREMENT , 1 , + )
		VALUES		= {
			  MARK( TOP )
			, ( BMP( ZAKO ) , 0 , 1 ) , ( BMP( ZAKO ) , 1 , 1 )
			, ( BMP( ZAKO ) , 2 , 1 ) , ( BMP( ZAKO ) , 3 , 1 )
			, ( BMP( ZAKO ) , 4 , 1 ) , ( BMP( ZAKO ) , 5 , 1 )
			, JUMP( TOP )
		}
	}

	# -----< ポインタ関連 >-----
	#
	&MovePointer	( 0 , POS )			# 0 番目のラインを移動パターンとして認識するポインタ
	&DrawPointer	( 0 , LAYER )		# 0 番目のラインを描画レイヤーとして認識するポインタ
	&DrawPointer	( 1 , PATTERN )		# 1 番目のラインをパターンとして認識するポインタ
}

 &SetClipArea で、キャラの存在可能範囲を指定してます。
 まぁ、画面から外れたら消えて欲しいし。

 この例では、配列ポインタ云々を、描画パターンのアニメーションにも使ってます。 理屈は同じです。
 で、この敵を、ボタンが押された瞬間に出すようにしてみましょう。

comset.hrn
# -----< 雑魚出現 01 >-----
#
&JoyButtonPressedEvent( APPEAR_ZAKO_01 ){
	BUTTON	= 0
} , DO_APPEAR_ZAKO_01L

&RequestEnemy( DO_APPEAR_ZAKO_01L ){
	OBJECT	= ZAKO01
	ATTRIBUTE = {
		EXIST	= TRUE
		POS		= ( 64*100 , 64*480 )
	}
} , DO_APPEAR_ZAKO_01R

&RequestEnemy( DO_APPEAR_ZAKO_01R ){
	OBJECT	= ZAKO02
	ATTRIBUTE = {
		EXIST	= TRUE
		POS		= ( 64 * ( 640 - 100) , 64*480 )
	}
}

 

event.hrn
#---------------------------------------------------------------------
#  - SHIORI - チュートリアル4
#---------------------------------------------------------------------

#----------< カウント駆動イベント >----------
#
&AddComSet( INITIALIZE_STAGE )


#----------< スティックイベント >----------
#
&AddComSet( APPEAR_ZAKO_01 )

ボタンを押すと、キャラが出る。 なんか本番のゲームっぽいモノには見える。



サンプルスクリプトのダウンロード