ゲームを作る際によく出てくる処理としてキー入力やFPS調整があります。
簡単に扱えるモジュールを作りましょう。
誰得!!?
目標FPSを少数単位で設定できるようになりました。
//--"keyFPS.hsp" #ifndef keyFPS #module keyFPS #uselib "winmm.dll" #cfunc keyFPStimer__ "timeGetTime" #deffunc manage_keyFPS__ //FPS変更 if fps ! prefps{ prefps = fps //新たなFPSでのタイムテーブルを作成 pn = table_num lpoke b gosa = 99999. sdim table, fps * FPStime repeat limit(fps * FPStime, 1, 65535), 1 a = 1000. * cnt / fps poke table, cnt - 1, b + a b = 0 - a if gosa > a + b{ gosa = a + b table_num = cnt } loop if pn ! table_num{ sdim time_record, table_num lpoke fps_counter lpoke total_time tm = 1000. * table_num } } i = fps_counter \ table_num fps_counter+ //FPS調整(ウェイトを行う) et = pt + peek(table, i) ; 今回の終了予定時刻 at = et - keyFPStimer__() ; 余裕時間 await at - 1 ; (余裕時間-1)だけ待って *@: if et > keyFPStimer__(): await: goto *@b ; 残りはawaitだけでループを回して時刻を合わせる apt = limit(stat - pt, 0, 255) ; 前回から今回までの経過時間 pt = stat ; 今の時間を記録 //FPS計測 if fps_counter > table_num{ total_time += apt - peek(time_record, i) cfps = tm / total_time }else{ total_time += apt cfps = 1000. * fps_counter / total_time } poke time_record, i, apt //マウス位置取得 w = ginfo(10) - ginfo(12) >> 1 mx = ginfo(0) - ginfo(4) - w my = ginfo(1) - ginfo(5) - ginfo(11) + ginfo(13) + w //キー取得 if ginfo(2) >= 0{ repeat max dup key, keys(cnt) dup c, count(key) getkey j, key if j{ if c > 0{ c+ }else{ if flag(key){ c- }else{ c = 1 } } }else{ lpoke flag(key) if c > 0{ c = -1 }else{ c- } } loop }else{ repeat max dup key, keys(cnt) dup c, count(key) if c > 0{ if type(key) = 2{ getkey j, key if j{ c+ }else{ c = -1 flag(key)+ } }else: if type(key) = 1{ getkey j, key if j{ c+ }else{ c = -1 } }else: if type(key): else{ c = -1 } }else{ if type(key) = 2{ c- getkey j, key if j: else: flag(key)+ }else: if type(key) = 1{ getkey j, key if j{ c = 1 }else{ c- } }else: if type(key): else{ c- } } loop } return #deffunc addkey__ int p1, int p2 if count(p1) || p1 <= 0 || p1 >= 256: return keys(max) = p1: max+ type(p1) = p2 lpoke flag(p1) if ginfo(2) >= 0 || p2 = 1{ getkey i, p1 count(p1) = (i * 2 - 1) << 1 }else{ count(p1) = -2 } return #deffunc delkey__ int p1 repeat max if keys(cnt) ! p1: continue lpoke count(p1) max- keys(cnt) = keys(max) break loop return #defcfunc getdbl_ms__ int p1, int p2 if ppt(p1) = pt: return peek(dbl_result, p1) if count(p1) = 1{ ppt(p1) = pt if pt - dbl_time(p1) <= p2{ lpoke dbl_time(p1) poke dbl_result, p1, 1 return 1 } dbl_time(p1) = pt } poke dbl_result, p1 return 0 #defcfunc getPhold__ int p1, int p2, int p3 if count(p1) = 1: return 1 #defcfunc gethold__ int p1, int p2, int p3 if count(p1) < p2: return 0 if p3: if (count(p1) - p2) \ p3: return 0 return 1 #deffunc init_keyFPS dim count, 256 dim ppt, 256 dim dbl_time, 256 sdim dbl_result, 256 FPStime = 3.0 fps = 60. pt = keyFPStimer__() return #global init_keyFPS //以下インターフェース ( このモジュールで使用可能になる全ての機能です ) #define global manage_keyFPS manage_keyFPS__ ; キーの取得とFPSの管理を行う #define global ctype ms_to_frame(%1) (%1 * fps@keyFPS / 1000) ; 現在のFPSにおいての ミリ秒→フレーム数を算出 #define global ctype frame_to_ms(%1) (1000 * %1 / fps@keyFPS) ; 現在のFPSにおいての フレーム数→ミリ秒を算出 //FPS関連 #define global setfps(%1) fps@keyFPS = limitf(%1, 3.92157, 360); 目標FPSを設定する #define global ctype getfpsf fps@keyFPS ; 目標FPS #define global ctype getrealfpsf cfps@keyFPS ; 実現FPS #define global ctype getfps (0 + fps@keyFPS) ; 目標FPS(整数) #define global ctype getrealfps (0 + cfps@keyFPS) ; 実現FPS(整数) #define global setFPStime(%1 = FPStime@keyFPS) FPStime@keyFPS = limitf(%1, 0.1, 9): dim prefps@keyFPS ; FPS精度を設定 #define global ctype getFPStime FPStime@keyFPS ; FPS精度 #define global ctype slowdown (at@keyFPS <= 0) ; 処理落ちしているかどうか #define global ctype frametime apt@keyFPS ; 前回のフレームにかかった時間 //キー状態取得関連 #define global ctype _getkey(%1) count@keyFPS(%1) ; キーの状態取得 //A宗向け(ms単位) #define global ctype getdbl_ms(%1, %2 = 0) getdbl_ms__(%1, %2) ; Double_Click #define global ctype gethold_ms(%1, %2 = 0, %3 = 0) gethold__(%1, ms_to_frame(%2), ms_to_frame(%3)) ; Hold #define global ctype getPhold_ms(%1, %2 = 0, %3 = 0) getPhold__(%1, ms_to_frame(%2), ms_to_frame(%3)) ; Press & hold //B宗向け(フレーム単位) #define global ctype getdbl(%1, %2 = 0) getdbl_ms__(%1, frame_to_ms(%2)) ; Double_Click #define global ctype gethold(%1, %2 = 0, %3 = 0) gethold__(%1, %2, %3) ; Hold #define global ctype getPhold(%1, %2 = 0, %3 = 0) getPhold__(%1, %2, %3) ; Press & Hold #define global ctype mousex_ mx@keyFPS ; マウスの位置x(画面外でも位置を取得) #define global ctype mousey_ my@keyFPS ; マウスの位置y(画面外でも位置を取得) //監視キー関連 #define global addkey(%1, %2 = 2) addkey__ %1, %2 ; 指定したキーを登録、%2 = 画面切り替え時の動作 #define global delkey(%1) delkey__ %1 ; 指定したキーを削除 #define global addkey_all(%1 = 2) repeat 255, 1: addkey__ cnt, %1: loop ; 全てのキー登録 #define global delkey_all repeat 255, 1: delkey__ cnt : loop ; 全てのキーを削除 //画面切り替え時の動作設定( 2がデフォルト値になっています ) ; 0 = 非アクティブ時には検出しない ; 1 = 非アクティブ時でも検出する ; 2 = アクティブ→非アクティブ 一旦離すまでは検出する ; 非アクティブ→アクティブ 一旦離すまでは検出しない ; アクティブ→非アクティブ→アクティブ 継続して検出されます。 ; 3 = 非アクティブ時は値が変化しない #define global setkey_type(%1, %2) type@keyFPS(%1) = %2 ; 画面切り替え時の動作設定を行う #define global ctype getkey_type(%1) type@keyFPS(%1) ; 画面切り替え時の動作設定を取得 #define global ctype keyFPStimer keyFPStimer__@keyFPS() ; Windows が起動してからの経過時間 ( timeGettime ) #endif //--"keyFPS.hsp" --End Of File
#ifndef __TEST posx = 300 posy = 250 c = $EEEEEE, $44FF99 addkey_all ; 全てのキーを登録 delkey 'T' ; Tキーは除外 repeat manage_keyFPS ; キーの取得とFPSの管理を行う。メインループの先頭で呼び出してください。 if _getkey(37) > 0: setfps getfpsf() - 1 ; FPSを上げます if _getkey(38) > 0: setfps getfpsf() + 0.0001 ; FPSを少し上げます if _getkey(39) > 0: setfps getfpsf() + 1 ; FPSを下げます if _getkey(40) > 0: setfps getfpsf() - 0.0001 ; FPSを少し下げます w = mousew if w > 0: setFPStime getFPStime() + 0.1 ; 精度を上げます if w < 0: setFPStime getFPStime() - 0.1 ; 精度を下げます if _getkey(1) = 1: posy += 40 ; 左クリック押した瞬間 if _getkey(1) = -1: posy -= 40 ; 右クリック離した瞬間 if getdbl_ms(2, 250): flag ^ 1 ; 右ダブルクリック(250ms以内に二回押されました) if getPhold_ms('Z',400,100): posx = limit(posx - 20, 0, 600) ; Z押した瞬間と長押し(400ms経つ時から、100ms毎に) if getPhold ('X', 9, 3): posx = limit(posx + 20, 0, 600) ; X押した瞬間と長押し(9フレーム後から、3フレーム毎に) if slowdown() & cnt \ 2: continue ; 処理落ちしているときは二回に一度描画スキップ redraw 2 color: boxf: pget 65535: pos 5, 5 mes "左右、上下キーでFPS変更、ホイールで精度変更" mes "目標FPS = " + getfpsf() mes "実現FPS = " + getrealfpsf() mes "精度 = " + getFPStime() mes "処理落ち = " + slowdown() mes mes "Tキーの状態 = " + _getkey('T') ; 登録されていないキーなので常に0です mes "スペースキーの状態 = " + _getkey(32) ; 押されている間は 1,2,3,4.... 押されていなければ, -1,-2,-3,-4.... mes mes "マウスX = " + mousex_() mes "マウスY = " + mousey_() mes mes "クリック → 上下" mes "右ダブルクリック → 色が変わるよ" mes "Z,Xキーを長押し → 左右" pos posx, posy color peek(c(flag),2), peek(c(flag),1), peek(c(flag)) mes "●" redraw loop #endif