HSPコンテスト2009- FPSを整えてみた

STGにおいてFPSの概念は重要です。
FPSが不安定だとゲームスピードが変わるので難易度が変わってしまいます。
(詳しくは「FPS(frame per second)を整える方法」)

d3module

d3module は、HSP の標準機能のみで簡単な 3D グラフィックを描画するためのモジュールです。 


3Dを扱うモジュールなんですが、ms単位の時間を取得できるとのことでこれを使います。
後で背景に3Dを使おうと思っていたので丁度いいかも。


実装

#const FLAME 16.666
//--------------------------------------------------------
//	初期化
//--------------------------------------------------------
*Init
	
	//----------------------------------------------------
	// KEY	init
	//----------------------------------------------------
	KEY_STATE = 0

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

	//----------------------------------------------------
	//	TIMER init
	//----------------------------------------------------
	CONST_TIME = d3timer()
	TIME = 0.0

	//----------------------------------------------------
	// Screen init
	//----------------------------------------------------
	screen 0,SCREEN_X,SCREEN_Y,0
	buffer 1,SCREEN_X,SCREEN_Y,0
	buffer 2,SCREEN_X,SCREEN_Y,0

	gsel 0

return
//--------------------------------------------------------
//	メインループ
//--------------------------------------------------------
*MainLoop
	
	gosub *nextState

	gosub *KeyInput : if KEY_STATE & KEY_ESCAPE : goto *Exit

	//---------------------------------------------------
	//	update
	//---------------------------------------------------
	gosub *Update

	//---------------------------------------------------
	//	draw
	//---------------------------------------------------
	if d3timer() < CONST_TIME + int(FLAME+TIME) : gosub *Draw

	//----------------------------------------------------
	//	FPS
	//----------------------------------------------------
	while d3timer() < CONST_TIME + int(FLAME+TIME)
	await 0
	wend
	
	TIME = TIME + FLAME

return

解説


1フレーム(ループ)当たりFLAME(16.666ms)を割り当てている。
前回分でオーバーした場合は描写をスキップして切り抜ける。(一番時間のかかる処理は描写)


FLAME=16.666と小数点なのが問題で、16では短すぎるし、17では長すぎる。
この時、小数部分と整数部分を切り離すことが必要になってくる。


そこで、時間の絶対位置を設定している。(全てはCONST_TIME+T秒で表現する)

処理後、時間がCONST_TIME+(N*FLAME)の時、次のフレームは(CONST_TIME+((N+1)*FLAME))まで


16.666→16ms 33.332→33ms 49.998→49ms 66.664→66ms 83.310→83ms
16 →16ms 32 →32ms 48 →48ms 64 →64ms 80 →80ms
17 →17ms 34 →34ms 51 →51ms 68 →68ms 85 →85ms


実装ではTIMEを浮動少数にしているため、式評価の時は切捨てが発生するが演算時には切捨てが発生しないので、誤差が蓄積されないという利点を持ち合わせている。




若干、FPSとは関係ない部分もあるが気にしないこと。