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は、仮想画面にフォーカスを移して実際の画面を更新させない命令です。
これを行わないと描写が間に合わなくて「ちらつき」という現象が発生します。
状態が増えるごとに各種設定することが多そうな予感。
もっと簡単な状態遷移の方法を考えたい。