- SHIORI - チュートリアル

ステップ0 キャラクタを動かしてみよう


0.テーマ設定

 絵は出せるようになりました。
 ということで、次はキャラを動かしてみましょう。
 今回は、我がZOUNDSの絵を引っ張ってきてみました。 これで、自機キャラを動かしてみましょう。

ZOUNDSの自機を動かす。

 前回2回は、いちいちファイルの中身まで全部解説しましたが、ここからは、あんまりそういった必要もないので、適当に飛ばして解説していきます。


1.必要なファイルとディレクトリを準備しよう

 前回2回と同じ手順で、ファイルやディレクトリを用意してください。
 用意できたら、前回2回でやった手順で、上の絵が出るところまで組んでみましょう。
 注意すべきなのは、今回は「背景」と「キャラクタ」が画面上にいて、「背景」が「キャラクタ」よりも手前に表示されてはいけない、という制約を、きちんと組み込むことです。
 まぁ具体的には、描画レイヤーを分けるというだけのハナシなのですけどね。

 とりあえず、上の絵までの設定は、以下のようになりますね。

config.hrn
# ----------------------------------------------------------------
#     - SHIORI -   チュートリアル3
# ----------------------------------------------------------------

# 描画デバイス設定
&SetLayers( 5 )


# ====================
#   ビットマップ登録
# ====================
#
# <<< 自機 >>>
&RegistBitmap	JIKI , ( 'sample03/bmp/jiki.bmp' , 0 )

# <<< 背景 >>>
&RegistBitmap	SPACE , ( 'sample03/bmp/space.bmp' , 0 )


# ======================
#   パレットの読み込み
# ======================
&RegistRQPalet MAINPALETTE ( 'sample03/bmp/zounds.rq' , 0 , 255 )


# ==================
#   スプライト登録
# ==================

# <<< ビックバイパー >>>
&RegistSprite	JIKI (  0,0 , 32-1,32-1 ) , ( 32/2,32/2 )
&RegistSprite	JIKI ( 32,0 , 64-1,32-1 ) , ( 32/2,32/2 )
&RegistSprite	JIKI ( 64,0 , 96-1,32-1 ) , ( 32/2,32/2 )


# ====================
#   グラフィック登録
# ====================
&RegistGraphic SPACE ( 0,0 ) , ( 640,480 )

prop.hrn
#---------------------------------------------------------------------
#  - SHIORI - チュートリアル3
#---------------------------------------------------------------------

#----------< 一般設定 >----------
#
&SetDimension	2

#----------< キャラクタ特性定義 >----------
#
# ================================================================================
#   自機
# ================================================================================
&DefineJiki( JIKI , 0,0,2 ){

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

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

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

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


# ================================================================================
#   背景グラフィック
# ================================================================================
&DefineGRP( SPACE , 0,0,2 ){
	&Axis			( X , Y )					# オブジェクトの座標系
	&LoopMode		( TRUE , TRUE )

	# レイヤー指定
	&Draw( 0 ){
		# 配列指定
		DIMENSION	= 1
		VALUES		= {
			( 4 , 1 )							# レイヤー番号
		}
	}

	# 描画パターン指定
	&Draw( 1 ){
		# 配列指定
		DIMENSION	= 1
		VALUES		= {
			( 0 , 1 )							# グラフィックページ番号 , カウント
		}
	}

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

comset.hrn
#---------------------------------------------------------------------
#   - SHIORI - チュートリアル3
#---------------------------------------------------------------------

#----------< 一般設定 >----------
#
&SetDimension	2

#----------< コマンドセット構築 >----------
#
# ====================================================================
#   ステージの初期化
# ====================================================================
# -----< 初期化開始 >-----
#
&CountEvent( INITIALIZE_STAGE ){
	COUNT = 0
} , REFLECT_PALETTE

# -----< パレットを適用する >-----
#
&ReflectPalette( REFLECT_PALETTE ){
	PAGE		= MAINPALETTE
	STARTINDEX	= 0
	ENDINDEX	= 255
	TARGETPAGE	= SCREENPALET
	TARGETINDEX	= 0
} , REQUEST_GRP

# -----< 背景グラフィックの出現 >-----
#
&RequestGRP( REQUEST_GRP ){
	OBJECT			= SPACE
	ATTRIBUTE = {
		EXIST		= TRUE
		POS			= ( 0,0 )
	}
} , REQUEST_JIKI

# -----< 自機の出現 >-----
#
&RequestJiki( REQUEST_JIKI ){
	OBJECT			= JIKI
	ATTRIBUTE = {
		EXIST		= TRUE
		POS			= ( 320*64,320*64 )
	}
}

comset.hrn
#---------------------------------------------------------------------
#  - SHIORI - チュートリアル3
#---------------------------------------------------------------------

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

 あとは敵配置マップ定義がありますが、どうせ空なので必要ないでしょう。
 では、こいつに動きをつけてみましょう。


2.キャラにコマンドセットをアタッチする

 キャラクタを動かすためには、そのキャラクタに、「動かす」という定義を組み込んでやらねばなりません。
 そういった場合は、おおきく分けて2つ方法があるのですが、ここではその1つめの方法、「コマンドセット」を使う方法を解説します。

 キャラクタの特性にコマンドセットをアタッチすると、画面上に出現した各キャラクタは、毎フレームそのコマンドセットを実行します。 これを利用して、キャラクタに動きを持たせます。

 まずは、特性に対して、その「動き」をアタッチしましょう。

 prop.hrnファイル内の、自機の定義の最後あたりに、こんな風に行を追加します。

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

	# -----< コマンドセット登録 >-----
	#
	&AddComSet( POSITIONING_JIKI )
}

 最後の行で、&AddComSet コマンドを使って、「POSITIONING_JIKI」というコマンドセットを、キャラクタにアタッチしています。 これで、ここで定義した特性「JIKI」で出現したキャラクタは、毎フレーム POSITIONING_JIKI コマンドセットを実行することになります。

 ところで、、POSITIONING_JIKI というコマンドセット自体は、まだ記述していませんが・・・ それは、これから記述するのです。


3.キャラを動かすコマンドセットを記述する

 とりあえず、キャラクタを一定速度で、上方向に動かしてみましょう。
 一定速度で上方向に動かすと、まぁ画面から外れて外に出ていってしまうワケですが、まぁそういった動きを作ってみましょう。

 キャラクタを動かすためのコマンドセット POSITIONING_JIKI を定義するのでした。
 上方向に一定速度で動かすには、以下のような記述を、prop.hrn に追加します。

prop.hrn
	(ここより上は略)

# ================================================================================
#   自機の動き設定
# ================================================================================

&Nop( POSITIONING_JIKI ) , POSITIONING_JIKI_VEL

# 一定速度の移動
&SetVel( POSITIONING_JIKI_VEL ){
	AXIS	= 1
	VALUE	= 64*(-1)
}

 それぞれ、1行ずつ解説していきましょうか。

何もしないコマンド
&Nop( POSITIONING_JIKI )

 ここで、特性定義でアタッチした POSITIONING_JIKI を定義しています。
 このコマンドは、「何もしないコマンド」と書いてあるとおり、何もしません。 単に、なにもせずに、次のコマンドに処理を渡します。

 実際に動かすためのコマンドは、次のコマンド「POSITIONING_JIKI_VEL」で定義しているのですが、、、 なぜ最初に &Nop として、ダミーのコマンドを噛ませてあるか、なんてことは、自分で色々とモノを書いていくと分かってくると思います。

 

キャラクタの速度属性に値を設定する
&SetVel( POSITIONING_JIKI_VEL )

 このコマンドは、キャラクタに対して「速度」を設定するコマンドです。
 ここでは、コマンドの属性として、軸方向に「1(Y方向)」,値に-64を指定していますので、1フレームあたり1ドットずつ上に動く速度を与えるということになります。

 ・・・ところで、上で「軸方向1(Y方向)」と書きましたが、厳密には「Y方向」というのは、表現として正しくありません。

 この AXIS 属性で指定する値というのは、そのキャラクタの速度を表す「速度ベクタ」があったとして、そのベクタの何番目の値に値を設定するか、ということを意味します。
 従って、特性定義で定義した &Axis コマンドが 「( X , Y )」 であれば、この指定でY方向に動くことになるのですが、仮に「( Y,X )」だったりすると、これはX方向に動くことになります。


4.じゃ、動かしてみようか。

 では、動かしてみましょう。
 実行した瞬間から、自機は上の方向に移動して、そのうち画面上から去っていったでしょうか? もしうまくいってなければ、どっかに何かの間違いがありますね。


5.も少し凝ってみよう。

 単に等速で上に抜けるだけでは、つまらんなぁ。 ということで、、、 こいつを「等加速度運動」にしてみましょうか。
 等加速度運動にするには、コマンドセットの &SetVel コマンドを、&SetAcc に変えてやればOKです。

prop.hrn
	(ここより上は略)

# ================================================================================
#   自機の動き設定
# ================================================================================

&Nop( POSITIONING_JIKI ) , POSITIONING_JIKI_ACC

# 一定速度の移動
&SetAcc( POSITIONING_JIKI_ACC ){
	AXIS	= 1
	VALUE	= -1
}

 で、動かしてみましょう。

 なんかこう、単に動いているだけではなくて、こうやって、ちょっと加速度をつけるだけで、画面から受ける印象ってのは、まるで違ってきますね。 こーゆー細かい配慮を、ゲーム全体で徹底して行うというのは、ゲームの見た目を向上させるのに、絶大なパワーを発揮します。 「魅せる」ためのテクニックと言っても良いかもしれないですね。


.も少し違う動きを、、、

 上に抜けるだけ、という例より、もう少し難しい例を取り扱ってみましょうか。
 次は、、、
右,下,左,上,右,下,左,上,右,下,左,上,・・・という風にして、延々とくるくる動くような、そんな動きを実現してみましょう。

 記述の方法はいくらかあるとは思うのですけど、例としては、こんなの。

prop.hrn
	(ここより上は略)

# ================================================================================
#   自機の動き設定
# ================================================================================

&Nop( POSITIONING_JIKI ) , POSITIONING_JIKI_AUTOMOVE_01

# 四角い軌道を描いて動く
#
# <<< カウント0で、右方向に速度を与える >>>
#
&CountEvent( POSITIONING_JIKI_AUTOMOVE_01 ){
	COUNT = 0
} , POSITIONING_JIKI_AUTOMOVE_02 , POSITIONING_JIKI_AUTOMOVE_11

&StopMove( POSITIONING_JIKI_AUTOMOVE_02 ) , POSITIONING_JIKI_AUTOMOVE_03
&SetVel( POSITIONING_JIKI_AUTOMOVE_03 ){
	AXIS	= 0
	VALUE	= 64*(1)
}
#
# <<< カウント60で、下方向に速度を与える >>>
#
&CountEvent( POSITIONING_JIKI_AUTOMOVE_11 ){
	COUNT = 60
} , POSITIONING_JIKI_AUTOMOVE_12 , POSITIONING_JIKI_AUTOMOVE_21

&StopMove( POSITIONING_JIKI_AUTOMOVE_12 ) , POSITIONING_JIKI_AUTOMOVE_13
&SetVel( POSITIONING_JIKI_AUTOMOVE_13 ){
	AXIS	= 1
	VALUE	= 64*(1)
}
#
# <<< カウント120で、左方向に速度を与える >>>
#
&CountEvent( POSITIONING_JIKI_AUTOMOVE_21 ){
	COUNT = 120
} , POSITIONING_JIKI_AUTOMOVE_22 , POSITIONING_JIKI_AUTOMOVE_31

&StopMove( POSITIONING_JIKI_AUTOMOVE_22 ) , POSITIONING_JIKI_AUTOMOVE_23
&SetVel( POSITIONING_JIKI_AUTOMOVE_23 ){
	AXIS	= 0
	VALUE	= 64*(-1)
}
#
# <<< カウント180で、上方向に速度を与える >>>
#
&CountEvent( POSITIONING_JIKI_AUTOMOVE_31 ){
	COUNT = 180
} , POSITIONING_JIKI_AUTOMOVE_32  , POSITIONING_JIKI_AUTOMOVE_41

&StopMove( POSITIONING_JIKI_AUTOMOVE_32 ) , POSITIONING_JIKI_AUTOMOVE_33
&SetVel( POSITIONING_JIKI_AUTOMOVE_33 ){
	AXIS	= 1
	VALUE	= 64*(-1)
}

&CountEvent( POSITIONING_JIKI_AUTOMOVE_41 ){
	COUNT = 240
} , POSITIONING_JIKI_AUTOMOVE_42

&StopMove( POSITIONING_JIKI_AUTOMOVE_42 ) , POSITIONING_JIKI_AUTOMOVE_43
&SetVel( POSITIONING_JIKI_AUTOMOVE_43 ){
	AXIS	= 0
	VALUE	= 64*(1)
} , POSITIONING_JIKI_AUTOMOVE_44

&RewindCount( POSITIONING_JIKI_AUTOMOVE_44 ){
	COUNT = 0
}

 いきなり長くなりましたなぁ( ̄▽ ̄)
 とはいえ、これは、「右」「下」「左」「上」と、同じようなことを4回くりかえし記述しているだけなので、怖じ気づかないようにしてください。
 いや、本当に重要なのです、怖じ気づかない、ということは。

 さて。 解説です。

特定のカウントで実行されるコマンド
&CountEvent( POSITIONING_JIKI_AUTOMOVE_01 )

 このコマンドは、現在のカウントが指定したカウントかどうかを調べ、その真偽によって、次に繋がるリンク先コマンドセットを切り分けるというコマンドです。
 これで、自機キャラの速度を変更したい瞬間に、速度を変更するコマンドを発動する、ということが可能になります。

 このコマンドは、カウントが一致した場合は、最初に定義したリンクコマンドセットに処理が飛びますが、一致しない場合は、ふたつめのリンクコマンドセットに処理が飛びます。
 ここではこの機能を使って、「もしカウントが0でなかったら、60を調べる、それでもなければ120かどうかを調べる・・・」という処理を実現しています。

 

キャラクタの移動を停止するコマンド
&StopMove

 キャラクタに、各方向の速度を設定する前に、それまで持っていた速度を0に戻します。
 この &StopMove を使うと、速度と加速度を全て0にしてくれるので、こういった場合は、使うと便利です。

 

キャラクタに速度を設定するコマンド
&SetVel

 まぁこれは、上で解説したので、ここで説明する必要はないでしょう。

 

カウントを巻き戻すコマンド
&RewindCount

 このコマンドでは、キャラクタやステージのカウント値を巻き戻すことができます。(早送りも出来ますが。)
 ひととおり1回転分の動きが終わったら、カウントを0に戻して、処理を最初にもどしてやります。


7.じゃ、最後に、ジョイスティックで動かしてみようか

 ということで、そんな感じで、じゃぁこんどはジョイスティックで動かしてみましょうか。
 これまで解説してきた技術と同じ感じで実現できますので、考えてみてください。
 自分で書いて、悩んで、なんとゆーかコツとか掴むと良い感じです、はい。

 とりあえず注意点というか、解説してないこと一つだけ、気にとめておいてください。
 ジョイスティックからの入力を有効にするには、キャラクタの特性定義に、

   &UseInput TRUE

の記述が必須です。 これだけ注意して、考えてみてください。

 要するに、、、まずは移動を止めると。 で、ジョイスティックが入ったら、そっち方向に速度を与えると。 そういう処理でいいわけです。

 

 ということで、今回は、ここまでです。


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