HSPコンテスト2009 全体の処理形態を考察してみた



まずは全体をどういう様子で回していくかを考えることにする。

MainLoop

定番的なメインループを実装する。
これはゲーム中の流れを止めることなく処理を続けるというものです。
ループを1週するのを1フレームという単位で呼ばれています。

TITLE "雲色の風"

gosub *Init

repeat
	gosub *MainLoop

	stick KEY_STATE
	if KEY_STATE&128 : break

	await 10
loop

end
//--------------------------------------------------------
//	初期化
//--------------------------------------------------------
*Init
	//----------------------------------------------------
	// KEY	init
	//----------------------------------------------------
	KEY_STATE = 0
	
return
//--------------------------------------------------------
//	メインループ
//--------------------------------------------------------
*MainLoop
return



stickはキー入力を確認するもので、各キーが各ビットに対応しています。
ESCは7ビット目に当てはめられています。(128=2^7)
理論和をとれば一目瞭然ですね。


repeatで永久ループさせているのですが、ESCを押したときだけループを抜けます。
また、awaitを入れているのはwindowsに処理を返しているためです。


PADには対応してないの?とかfpsどーなの?とかありますけど、それは後ほど。



SequenceSystem

ゲームの流れを考えると画面単位でまとめると分かりやすい。
例えば、タイトル画面、戦闘画面、会話画面、ゲームオーバー画面などである。


そこで、状態遷移の変数[SEQUENCE]を用意する。
これによって各画面の処理へと分岐することを考える。


title.hsp

//============================================================
//	TITLE SEQUENCE
//============================================================
//------------------------------------------------------------
//	Constructor
//------------------------------------------------------------
*TitleStateConstructor
return
//------------------------------------------------------------
//	Destructor
//------------------------------------------------------------
*TitleStateDestructor
return
//------------------------------------------------------------
//	update
//------------------------------------------------------------
*TitleStateUpdate
return
//------------------------------------------------------------
//	draw
//------------------------------------------------------------
*TitleStateDraw
return



main.hsp

//========================================================
//	 TITLE   雲色の風
//	SUMMARY  横スクロールSTG
//	VERSION  0.01
//	CREATED  千枝
//========================================================
goto *Start
#include "title.hsp"

//---------------------------------------------------------
//	開始地点
//---------------------------------------------------------
*Start
TITLE "雲色の風"

gosub *Init

repeat
	gosub *MainLoop

	stick KEY_STATE
	if KEY_STATE&128 : break

	await 10
loop

end
//--------------------------------------------------------
//	初期化
//--------------------------------------------------------
*Init
	//----------------------------------------------------
	// KEY	init
	//----------------------------------------------------
	KEY_STATE = 0

	//----------------------------------------------------
	// SEQUENCE init
	//----------------------------------------------------
	SEQUENCE_STATE = -1
	NEXT_SEQUENCE_STATE = 0

	//----------------------------------------------------
	// Screen init
	//----------------------------------------------------
	screen 0,640,480,0
	buffer 1,640,480,0

	gsel 0
return
//--------------------------------------------------------
//	メインループ
//--------------------------------------------------------
*MainLoop
	gosub *nextState
	
	gosub *Update
	gosub *Draw
return
//--------------------------------------------------------
//	更新
//--------------------------------------------------------
*Update
	if SEQUENCE_STATE = 0 : gosub *TitleStateUpdate
return
//--------------------------------------------------------
//	描写
//--------------------------------------------------------
*Draw
	redraw 0

	//----------------------------------------------------
	//	背景の初期化
	//----------------------------------------------------
	color 0,0,0 : boxf 0,0,640,480

	if SEQUENCE_STATE = 0 : gosub *TitleStateDraw

	redraw 1
return
//--------------------------------------------------------
//	更新
//--------------------------------------------------------
*nextState
	if NEXT_SEQUENCE_STATE = SEQUENCE_STATE : return


	if NEXT_SEQUENCE_STATE = 0 : gosub *TitleStateConstructor

	if SEQUENCE_STATE = 0 : gosub *TitleStateDestructor


	SEQUENCE_STATE = NEXT_SEQUENCE_STATE
return



このシステムでは、NEXT_SEQUENCEに次の状態のIDを入れると遷移が発生します。
初期状態では、NEXT_SEQUENCE=0となっていて
0の場合は、各種TitleStateの処理へ移っていることがわかると思います。
また、NEXT_SEQUENCEをわざわざ用意したのはConstructorとDestructorを作るためです。
Constructorは、自分のステータスになる瞬間に処理が行われます。
Destructorは、自分のステータスが終わる瞬間に処理が行われます。


また、UpdateとDrawに処理を分けたのは
後々フレームスキップを導入しようと考えているためです。


redrawは、仮想画面にフォーカスを移して実際の画面を更新させない命令です。
これを行わないと描写が間に合わなくて「ちらつき」という現象が発生します。




状態が増えるごとに各種設定することが多そうな予感。
もっと簡単な状態遷移の方法を考えたい。