mieki256's diary



2023/09/10() [n年前の日記]

#1 [hsp] 疑似3D道路その7

_昨日 の続き。HSP 3.6 を使って、疑似3D道路が作れないか試しているところ。環境は Windows10 x64 22H2。

坂道は一応実装できた気がする。以下のような感じになった。




各セグメントの位置を縦方向にもずらしたら道路が隙間だらけになって、各セグメントに対して場当たり的に1ラスターだけ塗り潰す量を増やしたりもしたけれど…。テキトーに弄ってたらソレっぽくなってくれた。カーブが表現できたら、それを縦方向にも適用する、という感じでなんとかなる気がする。

ソース :

ソースは以下。

_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
  • 仮想画面: 512x288 なら 60FPS も出せた。
  • 仮想画面: 800x450 なら 30FPS が出せた。60FPS は処理落ちする。
  • 仮想画面: 1280x720 なら 20FPS まで。30FPSは処理落ちする。
  • 仮想画面: 320x180 なら 60FPS も余裕だったけど、画面はめっちゃ粗くなる。でも、昔のゲーム画面っぽい粗さではあるなと…。
このクラスのCPUでも、この解像度・フレームレートになってしまうのか…。ちょっと残念。GPUを使って描画できればこのくらいの処理も楽勝なのだろうけど。

もしかして、元画像をあらかじめ拡大してイメージバッファに蓄えておいて、それをベタ転送したら多少は改善したり…。いや、それはメモリを滅茶苦茶食いそうか…。

gzoomを使った拡大縮小描画部分を手直し :

今回、HSP の gzoom を使ってビルボード(スプライト)の拡大縮小描画をしているけれど、画面外にはみ出しているはずの部分も一旦拡大描画してから仮想画面に転送していたので無駄な処理時間がかかっていた。そのあたりを改良して、画面内に収まっている部分だけを拡大描画するようにしてみた。

ss_fzoom_03_hsp_ss01.gif


サンプルソースは以下。

_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ぐらいにしてみたほうがいいだろうか。遠景も画像サイズを変えたいし、画像関係は全部作り直ししたほうがいいかな…。

*1: ソースの最初のあたりのコメントアウトを変更すればウインドウサイズを変更できる。

以上です。

過去ログ表示

Prev - 2023/09 - Next
1 2
3 4 5 6 7 8 9
10 11 12 13 14 15 16
17 18 19 20 21 22 23
24 25 26 27 28 29 30

カテゴリで表示

検索機能は Namazu for hns で提供されています。(詳細指定/ヘルプ


注意: 現在使用の日記自動生成システムは Version 2.19.6 です。
公開されている日記自動生成システムは Version 2.19.5 です。

Powered by hns-2.19.6, HyperNikkiSystem Project