HSPポータル
サイトマップ お問い合わせ


HSPTV!掲示板


未解決 解決 停止 削除要請

2013
0821
tomooncmd命令による処理高速化10解決


tomo

リンク

2013/8/21(Wed) 01:25:49|NO.56542

HSP3.32を用いてゲームを制作中です。

フレーム毎にgetkey命令で入力ボタン数回数キー入力を監視しているのですが、
動作がもたついている気がしました。

解決策が無いかと調べてみたら、
oncmd命令によって同様の処理を実現出来るのではと思いつきました。

思いついた具体的なソースを記述します


現行ソース

/////////////////////////////// repeat inkey = 0 getkey inkey,90 : if( inkey == 1 ) : var++ loop ///////////////////////////////



新提案ソース

/////////////////////////////// #define INKEY_DOWN $100 oncmd gosub *INKEY,INKEY_DOWN stop *INKEY if( wparam == 'Z') : var++ return ///////////////////////////////


どちらの方がより高速化を期待できると思われますか?
また、その他の方法があればご教授いただければと思います。

回答お待ちしています。








この記事に返信する


ツノン

リンク

2013/8/21(Wed) 04:28:12|NO.56543

繰り返し文を使用する方法がいいと思います。
上の方法は、メッセージループを省いている状態なので
ウィンドウにユーザー入力が伝わりにくい状況が起こってしまっています。
hspでは stop await wait または スクリプトの最終行 が実行されている際に、ユーザー入力を処理しているので。
それを省いてしまうと。動きが遅くなる、フリーズする等の不具合が発生しやすくなります。

*@ // 特にシステム変数 cnt を 使用する必要が無い限り。repeat loop を使用するよりも goto とラベルによる 無限ループを使用したほうが早い。 inkey = 0 getkey inkey,90 : if( inkey == 1 ) : var++ await 30 // これを省くと フリーズする可能性が有るので、急ぐ処理で無い場合は、記述しておく必要がある。 goto*@b



tomo

リンク

2013/8/21(Wed) 08:57:47|NO.56545

ツノン様

お答えいただき有難うございます。
サンプルにawaitを書き忘れていました。申し訳ない。
あくまで比較一例として書いたので、制作中のゲームにはawaitが記述されていました。

repeat〜loopよりもgotoの方が早いのは初耳ですね。
参考になる情報助かります。
初投稿なので不備が多いとは思いますが、お付き合いください。


質問の本題からは若干逸れますが、
全体の処理の高速化を目指すには何に気を付けるべきでしょうか?
今回の質問も入力監視には時間がかかるという発想からくる、
「getkeyで毎フレーム入力監視するよりも、oncmdで入力がある度に処理した方が早いのでは?」
と言った意味合いでの質問でした。

そもそも入力処理は処理速度に与える影響が少ないのであれば、
ここで質問を終わりにしたいと思っています。

再度訂正したサンプルを記述しておきます。


/////////////////////////////// *main //画面初期化 redraw 1 : redraw 0 color 255,255,255 : boxf //待機 await 16 //<その他計算描写処理> //入力表示 color 0,0,0 : pos 0,0 mes key_left mes key_up mes key_right mes key_down //入力処理 inkey = 0 getkey inkey,37 : if( inkey == 1 ) : key_left++ : else : key_left = 0 getkey inkey,38 : if( inkey == 1 ) : key_up++ : else : key_up = 0 getkey inkey,39 : if( inkey == 1 ) : key_right++ : else : key_right = 0 getkey inkey,40 : if( inkey == 1 ) : key_down++ : else : key_down = 0 goto *main ///////////////////////////////



Humi

リンク

2013/8/21(Wed) 12:27:38|NO.56546

キーボードのほとんどのキーを使うような処理なら
getkeyは少々効率が悪いかもしれませんが
4つほどならまぁあまりかわらないでしょう。

あと高速化についてよく言われるものを書いておきますね
・同じ処理はまとめる
・いらんものは出来るだけ排除

あと俺なりに高速化してみました。あまりかわらんけど

// #uselib "user32.dll" #cfunc GetAsyncKeyState "GetAsyncKeyState" int *main redraw 0//redrawは描画する空間だけ範囲を指定したらもっと早くなる color 255, 255, 255 :boxf 0, 0, 72, 72 color pos 0, 0 mes key_left mes key_up mes key_right mes key_down redraw 1 // APIだと変数が必要ないので若干速度変わる? // statに記録してるから変わらんかな? if GetAsyncKeyState(37) & 0x8000 :key_left++ :else :key_left = 0 if GetAsyncKeyState(38) & 0x8000 :key_up++ :else :key_up = 0 if GetAsyncKeyState(39) & 0x8000 :key_right++ :else :key_right = 0 if GetAsyncKeyState(40) & 0x8000 :key_down++ :else :key_down = 0 // 待機 await 16 goto*main //~



暇人

リンク

2013/8/21(Wed) 18:12:00|NO.56552

NO.56545のは処理の順番がおかしいんじゃ?

*main //画面初期化 redraw 0 color 255,255,255 : boxf //入力処理 inkey = 0 getkey inkey,37 : if( inkey == 1 ) : key_left++ : else : key_left = 0 getkey inkey,38 : if( inkey == 1 ) : key_up++ : else : key_up = 0 getkey inkey,39 : if( inkey == 1 ) : key_right++ : else : key_right = 0 getkey inkey,40 : if( inkey == 1 ) : key_down++ : else : key_down = 0 //入力表示 color 0,0,0 : pos 0,0 mes key_left mes key_up mes key_right mes key_down //<その他計算描写処理> //待機 await 16 redraw 1 goto *main
こうじゃないと入力からの処理が1フレーム遅れる


>フレーム毎にgetkey命令で入力ボタン数回数キー入力を監視しているのですが、
>動作がもたついている気がしました。
処理落ちでもしてなきゃawait 16で、それはおかしい(getkeyで全てのキーを取得しても処理時間は殆どかからない)
もしCPUコア一つ使い切ってるなら根本から改善するしかない

他の可能性として
Vista以降だとAero有効とグラボの設定で数フレーム遅延する
後は液晶モニター自体が遅延してる場合もある・・・



tomo

リンク

2013/8/21(Wed) 19:03:14|NO.56554

Humi様

有難うございます。
使用キー数は6つの予定です。増えたとしても10程度に収まります。
勉強も兼ねて#uselibと#cfuncを用いたAPI記述に挑戦してみます。

「redrawは描画する空間だけ範囲を指定したらもっと早くなる」
とのことですが、これは
redraw 0〜redraw 1の間には描写関連の記述のみを入れるべき。
という解釈でよろしいでしょうか?

ゲームのシーン単位で分割しており、
計算部分と描写部分はごちゃ混ぜです。
(場所によっては描写関数内で計算させています……。)
分離させるとなると少々面倒なことになりそうです。

画面の変更部分のみを更新した方が早い。
という解釈でしたら画面全体が良く動くゲームなので、
毎フレーム画面全体を更新しなければならない状態です。

「同じ処理はまとめる」「いらんものは出来るだけ排除」
に関しては耳が痛いです。気が付くとごちゃごちゃしたソースになっています。
地道に整理して行くしかありませんかね。

大分趣旨から外れた質問内容になってしまいましたが、
新規書き込みで再質問した方がよろしいでしょうか?
非常に勉強になる返答が多く、
続けさせて頂けるのであれば有難いです。

訂正したサンプルを記述しておきます。


(要素が増えるたびにソースを分割して#include結合していきたい方針)

main.hsp /////////////////////////////// //外部DLLの指定 #uselib "user32.dll" #cfunc GetAsyncKeyState "GetAsyncKeyState" int //メインループ *MAIN //一定の時間で待つ await 16 //計算処理 gosub *INKEY_CALCULATION //描写処理 redraw 0 color 0,0,0 : boxf gosub *INKEY_DRAW redraw 1 goto*MAIN //別ファイルを結合 #include "inkey.hsp" /////////////////////////////// inkey.hsp /////////////////////////////// //変数定義 key_left = 0 key_up = 0 key_right = 0 key_down = 0 *INKEY_CALCULATION if GetAsyncKeyState(37) & 0x8000 : key_left++ : else : key_left = 0 if GetAsyncKeyState(38) & 0x8000 : key_up++ : else : key_up = 0 if GetAsyncKeyState(39) & 0x8000 : key_right++ : else : key_right = 0 if GetAsyncKeyState(40) & 0x8000 : key_down++ : else : key_down = 0 return *INKEY_DRAW color 255,255,255 : pos 0,0 mes key_left mes key_up mes key_right mes key_down return ///////////////////////////////



tomo

リンク

2013/8/21(Wed) 19:26:38|NO.56555

暇人様

ご指摘ありがとうございます。
処理が1フレーム遅れるのは初めて知りました。本当に参考になります。
以前redraw 1記述もれバグで嫌な目にあったので、redraw 0とくっ付ける癖が。

実際のソースではメインループ間に1000行程度?の処理を挟んでいます。
申し訳ありませんが、何がどれくらいの処理速度なのか詳しく知りません。

NO.56545のような
入力監視してそれをmesで表示するのみ
ソースと、
celputを1ループ20回程度多用して時間や入力にあわせて画像がバンバン動く
ソースとで
動作に差を感じたため質問しました。

Windowsは7で動かしています。液晶モニター遅延も発生しているかも知れません。



暇人

リンク

2013/8/21(Wed) 19:53:52|NO.56556

>celputを1ループ20回程度多用して時間や入力にあわせて画像がバンバン動く
処理落ちしてるかが重要
celputを1ループ20回程度と言われても描画サイズや半透明使用で全然変る
まずFPSを表示させてFPSが落ちてないか確かめる事から



tomo

リンク

2013/8/21(Wed) 20:58:24|NO.56557

暇人様

丁寧な返信有難うございます。
速度がcelputの回数に依存するという固定概念があり、
大きさや半透明処理などが抜け落ちていました。
本当に助かります。

画面サイズは800x600。
表示画像の大きさは背景800x600から小物60x60まで様々です。
小物は透明色付きコピーによる黒抜きが多いですが、
透明色付き半透明合成コピーも若干使用しています。
将来的には色加算合成コピーも使いたいです。

FPSについてですが、
実装方法が複数あり少々戸惑っています。
私なりの実装をしてみました。

///////////////////////////////

//外部DLLの指定
#uselib "winmm.dll"
#cfunc timeGetTime "timeGetTime"

//変数定義
realfps = 0
start_time = timeGetTime()

//メインループ
*MAIN
//一定の時間で待つ
await 16

//計算処理
real_fps = 1000.0/(timeGetTime()-start_time)
start_time = timeGetTime()

//描写処理
redraw 0
color 0,0,0 : boxf
color 255,255,255 : pos 0,0 : mes real_fps
redraw 1
goto*MAIN

///////////////////////////////



tomo

リンク

2013/8/21(Wed) 21:34:54|NO.56558

再び失礼します。

NO.56557のソースを本編に組み込んでみました。
タイトル等で30前後、ゲーム本編では20前後に落ち込んでいました。

画像表示の大きさ等見直せるところを考えてみます。
FPSを監視しつつ妥協点を探してみますね。

本題から離れ過ぎたのでここで一旦解決とさせてください。
見直し次第また新規書き込みで質問させていただきます。

有難うございました。



暇人

リンク

2013/8/21(Wed) 22:17:06|NO.56559

とりあえずどれぐらいまで描画できるか確かめて(FPS60をキープして1フレームに640*480の画像を何枚コピーできるか)
必要な描画総量無いなら描画を小さく少なくして総量を減らすしかなくなる
描画調整だけじゃ限界がある場合
DirectX3Dを使用するプラグインかHGIMG4を使う方が良いかも



ONION software Copyright 1997-2018(c) All rights reserved.