2023/09/10(日) [n年前の日記]
#1 [hsp] 疑似3D道路その7
_昨日
の続き。HSP 3.6 を使って、疑似3D道路が作れないか試しているところ。環境は Windows10 x64 22H2。
坂道は一応実装できた気がする。以下のような感じになった。
各セグメントの位置を縦方向にもずらしたら道路が隙間だらけになって、各セグメントに対して場当たり的に1ラスターだけ塗り潰す量を増やしたりもしたけれど…。テキトーに弄ってたらソレっぽくなってくれた。カーブが表現できたら、それを縦方向にも適用する、という感じでなんとかなる気がする。
坂道は一応実装できた気がする。以下のような感じになった。
各セグメントの位置を縦方向にもずらしたら道路が隙間だらけになって、各セグメントに対して場当たり的に1ラスターだけ塗り潰す量を増やしたりもしたけれど…。テキトーに弄ってたらソレっぽくなってくれた。カーブが表現できたら、それを縦方向にも適用する、という感じでなんとかなる気がする。
◎ ソース :
ソースは以下。
_road05.hsp
_road05_hsp (色分け表示)
使用画像は以下。.hsp と同じ場所に置く。
_bg_bg0.png
_bg_bg1.png
_trees.png
実行時、以下のキーを受け付ける。
_road05.hsp
_road05_hsp (色分け表示)
使用画像は以下。.hsp と同じ場所に置く。
_bg_bg0.png
_bg_bg1.png
_trees.png
実行時、以下のキーを受け付ける。
- Up : アクセル
- Down : ブレーキ
- Left, Right : 左右移動
- Z : 仮想画面の解像度変更
- X : フレームレート変更
◎ 動作させてみた状況 :
CPUで拡大縮小描画処理をしているせいか、それなりに処理が重いので、一旦、小さ目のサイズの仮想画面に描画してから、それを実ウインドウサイズに拡大描画している。
CPU : AMD Ryzen 5 5600X の環境で、実ウインドウサイズを 1600x900 にして動かしてみているけれど…。 *1
もしかして、元画像をあらかじめ拡大してイメージバッファに蓄えておいて、それをベタ転送したら多少は改善したり…。いや、それはメモリを滅茶苦茶食いそうか…。
CPU : AMD Ryzen 5 5600X の環境で、実ウインドウサイズを 1600x900 にして動かしてみているけれど…。 *1
- 仮想画面: 512x288 なら 60FPS も出せた。
- 仮想画面: 800x450 なら 30FPS が出せた。60FPS は処理落ちする。
- 仮想画面: 1280x720 なら 20FPS まで。30FPSは処理落ちする。
- 仮想画面: 320x180 なら 60FPS も余裕だったけど、画面はめっちゃ粗くなる。でも、昔のゲーム画面っぽい粗さではあるなと…。
もしかして、元画像をあらかじめ拡大してイメージバッファに蓄えておいて、それをベタ転送したら多少は改善したり…。いや、それはメモリを滅茶苦茶食いそうか…。
◎ gzoomを使った拡大縮小描画部分を手直し :
今回、HSP の gzoom を使ってビルボード(スプライト)の拡大縮小描画をしているけれど、画面外にはみ出しているはずの部分も一旦拡大描画してから仮想画面に転送していたので無駄な処理時間がかかっていた。そのあたりを改良して、画面内に収まっている部分だけを拡大描画するようにしてみた。
サンプルソースは以下。
_gzoom_03.hsp
使用画像は以下。
_trees.png
実行すると、カーソルキーでスプライトを上下左右に動かせる。スプライトが画面外に出始めると、画面上で表示している dest w,h の値が増減するので、適切な描画面積に変更してから描画してることが分かる。
サンプルソースは以下。
_gzoom_03.hsp
; 画面外にはみ出す分、幅や高さを減らして gzoom で拡大縮小描画 #define SCR_W 640 #define SCR_H 360 ; #define SCR_W 1280 ; #define SCR_H 720 #define FRAMERATE 60 ; 同梱ファイル / bundled files #define SPR_FILE "trees.png" #pack SPR_FILE #packopt name "gzoom_03" ; exe filename #packopt type 0 ; generate ".exe" #packopt xsize SCR_W #packopt ysize SCR_H ; onkey goto *jobend randomize 0 ; get windows size screen 0, SCR_W, SCR_H, 0 gsel 0 ; width SCR_W, SCR_H dispw = ginfo_winx disph = ginfo_winy cls 4 ; load spite image sprimgid0 = 6 buffer sprimgid0, 1024, 512 picload SPR_FILE spr0w = ginfo_winx spr0h = ginfo_winy ; init temporary image buffer tmpid = 7 buffer tmpid, 4096, 4096 x = 16 y = 16 *mainloop #define KEY_ESC 128 #define KEY_UP 2 #define KEY_DOWN 8 #define KEY_LEFT 1 #define KEY_RIGHT 4 #define KEY_CTRL 64 ; ESC key to exit stick k, 255 if k & KEY_ESC : goto *jobend ; check cursor key spd = 8 if k & KEY_CTRL : spd = 1 if k & KEY_UP : y -= spd if k & KEY_DOWN : y += spd if k & KEY_LEFT : x -= spd if k & KEY_RIGHT : x += spd ; 描画開始 / draw start redraw 0 gsel 0 gmode gmode_gdi ; clear screen color 32, 64, 128 boxf 0, 0, dispw, disph ; draw sprite imgid = sprimgid0 imgw = spr0w imgh = spr0h dx = x dy = y scale = 1.5 dw = int(256.0 * scale) dh = int(256.0 * scale) n = 5 ; sprite No. draw_sprite_gzoom dx, dy, dw, dh, imgid, imgw, imgh, n, tmpid, dispw, disph, 0 ; draw text font "Arial", 18, 1 color 255, 255, 255 pos 6, 6 mes "Push cursor key" redraw 1 ; 描画終了 / draw end await (1000 / FRAMERATE) goto *mainloop #module #deffunc draw_sprite_gzoom int dst_x, int dst_y, int dst_w, int dst_h, int imgid, int imgw, int imgh, int n, int tmpid, int dispw, int disph, int dstid ; スプライト相当を拡大縮小して描画 ; ; dst_x, dst_y : 描画先の左上座標 ; dst_w, dst_h : 描画先のサイズ ; imgid : 元画像バッファID ; imgw, imgh : 元画像サイズ ; n : スプライトNo. ; tmpid : 作業用イメージバッファID ; dispw, disph : 画面サイズ ; dstid : 描画先イメージバッファID ; テクスチャのソース座標を算出 src_w = (imgw / 4) src_h = (imgh / 2) src_x = (n & 3) * src_w src_y = ((n >> 2) & 1) * src_h if dst_x >= dispw or (dst_x + dst_w) < 0 : return if dst_y >= disph or (dst_y + dst_h) < 0 : return dx = dst_x dy = dst_y dw = dst_w dh = dst_h sx = src_x sy = src_y sw = src_w sh = src_h ; 画面外になっている分、幅や高さを減らす if dx < 0 { w = (-dx) * sw / dw sx += w sw -= w dw += dx dx = 0 } if dy < 0 { h = (-dy) * sh / dh sy += h sh -= h dh += dy dy = 0 } if (dx + dw) > dispw { dwd = (dx + dw) - dispw swd = dwd * sw / dw sw -= swd dw -= dwd } if (dy + dh) > disph { dhd = (dy + dh) - disph shd = dhd * sh / dh sh -= shd dh -= dhd } ; gzoom は透明色を扱えないので小技が必要 ; 一旦、仮バッファに拡大縮小描画 gsel tmpid pos 0, 0 gzoom dw, dh, imgid, sx, sy, sw, sh, 0 ; 仮バッファから実スクリーンに gcopy でコピー ; gcopy なら RGB=(0,0,0) を透明色として扱える gsel dstid ; gmode gmode_rgb0 ; RGB=(0,0,0)を透明色として扱う pos dx, dy gcopy tmpid, 0, 0, dw, dh gmode gmode_gdi if 1 { ; draw text gmode gmode_gdi font "Arial", 18, 1 color 255, 255, 255 pos 6, 28 mes "x, y = " + dst_x + ", " + dst_y + " dest w,h = " + dw + ", " + dh } return #global *jobend end
使用画像は以下。
_trees.png
実行すると、カーソルキーでスプライトを上下左右に動かせる。スプライトが画面外に出始めると、画面上で表示している dest w,h の値が増減するので、適切な描画面積に変更してから描画してることが分かる。
◎ 課題 :
遠景の縦方向スクロールがどうもイマイチ。試しでテキトーに書いてみたけれど、仕組みについてもうちょっとしっかり考えないとダメだなと…。
また、遠景については、HSP の gcopy を使ってベタ転送・等倍で描画してるので、仮想画面サイズを変更すると見た目が変わってしまう。遠景も拡大縮小描画しないとダメかなと…。そもそも遠景の画像サイズが小さ過ぎる気もする。
各ビルボードの見た目が粗い気がする。1つにつき、テクスチャサイズを256x256で用意しているけれど、512x512ぐらいにしてみたほうがいいだろうか。遠景も画像サイズを変えたいし、画像関係は全部作り直ししたほうがいいかな…。
また、遠景については、HSP の gcopy を使ってベタ転送・等倍で描画してるので、仮想画面サイズを変更すると見た目が変わってしまう。遠景も拡大縮小描画しないとダメかなと…。そもそも遠景の画像サイズが小さ過ぎる気もする。
各ビルボードの見た目が粗い気がする。1つにつき、テクスチャサイズを256x256で用意しているけれど、512x512ぐらいにしてみたほうがいいだろうか。遠景も画像サイズを変えたいし、画像関係は全部作り直ししたほうがいいかな…。
*1: ソースの最初のあたりのコメントアウトを変更すればウインドウサイズを変更できる。
[ ツッコむ ]
以上です。