2022/06/08(水) [n年前の日記]
#1 [xlib] Xlibでタイルマップを描画
Xlibを使ってタイルマップ描画ができるか試してみた。タイルマップ描画ができれば、一気に2Dゲーム風の画面になる。はず。たぶん。おそらく。
環境は、Ubuntu Linux 20.04 LTS。Windows10 x64 21H2 + VMware Player 16.2.3 build-19376536 上で動かしてる。
こんな感じになった。
元画面は640x360。それを、ディスプレイ解像度 1440x900に拡大して描画してる。
BG相当を3枚も描画できれば、2Dゲーム風の画面を作るには十分過ぎるかなと。ファミコンやPCエンジンならBGが1面、メガドライブでもBGが2面だったし。
スーファミ(SFC)は何枚まで出せたんだろう。ググってみたらMode0からMode7まであったみたいだけど。Mode0が4枚まで出せたと書いてあるな…。ただ、1パレットが4色か…。
_Super Nintendo Entertainment System - Wikipedia
環境は、Ubuntu Linux 20.04 LTS。Windows10 x64 21H2 + VMware Player 16.2.3 build-19376536 上で動かしてる。
こんな感じになった。
元画面は640x360。それを、ディスプレイ解像度 1440x900に拡大して描画してる。
BG相当を3枚も描画できれば、2Dゲーム風の画面を作るには十分過ぎるかなと。ファミコンやPCエンジンならBGが1面、メガドライブでもBGが2面だったし。
スーファミ(SFC)は何枚まで出せたんだろう。ググってみたらMode0からMode7まであったみたいだけど。Mode0が4枚まで出せたと書いてあるな…。ただ、1パレットが4色か…。
_Super Nintendo Entertainment System - Wikipedia
◎ ソース。 :
ソースと使用画像は以下。
_09tilemap1.c
_scifi_bg_chip.xpm
一応、元画像(.png)も置いておきます。CC0 / Public Domain ってことで自由に使ってください。1チップ(1タイル) 64x64ドットが、8x8個並んでます。インデックスカラー画像、48色。だったはず。たぶん。
_scifi_bg_chip.png
コンパイルは以下。
実行は以下。
少し解説。
今回、今までのソースと違って、State という構造体を定義して、処理で利用する変数を全部その State の中に入れることにした。各関数に引数を渡すあたりの記述が面倒臭かったので、State のポインタを渡して全部の変数にアクセスできるようにしてしまえ、みたいな。
1枚の xpm を分割して複数の Pixmap を作るあたりは、split_pixmaps() という関数で処理してる。
ちょっとハマった点。マスク用のPixmapをコピー(XCopyArea)する時は、マスク用のGCを別途用意しないといけない。そのあたりを知らなかったもので、RGB部分とマスク部分の両方を同じGCで処理しようとして、エラーが出て悩んでしまった。RGB部分を持ってる Pixmap と、マスク用の Pixmap は深度(Depth)が違うので、GCも深度別に用意しないといけないのだとか。
タイルマップを描画するあたりは、draw_tilemap() で処理してる。
本来、この手の処理は、BG用の大きなバッファ(Pixmap)を用意しておいて、スクロールに応じて書き換えが必要な場所だけ書き換えて、そのBG用の大きなバッファをソースにして表示用バッファに描画、といった処理をしたほうが速度は稼げるのだけど。今回は面倒臭かったので、毎フレーム、愚直に、チップ(タイル)を何十個も描画し直すやり方を選んでしまった。まあ、これはこれで、BGのアニメーションはしやすかったりもするけれど…。
余談。タイルマップ用のデータは、Tiled 1.8.5 64bit版を使わせてもらいました。ありがたや。
_Tiled | Flexible level editor
ちなみに、Tiled から json でエクスポートするとタイル番号は1から始まるけれど、csv でエクスポートするとタイル番号は0から始まるのですな…。知らなかった…。
_09tilemap1.c
_scifi_bg_chip.xpm
一応、元画像(.png)も置いておきます。CC0 / Public Domain ってことで自由に使ってください。1チップ(1タイル) 64x64ドットが、8x8個並んでます。インデックスカラー画像、48色。だったはず。たぶん。
_scifi_bg_chip.png
コンパイルは以下。
gcc 09tilemap1.c -o 09tilemap1 -I /usr/include/X11 -lX11 -lXext -lm -lXpm
実行は以下。
./09tilemap1
少し解説。
今回、今までのソースと違って、State という構造体を定義して、処理で利用する変数を全部その State の中に入れることにした。各関数に引数を渡すあたりの記述が面倒臭かったので、State のポインタを渡して全部の変数にアクセスできるようにしてしまえ、みたいな。
1枚の xpm を分割して複数の Pixmap を作るあたりは、split_pixmaps() という関数で処理してる。
ちょっとハマった点。マスク用のPixmapをコピー(XCopyArea)する時は、マスク用のGCを別途用意しないといけない。そのあたりを知らなかったもので、RGB部分とマスク部分の両方を同じGCで処理しようとして、エラーが出て悩んでしまった。RGB部分を持ってる Pixmap と、マスク用の Pixmap は深度(Depth)が違うので、GCも深度別に用意しないといけないのだとか。
タイルマップを描画するあたりは、draw_tilemap() で処理してる。
本来、この手の処理は、BG用の大きなバッファ(Pixmap)を用意しておいて、スクロールに応じて書き換えが必要な場所だけ書き換えて、そのBG用の大きなバッファをソースにして表示用バッファに描画、といった処理をしたほうが速度は稼げるのだけど。今回は面倒臭かったので、毎フレーム、愚直に、チップ(タイル)を何十個も描画し直すやり方を選んでしまった。まあ、これはこれで、BGのアニメーションはしやすかったりもするけれど…。
余談。タイルマップ用のデータは、Tiled 1.8.5 64bit版を使わせてもらいました。ありがたや。
_Tiled | Flexible level editor
ちなみに、Tiled から json でエクスポートするとタイル番号は1から始まるけれど、csv でエクスポートするとタイル番号は0から始まるのですな…。知らなかった…。
◎ Core2Duo機でも動作確認してみた。 :
Intel Core2Duo E8400 (2コア, 3.0GHz) + NVIDIA GeForce 9500GT + Ubuntu Linux 20.04 LTS、ディスプレイ解像度 1920x1200 の環境でも動作確認してみた。今となっては非力なCPU+GPUのはずだけど、それでも大体 3〜 5msec で動いてたので、この程度の描画処理なら60FPSで動かせそうな気配がする。
もっとも、Ryzen 5 5600X + VMware Player + Ubuntu Linux 20.04 LTS、ディスプレイ解像度 1920x1080 では 0.9〜1.1msec で動いたので、Ryzen 5 5600X と比べると Core2Duo E8400 は 1/5 の速度、ということになるのだろうか。いやまあ、仮想PC上ではなくて実機上で動かしたら、また違う処理時間になるかもしれないけど。
もっとも、Ryzen 5 5600X + VMware Player + Ubuntu Linux 20.04 LTS、ディスプレイ解像度 1920x1080 では 0.9〜1.1msec で動いたので、Ryzen 5 5600X と比べると Core2Duo E8400 は 1/5 の速度、ということになるのだろうか。いやまあ、仮想PC上ではなくて実機上で動かしたら、また違う処理時間になるかもしれないけど。
◎ OpenGLを使うべきだろうか。 :
Xlib についてググったら、1985年頃に登場したものらしくて。
_Xlib - Wikipedia
そんなに古いライブラリ(?)を使ってもこのくらいの描画はできるのだな、という感想を持ったけれど、さすがにこういう感じの描画をしたいなら OpenGL だか glx だかを使うべきなのでは、という気もしてきた。
_GLX - Wikipedia
xscreensaver のドキュメント内でも、「高速な描画をしたいなら OpenGL/glx を使うことを検討すべきやで」みたいなことが書いてあった気もするし。
_Xlib - Wikipedia
そんなに古いライブラリ(?)を使ってもこのくらいの描画はできるのだな、という感想を持ったけれど、さすがにこういう感じの描画をしたいなら OpenGL だか glx だかを使うべきなのでは、という気もしてきた。
_GLX - Wikipedia
xscreensaver のドキュメント内でも、「高速な描画をしたいなら OpenGL/glx を使うことを検討すべきやで」みたいなことが書いてあった気もするし。
[ ツッコむ ]
#2 [pc] キーボードのキーを押しても電源がONにならない
メインPCの電源スイッチの塗装が微妙に剥げてきた。つまりはそれだけ何回も、電源スイッチを押してるわけで、これはなんだかちょっとアレだなと。
そこで、キーボードを押したら電源が入るようにできないかと思い立った。メインPCのM/B、GIGABYTE B450M S2H (rev. 1.x) のBIOS設定画面を表示して、該当項目を有効にしてみた。
しかし、キーボードを押しても電源が入らない。何故。USBハブを介して接続しているせいだろうか。
であれば、M/Bに直接接続しているマウスならどうだろう。マウスのダブルクリックをしたら電源が入るようにBIOS設定を変えてみた。しかし、こちらも効果無し。
ググってみたら、おそらくだけど理由が分かってきた。
_[マザーボード] BIOS設定で「PS/2キーボードによる電源オン」を有効にする方法 | サポート 公式 | ASUS 日本
_価格.com - 『キーボードからの電源ON』 GIGABYTE GA-EP35-DS3R Rev.2.1 のクチコミ掲示板
_Power on by keyboard/mouse doesn't work on my Gigabyte motherboard - Super User
キーボードやマウスで電源ONにする機能は、「PS/2キーボードなら使えます」と言う話だった模様。自分が使ってるキーボードも、マウスも、USB接続だった…。
親父さん用PCに使っていた Mini-ITX M/B、ASUS PRIME A320I-K と BIOSTAR RACING B350GTN は、キーボードのキーを押しても電源ONになったので、てっきり自分の使ってる GIGABYTE B450M S2H (rev. 1.x) もそのように設定できるだろうと思い込んでた。でも、思い返してみると、親父さんが使ってるキーボードは、PS/2キーボードだった気もする。メンテナンス時に、あの丸いPS/2コネクタを背面に差していたような…。いや、どうだったかな。自信が無くなってきた。そのうち確認してみよう…。
そこで、キーボードを押したら電源が入るようにできないかと思い立った。メインPCのM/B、GIGABYTE B450M S2H (rev. 1.x) のBIOS設定画面を表示して、該当項目を有効にしてみた。
しかし、キーボードを押しても電源が入らない。何故。USBハブを介して接続しているせいだろうか。
であれば、M/Bに直接接続しているマウスならどうだろう。マウスのダブルクリックをしたら電源が入るようにBIOS設定を変えてみた。しかし、こちらも効果無し。
ググってみたら、おそらくだけど理由が分かってきた。
_[マザーボード] BIOS設定で「PS/2キーボードによる電源オン」を有効にする方法 | サポート 公式 | ASUS 日本
_価格.com - 『キーボードからの電源ON』 GIGABYTE GA-EP35-DS3R Rev.2.1 のクチコミ掲示板
_Power on by keyboard/mouse doesn't work on my Gigabyte motherboard - Super User
キーボードやマウスで電源ONにする機能は、「PS/2キーボードなら使えます」と言う話だった模様。自分が使ってるキーボードも、マウスも、USB接続だった…。
親父さん用PCに使っていた Mini-ITX M/B、ASUS PRIME A320I-K と BIOSTAR RACING B350GTN は、キーボードのキーを押しても電源ONになったので、てっきり自分の使ってる GIGABYTE B450M S2H (rev. 1.x) もそのように設定できるだろうと思い込んでた。でも、思い返してみると、親父さんが使ってるキーボードは、PS/2キーボードだった気もする。メンテナンス時に、あの丸いPS/2コネクタを背面に差していたような…。いや、どうだったかな。自信が無くなってきた。そのうち確認してみよう…。
[ ツッコむ ]
以上、1 日分です。