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


HSPTV!掲示板


未解決 解決 停止 削除要請

2018
0106
もつく標準命令での解像度設定について13解決


もつく

リンク

2018/1/6(Sat) 12:07:49|NO.82188

お世話になってます。
「モックバトル」というロックマンエグゼ風ゲームを製作中の者です。
ゲーム公開ページ:https://www.freem.ne.jp/win/game/14306

素人なりに悪戦苦闘しながら製作を続けておりましたが、
今回どうしても不明な点があり質問させて頂きたいと思い投稿させて頂きました。

本題なのですが、不明な点というのは画像処理の負荷に関してです。
このゲームの解像度は 256x192 なのですが、

winx = 256 : winy = 192 //解像度設定 winsize = 3 ://オプションで設定する画面サイズ用変数 winx2 = winx*winsize winy2 = winy*winsize screen 0,winx2,winy2 //メインスクリーン作成 buffer 1,winx,winy //デフォルトサイズのバッファ作成 //本来はここからcelloadによる画像読み込み buffer 2 ,64,64 color 0,255,0 : boxf buffer 3 ,32,32 color 0,0,255 : boxf //画像読み込みここまで font "MS ゴシック",12 *main gsel 1 //バッファに書き込む redraw 0 color 255,255,255 : boxf //テスト用背景 //ここから画像等描画とメイン処理 color 0,0,0 : pos 0,0 : mes "現在サイズ:"+winx2+","+winy2+"" gmode : pos 32,32 : celput 2 gmode : pos 32,32 : celput 3 //メイン処理ここまで、実際は500枚ほど予め読み込み gosub *screendraw await 16 goto *main *screendraw //メインスクリーンにバッファを拡大表示 gsel 0 pos 0,0 gmode : celput 1,,winsize,winsize redraw 1 return

このように、一旦デフォルトサイズのバッファに全てを描画し、
メインスクリーンに拡大表示するという方法をとっているのですが、
どうやら環境によってはゲームが重くなってしまう場合があるようです。

何しろこういった方法での解像度設定が正しいのかどうかも理解しておらず、
他に原因がある可能性も十分ありますが、より負荷の低い描画方法がありましたら
よろしければご教授頂きたいです

文章拙くて申し訳ないです、よろしくお願い致します。



この記事に返信する


あまら

リンク

2018/1/6(Sat) 13:56:42|NO.82192

縦横3倍ということは実質9倍の情報量になるわけで、
それは重くもなるだろうと思いつつも
一応時間計測してみました。

計測に使ったのは
gmode : celput 1,,winsize,winsize

この行です。 ちなみに計測に使ったソースはこちらのURLからお借りしました。 http://hsp.tv/play/pforum.php?mode=pastwch&num=75057
gmode : celput 1,,winsize,winsize
の場合 7.0〜7.2ms

実数指定ということで
gmode : celput 1,,double(winsize),double(winsize)

などもやってみましたが、小数点以下のこれは誤差だろうというレベルでほぼ同じ結果でした。 ついでにCELでは無く、gzoomに変えて計測したところ
gmode : gzoom winx2, winy2, 1,,,winx, winy
5.8-6.0ms と微妙にこちらの方が高速になるようですね。


redraw0〜redraw1までのほかの描画を含めての計測もしてみましたが
あまり差異は無く、思っていた以上に拡大処理に負荷がかかっているようです。

gzoomの方が軽い、とはいえ1フレームあたりでこれだけ描画に時間がかかるようなら
60fpsではなく30fpsも選択肢に入れておくか、1フレームの所要時間によって
awaitの値を変えるとかするといいかもしれません。



もつく

リンク

2018/1/6(Sat) 16:57:55|NO.82198

>>あまらさん

お返事ありがとうございます!
なるほど、gzoomの方がわずかに軽いのは知りませんでした・・・
やはり重いですよね・・・処理自体に無理があるのだろうか
計測しながらいろいろ試行錯誤してみます!



エイカ

リンク

2018/1/6(Sat) 21:06:25|NO.82199

もしかして、この方法はご存知かもしれませんし
この方法でも軽くはならないかもしれませんが
私が取り組んでいたのとちょうど同じことで
タイムリーな話だったので
私のやり方をば

かなりアレな処理ですが
私は割り切って、再定義で済ませました
(HSP3dishでは、現時点の私の知識ですと
ファイルの差し替えが必要ですが)


xb=0.7:yb=0.7 mb=0.65 #undef pos #module #deffunc pos int iX,int iY pos@hsp xb@*iX,yb@*iY return #global #undef gzoom #module #deffunc gzoom int gX,int gY,int g1,int g2,int g3,int g4,int g5 gzoom@hsp xb@*gx,xb@*gy,g1,g2,g3,g4,g5 return #global #undef objsize #module #deffunc objsize int oX,int oY objsize@hsp xb@*oX,yb@*oY return #global #undef font #module #deffunc font str f1,int f2,int f3 font@hsp f1,mb@*f2,f3 return #global

こんな感じで

参考になれば幸いです。



あまら

リンク

2018/1/6(Sat) 21:17:11|NO.82200

ちょっと気になったのでこちらも色々やってみました。

で気付いたのですがソース内におかしな点がありました。
*main
gsel 1 //バッファに書き込む redraw 0 color 255,255,255 : boxf //テスト用背景 //ここから画像等描画とメイン処理 color 0,0,0 : pos 0,0 : mes "現在サイズ:"+winx2+","+winy2+"" gmode : pos 32,32 : celput 2 gmode : pos 32,32 : celput 3 //メイン処理ここまで、実際は500枚ほど予め読み込み gosub *screendraw await 16 goto *main *screendraw //メインスクリーンにバッファを拡大表示 gsel 0 pos 0,0 gmode : celput 1,,winsize,winsize redraw 1 return
これredraw 0の位置が違います。
gsel 1 1はバッファなので描画停止しても意味がなく、
gsel 0 の後でredraw 1で描画開始……

つまり0(メインウィンドウ)は常に描画状態。
メモリ上のウィンドウ1(バッファ)は常にメモリ上に描画。
どちらもredrawが実質無意味なことになっています。


gsel 1 //バッファに書き込む
;redraw 0 // こちらは消去 //************中略**************** gsel 0 redraw 0
このようにした方がチラつきなんかも無くなり、高速になるはずです。
実際これで計測してみたら倍程度高速になりました。

更に、使いどころが限られるマシン語を利用したモジュールを使って
拡大コピーしてみたらgzoomよりも早いという結果も出ましたので
モジュールを乗せておきます。
#uselib "kernel32.dll"
#func global VirtualProtect "VirtualProtect" var,int,int,var #define global xdim(%1,%2) dim %1,%2:VirtualProtect@ %1, %2*4,$40,AZSD #module // 縦横比固定 等倍コピー // src 描画元 // bai 倍率 #deffunc zoomcopy int src, int bai dist = ginfo_sel; // 描画先情報取得 mref dvram, 66; dvramp = varptr(dvram); dx = ginfo_winx; dy = ginfo_winy; // 描画元情報取得 gsel src; mref svram, 66; svramp = varptr(svram); sx = ginfo_winx; sy = ginfo_winy; gsel dist; dim size, 7; size(0) = dx, dy, sx, sy, bai, dvramp, svramp; if( (sx*bai != dx) || (sy*bai != dy) ) { return -1; // サイズが合わない } xdim fncode, 60 fncode( 0) = $83ec8b55, $458b1cec, $8b534008, $8d56105d, $e6834034, $01438dfc; fncode( 6) = $8df47589, $e0834004, $f04589fc, $8514458b, $bb8e0fc0, $8b000000; fncode(12) = $3357f055, $89c933ff, $4d89e87d, $001f0fec, $8e0fdb85, $0000008b; fncode(18) = $3320558b, $087589f6, $8df85d89, $c8030142, $4d89d02b, $89c38bfc; fncode(24) = $7d83e455, $148a0018, $8a198a0a, $3d7e0171, $8d184d8b, $758b3704; fncode(30) = $0ff98b1c, $c683c1af, $8bf00302, $fe5088c6, $8803408d, $7088fc58; fncode(36) = $01e983fd, $7503ef75, $184d8bf4, $7501ef83, $fc4d8be2, $8b08758b; fncode(42) = $7d8bf845, $e4558be8, $8303c683, $758903c1, $01e88308, $89fc4d89; fncode(48) = $9e75f845, $8bf4758b, $458bec4d, $105d8b14, $03f0558b, $83fe03ca; fncode(54) = $4d8901e8, $e87d89ec, $0f144589, $ffff5785, $5b5e5fff, $c35de58b; p = callfunc(size, varptr(fncode), 7); return 0; #global winx = 256 : winy = 192 //解像度設定 winsize = 3 ://オプションで設定する画面サイズ用変数 winx2 = winx*winsize winy2 = winy*winsize screen 0,winx2,winy2 //メインスクリーン作成 buffer 1,winx,winy //デフォルトサイズのバッファ作成 //本来はここからcelloadによる画像読み込み buffer 2 ,64,64 color 0,255,0 : boxf buffer 3 ,32,32 color 0,0,255 : boxf //画像読み込みここまで font "MS ゴシック",12 *main loopcount++; gsel 1 //バッファに書き込む color 255,255,255 : boxf //テスト用背景 //ここから画像等描画とメイン処理 color 0,0,0 : pos 0,0 : mes "現在サイズ:"+winx2+","+winy2+"" gmode : pos 32,32 : celput 2 gmode : pos 32,32 : celput 3 //メイン処理ここまで、実際は500枚ほど予め読み込み gosub *screendraw await 16 goto *main *screendraw //メインスクリーンにバッファを拡大表示 gsel 0 redraw 0 pos 0,0 ;gmode : celput 1,,winsize,winsize ;gmode : gzoom winx2, winy2, 1,,,winx, winy zoomcopy 1, winsize; redraw 1 return

zoomcopy p01, p02;
p01 描画元ID
p02 拡大率(1以上の整数)

gselで指定したウィンドウにp01のウィンドウの画像をp02倍してコピーします。

posなどの描画位置は無視、ウィンドウサイズが倍率に合わないとエラーとなります。
ほかでは非常に使いにくい物ですがこの場合に限っては少しは使えるかもしれません。



ZAP

リンク

2018/1/6(Sat) 22:15:02|NO.82201

環境にもよりますが、
gzoomよりgsquareのほうが断然早いと思いますよ。



ぜーっと!

リンク

2018/1/6(Sat) 23:51:55|NO.82203

みんな色んなこと知ってるなあ。研究熱心やね(*^ω^*)



もつく

リンク

2018/1/7(Sun) 01:52:34|NO.82204

>>エイカさん
なるほど、サイズに合わせて標準命令をまるっと置き換える訳ですね!
こんな方法もあったとは・・・可能そうであれば試してみたいと思います

>>あまらさん
redrawの位置については、自分のサンプルプログラムでのミスでした、申し訳ないです・・・
実際のゲームでの処理では、正しい位置にありました

マシン語を利用したモジュール・・?!とんでもない技術ですね・・・
素晴らしいモジュールをありがとうございます!
しかしながら、winsizeの部分はできれば実数で使いたいので
現段階では使用は難しいかな、といった感じでした

>>ZAPさん
gsquareという命令を初めて知りました・・・
試してみます、ありがとうございます!



ZAP

リンク

2018/1/7(Sun) 10:14:19|NO.82207

あ、昨日の投稿間違えてました。
「gsquare」ではなくて「grotate」です。
すみません・・・



あまら

リンク

2018/1/7(Sun) 15:38:07|NO.82208

実数ということで、
winsize = 2.5
winsize = 3
winsize = 3.5
の3パターンの各命令の拡大処理の時間計測をやってみました。

使ったのは gsquare、grotate、celput、gzoom(再定義はせずそのまま) の4つの命令です。

全てに共通したのは gsquare、grotate、celput の3つはほとんど差がありませんでした。
これは環境による違いが顕著に出るかもしれません。


2.5の場合はgzoomが一番遅くて1回あたり2.1msほど
ほか3種は共通して1.8〜1.9ms

3と3.5の場合は逆にgzoomが一番速くて2.8ms程度に対し、
ほかが4msを少し超えるという結果でした。

倍率が小さいときはgrotateなどが速く、
ある程度の大きさを超えるとgzoomが速いという事になりそうですが、
色んな環境でそれぞれ違った結果になりそうですね。



もつく

リンク

2018/1/8(Mon) 21:05:15|NO.82230

>>あまらさん

検証ありがとうございます!!
動作が重い人にはgrotateのほうが良さそうに見えてきますね・・・
一度変更してみてプレイヤーの方々の動作次第で考えてみようとおもいます



ぜーっと!

リンク

2018/1/8(Mon) 21:36:28|NO.82231

プレイヤーの環境によって、まちまちであれば、描画方法を内部に複数用意して
例えば、コンフィグでユーザー側で切り替えできるようにするという方法もあります。
内部的には、ifやswitchなどで分ける感じですね。



沢渡

リンク

2018/1/9(Tue) 21:45:09|NO.82248

変数winsizeの中に拡大率を入れていて、かつ拡大率は整数と決まっているのなら、
画面上に描画するキャラクターやマップのパーツをあらかじめ拡大してバッファに置いておき、
描画命令の座標やサイズはwinsizeを掛けるようにして指定するというのはどうでしょうか?
(私の作っているソフトがこの方式です)
以下のようなマクロを使えば楽になると思います。

#define ctype zm(%1) ((%1)*winsize) //たとえば、以下のように使う。 pos zm(x),zm(y) gcopy 1,0,0,zm(w),zm(h)
今からやるとなると結構な大手術になると思いますので、あくまでもこういう方法もあるという参考までに。



もつく

リンク

2018/1/18(Thu) 00:38:30|NO.82282

返信遅くなってしまい申し訳ないです・・・

>>ぜーっと!さん
なるほど、選択式にしてユーザーさんに選択して頂く形ですね
よほど差があるようでしたらその方がいいのかも・・・

>>沢渡さん
予めバッファに倍率分拡大して置いておく、なるほど・・・
やはり現在の方法のように描画後の拡大よりは予め用意しておいたほうが良いのですね
おっしゃるとおり結構な作業量になってしまいますので、まずは他の方法を探ってみようと思います・・・


皆様大変有益な情報ありがとうございます!
参考にさせて頂き、試しながら調整していこうと思います
解決済みとさせて頂きます



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