mieki256's diary



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

#1 [pc] 外付けHDDにアクセスできなくなった

手持ちのUSB3.0接続外付けHDDにアクセスできなくなってしまった。Windows10 x64 22H2からドライブ文字は見えるのだけど、ストレージの認識に時間がかかる上に、アクセスしようとすると「ディスク構造が壊れているため、読み取ることができません」と表示される。

問題を起こしたHDD+外付けHDDケースは以下。
ディスクの管理から確認したら、フォーマットがNTFSじゃなくてRAWになっていた。管理領域が壊れてしまったようだなと…。

別のHDDスタンドに差し替えた :

このHDDケースで作業をし続けるのは怖いので、HDDを取り出して、HDDスタンド Logitec LGB-1BSTU3 (2.5/3.5インチSATA接続HDDに対応。1ベイ。USB3.0接続) に差してみた。

状況が変わるかと期待したけど、相変わらず中身は見れない。フォーマットもRAWのまま。ということは、HDDケース側が壊れたわけではなくて、HDDが壊れた状態のようだなと。

chkdskをかけた :

ダメ元で、管理者権限でコマンドプロンプトを開いて、管理領域を修復できる(時もある)ツール、chkdsk H: /f をかけてみた。ずらずらとメッセージが表示されて、大量に「〜を削除」と表示されていった…。

chkdsk をかけたことで、HDD一覧にすんなりとHDDが出てくるようになったけど、これだけではまだ中身にアクセスできなかった。HDDを右クリック → プロパティ → セキュリティ、で、所有者を Everyone にしてみたり、子エントリにも適用をしてみたところ、ようやく中身が多少は見えるようになった。

HDDの中の状態 :

隠しフォルダで、found.000 というフォルダが作られていて、2TBほどのファイルやフォルダが入っていた。

ただ、それでも、500GBほどの何かのファイル群が消滅していた…。先日使った時は空き容量が300GBぐらいだったのに、復旧作業をしてみたら800GBになってる。ということは、500GBぐらい消えているのだろうなと…。

別HDDにファイルをコピー :

とりあえず、このHDDを今後も使い続けるのは怖いので、別のHDD、TOSHIBA MD03ACA400 (4TB, 7200rpm) を GW3.5AA-SUP3/MB の中に入れて、そちらにファイルをコピーしていくことにした。

HDDの温度がヤバイ :

CrystalDiskInfo 8.17.14 x64 でHDDの状態を表示しつつ作業をしていたけれど、GW3.5AA-SUP3/MB の中のHDD、MD03ACA400 のHDD温度が50度を超え始めた。経験上、この温度はヤバイ。もしかして、先日使っていた際も気づかないうちにこんな温度になっていて、それで管理領域が壊れたのでは…。

USB扇風機や、USB端子から電源を取って回す12cmFANを発掘して、HDDケースやHDDスタンドに風を当ててみたところ、HDDケースのほうは 48〜49度ぐらい、HDDスタンドのほうは41度ぐらいに下がってくれた。これでもまだヤバイ感じがするけれど、50度以上にどんどん上がり続けていくよりはマシだろう…。

とりあえず、ファイル一覧に見えているファイル群はコピーしておこう…。その後、削除ファイルを探せるらしいツールを動かしてみて、救い出せるかどうか試したい。まあ、望み薄だろうけど。

とか思っていたら、連続でファイルコピーしているうちに、HDDケース側のHDDがまた50度を超え始めた。これはマズイ。CPUクーラーを発掘して、ヒートシンク部分をHDDケースの上に置いてみたところ、ギリギリで49度まで下がってくれた。なんというか、綱渡りな感じがする。それにしても、ヒートシンクをHDDケースに載せて風をあてるだけでも温度が上がり続けるのを回避できるのだな…。

ファン付きのHDDケースが欲しい :

ファン付きのHDDケースが欲しいところだけど、イイ感じの製品がもはや市場にはほとんど無いのだよな…。

いやまあ、自分の環境の場合、そもそも外付けHDDケースに7200rpmのHDDを入れちゃってるのが間違ってる気もするけれど。7200rpm のHDDは、5400rpm のHDDと比べて、速度は多少速いけど、その分発熱するらしいので…。速くても、熱でファイルが壊れていくようでは意味が無い…。

デフラグのせいかもしれない :

今回問題を起こした外付けHDDケース、玄人志向 GW3.5AA-SUP3/MB についてググっていたら、気になる話を見かけた。

_価格.com - 『デフラグができるようになりました。』 玄人志向 GW3.5AA-SUP3/MB [マットブラック] のクチコミ掲示板
Windows10でデフラグをすると、途中でフリーズしてしまい、やむを得ず、強制終了すると、データが失われてしまう状況でした。(中略) 玄人志向のHPでダウンロードした、ファームウェアのアップデートをしたところ、問題なく、デフラグできるようになりました。

デフラグ…。そういえば先日使った際、デフラグをかけて、しかし処理が反映されなくて悩んでいた気がする…。もしかして、そのせいか…。このHDDケースは、ファームウェアのバージョンによってはデフラグをかけると一発で管理領域が壊れてHDDが読み出せなくなるのかもしれない…。

今後、外付けHDDでデフラグをかけるのはやめよう…。断片化が増えて、ちょっとぐらいアクセス速度が遅くなったとしても、デフラグをかけてHDD全体が読み出せなくなったら馬鹿馬鹿しいし。

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

#1 [pc] 外付けHDDケースのファームウェアを更新してみた

USB3.0接続外付けHDDケース、玄人志向 GW3.5AA-SUP3/MB のファームウェアを、138.01.00.01 から、69.02.00.03 に更新してみた。

_玄人志向 HDDケース「GW3.5AA-SUP3シリーズ」「GW3.5IDE+SATA/U3Pシリーズ」のファームウェアアップデートについて | 玄人志向

玄人志向のサイトから、「FW Update Utility v1.0.0.2.zip」を入手できる。解凍すると、中には「FW Update Utility v1.0.0.2.exe」と「お読みください.pdf」が入っているので、GW3.5AA-SUP3 だけをUSB接続している状態で「FW Update Utility v1.0.0.2.exe」を実行すればファームウェアを更新できる。

ちなみに、「JMS567FwUpdateTool_v1_0_0_0.zip」(Jmicron JMS-567 Firmware Version 138.01.00.01) というファームウェアも存在していて、そちらは 138.01.00.01 が入っている。日付が 2016/04/21。手元の個体は、以前、その 138.01.00.01 に更新していたらしい。

_mieki256's diary - 外付けHDDケースのファームウェアを更新してみた

玄人志向で入手できる公式版のほうは 2019/04/12 なので、一見すると公式版のほうが新しそうに見える…。が、どうもググった感じでは、環境によってどちらが安定して使えるかは違うようで…。

HDDケースに使われているチップについて :

このHDDケースには、JMicron JMS567 というチップが入ってるらしい。

_許すまじJMS567 | 豆腐の角

HDDケースや、USB3.0 - SATA変換に使われているチップの種類をググってみたら、以下があるようで。
  • JMicron JMS567
  • JMicron JMS578
  • JMicron JMS580
  • ASMedia ASM1153E
  • ASMedia ASM235CM
  • VL716
  • Innostor IS621

JMS567 は使用事例が多いけれど、相性問題や不具合事例も多数のようだなと…。ASM1153E は安定動作しているらしいけど、使っている製品がほとんど見つからなかった。

ASM235CM や VL716 は、2.5インチHDDケースやUSB-SATA変換ケーブルに使われてることが多い感じ。3.5インチHDDケースで使ってる製品は見かけなかった。

各製品について使用チップをググったら以下のような感じだった。製造された時期によって使用チップが変わってる可能性もありそうだけど…。
  • AINEX HDE-08 : ASM1153E
  • inateck FE3001 : ASM1153E
  • 玄人志向 GW3.5AM-SU3G2P : JMS580
  • 玄人志向 GW3.5AM-SU3P : JMS578
  • ORICO 7688U3 : JMS578

_放熱性を確保したヘアライン仕上げのアルミ製HDDケース - アイネックス USB3.0接続 UASP対応 3.5インチHDDケース HDE-08のレビュー | ジグソー | レビューメディア
_Windows 10:外付けHDDケースの使い方。3TB HDDのフォーマット解説もあるよ。〜inateck FE3001の使い方〜 - enjoypclife.net
_USB3.0 HDDケース GW3.5AM-SU3P - かってきままに!
_3.5インチHDDケースを買ってみた ORICO 7688U3 | まるむしアンテナ

#2 [nitijyou] TV用のヘッドフォンを購入

ケーズデンキで、audio-technica ATH-P100M を購入。975円。

今までも同じ型番のヘッドフォンを使ってたけど、イヤーパッドのスポンジがボロボロになってしまった。しかも、ヘッドフォンの横から挟み込む力が弱くなって、音もよく聞こえないし、すぐにずり落ちるしで…。

ath_p100m_old_new_ss.jpg

左が今まで使っていた個体。右が今回購入した個体。このぐらい、挟む力が違ってしまっている。

純正品の交換用イヤーパッド audio-technica HP-P100 は600円ぐらいするし、どのみち挟む力を復活させられないので、新品を買ってしまったほうがいいよなと。

前回購入したのは、2021/08/05。2年ぐらいでボロボロになるのだな。

_mieki256's diary - ダイソーで色々購入

イヤーパッド部分について :

イヤーパッド部分は別の商品で代用できなくもないらしい。

_ヘッドホンATH-P100Mのイヤーパッド交換 | ぞうさんブログ
_ヨドバシ.com - HP-P100 [交換イヤパッド 左右1セット]に関するQ&A詳細
外形は縦65mm X 横60mmの楕円形、挿入する部分の穴は35mmです。

もっとも、挟む力を復活できないとアレだけど…。

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

#1 [nitijyou] カナル型ステレオイヤホンを購入

ヨドバシカメラの通販で、カナル型ステレオイヤホン、SONY MDR-EX15LP (色は黒) を購入。1,060円。

先日ダイソーでカナル型ステレオイヤホン AL-04 を買ったけど、どうも音漏れが結構あるような気がしてしまって、別のイヤホンが欲しいなと…。音漏れを80%削減したと謳っている件の製品を購入してみた次第。

コードの長さを調整するアダプター、イヤーピースS、M、Lが付属してた。そのあたりは正直要らんのだけど、別売りじゃダメだったのかな。いやまあ、少しでも商品の訴求力を増やしたくて付けたのだろうけど。

肝心の音漏れは、正直よく分からない…。普段使ってるインナーイヤー型と比べたら明らかに少ない感じはするけれど、そのタイプと比較してもな…。

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

#1 [hsp] 疑似3D道路について試してる

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

参考ページ :

以下のページを参考にしながら作業してるのだけど、英文ページなので何が何やら…。

_Lou's Pseudo 3d Page
_How to build a racing game - straight roads | Code inComplete

ソース :

とりあえず、一直線の道路だけなら処理を書けた。

ss_road02a_ss01.gif

_road02a.hsp
    ; 疑似3D道路を描画する / Drawing pseudo 3D roads

    #define BGROAD_FILE "bg_road.png"
    #define BG_FILE     "bg_16col.png"
    #define SCR_W       640
    #define SCR_H       360

    ; 同梱ファイル / bundled files
    #pack   BGROAD_FILE
    #pack   BG_FILE
    
    #packopt name "road02a"     ; 生成exeファイル名 / generated exe file name
    #packopt type 0             ; exeファイルの生成を指定 / exe file generate
    #packopt xsize SCR_W
    #packopt ysize SCR_H
    
    onkey goto *jobend
    
    ; ウインドウサイズを取得 / 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 road image
    roadimgid = 6
    buffer roadimgid, 1280, 1440
    picload BGROAD_FILE
    roadimgw = ginfo_winx
    roadimgh = ginfo_winy

    ; 背景画像を読み込み / load bg image
    bgimgid = 4
    buffer bgimgid, 1280, 720
    picload BG_FILE
    bgw = ginfo_winx
    bgh = ginfo_winy

    dist = 150.0    ; 画面までの距離 / distance to screen
    
    angle = 0.0
    scroll_z = 0
    camera_x = 0

*mainloop

    ; ESC key to exit
    stick k
    if k & 128 : goto *jobend

    base_y = int(double(disph) * 0.5)
    road_y = 100
    road_x = 300
    h = disph - base_y
    
    camera_x = 0
    ; camera_x = 600.0 * sin(deg2rad(angle * 0.75))

    redraw 0    ; 描画開始 / draw start
    gsel 0
    
    ; 背景(遠景)を描画 / draw BG
    gmode 0
    
    ax = sin(deg2rad(double(angle) * 0.25)) * ((bgw - dispw) / 2)
    
    bg_x = (bgw / 2 - (dispw / 2)) + ax
    bg_y = bgh / 2 - base_y
    pos 0,0
    gcopy bgimgid, bg_x, bg_y, dispw, disph
    ; gradf 0, (disph / 2), dispw, (disph / 2), 1, $449044, $080808

    ; 道路を描画 / draw road
    repeat h
        scrn_y = h - cnt - 1
        if scrn_y = 0 : continue
        
        road_z = road_y * dist / scrn_y
        scrn_x = road_x * dist / road_z
        
        center_x = (camera_x * dist / road_z)
        
        u = center_x + (roadimgw / 2) - (dispw / 2)
        addv = ((roadimgh / 2) * (((road_z + scroll_z) / 32) & $1))
        v = scrn_x + addv
        
        ; 1ラスター分を描画 / drawing 1 raster
        pos 0, scrn_y + base_y
        gcopy roadimgid, u, v, dispw, 1
    loop

    redraw 1    ; 描画終了 / draw end
    
    angle += 1
    scroll_z += 10
    
    await (1000 / 30)
    goto *mainloop

*jobend
    end

使用画像は以下。道路用画像。

bg_road.png
_bg_road.png

背景用画像。

bg_16col.png
_bg_16col.png

画像は、.hsp と同じフォルダ階層に置いておく。

考え方 :

実装する際の考え方を一応メモ。

以下は、横から見た図。

about_road_pers_01.png

画面上の特定のy座標 = sy に道路が表示されているとして、その位置の道路のz値 = rz を知りたい。
  • 画面までの距離 sz は決めておく。
  • 画面上のy座標 sy も決めておく。
  • 道路の高さ(低さ) ry も決めておく。
  • 道路のz値 rz だけが分からない。

sz,sy で作られる三角形と、rz,ry で作られる三角形は、大きさが違うだけで形は同じ(相似)なので、以下の式が成り立つ。
sz : sy = rz : ry
sy * rz = sz * ry
rz = ry * sz / sy
これで、画面上のy座標 sy に表示されている道路のz値、rz を求めることができた。

更に、その位置に表示されている道路の見た目の幅(片方の幅)を知りたい。上から見た図で考える。

about_road_pers_02.png

  • 画面までの距離 sz は決めておく。
  • 道路の実際の幅 rx も決めておく。
  • 道路のz値 rz は先ほど求めることができた。
  • 画面上の道路の見た目の幅 sx だけが分からない。

sz,sx で作られる三角形と、rz,rx で作られる三角形は、大きさが違うだけで形は同じ(相似)なので、以下の式が成り立つ。
sz : sx = rz : rx
sx * rz = sz * rx
sx = rx * sz / rz
これで、画面上のy座標 sy に表示されている、道路の見た目の幅、sx を求めることができた。

道路の見た目の幅が分かったので、事前に用意した道路用の画像内から、合致する1ラインを持ってきて画面に描画する。

bg_road.png

上記の画像は45度の角度で道路の幅が広がっていくように描いたので…。例えば道路の見た目上の幅が 120 なら、y = 120 のあたりの1ラインを使って画面に描画してやればいい。

更に、奥から手前に向かって、白線が点線になってるように、かつ、道路や地面の色が縞々になるように描画したい。

道路のz値が得られているので、そのz値を元にして 0 か 1 かを決めて…。
  • 0 なら白線のある画像側を ―― 上記の画像であれば上半分側を使って描画。
  • 1 なら白線のない画像側を ―― 上記の画像であれば下半分側を使って描画。
これで、白線は点線になるし、道路や地面の色も縞々になる。

その際、道路のz値に、別途スクロール値を加算して 0 or 1 を決めてやれば、道路が奥から手前に向かってスクロールしてるように見えるはず。

ここまでの処理を、画面の下半分程度、ループ処理で描画してやれば、疑似3D道路が描画できるはず。

余談。昔のゲーム機ならパレット書き換えができただろうから、水平帰線割り込みを使って、水平帰線期間内に道路用パレットの一部の値(白線、道路、地面の3色)を書き換えてやれば、わざわざ似たような画像を用意しなくても、点線状の白線や、縞々模様を実現できたのではないかなと想像するのだけど、実際はどうだったんだろう。

道路の画像を使わない版 :

昔のゲーム機は、基本的には事前に用意した画像を画面に表示することしかできなかったので、前述のように道路用画像を別途用意しておかなければいけなかったと思うのだけど。

今時のハードウェアは、というかPCは、えてしてフレームバッファを持っているので、点だの、線だの、矩形だのをその都度描画することができるなと。だったら、この程度のシンプルな形状であれば毎回プログラムで計算して描いちゃってもいいんじゃないかと思えてきた。

そんなわけで、道路用の画像を使わない版も書いてみた。

ss_road02b_ss01.gif

_road02b.hsp
    ; 疑似3D道路を描画する / Drawing pseudo 3D roads
    ; 道路画像を使わずにプログラムで描画する版

    #define BG_FILE     "bg_16col.png"
    #define SCR_W       640
    #define SCR_H       360

    ; 同梱ファイル / bundled files
    #pack   BG_FILE
    
    #packopt name "road02b"     ; exe filename
    #packopt type 0             ; generate ".exe"
    #packopt xsize SCR_W
    #packopt ysize SCR_H
    
    onkey goto *jobend
    
    ; 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 bg image
    bgimgid = 4
    buffer bgimgid, 1280, 720
    picload BG_FILE
    bgw = ginfo_winx
    bgh = ginfo_winy

    dist = 150.0    ; 画面までの距離 / distance to screen
    
    angle = 0.0
    scroll_z = 0
    camera_x = 0

*mainloop

    ; ESC key to exit
    stick k
    if k & 128 : goto *jobend

    base_y = int(double(disph) * 0.5)
    road_y = 100
    road_x = 300
    h = disph - base_y

    camera_x = 0
    ; camera_x = 600.0 * sin(deg2rad(angle * 0.75))
    
    redraw 0    ; 描画開始 / draw start
    gsel 0
    
    ; 背景(遠景)を描画 / draw BG
    gmode 0
    
    ax = sin(deg2rad(double(angle) * 0.25)) * ((bgw - dispw) / 2)
    
    bg_x = (bgw / 2 - (dispw / 2)) + ax
    bg_y = bgh / 2 - base_y
    pos 0,0
    gcopy bgimgid, bg_x, bg_y, dispw, disph
    ; gradf 0, (disph / 2), dispw, (disph / 2), 1, $449044, $080808

    ; 道路を描画 / draw road
    repeat h
        scrn_y = h - cnt - 1
        if scrn_y = 0 : continue
        
        road_z = road_y * dist / scrn_y
        scrn_x = road_x * dist / road_z
        
        center_x = camera_x * dist / road_z
        
        addv = (((road_z + scroll_z) / 32) & $1)
        
        ; 1ラスター分を描画 / draw 1 raster
        road_w = scrn_x * 2
        draw_x = -scrn_x + (dispw / 2) + center_x
        draw_y = scrn_y + base_y
        kind = addv
        gosub *draw_raster_road
    loop

    redraw 1    ; 描画終了 / draw end
    
    angle += 1
    scroll_z += 10
    
    await (1000 / 30)
    goto *mainloop

*draw_raster_road
    ; 道路を1ラスター分描画
    ;
    ; draw_x, draw_y : draw x, y
    ; road_w : road width
    ; kind : 0 or 1
    ; dispw : screen width

    ; draw ground
    if kind = 0 {
        ; color R, G, B
        color 114, 185, 66
    } else {
        color 22, 174, 63
    }
    ; boxf x0, y0, x1, y1
    boxf 0, draw_y, dispw, draw_y

    ; draw road base
    if kind = 0 {
        color 133, 149, 158
    } else {
        color 149, 168, 179
    }
    boxf draw_x, draw_y, draw_x + road_w, draw_y

    ; draw white line
    lw = double(road_w) * 48.0 / 2048.0     ; white line width
    
    if kind = 0 {
        color 255, 255, 255
        
        lx = double(draw_x)
        boxf lx, draw_y, lx + lw, draw_y
        
        lx = lx + road_w - lw
        boxf lx, draw_y, lx + lw, draw_y
        
        lx = double(draw_x) + (double(road_w) * 0.5) - (lw * 0.5)
        boxf lx, draw_y, lx + lw, draw_y
        
        lx = double(draw_x) + double(road_w) * 0.25 - (lw * 0.5)
        boxf lx, draw_y, lx + lw, draw_y
        
        lx = double(draw_x) + double(road_w) * 0.75 - (lw * 0.5)
        boxf lx, draw_y, lx + lw, draw_y
    } else {
        color 228, 236, 252
        
        lx = double(draw_x) + lw
        boxf lx, draw_y, lx + lw, draw_y
        
        lx = double(draw_x) + road_w - (lw * 2)
        boxf lx, draw_y, lx + lw, draw_y
    }
    return

*jobend
    end

見た目では違いが分からないな…。

lineとboxf :

HSP は、line で線を描画、boxf で矩形塗り潰しができるけど、1ラインだけ描画するならどちらが速いのか気になったので少し試してみた。環境は Windows10 x64 22H2 + HSP 3.6。

_bench.hsp
    ; line と boxf のベンチマーク

    #include "d3m.hsp"
    
    #define SCR_W       640
    #define SCR_H       360

    #packopt name "bench"       ; 生成ファイル名
    #packopt type 0             ; .exe生成を指定
    #packopt xsize SCR_W
    #packopt ysize SCR_H
    
    onkey goto *jobend
    
    ; 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

*mainloop
    ; ESC key to exit
    stick k
    if k & 128 : goto *jobend
    
    redraw 0    ; 描画開始
    gsel 0
    gmode 0

    lp = 1000
    
    starttime = d3timer()
    repeat lp
        repeat (disph - 1)
            color 16, 32, 64
            ; line x1, y1, x0, y0
            line dispw, cnt, 0, cnt
            
            ; pos 0, cnt
            ; line dispw, cnt
        loop
    loop
    tm1 = d3timer() - starttime

    starttime = d3timer()
    repeat lp
        repeat (disph - 1)
            color 16, 32, 64
            ; boxf x0, y0, x1, y1
            boxf 0, cnt, dispw, cnt
        loop
    loop
    tm2 = d3timer() - starttime

    color 255, 255, 255
    pos 8, 8
    mes "line : " + tm1
    pos 8, 32
    mes "boxf : " + tm2
    
    redraw 1    ; 描画終了
    
    await (1000 / 60)
    goto *mainloop

*jobend
    end

ss_bench.gif

微妙に boxf のほうが速いようだなと…。まあ、劇的に違いが出るわけでもないので、今回はどっちを使っても良さそうだけど。

ただ、ループ内の color 命令をコメントアウトすると、line のほうが速くなったりもした。なんでだろ。

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

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

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

カーブを実装したいのだけど、何をどうしたらいいのやら。とりあえず、セグメントなる概念でデータテーブルを用意しないとカーブにしろ丘にしろ表現しづらい感じがしてきたので、まずはセグメントの形で道路のデータを持てないか試している。

配列変数の初期化について :

HSP は配列変数の初期化をする際に、カンマ区切りでずらずらと数値を書けないようで…。以下のような書き方になってしまう。
    dim a, 5, 3
    a(0, 0) = 20        ; count
    a(0, 1) = 0         ; curve
    a(0, 2) = 0         ; pitch
    a(1, 0) = 30
    a(1, 1) = 10
    a(1, 2) = 0
    a(2, 0) = 20
    a(2, 1) = -10
    a(2, 2) = 0
    a(3, 0) = 20
    a(3, 1) = 0
    a(3, 2) = 2
    a(4, 0) = 20
    a(4, 1) = 0
    a(4, 2) = -2
このへんどうにかならんのか。

マクロを書いて、多少は見た目を改善する方法はあるっぽい。

_配列変数の連続代入について - HSPTV!掲示板
#define set_array(%1, %2,  %3, %4, %5) \
  %1(%2, 0) = %3 :\
  %1(%2, 1) = %4 :\
  %1(%2, 2) = %5 :

set_array a, 0, 20, 0, 0
set_array a, 1, 30, 10, 0
set_array a, 2, 20, -10, 0
set_array a, 3, 20, 0, 2
set_array a, 4, 20, 0, -2

配列の中にdoubleを混ぜたい :

配列変数の中に int と double を混在させたいのだけど、エラーが出てしまった。

double だけを列挙するのであれば、ddim を使えるようだけど…。ddim を使うと、int が記述できなくなる。

仕方ないので、double として使いたい数値は、100倍して int として入れておくことにした。取り出す際に、double(a(0, 0)) * 0.01 とでもすれば、double として扱えなくもないだろう…。

考えてみたらアセンブラで書いてた頃は、256倍なり65536倍なりして固定小数点で色々やってたので、そういう書き方をすればいいのかな。でも、この時代ににそんな書き方はしたくない…。

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

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

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

道路のデータをセグメントで持つあたりは実装できたので、カーブ処理を追加してみた。

参考ページ :

_PICO-8 を使った、以下のチュートリアル記事がとても参考になった。ありがたや。

_Creating a pseudo 3D racer
_Creating a pseudo 3D racer - part 2
_Creating a pseudo 3D racer - part 3

雛形を一つ一つ作って、そこで起きる不具合を実際に目にして、その問題を少しずつ解決していくあたりが非常に分かりやすいなと…。また、PICO-8用に書かれた各サンプルの下にある「Code」をクリックすればソースコードが全部見れるので、英文が分からなくてもソースコードを眺めていけばなんとかなりそう。

余談。PICO-8 については以下が参考になるかなと…。

_PICO-8って何? - PICO-8ゲーム開発入門(1) - AUTOMATON
_PICO-8 ゲーム開発のススメ
_PICO-8で遊ぼう!【PICO-8入門】 | INWAN'S LABO

動作画面 :

書いたサンプルの動作画面は以下。それらしくカーブが表示されている、ような気がする。




  • カーソルキーの上下で、速度を上げたり下げたりできる。
  • カーソルキーの左右は動作確認用。遠景の横方向スクロールのテスト。

ソースコード :

以下のようなソースコードになった。

_road03.hsp
    ; 疑似3D道路を描画する / Drawing pseudo 3D roads
    ; セグメントで道路を管理してカーブを実装

    #include "hspmath.as"

    #define BG0_FILE    "bg_bg0.png"
    #define BG1_FILE    "bg_bg1.png"
    #define SCR_W       640
    #define SCR_H       360
    
   ; セグメントの区切りを色分け. 0 or 1
    #define SEG_DELIMITER   0

    ; 同梱ファイル / bundled files
    #pack   BG0_FILE
    #pack   BG1_FILE
    
    #packopt name "road03"      ; exe filename
    #packopt type 0             ; generate ".exe"
    #packopt xsize SCR_W
    #packopt ysize SCR_H
    
    ; onkey goto *jobend
    
    ; 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 bg image
    bgimgid0 = 4
    buffer bgimgid0, 1280, 720
    picload BG0_FILE
    bg0w = ginfo_winx
    bg0h = ginfo_winy
    
    bgimgid1 = 5
    buffer bgimgid1, 1280, 720
    picload BG1_FILE
    bg1w = ginfo_winx
    bg1h = ginfo_winy
    
    ; セグメント作成用データ初期化用マクロ
    #define set_array(%1, %2, %3, %4, %5) \
        %1(%2, 0) = %3 :\
        %1(%2, 1) = %4 :\
        %1(%2, 2) = %5 :

    ; セグメント作成用データ
    dim segm, 12, 3
    ; set_array 配列変数名, index, count, curve, pitch
    ; curve と pitch は100倍した値。
    ; HSPは int と double を配列内で混在できないらしいので…
    set_array segm, 0, 20, 0, 0
    set_array segm, 1, 10, 50, 0
    set_array segm, 2, 60, 200, 0
    set_array segm, 3, 10, 50, 0
    set_array segm, 4, 50, 0, 100
    set_array segm, 5, 10, -100, 0
    set_array segm, 6, 30, -400, 0
    set_array segm, 7, 10, -100, 0
    set_array segm, 8, 20, 0, -100
    set_array segm, 9, 50, -100, 0
    set_array segm, 10, 25, 200, 0
    set_array segm, 11, 20, 0, 0

    ; セグメント総数を取得
    seg_max = 0
    repeat length(segm)
        seg_max += segm(cnt, 0)
    loop
    
    ; セグメントのz幅を指定
    seg_length = 20
    seg_total_length = seg_length * seg_max

    ; 参照されるセグメントデータとして展開
    dim seg, seg_max, 3
    z = 0
    i = 0
    repeat length(segm)
        lp = segm(cnt, 0)
        curve = segm(cnt, 1)
        pitch = segm(cnt, 2)
        repeat lp
            seg(i, 0) = z
            seg(i, 1) = curve
            seg(i, 2) = pitch
            z += seg_length
            i++
        loop
    loop
    
    dist = 200.0    ; 画面までの距離 / distance to screen
    
    camera_z = 0.0
    
    spd = 0.0
    spda = 0.1
    spd_max = 16.0

    xd = 0.0
    yd = 0.0
    zd = double(seg_length)
    
    bgx = 0.0
    tgt_bgx = 0.0

*mainloop

    ; ESC key to exit
    stick k, 255
    if k & 128 : goto *jobend
    
    ; check cursor key
    if k & 2 {
        ; Up key
        spd += spda
        if spd >= spd_max : spd = spd_max
    }
    if k & 8 {
        ; Down key
        spd -= (spda * 3)
        if spd <= 0.0 : spd = 0.0
    }
    if k & 1 {
        ; Left key
        bg_x -= 16
    }
    if k & 4 {
        ; Right key
        bg_x += 16
    }

    road_y = 100        ; 道路のy位置
    road_x = 300        ; 道路の幅(片側の幅)
    
    base_y = int(double(disph) * 0.5)
    h = disph - base_y

    ; 最初のセグメント番号を取得
    if camera_z = 0 {
        seg_index = 0
    } else {
        ; "\"はHSPの剰余記号。一般的なプログラミング言語なら "%" に相当
        seg_index = (int(camera_z) / seg_length) \ seg_max
    }
    
    ; カメラが居るセグメントのカーブ量を求める
    curve = double(seg(seg_index, 1)) * 0.01
    
    ; カメラがセグメント内のどの位置に居るか割合を求める
    z0 = seg(seg_index, 0)
    z1 = z0 + seg_length
    ccz = camera_z \ seg_total_length
    camz = double(ccz - z0) / double(z1 - z0)

    ; セグメント内のカメラ位置に応じて事前に横方向にある程度ずらしておく
    xd = (-camz * curve)
    yd = 0.0
    zd = double(seg_length)
    
    cx = -(xd * camz)
    ; cx = 0.0
    cy = double(road_y) + (yd * camz)
    cz = 0.0
    
    bg_x += curve * (spd * 0.5)

    redraw 0    ; 描画開始 / draw start
    gsel 0
    
    ; 背景(遠景)を描画 / draw BG
    bgw = bg1w
    bgh = bg1h
    bgx = int(double(bg_x) * 0.4) \ bgw
    bgy = bgh / 2 - base_y
    bgid = bgimgid1
    gmode 0
    gosub *draw_bg

    bgw = bg0w
    bgh = bg0h
    bgx = int(double(bg_x) * 0.5) \ bgw
    bgy = bgh / 2 - base_y
    bgid = bgimgid0
    gmode 2
    gosub *draw_bg
    
    gmode 0

    ; 道路を描画 / draw road
    
    seg_z_max = 0
    seg_distance = 96
    repeat seg_distance
        ; セグメントのz値、カーブ量、ピッチ量を取得
        idx = (seg_index + cnt) \ seg_max
        z0 = seg(idx, 0)
        curve = double(seg(idx, 1)) * 0.01
        pitch = double(seg(idx, 2)) + 0.01
        
        ; 最後のセグメントを超えて最初にループする場合、z値を調整する
        if z0 > seg_z_max : seg_z_max = z0
        if z0 < seg_z_max : z0 += seg_total_length
        
        cam_z = int(camera_z) \ seg_total_length
        z0 -= cam_z
        z1 = z0 + seg_length
        if z1 <  (dist / 4) : goto *seg_cancel
        
        if z0 = 0 : z0 = 1      ; 0で除算しないように微調整
        
        ; 画面上で描画すべきy座標位置を取得
        y0 = int(road_y * dist / z0)
        y1 = int(road_y * dist / z1)
        
        ; 画面上で描画すべき道路の幅(片側の幅)を取得
        x0 = double(road_x) * double(dist) / double(z0)
        x1 = double(road_x) * double(dist) / double(z1)

        ; 画面上でずらすべき中心線の位置を取得
        cx0 = double(cx) * double(dist) / double(z0)
        cx1 = (double(cx) + double(xd)) * double(dist) / double(z1)
        
        h = abs(y1 - y0)
        dsy = sgn(y1 - y0)
        if dsy = 0 : dsy = 1
        repeat h
            sy = y0 + (dsy * cnt)
            draw_y = sy + base_y
            
            ; 画面縦幅を超えたy座標なら描画しない
            if draw_y < 0 | draw_sy > disph : continue
            
            ; 2次元的な計算で割合を求める
            if y0 == y1 {
                p = 0.0
            } else {
                p = double(sy - y0) / double(y1 - y0)
            }
            z = (double(z1) - double(z0)) * p + double(z0)
            x = (double(x1) - double(x0)) * p + double(x0)
            center_x = (cx1 - cx0) * p + cx0
            addv = ((int(z) + int(camera_z)) / 40) & $1
            
            ; 1ラスター分を描画 / draw 1 raster
            road_w = x * 2
            draw_x = -x + (dispw / 2) + center_x
            
            kind = addv
            if SEG_DELIMITER = 1 {
                ; セグメントの区切りを色分けしたい場合
                if sy = y0 : kind = 2
            }
            gosub *draw_raster_road
        loop
        
*seg_cancel
        cx += xd
        cy += yd
        cz += zd
        
        xd += curve
        ; yd += pitch
    loop

    ; draw text
    font "Arial", 18, 1
    color 1, 1, 1
    pos 8, 4
    mes "Press cursor key"
    pos 8, disph - 32
    mes "seg_index : " + seg_index

    redraw 1    ; 描画終了 / draw end
    
    camera_z += spd
    
    await (1000 / 60)
    goto *mainloop

*draw_raster_road
    ; 道路を1ラスター分描画 / draw road 1 raster
    ; draw_x, draw_y : draw x, y
    ; road_w : road width
    ; kind : 0 or 1 or 2
    ; dispw : screen width

    ; draw ground
    if kind = 0 {
        ; color R, G, B
        color 114, 185, 66
    } else {
        color 22, 174, 63
    }
    ; boxf x0, y0, x1, y1
    boxf 0, draw_y, dispw, draw_y

    ; draw road base
    switch kind
    case 0
        color 133, 149, 158
        swbreak
    case 1
        color 149, 168, 179
        swbreak
    case 2
        color 255, 0, 0
        swbreak
    swend
    boxf draw_x, draw_y, draw_x + road_w, draw_y

    ; draw white line
    lw = double(road_w) * 48.0 / 2048.0     ; white line width

    switch kind
    case 0
        color 255, 255, 255
        
        lx = double(draw_x)
        boxf lx, draw_y, lx + lw, draw_y
        
        lx = lx + road_w - lw
        boxf lx, draw_y, lx + lw, draw_y
        
        lx = double(draw_x) + (double(road_w) * 0.5) - (lw * 0.5)
        boxf lx, draw_y, lx + lw, draw_y
        
        lx = double(draw_x) + double(road_w) * 0.25 - (lw * 0.5)
        boxf lx, draw_y, lx + lw, draw_y
        
        lx = double(draw_x) + double(road_w) * 0.75 - (lw * 0.5)
        boxf lx, draw_y, lx + lw, draw_y
        swbreak
    case 1
        color 228, 236, 252
        
        lx = double(draw_x) + lw
        boxf lx, draw_y, lx + lw, draw_y
        
        lx = double(draw_x) + road_w - (lw * 2)
        boxf lx, draw_y, lx + lw, draw_y
        swbreak
    swend
    
    return

*draw_bg
    ; BGを1枚描画 / draw BG. 1 layer
    ; bgid : bg image buffer id
    ; bgx, bgy : bg position
    ; bgw, bgh : bg image width, height
    ; dispw, disph : screen width, height
    if bgx >= 0 & bgx < (bgw - dispw) {
        pos 0,0
        gcopy bgid, bgx, bgy, dispw, disph
    } else {
        if bgx < 0 {
            w = -bgx
            pos 0, 0
            gcopy bgid, bgw - w, bgy, w, disph
            pos w, 0
            gcopy bgid, 0, bgy, dispw - w, disph
        } else {
            w = bgw - bgx
            pos 0, 0
            gcopy bgid, bgx, bgy, w, disph
            pos (bgw - bgx), 0
            gcopy bgid, 0, bgy, dispw - w, disph
        }
    }
    return

*jobend
    end

使用画像は以下。road03.hsp と同じフォルダ階層に置く。

bg_bg0.png
_bg_bg0.png

bg_bg1.png
_bg_bg1.png

考え方 :

考え方は、前述の参考ページが分かりやすいかなと…。

_Creating a pseudo 3D racer

実のところ、カーブを表現する処理について、まだ今一つ仕組みが分かってないけど…。

とりあえず、道路データは、セグメントと呼ばれるソレで管理する。以下の画像の赤い線がセグメントの区切り部分。

ss_road03_ss02.png

セグメントが横方向に少しずつずれていくことで、カーブが表現できるということらしい。


参考ページのセグメントデータは、そのセグメントが並ぶ個数(ct)、カーブ量(tu)、の2つを並べていくけれど。
road={
 {ct=10,tu=0},
 {ct=6,tu=-1},
 {ct=8,tu=0},
 {ct=4,tu=1.5},
 {ct=10,tu=0.2},
 {ct=4,tu=0},
 {ct=5,tu=-1},
}

今回はそれに近い元データを一旦展開(?)して、ベタなセグメントの並びを作ってから処理するようにしてみた。

about_segment_ss01.png

こうしておけば、z値とどのセグメントが対応してるか計算しやすくなるかなと…。メモリは多少食うけれど。


さて。各セグメントはz値を持っている。もしくは、セグメントのインデックス番号に、1セグメント当たりのz幅をかけてやれば、そのセグメントのz値を求めることができる。そして、道路の幅は今回一定としているので…。各セグメントのz値と道路幅を透視変換してやれば、各セグメントの区切りに相当する線が画面上のどのあたりに位置するかを求めることができる。

ss_road03_ss03.png


セグメント[n] と、セグメント[n+1]、二本の水平線の、画面上での位置を得ることができれば…。その二本の線で作られる台形を塗り潰すように描画してやることで、1セグメント分の道路を描画できる。

about_segment_ss02.png

台形の塗り潰しは、HSP の場合、line で線を引いても、boxf で矩形塗り潰しをしても、どちらでもOK。横一直線 ―― 1ラスター分の塗り潰しが可能なら、それを台形の縦幅分繰り返すことで、台形の塗り潰しはできる。

これを、画面に出ているセグメント個数分繰り返せば、道路が描画できる。

また、セグメント[n」に対して、セグメント[n+1]が、横方向にある程度ずれていれば、そこの部分だけ道路が傾いているように見える。昔のレースゲームの道路は横方向のラスタースクロールをすることでそれらしく見せることができていた、というのはそういう話だろうなと。

疑問点その1 :

ここでちょっと気になった。本当にセグメント単位で台形の形を求めて、そこを塗り潰すだけでいいのだろうか…? そんな処理をしたら、カーブにさしかかった時、道路がカクカクした形に見えたりしないだろうか。細かい直線で道路が作られているように見えてしまって、なんだかイマイチだったりしないか…。

しかし実際に試してみたら、パッと見た感じ、それほど気にならなかったので、まあいいか、と。

考えてみたら、現実世界の道路だって、道路の端にある縁石の一つ一つ、側溝の蓋の一つ一つなどは、カーブに沿って曲線を描く形になっていない。縁石も、側溝も、直線で構成されているなと…。だけど道路を走っていて、カーブではちゃんと道路が曲がっているように見えているわけだから、道路のカーブが細かい直線の並びで作られていたとしても案外気にならないのかもしれない。

疑問点その2 :

もう一点気になった。台形の形を求めた後、台形内のラスター単位でz値を求めて、そのz値に応じて道路の白線を描いたり描かなかったりするようにしてみたのだけど。その処理は、3Dで計算してるわけじゃなくて、2Dで計算してるわけで…。そのことで見た目がおかしくなったりしないのだろうか?

これも、実際に試してみたら全然気にならなかったので、まあいいか、と。

考えてみたら、プレステ1やセガサターンの頃だって、各ポリゴン内に描かれるテクスチャは単に2D的な変形で塗り潰していたけれど、それほど気にならなかったよなと…。いやまあ、そのポリゴンが画面に大きく表示された時は「ギャーッ」って感じではあったけど、面積が小さければほとんど気にならなかったし。

先ほどの直線云々の話もそうだけど、面積だの幅だのがそれなりに小さければ、このあたりは案外気にならないのだろう。たぶん。

カーブに入った時のガクガク感 :

カーブに入ると道路が急に曲がったような感じがする。本来なら、少しずつ曲がっていって、本来の曲がり具合になってから、また徐々に曲がりが少なくなっていくように感じられるほうがいいだろうなと…。

そのあたりは、セグメントデータを展開するあたりで手を加えれば多少は改善できるかもしれない。カーブ量を持っているセグメントにさしかかったら、イージングを使って少しずつ本来の角度(ずれ具合)に近づくようにセグメントを並べていけば滑らかさを付加できるのではないかと…。

たしか、現実世界の道路も、カーブに入ったら急に曲がるようにはなってないはず。カーブに入るところ、出るところで、少しずつ曲がり具合が増減するようになっていた記憶がある。そういう設計になってないダメダメな道路は、車が曲がり切れずに事故が起きる確率が高いのだとか。

遠景もスクロールさせてみた :

試しに、カーブに差し掛かったら遠景も横スクロールするようにしてみた。セグメントのカーブ量を遠景BGの横スクロール量に加算してみたけど、これでいいのだろうか…。もっと違う処理のほうがらしく見えないか…。

せっかく疑似3Dでやっていることだし、遠景を2つにわけて、雲の部分と山の部分のスクロール量を変えて、多重スクロールを ―― パララックス(parallax、視差)スクロールを試みたのだけど。なんだかあまり効果が感じられないというか、不自然さが増してしまった気もするなと…。

既存のレースゲームの動画を眺めて遠景スクロールはどうしているのか確認してみたけれど、一枚絵をスクロールさせてる事例、パララックススクロールにしてる事例、どちらもあるのだよな…。

余談。デフォルメ派とリアル派 :

ここからは余談だけど。本来、リアルに考えたら、遠景なんだから別々にスクロールするはずはないのだよな…。めちゃくちゃ遠くにある風景なのだから視差を感じられる動きになるわけがない。ただ、遠景がスクロールしてますよ感を誇張、というかデフォルメするために、ここはあえて嘘をついて別々にスクロールさせるのもアリと言えばアリ、とも思っていて…。このあたり、大昔に関わった某ゲームの一シーンを思い出したりもする。担当プログラマーさんは、リアルに考えたら遠景は一枚絵でスクロールするはず、と主張してた気がするのだけど、カーブのスピード感を増すために、別々に、かつ、リアルではない速度で動かしたほうが、と自分が主張してしまって…。当時の自分の主張は正しかったのかどうか、間違っていたのではないかと、実は未だに、ふとした拍子に悩み始めてしまったりする。

せっかくの疑似3Dだし、しかもゲームなんだから、いっそ思い切って誇張したほうが、という考えもアリじゃないのかと思うのだけど、たとえ疑似であってもできる範囲でリアルに見えるように、というのもアリだよなとも思えるし。

ゲームに限らず、漫画やアニメ等もそうだろうけど。娯楽商品関係には、色々な答えがあるけれどどれも正解と言えば正解、という場面があって…。そんなとき何を判断基準にしてアリナシを決めていくか、というのがちょっと悩ましいよなと。まあ、最終的には「お客さんが一番楽しめそうなのはどれか」で考えるのが理想だろうけど。それもまた、「デフォルメしたほうが楽しめるよ」派と「リアルにしたほうが楽しめるよ」派が…。

もっとも、ゲームに限って言えば、今の時代は疑似3Dなんてやらなくても3Dでゲーム画面が作れるわけで、なのにあえて疑似3Dを選ぶということは、それはもう最初からデフォルメして見せる気満々だから、ということだよなと。リアルにしたいなら、まずは疑似3Dを選ばないのが妥当だろう…。

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

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

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

セグメントデータで道路を管理して、カーブの表現も出せるようになったので、ビルボード(拡大縮小スプライト相当)も追加してみようと思い立った。セグメント1つにつき、ビルボード1つを割り当てて管理すれば、それっぽくならないかと。

その前に、ビルボード用の画像を作らないといけない。GIMP 2.10.34 や EDGE2 1.19 dev006 を使って作業を始めたけれど、この作業で時間がかかってしまって…。今日は画像作成だけで終わりそう。

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

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

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

ビルボード(スプライト相当)用に使えそうな画像を多少は作れたので、ビルボード描画処理も付け加えてみた。こんな感じになった。




ちなみに、ビルボードと言うのは、日本語だと「立て看板」になるのかな…。この手のプログラムでは、常にカメラを向いているポリゴンのことをビルボードと呼ぶ。まあ、今回は、単にz値に応じて拡大縮小するスプライト相当なのだけど…。

ビルボードについては、以下のページの解説が分かりやすいかもしれない。

_【ゲーム】ビルボード

ソース :

ソースコードは以下。

_road04.hsp
_road04.hsp (色分け表示)

ソースが長くなってきたので、この日記ページにコピペするのは厳しくなってきた…。色分け表示してくれる JavaScript、 _HSP Syntax Highlight を使わせてもらって、別のhtml として置いてみたけど、表示出来ているだろうか。

使用画像は以下。.hsp と同じフォルダ階層に置いておく。

bg_bg0.png
_bg_bg0.png

bg_bg1.png
_bg_bg1.png

trees.png
_trees.png

ビルボード用画像は自作したものなので、自由に使ってください。CC0 / Public Domain ってことで。

今回やったこと :

各ビルボードは、1つのセグメントにつき、1枚のビルボードを持てるように管理してる。もしかすると、道路の右、左、真ん中に、ビルボードを持てるようにしたほうがいいのかもしれないけれど…。参考にしたページでは、そういう感じでデータを持っているようだし…。

_Creating a pseudo 3D racer - part 2


ビルボード(スプライト)の拡大縮小描画は、gzoom を使っている。そのあたりは、以前書いたサンプルその他が参考になるはず。

_HSPのgzoomで透明色があるように見せかけるソレについて


今まで、各セグメントは手前から奥に向かって描画していたのだけど。ビルボードを描画する際は、奥から手前に向けて描画していくほうが都合がいい。遠くにあるビルボードと、近くにあるビルボードが重なった時、近くにあるビルボードで遠くにあるビルボードを上書き・塗り潰したほうが見た目がそれっぽくなる。

about_billboard_ss01.png

そこで、セグメントの描画についても、奥から手前に向かって描画していくように変更してみた。ただ、各セグメントの位置や形を求めるためには、手前から奥に向かって計算していかないといけないので、一旦、手前から奥に向かって計算してみて、そこで得られたセグメントの台形相当の形をバッファに記録しておいて、それを描画時に奥から手前に向けて描画する、という処理にしてある。

課題 :

今のところ、各ビルボードは、256x256のサイズで決め打ちして処理しているけれど。ビルボードの形によっては、横長、縦長、小さくても済むモノ、大きくないと困るモノ、色々あるので…。サイズは固定にしないで、どのビルボードがテクスチャ内のどの範囲なのか指定するデータを別途持って、それぞれ違うサイズで管理したほうがいいのかもしれない。

60FPSで動かしたら、CPU Ryzen 5 5600X の環境でも処理落ちしてる感じになってしまった。タスクマネージャで確認したら、CPUコア1つ分が負荷100%に近い。30FPSにすれば、まあ、なんとか…。おそらくだけど、各ビルボードの拡大描画で重くなってるのかなと。一旦、各ビルボードの全ドットをまるっと拡大描画して、そこから画面にコピーしてるあたりで無駄な処理をしてるはず。実際に画面に描画される範囲を考慮して、元画像内の適切な範囲を、適切なサイズに拡大描画すれば処理の重さも改善されるかもしれない。 *1

画像素材 :

せっかくだから、ビルボード用画像の元画像も置いておきます。使えそうなら自由に使ってください。CC0 / Public Domain ってことで。

beam01_1024x1024.png
_beam01_1024x1024.png

grass02_edit02.png
_grass02_edit02.png

grass07_edit01.png
_grass07_edit01.png

roadsign_board.png
_roadsign_board.png

roadsign_board_and_pole.png
_roadsign_board_and_pole.png


余談。草むらを作りたくて、久々に Vue 5 Easel を起動して作業した。使い方を忘れていて時間がかかった上に、なかなか望み通りの画像は得られなかったけど…。とりあえず、以下のような感じで、欲しいオブジェクトの後ろに単色の箱を置いてレンダリング。GIMP 2.10.34 で青色だけ透明化。みたいな。

grass07.png

作業が終わった後で知ったけれど、GIMP 2.10 の「色を透明度に」の仕様が変わっていたのだな…。

_GIMP 2.10.8 において指定の色を透明度にする機能の仕様が変わっていて戸惑った件 | ゆとり院卒Life
_8.34. 色を透明度に...

もしかすると自分、色域指定で選択範囲を作って削除、みたいな感じで作業してたのだろうか。

*1: DirectX や OpenGL を使うライブラリで描画すればCPUの負荷を増やさずに描画できるだろうけど、今回は最終的にスクリーンセーバにしてみることを念頭において作業しているので…。

#2 [nitijyou] 玄関の照明がおかしい

数日前から、玄関の照明が点いたり消えたりを繰り返してる。何かが寿命になったんだろうけど。

今朝、状態を調べてみた。高い場所に設置されてるので、脚立を使って作業。ガラス製のカバーを、上から見て反時計方向に回したら、カバーを外せた。

中には、Uの形をした蛍光灯と、点灯管 FG-1E が入っていた。

点灯管 FG-1E を新しいものと交換してみたけれど、相変わらず点いたり消えたりする。点灯管の寿命というわけではないようだな…。蛍光灯の寿命だろうか。それとも器具自体の寿命だろうか。

蛍光灯について :

蛍光灯の表面には、「National 電球色 FUL 9 LE ME9ワット」と書いてあった。型番でググっても出てこないけれど、おそらく、「コンパクト蛍光灯 U型蛍光灯」という商品ジャンルではなかろうか。

FUL9EX という製品が昔はあったらしいけど、生産終了品扱いになってる。ただ、代替品として、ツイン蛍光灯 Panasonic FPL9EX-NF3、FPL9EX-LF3、 が使えるらしい。前者が昼白色。後者が電球色。

_FPL9EXNF3 | 照明器具検索 | 照明器具 | Panasonic
必ず専用器具でご使用ください。ツイン1(6形・9形・13形・18形)はU形蛍光灯と互換性があります。

たしかに、U型蛍光灯の代わりに使えるようだなと…。しかし、このツイン蛍光灯も、今では入手が少し難しいようで…。

ヨドバシカメラで FPL9EXNJF3 という型番も見かけたけど、これは何が違うのか…?

_【蛍光灯】品番の記載箇所、見方を教えてください。 - 蛍光灯・放電灯 - Panasonic
(9)内部管理記号
R、F2、F3、F3D、CF3、JF3・・・などの英数記号
内部管理記号の有無で互換性には影響しない

「最後のあたりの F3 とか JF3 は気にしなくてよろしい」ということでいいのかな。

使える点灯管について :

FPL9EXNF3 の仕様書PDFを眺めたら、以下の記述があった。
  • 適合点灯管 : FG-7EL, FG-7PL
  • 適合電子点灯管 : FE7E, FE1E

FG-1E は使えないのだろうか…?

ググった感じでは、口金という、点灯管を差し込む部分の大きさは、FG-7EL も FG-1E も、どちらもE17型で同じらしい。

_グローランプについて FG-1E FG-7E FG-4P この3つはどのようなもの... - 教えて! 住まいの先生 - Yahoo!不動産
  • FG-7E は直管蛍光灯(棒のような形の蛍光灯)専用。
  • FG-1E は直管蛍光灯と環形蛍光灯(ドーナツのような丸い蛍光灯)に対応。

FG-1E なら二種類の蛍光灯に対応してるのだな…。でも、なぜ FPL9EXNF3 の仕様書に記述がないのか。罠があるのか…?

親父さんがケーズデンキで代替品を買ってきた :

どこで購入したのものかと悩んでたけれど。夕方、親父さんが、「ケーズデンキで代わりになる蛍光灯を買ってきて取り付けておいたぞ」と。

なんでも、今まで使ってた蛍光灯をケーズデンキに持っていって同じものが欲しいと言ったら生産終了品と伝えられて困ったけれど、たぶんこれが代わりに使えると教えてもらった品を買ってきたらしい。

パッケージを確認したら、ヨドバシカメラで扱ってるものと同様、FPL9EXNJF3 (FPL9EX-N JF3) だった。2023/09 の時点では、ケーズデンキ、ヨドバシカメラに、まだ在庫が少しだけ残ってる、ということになるのかな。

点灯管は FG-1E のままだけど、フツーに蛍光灯が点いてしまった。FG-1E も直管蛍光灯に対応してるらしいし、一応使えるということだろうか。使い続けて問題があるのかどうかは分からんけど。

2023/09/09追記。点灯管を購入 :

ケーズデンキで、点灯管 Panasonic FG-7EL F2/X (FG7ELF2X) を買ってきた。150円ぐらいだった気がする。

パッケージ表とパッケージ裏に、利用できる蛍光灯の種類がちゃんと書いてあった。

fg7el_ss01.jpg

fg7el_ss02.jpg
  • FG7ELF2X
  • 適合ランプ : 蛍光灯 4〜10形
  • 直管蛍光灯 : 4,6,8,10形
  • 丸形蛍光灯 : 9形
  • ツイン蛍光灯 : 4,6,9形
  • 作動回数 : 約18000回

自宅にあった、Panasonic FG-1EL/2P (FG1EL2P)のパッケージも確認してみた。そちらにも利用できる蛍光灯の種類がちゃんと書いてあった。

fg1el_ss01.jpg

fg1el_ss02.jpg
  • FG1EL2P
  • 適合ランプ : 蛍光灯10〜30形
  • 直管蛍光灯 : 10,15,20,30形
  • 丸形蛍光灯 : 15,20,30形
  • ツイン蛍光灯 : 13,18,27形
  • 作動回数 : 約18000回

要するに、以下のような使い分けをせよ、ということらしい。たぶん。
  • 小さい蛍光灯 → FG-7E
  • 大きい蛍光灯 → FG-1E

つまり、昨日親父さんが購入した、ツイン蛍光灯 9形は、FG-7EL、FE-7E を使うべし、ということなのだな…。わざわざこうしてパッケージに記載されているということは、ツイン蛍光灯 9形に FG-1E を使わないでほしいということなのだろう…。問題無く使えるなら、FG-1E のパッケージにも、その旨が記載されているはずだし。

2023/09/11追記 :

玄関の照明の点灯管を、FG-1EL から FG-7EL に交換しておいた。これで安心して使えそうかなと…。

余談。電子点灯管の適正価格が気になる。

FG-7EL のパッケージには、「従来製品より3倍長持ち」と書いてある。そして、電子点灯管 FE-7E のパッケージには、「従来製品より10倍長持ち」と書いてある。

ケーズデンキの店頭で眺めた感じでは、3倍長持ちする FG-7EL は 150円。10倍長持ちする FE-7E は 約800円。本来なら、10倍長持ちする製品は、500円ぐらいが妥当なのではなかろうか…。800円では割高な気がする…。

いやまあ、電子点灯管はスイッチを入れるとすぐに蛍光灯がつくのが売りらしいので、その利便性に300円払うかどうかという話になるのかもしれんけど。というか、ツイン型蛍光灯 + 点灯管をLEDに置き換えられる製品を出してほしい気もするのだけど…。もっとも、器具の寿命等も絡んでくるからそういうのを出しても割に合わないのだろうか。

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

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

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

坂道を表現しようとして手を入れているところ。以下の解説ページがとても参考になった。

_Creating a pseudo 3D racer - part 3

各セグメントには、坂道にするためのピッチ量も持たせておくのだけど、上記のページの例ではその値が線形補間で少しずつ変化していくようにしてあるようだなと…。自分が書いてるソレは、大雑把なセグメントデータから、ベタで並んでるセグメントデータに展開させてから使っているので、その展開処理をするところで、線形補間で得られた値を持たせるようにしてみた。

もしかすると線形補間の代わりにイージングを使えばもっと滑らかな見た目になるのでは、と思えてきたので試しにイージングで補間値を求める処理も入れてみたけど、線形補間で十分っぽい感じがする…。ちなみに HSP にはイージングをするための命令があるようで、それを知らずに自分で式を書いてしまった…。

_OHDL - setease

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: ソースの最初のあたりのコメントアウトを変更すればウインドウサイズを変更できる。

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

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

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

1つのスプライト画像サイズを 256x256 にしていたけれど、サイズが小さくて画面に描画した時に見た目がボコボコしてる感じがしてきたので、256x256 から 512x512 にするべく画像を再作成中。

縮小描画と市松模様 :

自分はドット画っぽい見た目というか、市松模様(ディザパターン、メッシュ)が大好きな変人なので、フルカラー画像をディザパターン付きで16〜32色ぐらいに減色してからドット修正、みたいな感じでスプライト用画像を作成していたのだけど。例えば半透明っぽく見せたいところはメッシュにしてみたり、とか…。

しかし、画面に出してみたら、なんだか酷い見た目になってしまって…。

考えてみたら、線形補間すら使わない、単純な拡大縮小(最近傍補間、Nearest neighbor)をした場合、拡大描画はともかくとして、縮小描画をすると市松模様は酷いことになるわなと…。

about_pixelart_scale_ss01.png

等倍で表示される状況なら問題無いけど、各画像を拡大縮小する可能性があるなら…。1ドット単位でこだわったドット画を描いてしまうと、縮小した時、元のシルエットすら分らない奇天烈な見た目になってしまう…。もちろん、メッシュを使った半透明なんて、効果としてはほとんど期待できない。

少ない色数でどうにかしようとするから市松模様を使うことになるし、市松模様を使うから縮小描画時におかしなことになるのだよな…。ここはフルカラーでスプライト画像を用意したほうがまだマシかもしれない。そんなわけで、またまた画像を再作成する羽目になった。

もしかすると、縮小描画する可能性があるドット画は、あらかじめ、少々のぼかしフィルタをかけておく、という手もあるかなと。クッキリ感は無くなってしまうけれど、ソレが画面内でそこそこの速度で動いてるなら気にならないかもしれないし。

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

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

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

仮想画面の解像度を変更した際に、 BG/遠景の見た目が変わってしまっていたので、HSP の gzoom を使って拡大縮小描画をして、見た目を合わせようとしているところ。しかし、gzoom に与えるべき数値を計算するあたりで頭がこんがらがってきた。とりあえず、BG表示しかしないテストプログラムを書いて実験しよう…。

moduleとdeffunc :

HSPは基本的に、変数が全てグローバル変数になってしまう。各処理の中でしか使わない変数についてはローカル変数(局所変数)にしたいのだけど、何か手は無いものか。

そのあたりをググっていたら、#module と #deffunc を使えばどうにかなりそうだと分かってきた。HSP 3.0以降で使えるらしい。

_HSP3 モジュール機能ガイド
_OHDL - #deffunc
_HSPで関数や局所変数を使いたい
_HSP3.0-変数の有効範囲

#module
#deffunc test int a
    b = a + 1
    ; 何か処理
    return
#global

要するに、#module、#deffunc と #global で挟み込めば、その中で用意した変数は他から見えなくなるのだな…。

ただし、外で用意した変数も中から見えなくなるので、処理に必要な変数は引数として全部渡すようにしないといけないのだろう。一応、「変数名@」と書くことで、モジュール外の変数を参照することもできるようではあるけど、推奨はされてない模様。

剰余の結果がわからない :

HSP は、「3 \ 2」といった感じで、「\」を使うと剰余(余り)を求めることができる。一般的なプログラミング言語なら、「%」を使うことが多いだろうか。「3 % 2」みたいな書き方が多い、そんなイメージがあるのだけど。

さておき。プラス値はともかく、マイナス値に対して剰余を求めたらどうなるのかが分からなかったので、テストプログラムを書いて調べてみた。

; 剰余の結果がどうなるかテスト

    #packopt name "mod_test"    ; exe filename
    #packopt type 0             ; generate ".exe"

    onkey goto *jobend
    
*mainloop
    v0 = -41
    v1 = 20
    
    cls 4
    
    font "Arial", 18, 1
    color 255, 255, 255
    pos 4, 4
    mes "mod : " + v0 + " , " + v1 + " = " + int(v0 \ v1)
    
    await (1000 / 60)
    goto *mainloop
    
*jobend
    end

ss_mod_tes_ss01.png

マイナス値が返ってくるのだな。

このあたり、Python の IDLE や、Ruby の irb のように、対話形式で HSP の言語仕様を確認できる何かは無いのだろうか。

余談。Python IDLE や Ruby irb で -41 % 20 をしたら 19 になった。これが C言語なら、試してないけどマイナス値になるそうで。プログラミング言語によって結果が違ってくるのだな。

_【C言語】負の値に対する剰余演算の結果まとめ | だえうホームページ

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

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

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

一応、BG/遠景を、仮想画面の解像度に合わせて縮小描画させつつスクロールできるようにはなったのだけど、目で見て分かるぐらいに処理落ちが増えてしまった。元画像から縮小しながら 1280x720 の面積で、多重スクロールのためにBGを2枚描画するのは、今時のCPUで処理しても厳しいものがあるのだなと…。

DircetX や OpenGL を使ってGPUに描画させればあっさり状況は変わりそうだけど、後々スクリーンセーバにしたいと考えているので…。HSP でスクリーンセーバを作る際、DirectX や OpenGL が使えるのかどうかがよく分からなくて、おそらくは CPU で真面目に計算して拡大縮小描画をしているのであろう gzoom命令を使ってるという…。

ここまで遅くなるのでは、何か策を打たないといけない気がする。 そのあたりを試してみようかなと。

余談。上記の方針を立てて画像の再作成作業を始めたら、メインPCがブルースクリーン(BSOD)に。最近BSODは見かけなかったのだけどなあ…。ちょうど Windows Update のタイミングだったようで、そのあたりが影響してる気がする…。

テストプログラムを置いておく :

一応、2枚のBG画像を縮小描画しながらスクロールさせるテストプログラムを置いておく。

_bgscroll.hsp
; BGスクロールのテスト
;
; Left, Right, Up, Down key : 表示位置変更
; Z key : 仮想画面の解像度変更
;
; 2023/09/13 by mieki256

    ; 実画面解像度
    #define SCR_W       640
    #define SCR_H       360
    ; #define SCR_W       1280
    ; #define SCR_H       720
    ; #define SCR_W       1600
    ; #define SCR_H       900
    ; #define SCR_W       1200
    ; #define SCR_H       900
    ; #define SCR_W       1920
    ; #define SCR_H       1080

    #define set_array_n2(%1, %2, %3, %4) \
        %1(%2, 0) = %3 :\
        %1(%2, 1) = %4 :
    
    ; 仮想画面解像度
    dim vscr_size, 6, 2
    set_array_n2 vscr_size, 0,  640, 360
    set_array_n2 vscr_size, 1,  800, 450
    set_array_n2 vscr_size, 2, 1280, 720
    set_array_n2 vscr_size, 3,  320, 180
    set_array_n2 vscr_size, 4,  480, 270
    set_array_n2 vscr_size, 5,  512, 288
    ; set_array_n2 vscr_size, 6, 1920, 1080
    
    vscr_size_idx = 0

    VSCR_W_MAX = 1920
    VSCR_H_MAX = 1080

    ; 同梱ファイル / bundled files
    #define BG0_FILE    "bg_bg0.png"
    #define BG1_FILE    "bg_bg1.png"
    ; #define BG0_FILE    "bg_bg0_orig.png"
    ; #define BG1_FILE    "bg_bg1_orig.png"
    #pack   BG0_FILE
    #pack   BG1_FILE

    #packopt name "bgscroll"    ; exe filename
    #packopt type 0             ; generate ".exe"
    #packopt xsize SCR_W
    #packopt ysize SCR_H

    ; get windows size
    screen 0, SCR_W, SCR_H, 0
    gsel 0
    screen_w = ginfo_winx
    screen_h = ginfo_winy
    cls 4
    
    ; init virtual screen buffer
    vscrbufid = 1
    buffer vscrbufid, VSCR_W_MAX, VSCR_H_MAX
    dispw = vscr_size(vscr_size_idx, 0)
    disph = vscr_size(vscr_size_idx, 1)

    ; load bg image
    dim bgimgid, 2
    dim bgw, 2
    dim bgh, 2
    dim bgfilename, 2
    
    bgfilename(0) = BG0_FILE
    bgfilename(1) = BG1_FILE
    
    repeat 2
        bgimgid(cnt) = 4 + cnt
        buffer bgimgid(cnt), 4096, 2048
        picload bgfilename(cnt)
        bgw(cnt) = ginfo_winx
        bgh(cnt) = ginfo_winy
    loop
    
    ; init temporary image buffer
    tmpid = 7
    buffer tmpid, 4096, 4096

    ; bg scroll. 0.0 - 1.0
    bg_x = 0.0
    bg_y = 0.0
    
    vscr_change = 0
    nowframerate = 60.0

*mainloop
    #define KEY_ESC     128
    #define KEY_UP      2
    #define KEY_DOWN    8
    #define KEY_LEFT    1
    #define KEY_RIGHT   4
    #define KEY_Z       2048
    #define KEY_X       4096
    #define KEY_PRESS   (KEY_UP + KEY_DOWN + KEY_LEFT + KEY_RIGHT)
    
    stick k, KEY_PRESS

    ; ESC key to exit
    if k & KEY_ESC : goto *jobend

    ; 仮想画面サイズを変更
    if k & KEY_Z {
        if vscr_change == 0 {
            vscr_change = 1
            vscr_size_idx = (vscr_size_idx + 1) \ length(vscr_size)
            dispw = vscr_size(vscr_size_idx, 0)
            disph = vscr_size(vscr_size_idx, 1)
        }
    } else {
        vscr_change = 0
    }
    
    ; check cursor key
    spd = 1.0 / (nowframerate * 1.0)
    if k & KEY_UP : bg_y -= spd
    if k & KEY_DOWN : bg_y += spd
    if k & KEY_LEFT : bg_x -= spd
    if k & KEY_RIGHT : bg_x += spd
    
    if bg_y < -1.0 : bg_y = -1.0
    if bg_y > 1.0 : bg_y = 1.0
    
    base_y = int(double(disph) * 0.5)
    
    ; 描画開始 / draw start
    redraw 0
    gsel vscrbufid
    
    ; 背景(遠景)を描画 / draw BG
    draw_bg vscrbufid, bg_x, bg_y, bgimgid, bgw, bgh, dispw, disph, tmpid
    
    ; 仮想画面を実画面に転送
    gsel 0
    gmode gmode_gdi
    if screen_w == dispw and screen_h == disph {
        ; 等倍で転送
        pos 0, 0
        gcopy vscrbufid, 0, 0, dispw, disph
    } else {
        ; 拡大縮小して転送
        xscale = double(screen_w) / double(dispw)
        yscale = double(screen_h) / double(disph)
        
        ; if xscale < yscale : scale = xscale : else : scale = yscale
        if xscale < yscale : scale = yscale : else : scale = xscale
        
        dstw = int(double(dispw) * scale)
        dsth = int(double(disph) * scale)
        dstx = (SCR_W - dstw) / 2
        dsty = (SCR_H - dsth) / 2
        pos dstx, dsty
        gzoom dstw, dsth, vscrbufid, 0, 0, dispw, disph, 0
    }

    ; draw text
    if 1 {
        gsel 0
        font "Arial", 16, 1, 2
        objcolor 255, 255, 255
        color 1, 1, 1
        pos 4, 20
        mes "Press cursor key or Z", 4
        pos 4, 40
        mes "Res:" + dispw + "x" + disph, 4
        pos 4, 60
        mes "bg_x, bg_y = " + bg_x + ", " + bg_y, 4
    }

    redraw 1    ; 描画終了 / draw end
    
    await (1000 / int(nowframerate))
    goto *mainloop

#module

#deffunc draw_bg int dstid, double bg_x, double bg_y, array bgimgid, array bgw, array bgh, int dispw, int disph, int tmpid
    ; BGを描画 / draw BG
    ;
    ; dstid : 描画先バッファID
    ; bg_x, bg_y : bg position. 0.0 - 1.0
    ; bgimgid : bg images buffer ID. array.
    ; bgw, bgh : bg width, height. array.
    ; dispw, disph : screen width, height
    ; tmpid : 作業バッファID
    
    bx = bg_x
    by = bg_y
    if by < -1.0 : by = -1.0
    if by > 1.0 : by = 1.0
    
    repeat 2
        i = (2 - 1) - cnt
        bgid = bgimgid(i)
        bw = bgw(i)
        bh = bgh(i)
        
        shiftx = bx
        if i == 1 : shiftx *= 0.75
        
        sx = int(double(bh / 4) * shiftx) \ bw
        sy = int(double(bh / 4) * by) + (bh / 2) - (bh / 4)
        sw = (bh / 2) * dispw / disph
        sh = bh / 2
        
        dx = 0
        dy = 0
        dw = dispw
        dh = disph
        
        if sx >= 0 and (sx + sw) < bw {
            draw_by_gzoom dstid, dx, dy, dw, dh, bgid, sx, sy, sw, sh, tmpid, dispw, disph
        } else {
            if (sx + sw) > bw : sx = (sx - bw) \ bw
            w = -sx
            sw0 = w
            sx0 = bw - w
            dx0 = 0
            dw0 = w * dw / sw
            
            sw1 = sw - w
            sx1 = 0
            dx1 = dw0
            dw1 = dw - dw0
            
            draw_by_gzoom dstid, dx0, dy, dw0, dh, bgid, sx0, sy, sw0, sh, tmpid, dispw, disph
            draw_by_gzoom dstid, dx1, dy, dw1, dh, bgid, sx1, sy, sw1, sh, tmpid, dispw, disph
        }
    loop
    return
#global

#module
#deffunc draw_by_gzoom int dstid, int dstx, int dsty, int dstw, int dsth, int srcid, int srcx, int srcy, int srcw, int srch, int tmpid, int dispw, int disph
    ; 画面外にはみ出る分を考量して最小面積で画像を拡大縮小描画
    ;
    ; dstid : 描画先バッファID
    ; dstx, dsty, dstw, dsth : 描画先左上座標, 描画先サイズ
    ; srcid : 元画像バッファID
    ; srcx, srcy, srcw, scrh : 元画像左上座標, 元画像サイズ
    ; tmpid : 作業用イメージバッファID
    ; dispw, disph : 画面サイズ
    
    dx = dstx
    dy = dsty
    dw = dstw
    dh = dsth
    sx = srcx
    sy = srcy
    sw = srcw
    sh = srch
    
    if dx >= dispw or (dx + dw) < 0 : return
    if dy >= disph or (dy + dh) < 0 : return
    
    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, srcid, 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

    ; draw text
    if 0 {
        gmode gmode_gdi
        font "Arial", 18, 1
        color 255, 255, 255
        pos 4, 80
        mes "x, y = " + dstx + ", " + dsty
        pos 4, 100
        mes "dst x, y, w, h = " + dx + ", " + dy + " ," + dw + " ," + dh
        pos 4, 120
        mes "src x, y, w, h = " + sx + ", " + sy + " ," + sw + " ," + sh
    }

    return
#global

*jobend
    end

使用画像は以下。

_bg_bg0.png
_bg_bg1.png

動作結果は以下。

ss_bgscroll_ss01.gif

今気づいたけど、奥側のBGレイヤーについては、RGB=(0,0,0) を透明色として扱う gmode gmode_rgb0 を使わずに、ベタ転送する gmode gmode_gdi を使ったほうが良かったのでは…? そうすれば、少しは処理時間が短くなったのでは…。いや、焼け石に水か…。

これまた今気づいたけど、手前側のBGレイヤーの下半分で、奥側のBGレイヤーは完全に隠されてしまうのだから、そこは奥側を描画しなくても良かったのでは…? そうすれば、少しは処理時間が短くなったのでは…。まあ、それも焼け石に水かな…。

考えてみたら、BGが1枚しかなくても、ラスタースクロール相当をすれば多重スクロールに見えるよな…。縦方向に多重スクロールさせないなら、それで十分かも。まあ、そういう画像を作らないといかんのだけど。

#2 [nitijyou] 近所の池が埋め立てられることになった

自宅近くの池が埋め立てられることになったようで、池の水が抜かれ始めていた。もう1/3ぐらいの水の量になっている。

子供の頃にフナ釣りをしていた池なので、消滅するのはなんだか残念。寂しいので、せめて写真ぐらいは残しておこうと、周囲を歩いてスマホで何枚か撮影。

撮影時に気づいたけれど、色んな鳥が池を住処にしていたようで。体が真っ青な奇麗な小鳥が枝にとまっていたり。翼を広げると1m以上ある大きな鳥が泥の上をひょこひょこと歩いていたり。そういえば昨日の夕方は、おそらく鴨が数十羽ほど池に浮かんでいたっけ。彼等はこれから別の住処を探さないといけないのだな…。

それにしても、この手の池の埋め立て云々は、一体誰が決めているのだろう。まあ、鳥達と違って人間にとっては、今となっては利用価値も少ないだろうけど。昔はこのあたり一帯が田んぼだったから水を確保するために池が必要だったはずだけど、それらの田んぼは当の昔に埋め立てられて、アパートだのマンションだの、住宅だのコンビニだのがずらりと建ってるし。阿武隈川が洪水になったら水が上がってくる場所なのに、ガンガン建てちゃって…。実際数年前にそのあたり浸水してた気がするけど…。

大雨が降った時、一気に下まで水が流れて行かないよう、この池はバッファの役目も果たしていたのではないかと思えるのだよな…。犬の散歩で池の周囲を歩いた際、周囲の丘や坂から集まってきた雨水が轟音を立てて池に噴射されてる様子を何度も目にしているし。プチ・ダム放流。みたいな。あの水量が、これからは一気に下の住宅地に流れていくのだなあ…。いや、今回埋め立てられるのは上池で、まだ下池が一応残っているから、直接住宅地まで流れるわけではないのだな。もっとも、下池は道路を作った時に、1/3〜1/4まで小さくされてしまったし。あの水量を、小さくなった下池だけで受け止められるものかな…。さて、どうなることやら。

2023/09/14追記 :

一応写真も置いておこう…。数日後には、在りし日の上池、ということになるのだろうな…。

ike_ss01.jpg

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

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

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

BG/遠景関連を修正して、BG2枚だったのを1枚に、かつ、仮想画面の解像度分、事前にBG用画像を縮小して作っておいて、メインループ内では gcopy でベタ転送(等倍描画)するようにしてみた。この修正で処理落ちが若干少なくなったような気がする。また、仮想画面解像度を変更しても、遠景の見た目がほぼ一致するようにもなった。

ソース :

ソースは以下。

_road07.hsp
_road07_hsp (色分け表示)

使用画像は以下。.hsp と同じフォルダ階層に置く。

_bg_2560x1440.jpg
_trees.png


ちなみに、BG/遠景用の画像は、 _Pixabay で配布されている以下の画像を、左右がループするように加工して使っている。2013年頃にアップロードされた画像らしい。

_Landscape Spring Summer - Free photo on Pixabay - Pixabay

#2 [gimp] GIMPで左右がループする画像を作成

GIMP 2.8.22 x86 Portable + Windows10 x64 22H2 を使って、左右がループする画像を作成する手順をメモ。

自分の場合、seamless_advanced_v1.16.py という Python-Fu (Gimp-Python) プラグインを導入して使ってる。今は亡き、registry.gimp.org で配布されてた。

_registry.gimp.org_static/registry.gimp.org/files/seamless_advanced_v1.16.py_0.txt at master - pixlsus/registry.gimp.org_static - GitHub

上記ページ内の「Raw」を右クリックして保存してもいいし、github の該当ページから zip をDLして解凍しても入手できる。


以下でも紹介されている。もしかするとコレを見て試用し始めたのかもしれないけれど記憶が無い。

_Seamless tiles maker? - Page 6 - GIMP Chat

使い方 :

導入すると、フィルタ → マップ (or カラーマッピング) → Make Seamless Advanced...、という項目が増える。

gimp_seamless_ss02.png


例えば、以下のような画像の左右をループさせたい時…。

gimp_seamless_ss01.png


件の、「Make Seamless Advanced...」 を呼び出して、横方向(Horizontal overlap)だけ数値を指定して実行。

gimp_seamless_ss03.png

ちなみに、後々修正が必要なら、Flatten を「しない」にして、レイヤー分けを維持しておいたほうがいい。Flatten を「する」にしておくとレイヤー統合される。


以下のように、左右がループしている画像になる。先ほど指定した幅分、元画像より小さくなっていることに注意。

gimp_seamless_ss04.png


レイヤー → 変形 → オフセット、で横方向にだけずらしてみると滑らかに繋がってることが分かる。まあ、なんだかおかしな見た目だったりもするけど、それでも一応、たしかに繋がっているようには見えている。

gimp_seamless_ss05.png

仕組みをメモ :

このプラグイン(スクリプト)がやっている仕組みをメモ。

まず、画像の左側から指定した幅分、画像をカットして、右側の端に重なるように、レイヤーにして上に置く。こうすることで、左側と右側が繋がっているように見えてくれるはず。

gimp_seamless_ss06.png


そのままだと置いたレイヤーのところだけ見た目が浮くので、レイヤーマスクを追加して、左のほうは透明、右のほうは不透明になるようにしている。

gimp_seamless_ss07.png


ただ、レイヤーマスクの内容を、単にグラデーションで変化させたものにすると、それもまた不自然になるので、何かの値を参考にしてレイヤーマスクの内容を作成している模様。例えば上記のような画像だと、レイヤーマスクは以下のような感じになっていた。

gimp_seamless_ss08.png

もし、仕上がりに不満があれば、レイヤーマスクをブラシで修正することで、見え方を調整できる。


ところで、この Python-Fu プラグイン、GIMP 2.8.xx なら問題無いけど、GIMP 2.10.xx で動かすと何かの警告が大量に出てくるのだよな…。それでも一応動いてるようには見えているけど。

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

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

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

道路の描画自体はイイ感じになってきた。そろそろ車の類を道路の上に出してみようかなと。せっかくだから、ゆるキャンのしまりんビーノっぽい感じの可愛いスクーターでも出してみたい。

そんな妄想をしながら関連資料をググって眺めていたのだけど、このデザインをそのまま画面に描画したら訴えられてしまうのではないかと不安になってきた。無料で公開してるプログラムなのに、訴えられたり使用料を払う羽目になったら馬鹿馬鹿しいよな…。

とは言え、スクーターでのんびりトロトロと走るイメージは捨てがたい。そこでふと、昔のスクーターなら画面に出してもいいんじゃないかと閃いた。既にスクーターの生産から撤退したメーカの、今ではもう見かけない大昔のデザインなら、どうこう言われないのではないか…。

そもそも工業製品は意匠権で守られていたような記憶があるけど、工業製品の意匠権は保護期間が20年ぐらいだった気がする。 *1 であれば、20年より前に生産終了してるスクーターのデザインなら問題無いのでは…。

ということで、「レトロスクーター」「ヴィンテージスクーター」という単語でググって画像を眺めているところ。今見ると、オシャレなデザインのスクーターが多くて、これはこれでアリかもしれない。ただ、どれも斜め前から見た写真ばかりで、真後ろから見た写真は皆無。想像で描くしかないかな…。

車やバイクを絵にする分には問題無いらしい :

昔のスクーターの画像を探してるうちに、ふと疑問が湧いた。例えば車のプラモデルなどは、実際に存在する車のデザインをそのまま再現してるけれど、ああいったものは商品として許されるのだろうか…。

そのあたりが気になってググってみたら、そもそも車を絵で描く分には問題無いらしい。

_自動車の絵が描きたい - 窓の杜
_プラモデルなどの乗り物の意匠権について質問です。 - 例えば鉄... - Yahoo!知恵袋
_プラモデルの著作権や模写の著作権ってどうなっているのですか?プラモ... - Yahoo!知恵袋
_実在する自動車を絵に描いて販売することは、著作権・意匠権的に問題ないでしょ... - Yahoo!知恵袋
_車のイラストを描いて売るというのは著作権侵害にあたるのでしょうか?... - Yahoo!知恵袋
_実在するトヨタなどの車をデザインそのまま使って絵を描いて、それをポストカード... - Yahoo!知恵袋
_漫画家志望のものです。 - 漫画に自動車を入れたいのですが、そのままト... - Yahoo!知恵袋
_デザイン業界がざわめいた!? 130年ぶりの意匠法大改正 岡本健太郎|コラム | 骨董通り法律事務所 For the Arts
_【2020年4月1日施行】意匠法改正で、意匠権制度はどうなった?【知財タイムズ】
_もしもバイクや車のデザインが作品ならカスタムは犯罪になる話 - きぴろの日記

  • 車やバイクなどの大量生産される工業製品のデザインは、著作権で保護されない。その代わり、意匠権で保護される。
  • 意匠権は、しかるべきところに申請して認定されないと主張できない。
  • 意匠権は25年保護される。以前は20年だったけど、近年の法改正で期間が伸びてしまった。
  • 意匠権は、同じ製品ジャンルの中で模倣された時にアウト扱いになる。車やバイクであれば、別メーカがそのデザインをパクって、車やバイクを販売したら問題になる。
  • プラモデルや漫画やアニメは、車やバイクと異なるジャンルの商品なので、既に世の中にある車やバイクとそっくりのデザインが出てきても問題にならない。
もしかすると間違ってるかもしれんけど、大体こういう話なのかなと。

メーカと交渉してデザインを使用するライセンス契約を結ぶのが一番問題が無いだろうけど、法的には、そのデザインを漫画やアニメの中に出してしまっても問題無いのだな…。ということは、おそらくゲームの類もそうだろうなと。ゲームを買って、これに乗って高速道路を走れるぞとか、郊外のイオンまで買出しに行けるぞ、なんて思う人は居ないわけだし。ゲームはゲーム。車やバイクと間違えて買う人は居ない。

ただ、その車やバイクを撮影した写真を、そのまま別の何かに使おうとすると、これは著作権違反になるそうで。写真は、その写真を撮った人に著作権があるので…。どこかのサイトに載っていた車やバイクの写真画像を加工してゲームの中で表示したら、それは著作権違反でアウトになるのだろう。

アニメキャラも同様だろうなと。例えば、ゆるキャンのしまりんにしか見えないキャラが、許可も貰わずにゲームの中でしれっと表示されていたら、これも著作権違反でアウトになるのだろう。たぶん。

*1: 注意。後でググって知ったけど、近年の法律改正で、20年から25年に保護期間が伸びたらしい。

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

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

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

レトロスクーターについての覚書 :

もはや HSP とは関係ない話になっているけれど、レトロスクーターについて調べてた。どうやら、富士産業(SUBARU)のラビットというスクーターと、中日本重工業(三菱重工業) のシルバーピジョンというスクーターが、昔の日本では流行ってたようだなと…。

_ラビットスクーター - Wikipedia
_三菱・シルバーピジョン - Wikipedia

どちらも1960年代に製造終了になっているので、さすがに意匠権はもう保護されていないだろう…。このスクーターなら、デザインを真似して描いて画面に出しても問題無いのではないかな…。たぶん。 *1

ラビットのほうは、今でも走れる個体が残ってるようで、オーナーさん達がラビットに乗って集まって走行会をしている様子が YouTube にアップロードされていたりした。YouTubeで「ラビットスクーター」で検索すればそれらの動画に辿り着ける。後ろから撮影してるカットも結構あるので参考になりそう。ありがたや。

しかし、それらの動画を眺めていて、あることに気づいた。どのスクーターもかなりの速度で走ってる…。原付って30kmまでしか出せないのではなかったか…。それに道路の真ん中を堂々と走ってたりもする。原付って道路の端っこを走らないといけないのではなかったか…。

改めて調べてみたら謎が解けた。当時のスクーターは100cc、200cc台のエンジンを積んでいたのだな…。速度も、85km/h 出せる車種もあった、みたいな話が。50ccのエンジンを積んでいたのはラビットスカーレット S-102 ぐらいしかなく、しかもその S-102 は不人気でそんなに売れなかったとか…。

_富士重工ラビットスカーレット S102 | 旧き良きモノ?

ゆるキャンのしまりんのビーノの代わりに画面に出せないかと思ってたけど、レトロスクーターはスペックがもっと上なのだな…。トロトロと走るソレではなく、結構な速度でビュンビュン走るソレだから、ちょっと代わりにはならない気がしてきた…。

余談。しまりんの乗ってるスクーターはビーノと思い込んでたけど、ググってるうちに、漫画版やアニメ版に出ていたのは、あくまでビーノ風スクーターで、ビーノそのものではないと知った。現在のビーノは三代目だけど、しまりんのソレの見た目は二代目に近く、しかしエンジン音は一代目に近いとかなんとか。実写ドラマ版ではさすがに実車を用意しないといけなかったので三代目を登場させてるのだとか。

_志摩 リンの愛車!!「ゆるキャン△」で人気のヤマハ ビーノって、どんなスクーター? | モーサイ
_「ゆるキャン△」志摩リンが愛したヤマハ・ビーノ。 漫画、アニメ、ドラマの違いをマニアックな視点で熱く語る! - Fav-Log by ITmedia

アレは架空のスクーターだったのか…。

*1: もっとも、絵にする分には、今のスクーターを画面に出しても法的には問題無いはずだけど。あくまで、法的には。

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

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

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

スクーターの画像を作成中 :

もはやHSPの話ではないけれど、関連した作業内容なので一応メモ。

数少ない50ccのレトロスクーター、ラビットスカーレット S-102 を後ろから見た感じの画像を、Inkscape 1.3 x64 を使って作成中。

ゆるキャンのしまりんビーノの画像を参考にして、最初はトレースから始めてみたものの。元画像が荒かったことや、別の車種を描いているせいもあって、結果的にはほとんど描き直した感じの状態になった。元にした参考画像の痕跡は、ヘルメットのシルエットのカーブと、キャラとスクーターの見た目の比率ぐらい。

当初、Moho Pro 13.5 で作業しようとしたのだけど、描画ツールの使い方をすっかり忘れていて、これでは作業が厳しいなと。少ない制御点でパスを作ってからシェイプ作成をしたら制御点の数がやたらと増えてしまって悩んだり。何かの拍子にシェイプが二重に作られて悩んでしまったりで。これは仕様なのか。それとも自分の操作がおかしいのか。どこかの時点で再学習しないと…。いやまあ、そもそも、Moho の描画ツールってなんだか妙な仕様になってる印象もあるのだけど。一つのツールにまとめられそうな内容を一々別ツールに分けてる感じがするというか…。

一応画像はできたと思ったけれど、服装が変だなと気づいた。ゆるキャンは秋冬キャンプがテーマの作品だろうから防寒がしっかりしてる服を来てスクーターに乗るけれど、今回作ってるソレは緑が多い道路だったりするので、おそらく春や夏の服装じゃないとおかしいだろう…。しかしバイク乗りの人達が春や夏にどんな服装で走るのか分からない。そこからして調べ直すことになった。

バイク乗りの人達は、暑さ対策として、風通しが良いメッシュ地のジャンパーだかパーカーだかを着ることが多いらしい。転んだ時のことを考えて肘が露出してる服は着ないほうが良い、例えばTシャツだけなんてのは絶対にダメ、ということになっているようで。であればと、そういう感じの服に描き直してみた。コレ、楽天のサイトで実際販売されてるソレを参考にしたけど、本来なら許可を取ったりしないといかんのでは…。せめて色だけでも変えておくか…。

これで画像は完成と思ったけれど、考えてみたら、ほぼ真後ろから見た感じの画像は違うのではという気がしてきた。疑似3D道路上に表示する場合、少し高い位置から見た感じが正しいのでは…?

いや、でも、遠くにある場合はほとんど真後ろから見てる状態になるから、これでいいのかな。まあ、このあたり、実際画面に出してみないと判断がつかないわな…。

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

#1 [nitijyou] 溜まっていたRSSを消化

自分は Inoreader というRSSリーダーサービスを使わせてもらっているのだけど、気づいたら3000以上未読になっていたので、溜まっていたRSSを消化。

余談。昔は Firefox のアドオンで、何かのキーを押しながらマウスカーソルを動かすと、その軌跡上にあるリンクを一気に開けるものがあったので、それを使ってこの手のRSSをごっそりタブで開いてざっと眺めてガンガン閉じて、という感じでサクサクとチェックできていたのだけど。Firefox が昔のアドオンを切り捨てて、件のアドオンも使えなくなって、マウスの中ボタンクリックで、一つ一つのリンクをポチポチとクリックしてタブを開くことになってしまって…。なんとも面倒臭い。何かいい手は無いものか。選択範囲の中に含まれているリンクを一気に開くアドオンはあるけれど、Inoreader のページでソレをやると、クリックしてはいけない管理系のリンクまで開いてしまうので使えない…。

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

#1 [nitijyou] 自宅サーバ止めてました

雷が鳴ったので、13:50-18:30の間、自宅サーバを止めてました。申し訳ないです。

昼ぐらいから激しい雨。更に雷が鳴り始めて。雨雲レーダーを確認したらこのあたりだけ真っ赤になっていて…。ここ最近、極一部に集中して雨が降ることが多くなってきたような気が…。

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

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

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

画面内にスクーターを出してみたけれど、それらしい位置に表示させるあたりで少しハマってしまった。結局、道路(セグメント)の描画用として計算した値を、セグメントのデータ配列にも記録しておいて、それをスクーターの表示位置算出にも流用することにした。スクーターのZ値を元にして、一番近いセグメントを特定して、そのセグメントに記録されてる描画用の座標値に、スクーター用の座標値をプラスしてスクーターの描画位置を決める、みたいな感じ。

問題点その1 :

スクーターは、セグメントとセグメントの間に位置することがほとんどなので、二つのセグメントの描画位置を得て、その二つの描画位置の補間をするような感じで位置決めしているけれど…。3Dの座標を参照せず、2D座標を元にして補間しているせいか、スクーターがガタガタと動いてしまっている感じがする。

もっとも、そのガタガタ感が、スクーターの走行感を醸し出している気もするので、これはこれでアリかもしれないけれど。どうしたもんか。もっと滑らかに動くようにしたほうがいいのだろうか。でも、滑らかに動いてしまうと、滑ってる感が増しそうな気もするし…。しかし、現状では、「なんでコレ、ガタガタしてるの?」と気になりそうでもあるし…。

問題点その2 :

プレイヤーキャラに相当するスクーターについては、道路(セグメント)や木(ビルボード)を描いた後、最後に描画する感じでも問題なさそうだけど。他の車も走らせるとなると、そういうわけにはいかんよなと悩んでしまった。

道路がアップダウンする場面があるから、車が道路の奥でチラチラと見えている瞬間もあるはずで。となると、描画順を考えないと…。車を先に描画してから、道路(セグメント)と木(ビルボード)で上書き描画しないといけないなと。今は道路と木を奥から手前に向かって一気に描いているけれど、途中で車も一緒に描くような仕組みにしないと…。

さて、どうするか。各セグメントのデータ配列に、車も描画すべきかどうかを記録しておく、とか? ただ、その場合、1つのセグメントに複数の車が登録されてしまう場面もありそう。何台ぐらい追加されるのか予測もつかないから、リンク構造にしておかないといけない気もする。ただ、その複数の車も、z値に応じて描画順が絡んでくるだろうから、z値によるソート処理が必要になるのでは…?

あるいは、全てをビルボード扱いにしてしまう手もありそうだなと。セグメント一つ一つ、ビルボード一つ一つを、描画すべきオブジェクトとしてどこかに登録していって、最後にz値でソートして奥から手前に向かって描画、みたいな。どちらのほうが楽に実装できるだろうか…。

これが昔のハードウェアなら、スプライトとBGの優先順位フラグで、このあたりをどうにかするしかなかったのだろうな…。もちろんスプライトについてはz値でソートしないといかんのだろうけど…。BGより奥にあるスプライトと、BGより手前にあるスプライト、どうやって判別していたのだろう。丘、谷、丘のような道路になった時は困りそうだけど…。

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

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

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

道路と車の描画順について悩んでる。考えてみたら、車のz値が同じでも、道路を描いてから車を描くか、車を描いてから道路を描くか、という別々の状態が発生しそうな気がする…。

2023/09/22追記 :

図を描いてみた。

about_car_road_draw_order_ss01.png

横から見た図で考えてる。茶色の線が道路。オレンジの線がセグメント(=道路データ)の区切り。

各セグメント内の描画順だけを考えても、道路を描いてから車を描く、車を描いてから道路を描く、この2つがあるよなと…。

ふと気が付いた。今現在、道路の描画時、セグメントの手前がセグメントの奥より上にある時、つまりは下り坂相当のセグメントについては、そもそも道路の描画をスキップしてることを忘れてた。図で言えば、車を描いてから道路を描くべき、とされているセグメント。

道路を描いてないのだから、描画順を気にする必要は無いのでは…? つまり、どんな時も、道路を描いてから車を描く、という描画順でいいのではないかな…。

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

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

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

セグメントデータを int の配列で持っていたけど、後々計算途中の値を格納する際に double じゃないと面倒なので、全部 double にすることにした。これで描画用に別途用意していた配列は全部不要になったはず。その代わりソース内が、int(〜) だらけに…。ダサい…。

スクーターの描画位置を、2D座標を元にした計算ではなくて、3Dで計算してから透視変換で求めるように変えてみた。見た目はガクガクしない状態になったものの、今度は表示位置がおかしい…。

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

#1 [hsp][editor][notepadpp] Notepad++でHSPファイルを扱えるように設定

HSP関連の情報をググっていたら、Notepad++ でHSPファイルを扱えるようにする記事と遭遇。

_Notepad++でHSPスクリプトを編集・実行できるようにする - ウチツクシ

せっかくだから手元の環境でも設定しておくことにした。環境は、Windows10 x64 22H2 + Notepad++ 8.5.7 32bit Portable。

前述のページを参考にして作業していけばOKだけど、一応念のために手元でも手順をメモ。

色分け表示設定 :

.hspファイルを開いたら色分け表示されるようにしたい。Notepad++ 用の設定ファイルが公開されてるので利用させてもらう。ありがたや。

_Notepad++用 HSP(3.6 beta2) 自動補完キーワードとシンタックスハイライト - GitHub

上記のページで「Download ZIP」をクリックして .zip を取得。解凍すると、以下の2つのファイルが入っている。
  • hsp.xml : 入力補完用設定ファイル
  • NppHspLang.xml : 色分け表示(シンタックスハイライト)用設定ファイル

Notepad++ を起動。言語 → ユーザー定義 → 言語を定義、を選択。

hsp_notepadpp_ss01.png


インポートをクリック。NppHspLang.xml を選んでインポートする。

hsp_notepadpp_ss02.png


Notepad++ を再起動。言語 → HSP があることを確認。

hsp_notepadpp_ss03.png

.hsp ファイルを読み込んで、色付けされることを確認。もしかすると、言語 → HSP、を選ぶ必要があるかもしれない。


公開されているソレはダークモードに合わせた配色になっているようで、背景色が黒になっていた。白系に変更したい。
  1. 言語 → ユーザー定義 → 言語を定義、を選ぶ。
  2. 言語名で「HSP」を選ぶ。
  3. 「スタイル設定」というボタンをクリックすれば色その他を再設定できる。
hsp_notepadpp_ss04.png

.hspファイルを開いた状態で上記の作業をすれば、即座に反映されて見た目の色が変わっていく。設定ダイアログ上の色んな所に「スタイル設定」ボタンをがあるので、片っ端からクリックして再設定していった。

入力補完設定 :

Notepad++インストールフォルダ\plugins\APIs\ 以下に、hsp.xml をコピーする。

HSPファイルをコンパイルして実行 :

開いた .hsp を実行したい。cmptage.exe を入手する。

_GitHub - skymonsters-Ks/Cmptage: HSPスクリプトコンパイル補助ツール
_Releases - skymonsters-Ks/Cmptage - GitHub

cmptage_0.8.0.0.zip を入手して解凍。cmptage.exe を、HSPインストールフォルダにコピーする。ちなみに今回は、C:\Prog\hsp36\ 以下にコピーした。

Notepad++ を起動して、実行 → ファイル名を指定して実行。

hsp_notepadpp_ss05.png


以下を入力。
"HSPインストールフォルダ\cmptage.exe" "$(FULL_CURRENT_PATH)" /d
手元の環境では以下を入力。
"C:\Prog\hsp36\cmptage.exe" "$(FULL_CURRENT_PATH)" /d

hsp_notepadpp_ss06.png

最後の「/d」はデバッグウインドウ付きで実行することを指定している。デバッグウインドウが無くてもいいなら、「/d」は要らない。

「実行」をクリックすれば、.hspファイルのコンパイルと実行ができる。ちなみに「登録」をクリックすれば、実行メニューの下に項目として並べたり、ショートカットキーを割り当てたりできる。

hsp_notepadpp_ss07.png

関数リスト関連設定 :

.hspファイル内のラベル等を一覧表示したい。Notepad++ の場合、「関数リスト」機能を使えばそういったことができるらしい。

前述の解説ページでは、functionList.xml に色々追記することになっているけれど、Notepad++ 8.5.7 32bit Portable の時点では、設定ファイルを置く場所が違う模様。

_Notepad++ でアウトライン(目次みたいなもの)を表示させたい - Qiita
_can i use function list in Notepad++ 7.9.5? | Notepad++ Community

前提条件として、HSPの色分け表示ができている状態、つまりはユーザ定義のHSP用言語ファイルが既に存在する状態じゃないと関数リストは使えない。今回、色分け表示は前述の作業で実現できているので、条件は満たしている。

Notepad++インストールフォルダ\functionList\ 以下に、hsp.xml というファイルを作成。内容は以下。
<?xml version="1.0" encoding="UTF-8" ?>
<!--
  To learn how to make your own language parser, please check the following
  https://npp-user-manual.org/docs/function-list/
  -->
<NotepadPlus>
  <functionList>
    <parser
      displayName="HSP"
      id="hsp_function"
      commentExpr="(/\*.*?\*)/"
      >
      <function
        mainExpr="^\s*(#(mod(ule|init|term)|(def|mod)c?func|global)|\*[@\w]).*?$"
        displayMode="$functionName$"
        >
        <functionName>
          <nameExpr expr="(#|\*).*?$"/>
        </functionName>
      </function>
    </parser>
  </functionList>
</NotepadPlus>

記述内容については以下が参考になるらしいけど、英語だから何がなんだか…。

_Function List | Notepad++ User Manual


更に、Notepad++インストールフォルダ\functionList\ の中に overrideMap.xml というファイルがあるので(あったので)修正。このファイルで、どの言語設定ファイルが使われる時に、どの関数リスト設定ファイルを利用するかを指定するらしい。

自分は Notepad++ Portable版を使ってるので、overrideMap.xml が件の場所にあったけど、一般的なインストールをした場合は、%APPDATA$\Notepad++\ の中にありそうな気もする…。Win + R を叩いて、「ファイル名を指定して実行」で、「%APPDATA$\Notepad++\」を打ち込んで開いてみて確認したほうがいいのかもしれない。

overrideMap.xml の、<associationMap> 〜 </associationMap> の間のどこかに、以下を追加。
            <association id= "hsp.xml"                userDefinedLangName="HSP"/>
ユーザ定義の言語設定として、"HSP" が利用された時、hsp.xml を参照しろ、という指定だろうか。要するに、overrideMap.xml の最後のあたりは、以下のような見た目になる。
...
            <!-- ==================== User Defined Languages ============================ -->
            <association id= "krl.xml"                userDefinedLangName="KRL"/>
            <association id= "nppexec.xml"            userDefinedLangName="NppExec"/>
            <association id= "sinumerik.xml"          userDefinedLangName="Sinumerik"/>
            <association id= "universe_basic.xml"     userDefinedLangName="UniVerse BASIC"/>
            <association id= "hsp.xml"                userDefinedLangName="HSP"/>
            <!-- ======================================================================== -->
        </associationMap>
...

Notepad++ を再起動。.hsp ファイルを開いてから、表示 → 関数リスト、を選ぶと、ラベル一覧っぽいものが表示された。

hsp_notepadpp_ss08.png

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

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

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

スクーターの描画位置を3Dで計算すると妙な位置に表示されてしまってずっと悩んでいたけれど、原因が分かった。#define の定義が間違ってただけだった…。こんなしょーもないことで3日もハマっていたなんて、自分、間抜けすぎる…。

バグの原因 :

配列に x,y,z値を格納して処理しているけれど、そのままだとソース内で謎の数値が列挙されて(ハードコーティング?)、何が何やら分からなくなってしまう。そこで、配列のインデックス値を、#define を使って意味が分かる単語に置き換えていたのだけど…。
    #define SEG_CX          10  ; x方向にずらす量(3D)
    #define SEG_CY          11  ; x方向にずらす量(3D)
...
            seg(i, SEG_CX) = 0.0    ; 本来の位置からずらす量 x値
            seg(i, SEG_CY) = 0.0    ; 本来の位置からずらす量 y値

その #define で指定する値を間違えていて、妙なことになっていたという…。トホホ。
    ; 記述するインデックス値を間違えてる。コピペ時のあるあるネタ
    #define SEG_CX          10  ; x方向にずらす量(3D)
    #define SEG_CY          10  ; x方向にずらす量(3D)

バグが出にくいソースにしようとして、かえってバグを入れてしまうとか、なんだかな。HSP が構造体だの連想配列だのを使える言語仕様だったら、こんなことしなくても済んだのだろうけど…。

※ 2023/09/25追記。#enum を使えばこういうミスを防げると知った。追記終わり。

車の台数を増やしてみた :

スクーターがそれらしく表示できたので、道路上を走らせる車の台数を4台まで増やしてみた。4車線に見える道路なので、1車線につき車1台を走らせる感じ。

各車のワークには z値を持たせた。そのz値から、その車が居るはずの道路のセグメントを特定できる。

各セグメントには、車を描画するかしないかの変数を持たせることにした。今回は車を4台しか出さないつもりなので、bit単位で、車を描画するかしないかのフラグにしてみた。
0b0000xxxx
      ||||
      |||+- 1台目の車を描画
      ||+-- 2台目の車を描画
      |+--- 3台目の車を描画
      +---- 4台目の車を描画
車の台数がもっと増えてきたら、こんな管理の仕方ではマズいだろうけど、今回は数が少ないからこれでもいいかなと…。

これで、セグメント(道路)とビルボード(木)を描画するタイミングで車も描画できるようになったので、奥のほうから手前に向かってセグメント単位でアレコレ描画していけば済むようになった。

車について調べ始めた :

車の画像を作らないといかんなと、車種について調べ始めた。

ゆるキャンに出ていた感じの車がいいなとググってみたけれど、ゆるキャンに出ていたグビ姉先生の車は、スズキ ハスラーという車種らしい。画像を検索して、形を把握しようとしているところ。

2023/09/25追記 :

以下の記事を眺めていたら、#enum を使えば順々に数値を増やしていく定義ができると知った。

_HSPにおける構造体機能の代替 - Qiita
_OHDL - #enum
例 :
    #enum KAZU_A = 0    ; KAZU_Aは0になる
    #enum KAZU_B        ; KAZU_Bは1になる
    #enum KAZU_C        ; KAZU_Cは2になる

    a=KAZU_B
        ↓(展開後)
    a=1

これを使っておけば、今回のようなミスをしなくても済んだのだな…。

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

#1 [nitijyou] 右前と左前を間違えた

冬に部屋の中で来ているジャンパーの、ファスナー部分が壊れてしまって、一度締めたら開くのに苦労する状態になってしまった。ファスナー部分をハサミで切って、とりあえず左右がくっつく状態になればそれでいいかなとスナップボタンをつけてみたのだけど、実際に着てスナップボタンを閉じようとしたら、なんだか妙な感じ。

どうやら、右前と左前を間違えてつけてしまったようだなと…。右前 ―― 服を真正面から見て右側が手前になるようにつけなければいけなかったのに、今回、左前でつけてしまった…。利き腕ではない左手で力を込めるから妙な感じがしたのだな…。

_右前?左前? お洋服の前合わせ | ラ・スーラ ブログ
_Akira's Blog:左前
_ボタンの「右前」「左前」ボタンホールの位置と呼び方、その意味について | ファッションをわかりやすく説明するスタイリスト土居コウタロウ ブログ大阪梅田東京新宿

どうしよう。付け直そうか。でも面倒臭い。どうせ作業し直すなら、ファスナーを付け直すほうがいいよな…。

付け直した :

面倒臭いからこのままでいいかと思っていたけど、次第に辛くなってきて、結局付け直した。やはり利き腕の右手を使ってパチンと差し込むほうが楽だなと。

ファスナーについて少し調べた :

どうせならファスナーを付けたいなと思ってググってみたのだけど、60cmぐらいのファスナーとなると、そのへんのお店で売ってる感じではなさそうで。20cmぐらいなら以前100円ショップで探したときに目にした記憶もあるのだけど。市内の手芸店なら扱ってるかな。どうかな。

ジャンパー等につけるファスナーは、左右に分離できないと困る。そういったタイプはオープンファスナーと呼ぶ模様。ただ、必ずオープンファスナーと呼ぶわけでもないようで、「開製品」なる呼称も見かけた。それってどういう読み方をするの…?

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

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

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

画面に出すべき車の画像を、Inkscape 1.3 x64 を使って作成中。ゆるキャンに出てきたらしい車種、スズキ ハスラーと、日産ラフェスタの写真を参考にして、それっぽく見える感じがする画像を作れないかと試してるところ。

著作権が怖い :

当初、ネットから入手した車の写真画像をそのままトレースして画像を作っていたのだけど。ほぼ仕上がって、HSPのプログラムで画面に出して確認してる最中に、著作権のことを思い出した。自分が行った、このトレース作業って、著作権的にはアウトなんじゃないか…?

車のような工業製品のデザインは、著作権ではなく、意匠権で保護される。この意匠権は、同じ製品ジャンルでデザインを盗まれないようにするためのものなので、その車のデザインを絵に描いたりする分には問題無い。絵に描いた車で実際に走れるわけじゃないので…。ジャンルが違うから大丈夫。ということになっているらしい。

_自動車の絵が描きたい - 窓の杜

ただ、その車を写真に撮ると、その写真には撮影者の著作権が発生する。だから、写真を元にしてトレースしたら、これは著作権違反になりそうな気がする。たぶん。実際、雑誌や書籍に載っていた写真をトレースして漫画にしたら、撮影者から著作権違反として訴えられて面倒なことになった漫画作品の事例があったはず。 *1

_写真二次使用の著作権 - REV's blog

しかし、著作権が発生する条件、というものもあったはずだよなあ、という気もしてきた。車を真正面から、もしくは真後ろから撮っただけの写真に、著作権は発生するのだろうか? 誰がやってもそうなるし、誰でも容易にそれができる、といったものに対しては、著作権は発生しないのではなかったか…。構図が独自性を持っているとか、照明の当て方が独特とか、その場所に行くのがとにかく大変とか、要は「この人が撮影したからこそこういう写真になったんだね」「フツーの人はこんなの撮れないよね」と思えるような成果物じゃないと、著作権を主張できなかったような気もする…。このあたり、どうだったかな。

_具体的にどういうものが「著作物」になるんでしょうか? - これだけ知っとけ著作権講座
著作物 思想又は感情を創作的に表現したものであつて、文芸、学術、美術又は音楽の範囲に属するものをいう。

具体的にどういうものが「著作物」になるんでしょうか? - これだけ知っとけ著作権講座 より


「そんなの関係なくとにかく著作権は発生するよ」という主張もどこかで見たことがあるような気もするけれど、その主張を通してしまうと社会がめちゃくちゃになるよなと…。

例えば、車を真正面から撮った写真なんて昔からあるわけだけど、今から車を真正面から撮ったら、それは既存の写真作品の構図を模倣しているから著作権違反です! と言われてしまうのだろうか。そうなると、もはや誰も、今後は車を真正面から撮影することができなくなる。世の中で一番最初に車を真正面から撮った人のところに菓子折りでも持っていって、「今度出す雑誌に車を真正面から撮った写真を載せたいんです。許諾していただけませんか?」とお願いしに行くことになるのだろうか。いや、それだけじゃ済まないよな。真横から撮った構図、真後ろから撮った構図、全ての角度で、誰かしらに許諾を貰いにいかないといけない。どう考えてもそんなの狂ってる。

何にせよ、裁判沙汰になった(と語られてしまっている)漫画作品の事例を思い返すと、トレースはやっぱりダメなんじゃないか、という気がしてきたわけで…。ということで、あえて斜めから撮影した写真画像を横に置いて、真後ろから見たらおそらくこうなるのかなあ、と想像しながら画像を再作成することにした。さすがにこういう作り方なら訴えられたりはしないだろう…。

細かく描き込むとかえってマズイかも :

車の画像を作成できたので、画面に出してみたのだけど、Nearest neighbor による拡大縮小描画をしているせいか、見た目がボロボロで…。結構苦労して画像を作ったのに、この見た目は悲しい…。

Inkscape上で作業をする際、ついつい細かいところもちゃんと描こうとして、アレコレをネチネチと描き込んでしまったのだけど、かえってそれが酷い結果に繋がっているような気がしてきた。こういった、粗い拡大縮小処理を経由する画像に関しては、もっとざっくりとした、大雑把な見た目のスタイルで描かないとダメなんじゃないかな…。

もしかすると、単に矩形塗り潰しをひたすら駆使したスタイルのほうがいいのかもしれない。例えば、MZ-700版スペースハリアーのような見た目とか。いや、アレは市松模様を多用してるからアレだけど。

_古籏一浩氏の昔話【後篇】 〜 MZ-700版スペースハリアーの開発話 - Togetter
_MZ-700版スペースハリアー - YouTube


もしくは、ぴゅう太の画面みたいな荒々しい感じで…。と思ったけれど、改めて確認してみると実は結構細かいな…。なんでも、解像度が256x192ドットもあったそうで。子供心に「これはないわー」と思ったぐらいに画面が粗いイメージを持ってたんだけどな…。意外と細かい…。

_ぴゅう太 (タカラトミー)
_ぴゅう太 - Wikipedia
_ぴゅう太が発売40周年。トミーが発売したゲーム特化のホビーパソコン。『ナイトフライト』や『フロッガー』『スクランブル』などで遊んだ思い出【今日は何の日?】 | ゲーム・エンタメ最新情報のファミ通.com


いっそのこと、プログラムでその都度矩形塗り潰しをして木や車を描いちゃうのもアリだろうか。PC-9801用ターボフリーウェイみたいな、あんな感じで…。

_TURBO FreeWay
_【解説付き】PC-98 ターボフリーウェイをクリアまで - YouTube

まあ、元画像を小さくして、縮小描画ではなく、ほとんどが拡大描画になるようにしちゃう手もありそうか…。

*1: ただ、実際に裁判にまでなった事例はほとんどない、という話も見かけた。そうなる前に出版社側がその漫画作品を絶版にしたり、権利者と話し合って和解したりする場合が多いとかなんとか。「沈黙の艦隊」も、「裁判になったとよく言われてるけどアレ実は裁判にまではなってないよ」という主張をどこかで見かけたりもした。ホントかどうかは知らない。

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

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

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

拡大縮小描画に gzoom を使っていたけど、grotate や gsquare を使っても拡大縮小描画ができると今頃になって知ったので、処理速度がどのくらい違うのか試していた。

拡大縮小描画について :

今まで、HSP 3.6 で拡大縮小描画をしたかったら gzoom という命令を使うしかないのかなと思い込んでいたのだけど、その後ググってたら、grotate や gsquare という命令を使っても拡大縮小描画ができると知った。名前からして grotate は回転描画しかできないのかなと思い込んでた…。

_grotateとgzoom - HSPTV!掲示板
_gzoomにgmodeを適用する方法 - HSPTV!掲示板
_透明色付き縮小コピーのやり方がわからない! - HSPTV!掲示板
_gmodeが効かない - HSPTV!掲示板
_標準命令での解像度設定について - HSPTV!掲示板

gzoom は、RGB=(0,0,0) を透明色として扱うための gmode gmode_rgb0 の指定が反映されないので、透明部分を含んだ画像を拡大縮小描画しようとすると少し面倒なことになる。仮バッファを用意して、一旦仮バッファに gzoom で拡大縮小描画をしてから、その仮バッファの内容を gcopy で画面に転送することで透明部分を扱ってるように見せかけるのだけど、本来なら1回の描画で済みそうなところを、2回描画してるわけだから、処理も遅くなるだろうと容易に想像できるわけで…。

その点、grotate や gsquare は、gmode gmode_rgb0 の指定を反映しつつ拡大縮小描画ができるので、1回の描画で済む。その代わり、gzoom と比べると精度が粗いそうで…。

命令メリットデメリット
gzoom精度がそこそこ良いので描画結果が比較的マシ処理が重い。透明色を扱えない(gmode設定が反映されない)ので、透明部分を含む画像を扱う時は実質2回描画することになるから遅い。
grotate透明色を扱える。1回の描画で済むから処理が速い。回転描画もできる精度が粗い。描画結果はよろしくない。描画座標として中心点を指定するあたりでミスしがち
gsquare透明色を扱える。1回の描画で済むから処理が速い。四角形を任意の形で描画できる精度が粗い。描画結果はよろしくない。引数を配列で渡すあたりは少し面倒臭い

試しに、今まで gzoom で描画していた部分を、grotate や gsquare で置き換えてみた。該当部分だけ抜き出して貼ってみる。

    ; sx, sy, sw, sh : 転送元の x, y, 幅, 高さ
    ; dx, dy, dw, dh : 転送先の x, y, 幅, 高さ
    ; srcid : 転送元イメージバッファID
    ; dstid : 転送先イメージバッファID
    ; tmpid : 仮イメージバッファID

    switch zoom_kind@
    case 0
        ; gzoomで処理
        ; gzoom は透明色を扱えない(gmode設定が反映されない)ので小技が必要
        ; 一旦、仮バッファに拡大縮小描画する
        gsel tmpid
        pos 0, 0
        gzoom dw, dh, srcid, 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
        swbreak

    case 1
        ; grotateで処理
        ; grotate なら一発で透明色(RGB=(0,0,0))を扱えるので処理が速い
        ; その代わり精度が荒くて描画結果がプルプルと震える
        gsel dstid
        gmode gmode_rgb0, sw, sh            ; 転送元サイズをここで指定
        pos dx + (dw / 2), dy + (dh / 2)    ; 中心座標を転送先座標として指定
        grotate srcid, sx, sy, 0, dw, dh    ; 転送元座標、転送先サイズを指定
        swbreak

    case 2
        ; gsquareで描画
        ; gsquareも一発で透明色(RGB=(0,0,0))を扱えるので処理が速い
        ; その代わりこれも精度が荒い。プルプルする
        dim _dx, 4
        dim _dy, 4
        dim _sx, 4
        dim _sy, 4
        
        ; 転送先座標
        _dx(0) = dx
        _dy(0) = dy
        _dx(1) = dx + dw - 1
        _dy(1) = dy
        _dx(2) = dx + dw - 1
        _dy(2) = dy + dh - 1
        _dx(3) = dx
        _dy(3) = dy + dh - 1
        
        ; 転送元座標
        _sx(0) = sx
        _sy(0) = sy
        _sx(1) = sx + sw - 1
        _sy(1) = sy
        _sx(2) = sx + sw - 1
        _sy(2) = sy + sh - 1
        _sx(3) = sx
        _sy(3) = sy + sh - 1
        
        gsel dstid
        gmode gmode_rgb0
        gsquare srcid, _dx, _dy, _sx, _sy
        swbreak
    swend


grotate や gsquare で描画してみたところ、劇的に処理が軽くなった。ちなみに CPU は AMD Ryzen 5 5600X の環境。
  • gzoom 利用時は、仮想画面サイズを 1280x720 にすると 15FPSが限界だった。
  • grotate、gsquare 利用時は、仮想画面サイズを 1280x720 にしても 30FPSが出せた。
単純計算では、描画回数(描画面積)が半分になっているわけだから、半分の処理時間で済むということかなと…。さすがに60FPSは無理だったけど、30FPSなら、まあ、全然見れる雰囲気。

ただ、描画結果は少々厳しいことになった。じわじわと拡大率が変わっていく状況では、ビルボード(スプライト)がプルプルと震える…。

これが例えばアウトランシリーズのように、スゴイスピードでビュンビュン走っていく疑似3D道路だったら、そのプルプル感は全然気にならないのだけど。今回、スクーターでトロトロとのんびり走っていく雰囲気にしたいので、このプルプル感はちょっとなあ、という気もする…。しかし、この処理の軽さは捨てがたい…。gzoom ならプルプルしないけど、その代わりフレームレートを半分まで落とさないといかんし…。

FPS測定について :

実際どのくらいのFPSが出てるのか測定したいと思って、あちこちの解説記事を眺めていたのだけど。HSP 3.6 の場合、d3module という拡張プラグインの中に、FPSを取得する命令、d3getfps() があったので、試しに使ってみたところ、あっさりと表示できてしまった。これでいいんじゃないかな…。

_OHDL - d3getfps
_OHDL - sample_08_ball.hsp

昔の HSP では、このあたり自前で用意しないといけなかったようだなと…。

時間待ちをするawaitについて :

時間待ちをしてフレームレートを一定にする await についても、昔と今とでは状況が違うらしい。

昔は使っているタイマーの精度が低かったから、自前で似たような処理を書いてフレームレートの安定化を試みないといけなかったようだけど。HSP 3.31β1 の時点で使うタイマーを変えて精度が上がったようで。HSP 3.6 なら await を使うだけでもそこそこ真っ当なフレームレートになってくれる、という話を見かけた。

_hsp3関連 更新履歴
_ゲーム等を作るときのウェイトについて - HSPTV!掲示板

ちなみに await は、wait と違って、前回呼ばれてから今回呼ばれるまでの時間を測っていて、あとどのくらい sleep すればいいかをその都度変えている、とのことらしい。

_HSPのwaitとawaitの違い - まどろみの思考空間
_await命令の、説明文がわかりません。 - HSPTV!掲示板

余談。ふと思ったけど、await が、指定されたミリ秒より多い時間がかかったか、かかってないかをフラグで返してくれたら、そのフラグを見て次のフレームは描画をスキップ、といったこともできるのではなかろうか…。

でもまあ、前回のフレームからの経過時間を自前で調べて、その時間を使って各オブジェクトの移動量を求めるほうが妥当かもしれないけど。例えばLove2Dなどは、そういう感じの処理を推奨してるようだし。

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

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

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

ビルボードの種類を増やして、建物の類を表示したい。でも、どういう見た目の画像を用意したらいいのかで悩んでしまった。 そのあたり、どれがいいのかなと。

とりあえず、YouTubeで疑似3D道路を使ってるゲームの動画を眺めて、一時停止してビルボードの建物の見た目を確認してみたけれど…。まあ、色々あるなと…。

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

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

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

ビルボードの種類を増やして、建物の類を表示したい。ビルボードとして用意する画像について、既存のゲームの動画を眺めて研究中。今のところ、以下のようなタイプがありそうだなと…。

about_billboard_ss01.png

OutRunners は、もしかすると、ステージ毎に担当したグラフィッカーさんが違っていて、それでビルボード内の建物の向きも違ったりしたのかなと想像してみたりして。

Cisco Heat は、坂の有無でビル類の見た目が違ってくる。坂が無ければBだけど、坂に差し掛かると上から見たようなビルの見た目になる。坂を下ってる時は屋上の中が見えたり、坂を上ってる時は下から見上げたようなビルになる。

基準点についても悩んでしまった。ビルボードの底辺上に基準点を置くのがフツーかなと思い込んでたけど、C タイプの場合、基準点は別途指定できたほうが良さそうでもあるなと…。

道路がアップダウンして結構激しい丘や谷が発生する場合、ビルボード内の人工物の画は角度を持たないほうが良さそうな気もする。丘や谷がほとんどない道路なら、一点透視を意識して、上辺や底辺が一直線に並ぶ感じの画像にすればいいのだろうけど、坂になると見た目のガタガタ感が増すわけで…。めちゃくちゃアップダウンする OutRunners と、ほとんどアップダウンが無い Slip Stream を見比べると、そのあたりの違いを感じるというか…。

今の時代、わざわざ疑似3Dをやりたい人なんてほとんど居ないせいか、このあたりのノウハウは記事の類になってないようで、動画を見て推測していくしかなさそう…。なんだかちょっと考古学っぽい気配も…。

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

#1 [blender] blender で 3dsファイルを開きたい

無料で利用できる3DCGソフト blender で、拡張子が .3ds になっているファイルを開きたい(インポートしたい)。

環境は、Windows10 x64 22H2 + blender 3.6.4 x64 LTS。

経緯 :

ログハウスの画像を作成したい。でも、手描きで作るのは大変そう。blender を使ってレンダリングして、それを利用できないか。

幸い、ログハウスの3Dモデルデータは入手できた。archive3d (Archive3D.net) というサイトで、Free と称してモデルデータが配布されている。

_Free 3D Models and Objects Archive. Download 3ds, obj, gsm, max models
_House wooden N281214 - 3D model (*.gsm+*.3ds) for exterior 3d visualization. | Buildings and Houses
_Free 3D Models and Objects Archive. Download 3ds, obj, gsm, max models
_3Dモデル素材サイト「archive3d」使い方解説 | STYLY

件のモデルデータを利用して、POV-Ray を使ってレンダリングしてる事例もあった。

_Archive3D.netからダウンロードしたログハウスの3Dモデリングデータ4件 | KOKAのつぶやき
_Archive3D.netで入手した建物の3Dモデリングデータ、"House wooden 04 N070116" | KOKAのつぶやき

ただ、ライセンスがよく分からないあたりが不安ではあるけど…。「Free」ってどういう意味の「Free」なのか…。もっとも、これらは3Dモデルデータなのだから、再配布したり、モデルデータをゲームにそのまま持ち込んで利用したらダメだけど、3DCGソフトでレンダリングした画像をアレコレ加工して別の何かに利用するぐらいなら大丈夫なのかな、ぐらいに思っておくことにする。

※ 2023/10/01追記。その後気になってググってみたら、怪しい話がチラホラ。

_Free models for your work in Blender ain't so free... - General Forums / Blender and CG Discussions - Blender Artists Community
_Is Archive3d safe? : r/gamedev

なんだか不安になってきた。まあ、商用利用はしないほうがいいだろうな…。

3dsとgsm :

前述のサイトで配布されてるデータが .3ds と .gsm なので悩んでしまった。それってどういう種類のモデルデータ形式なんだろう。

_3DSファイルについて | Adobe
3DSファイルは、Autodesk製3DソフトウェアアプリケーションであるAutodesk 3D Studioのネイティブ形式です。このアプリケーションの最も古いファイル形式のひとつである3DSには、あらゆるデバイスでアクセス可能な3Dグラフィックに関する情報が保存されます。

3DSファイルについて | Adobe より


Autodesk 3D Studio、というのは、もしかして 3ds Max のことだろうか?


_ArchiCADライブラリ部品 - Wikipedia
GSM拡張子を持つファイルで、GDLや、2Dおよび3Dバイナリで作成されたモデルを含む

ArchiCADライブラリ部品 - Wikipedia より


.gsm は、ArchiCAD 用のファイルらしい。

blender 2.79b でインポート :

blender 2.79b なら、.3ds のインポータが標準で入っているらしい。試してみた。インポートしたファイルは、House wooden N281214.3DS。

ファイル → インポート → 3D Studio (.3ds)、を選択。

3ds_import_ss01.png


.3ds ファイルを選択して、「3DSをインポート」ボタンをクリック。

3ds_import_ss02.png


結果は以下。

3ds_import_ss03.png

なかなか悲惨なことになった…。インポート時のオプション項目で、「トランスフォームを適用」の有効無効を切り替えてみたけど、結果は変わらなかった。

blender 3.6.4 x64 LTS でインポート :

blender は、2.8x 以降、.3ds のインポート機能は省かれていたらしいのだけど、blender 3.6 から復活したらしい。

_「Blender 3.6 LTS」の新機能・改善を紹介! | CGbox
Blenderユーザーの要望にこたえる形で、レガシーな3Dフォーマットである「Autodesk 3DS」ファイルの形式を再びインポート・エクスポートできるようになりました

「Blender 3.6 LTS」の新機能・改善を紹介! | CGbox より


ならばと、blender 3.6.4 x64 LTS で試してみた。

アドオンを有効化。設定画面で、アドオンを選んで、検索欄に「3ds」と打ち込めばインポータがリストアップされる。チェックを入れて有効化。

3ds_import_ss04.png

ただ、下のほうに気になる一文が…。「Images must be in file folder, filenames are limited to DOS 8.3 format」と書いてある。画像はファイルと同じフォルダーに置いておけ、ファイル名は DOS の 8.3フォーマットしか受け付けないよ、と…。前者はともかく、後者は厳しい。入手したファイル群は長いファイル名をつけてあるんだけどなあ…。

_8.3形式 - Wikipedia


さておき、ファイル → インポート → 3D Studio (.3ds)、を選んでインポート。

3ds_import_ss05.png


オプションで、「トランスフォーム」はチェックを外してインポート。

3ds_import_ss06.png


結果は以下。

3ds_import_ss07.png

それっぽい感じでインポートされた、と思いきや、色々なパーツが妙なところに配置されてしまっている…。

Wings3D 2.2.9 x64 でインポート :

どうも blender で、.3ds を直接インポートするのは厳しい感じがしてきた。別の3DCGソフトで読み込めるなら、そちらを使ったほうがいいのだろうか。ググってみたら、無料で利用できる Wings3D も .3ds のインポートに対応しているらしい。今回は Wings3D 2.2.9 x64 を使って試してみた。

ファイル → 読み込み → 3D Studio (.3ds)、を選択。

3ds_import_ss08.png


ファイル選択の前に、オプション設定が表示される。そのままだとかなり大きな見た目で読み込まれてしまうので、読み込み時のスケールに 0.01 を指定。

3ds_import_ss09.png


ファイル選択後、インポートされた。

3ds_import_ss10.png


一見するとそれらしく読み込まれているように見えたけど、実は細かいところで問題が起きていた。今回、ドアや窓のひさし?部分がおかしくなっていた。また、ドアや窓の半数は、位置がずれていた。

3ds_import_ss11.png


この状態で、Wings3D から .obj でエクスポートすると、マテリアル情報が格納されている .mtl と、メッシュ情報の .obj の2ファイルが保存された。blender 3.6.4 x64 LTS で .obj を読み込むことはできた。

ただ、細かいところが色々おかしいので、おかしい部分を見つけて、ポリゴン一つ一つを修正していくのが面倒。

更に、テクスチャ情報は反映されない。一応、UV情報は残っているようだけど…。blender上で、Archive3D.net 上のサムネイル画像を参考にしながら、なんとなくの勘で、テクスチャ画像を再指定していかないといけない。

Autodesk FBX Converter で変換 :

Autodesk FBX COnverter を使えば、.3ds から .fbx に変換できそうな気配がする。.fbx にできれば blender でインポートできるだろうし、もしかするとテクスチャ情報もある程度何かしら残ってくれるのではないか…。

FBX Converter は開発終了しているらしいけど、一応まだ入手できる。

_Fbx Converter Archives
_Autodesk FBX Converter について
_AutoDesk FBX Converterのインストール手順 - MRが楽しい

fbx20133_converter_win_x64.exe を入手してインストールした。起動して、.3ds を左側に追加して、右側で FBX 2013、Binary を指定して変換しようとしたのだけど、「Not enough parameters」と表示されて変換できなかった。元の .3ds が何かおかしいのだろうか?

pCon.planner で変換 :

ググっていたら、pCon.planner なるソフトを使ってこの手の変換をしている方が居るらしいので試してみた。

_The 3D Interior Design Software for Experts | pCon.planner
_5 Best Free 3DS To OBJ Converter Software For Windows
_スケッチアップ無料版でインポートを使いこなそう | おうちシミュLife

pCon.planner_setup.exe を入手してインストール。起動はしたものの、3ds を開こうとしてもエラーが出て開けない。残念。

FreeCAD で変換 :

FreeCAD も .3ds の読み込みに対応してるらしいので試してみた。FreeCAD 0.21.1 を使用。

_FreeCAD: あなたのための 3D パラメトリック・モデラー
_FreeCAD: Download - あなたのための 3D パラメトリック・モデラー

FreeCAD-0.21.1-WIN-x64-installer-1.exe を入手してインストール。しかし、.3ds を開こうとしたら、Pythonスクリプトがエラーを出してしまう。これも開けないようだなと…。残念。

オンラインの変換サイトを利用 :

モデルデータのファイル形式を変換できるオンラインサービスを利用してみる。

_3DS FBX 変換 オンライン - AnyConv
_3DSをOBJに無料で変換 - ImageToStl
_3DSをBLENDに無料で変換 - ImageToStl
_3DSをFBXに無料で変換 - ImageToStl

色々試してみたけど…。
  • .obj に変換するとマテリアル情報もUV情報も失われるので、テクスチャを再度貼り付けていく作業がキツイ。.obj 以外が選べるならそちらのほうが良さそう。
  • ImageToStl は、どのファイル形式に変換しても、マテリアル情報やUV情報が失われるので、後の作業がキツイ。
  • AnyConv で .fbx に変換すると、マテリアルやUV情報等はある程度残っているようで、修正作業は楽に感じた。ただ、マテリアルのメタリックが1.0にされてしまって、やたらキンピカの見た目になるけれど…。

余談 :

どの方法で blender に .3ds を持ってきても、テクスチャ画像の再指定は避けられないので、そこがシンドイなと。本当にそのテクスチャで合っているのかも分らんし…。

以上、30 日分です。

過去ログ表示

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