2021/09/16(木) [n年前の日記]
#1 [love2d] love2dで疑似ラスタスクロールを使って立体的な見た目にできるか試した
love2d 11.3 を使って、疑似ラスタースクロールのみを利用して、立体的な見た目にできるか実験してみた。
いやまあ、仕組み自体は分かっているのだけど、どんな元画像を用意すればいいのか、どんなスクロール値を設定すればいいのか、そこらへんが分からなかったので…。実際に描いて/書いてみないと分からんなと…。
こんな感じになった。マウスカーソルの横位置によってスクロール速度が変わるようにしてみた。
一応、love.js ( _LoVE Web Builder )を使って、Webブラウザ上でも動く版も用意してみた。
_05_fake_rasterscroll_e
Windows10 x64 21H1 + Firefox 92.0 64bit、Google Chrome 93.0.4577.82 64bit では動いてるように見えるけど、どうだろう…。
いやまあ、仕組み自体は分かっているのだけど、どんな元画像を用意すればいいのか、どんなスクロール値を設定すればいいのか、そこらへんが分からなかったので…。実際に描いて/書いてみないと分からんなと…。
こんな感じになった。マウスカーソルの横位置によってスクロール速度が変わるようにしてみた。
一応、love.js ( _LoVE Web Builder )を使って、Webブラウザ上でも動く版も用意してみた。
_05_fake_rasterscroll_e
Windows10 x64 21H1 + Firefox 92.0 64bit、Google Chrome 93.0.4577.82 64bit では動いてるように見えるけど、どうだろう…。
◎ ソースと使用画像。 :
ソースと使用画像は以下。
_main.lua
_conf.lua
_bg1.png (1.25MB)
_bg2.png (528KB)
_main.lua
-- Fake raster scroll -- init function love.load() -- set filter love.graphics.setDefaultFilter("nearest", "nearest") -- set canvas size scr_w, scr_h = 1280, 720 canvas = love.graphics.newCanvas(scr_w, scr_h) -- get window width and height wdw_w, wdw_h = love.graphics.getDimensions() scr_scale = math.min((wdw_w / scr_w), (wdw_h / scr_h)) scr_ofsx = (wdw_w - (scr_w * scr_scale)) / 2 scr_ofsy = (wdw_h - (scr_h * scr_scale)) / 2 -- load image img = love.graphics.newImage("bg1.png") img2 = love.graphics.newImage("bg2.png") -- make Quad (raster) imgs = {} bg_x_list = {} for i = 1, img:getHeight() do local x = 0 local y = i - 1 imgs[i] = love.graphics.newQuad(x, y, img:getWidth(), 1, img:getDimensions()) bg_x_list[i] = 0 end bg_x = 0 end -- update function love.update(dt) local w0 = 684 local w1 = 1195 local mx = love.mouse.getX() local d = mx - (scr_w / 2) bg_x = (bg_x + 2 * d * dt) % w0 -- set bg_x_list local x0 = -bg_x local x1 = -bg_x * w1 / w0 for i = 1, img:getHeight() do local y = i - 1 bg_x_list[i] = x0 + y * (x1 - x0) / (img:getHeight() - 1) end end -- draw function love.draw() -- set canvas love.graphics.setCanvas(canvas) -- fill BG color love.graphics.setColor(0, 0, 1.0) love.graphics.rectangle("fill", 0, 0, scr_w, scr_h) -- draw bg upper love.graphics.setColor(1.0, 1.0, 1.0) love.graphics.draw(img2, -bg_x, 0) -- draw raster local y = scr_h - img:getHeight() love.graphics.setColor(1.0, 1.0, 1.0) for i = 1, img:getHeight() do love.graphics.draw(img, imgs[i], bg_x_list[i], (y + i - 1)) end -- unset canvas love.graphics.setCanvas() -- draw canvas to window love.graphics.setColor(1.0, 1.0, 1.0) love.graphics.draw(canvas, scr_ofsx, scr_ofsy, 0, scr_scale, scr_scale) -- print FPS love.graphics.print("FPS: "..tostring(love.timer.getFPS()), 10, 10) end function love.keypressed(key, isrepeat) -- ESC to exit if key == "escape" then love.event.quit() end end
_conf.lua
function love.conf(t) t.window.title = "Fake Raster Scroll" t.window.width = 1280 t.window.height = 720 t.window.vsync = true t.modules.joystick = false -- t.window.fullscreen = true -- t.window.fullscreentype = "exclusive" end
_bg1.png (1.25MB)
_bg2.png (528KB)
◎ 分かったこと。 :
台形に見えている部分がループするわけだけど、台形の、上辺の幅と下辺の幅が分かれば、プログラム側の処理というか、ラスタースクロール値の算出については全然難しくなかったなと…。幅の狭いほうを基準として、幅の広いほうは何倍の速度でスクロールするかを考えれば楽かもしれない。
また、ループ部分がこのくらいの幅であっても、結局のところ、「ある程度スクロールしたらスクロール値をリセットする」という方法で対処できると分かった。
元画像についても、初期状態の見た目が画像の左半分に収まるように描けばどうにかなる、と分かった。ただ、その元画像を作るのがちょっと面倒だった気もするけれど…。
さておき、今のハードウェアならこのくらいの大きさの画像をベタで持っても問題無いだろうけど、昔のゲーム機 ―― メガドラあたりでこういうBGを持とうとしたらセル? パターン? キャラ? の領域(1セル8x8ドット)をかなり圧迫しそうだなと今更ながら気付いたりもして。節約術が求められそう。
念のために書いておくけど、今時のハードウェアで、ラスタースクロールをわざわざ疑似的に再現してまで、新規にこういう処理を書く必要は全く無いです…。3DCGだのポリゴンだので描画すればいいじゃん、で済んでしまうので…。まあ、こういうのって、プログラマーにとっての頭の体操と言うかお遊びパズルと言うかそういう感じのアレってことで…。
また、ループ部分がこのくらいの幅であっても、結局のところ、「ある程度スクロールしたらスクロール値をリセットする」という方法で対処できると分かった。
元画像についても、初期状態の見た目が画像の左半分に収まるように描けばどうにかなる、と分かった。ただ、その元画像を作るのがちょっと面倒だった気もするけれど…。
さておき、今のハードウェアならこのくらいの大きさの画像をベタで持っても問題無いだろうけど、昔のゲーム機 ―― メガドラあたりでこういうBGを持とうとしたらセル? パターン? キャラ? の領域(1セル8x8ドット)をかなり圧迫しそうだなと今更ながら気付いたりもして。節約術が求められそう。
- 初期画面の左半分は、右半分を水平反転してキャラ数を節約。
- ループ幅を狭くしたラインをキャラ単位で部分的に用意してキャラ数を節約。
- ベタ部分を極力増やしてキャラ数を節約。
念のために書いておくけど、今時のハードウェアで、ラスタースクロールをわざわざ疑似的に再現してまで、新規にこういう処理を書く必要は全く無いです…。3DCGだのポリゴンだので描画すればいいじゃん、で済んでしまうので…。まあ、こういうのって、プログラマーにとっての頭の体操と言うかお遊びパズルと言うかそういう感じのアレってことで…。
◎ 元画像の作り方。 :
メモしておかないと作業手順を忘れそうなので一応メモしておく。
*1
今回は、GIMP 2.10.22 x65 Portable samj版を使って作業した。
まずは、ループ部分になる画像を用意する。今回は 1280x720 のウインドウサイズで表示するので、ループ部分も 1280x720 のサイズにしておいた。
横方向に並べる。フィルター → カラーマッピング → 並べる、を選択。ちなみに、GIMP 2.8 の場合は、カラーマッピングではなくてマップになってた気がする。
11枚とか15枚とかそのぐらいの数を並べる。単位を「%」にすると楽。
ずらりと横に並んだ画像ができた。
奥のほうをちょっと暗めにしておくと後々遠近感が出るので、グラデーションツールで少し化粧する。
ここから遠近感をつけた変形をするけれど、ガイドを作って、制御点をガイドに吸着させると作業が楽。画像 → ガイド → 均等にガイド、を選択。この「均等にガイド」は追加スクリプト。
_均等にガイド(Grid of guides)
ちなみに、かつて日本のGeoCitiesで公開されていた 「GIMP2を使おう」というサイトは、GeoCities のサービス終了で消滅してしまったのだけど、GeoLog Project のおかげで閲覧だけなら今でも可能らしい。ありがたや…。
_GeoLog Project
閑話休題。遠近感をつけて変形させる。遠近法ツールを選択。
遠近感をつけた変形ができた。ポイントとしては、台形の幅の広い辺(この場合は下辺)が、画面横幅(今回は1280ドット)よりちょっと狭い程度の長さになるようにしておくと、最終的な画像の横幅が画面2枚分よりは少なくなってイイ感じかもしれない。
切り抜きツールを選択。サイズは固定にして、(画面横幅 x 2) x 任意の縦幅、を指定。
画像の左半分に初期状態の見た目が収まるような配置にする。
Enterキーを叩いて切り抜きを実行。画像が得られた。
それにしても、なんだか作業が富豪的というか…。メガドラ時代は Photoshop の類は使えなくて、なんでもかんでもドットエディタで頑張ってた記憶があるので、当時のツールでこういう画像を作ろうとしたら結構大変だったのではないかしらん。いや、でも、数年後のPS1やSS向けの開発では Photoshop をガンガン使ってた記憶も…。メガドラも末期の開発では Photoshop 等を使えたのだろうか。どうなんだろう。そういえばX68Kも既にあったっけ…。
今回は、GIMP 2.10.22 x65 Portable samj版を使って作業した。
まずは、ループ部分になる画像を用意する。今回は 1280x720 のウインドウサイズで表示するので、ループ部分も 1280x720 のサイズにしておいた。
横方向に並べる。フィルター → カラーマッピング → 並べる、を選択。ちなみに、GIMP 2.8 の場合は、カラーマッピングではなくてマップになってた気がする。
11枚とか15枚とかそのぐらいの数を並べる。単位を「%」にすると楽。
ずらりと横に並んだ画像ができた。
奥のほうをちょっと暗めにしておくと後々遠近感が出るので、グラデーションツールで少し化粧する。
ここから遠近感をつけた変形をするけれど、ガイドを作って、制御点をガイドに吸着させると作業が楽。画像 → ガイド → 均等にガイド、を選択。この「均等にガイド」は追加スクリプト。
_均等にガイド(Grid of guides)
ちなみに、かつて日本のGeoCitiesで公開されていた 「GIMP2を使おう」というサイトは、GeoCities のサービス終了で消滅してしまったのだけど、GeoLog Project のおかげで閲覧だけなら今でも可能らしい。ありがたや…。
_GeoLog Project
閑話休題。遠近感をつけて変形させる。遠近法ツールを選択。
遠近感をつけた変形ができた。ポイントとしては、台形の幅の広い辺(この場合は下辺)が、画面横幅(今回は1280ドット)よりちょっと狭い程度の長さになるようにしておくと、最終的な画像の横幅が画面2枚分よりは少なくなってイイ感じかもしれない。
切り抜きツールを選択。サイズは固定にして、(画面横幅 x 2) x 任意の縦幅、を指定。
画像の左半分に初期状態の見た目が収まるような配置にする。
Enterキーを叩いて切り抜きを実行。画像が得られた。
それにしても、なんだか作業が富豪的というか…。メガドラ時代は Photoshop の類は使えなくて、なんでもかんでもドットエディタで頑張ってた記憶があるので、当時のツールでこういう画像を作ろうとしたら結構大変だったのではないかしらん。いや、でも、数年後のPS1やSS向けの開発では Photoshop をガンガン使ってた記憶も…。メガドラも末期の開発では Photoshop 等を使えたのだろうか。どうなんだろう。そういえばX68Kも既にあったっけ…。
*1: いやまあ、メモしてどうするんだという気もするけど…。今後、新規にこんな画像を作らなければいけない機会はまず無いだろうけど…。
[ ツッコむ ]
#2 [love2d] Firefox 92.0 で love.js が動かない
love2d用の .love ファイルは、LoVE Web Builder というオンラインサービス、love.js というプログラムを使うことで、Webブラウザ上でも動かせる状態に変換できるのだけど。
_LoVE Web Builder - Home
_Davidobot/love.js: LOVE ported to the web using Emscripten, updated to the latest Emscripten and LOVE (v11.3)
しかし、以前日記ページにアップロードしていた love.js使用ファイル群が、Firefox 92.0 64bit上で動かなくなっていた…。環境は Windows10 x64 21H1。ちなみに、Google Chrome 93.0.4577.82 64bit なら動く。Firefox だと動かない。以前の Firefox なら動いていたのだけどな…。なんでだろ。
_love2dをWebブラウザ上で動かしたい
_love.jsをnpm経由でインストールしてみた
当時と今とでは、WebサーバのバージョンとOS種類が違っているけど…。以前は、Apache2 2.2.31-3vl6 + Vine Linux 6.5 32bit だった。と思う。たぶん。今現在は、Apache2 2.4.38-3+deb10u5 + Debian Linux 10 buster 32bit。そのあたりは関係しているのか、いないのか。
Firefox上でF12キーを押して、ウェブ開発ツールを表示して、コンソールに切り替えてみたところ、以下のエラーメッセージが出ていた。
ジョイスティックなんて使ってないんだけどな…。
これが不思議なことに、ローカル環境(Windows10 x64 21H1上)で Python 3.9.5 64bit を使って簡易httpサーバを立ち上げて、Firefox で該当ページ(http://localhost:8000/)を開くと、同じ .html + .js なのに動作してしまう…。
また、 _LoVE Web Builder の Run a LoVE Project で .loveファイルを渡して動作確認してみると、そちらでも動いてしまう。何故。Webサーバの設定に問題があるのだろうか…?
_LoVE Web Builder - Home
_Davidobot/love.js: LOVE ported to the web using Emscripten, updated to the latest Emscripten and LOVE (v11.3)
しかし、以前日記ページにアップロードしていた love.js使用ファイル群が、Firefox 92.0 64bit上で動かなくなっていた…。環境は Windows10 x64 21H1。ちなみに、Google Chrome 93.0.4577.82 64bit なら動く。Firefox だと動かない。以前の Firefox なら動いていたのだけどな…。なんでだろ。
_love2dをWebブラウザ上で動かしたい
_love.jsをnpm経由でインストールしてみた
当時と今とでは、WebサーバのバージョンとOS種類が違っているけど…。以前は、Apache2 2.2.31-3vl6 + Vine Linux 6.5 32bit だった。と思う。たぶん。今現在は、Apache2 2.4.38-3+deb10u5 + Debian Linux 10 buster 32bit。そのあたりは関係しているのか、いないのか。
Firefox上でF12キーを押して、ウェブ開発ツールを表示して、コンソールに切り替えてみたところ、以下のエラーメッセージが出ていた。
Error: Could not initialize SDL joystick subsystem (Could not set gamepad connect callback)
ジョイスティックなんて使ってないんだけどな…。
これが不思議なことに、ローカル環境(Windows10 x64 21H1上)で Python 3.9.5 64bit を使って簡易httpサーバを立ち上げて、Firefox で該当ページ(http://localhost:8000/)を開くと、同じ .html + .js なのに動作してしまう…。
python -m http.server 8000
また、 _LoVE Web Builder の Run a LoVE Project で .loveファイルを渡して動作確認してみると、そちらでも動いてしまう。何故。Webサーバの設定に問題があるのだろうか…?
◎ とりあえずの対策。 :
ググっていたら、以下のやり取りに遭遇。
_Error: Could not initialize SDL joystick subsystem on Firefox : love2d
ジョイスティック関連でエラーが出ていて、しかし元々のスクリプト内でジョイスティックを使っていないなら、conf.lua の中でジョイスティック用モジュールを無効化することで状況が変わるかもしれない、具体的には以下を記述せよ、とのことで。
試してみたところ、この対応で一応動作するようになった。でも、どうしてこんなことになるんだろう…。
_Error: Could not initialize SDL joystick subsystem on Firefox : love2d
ジョイスティック関連でエラーが出ていて、しかし元々のスクリプト内でジョイスティックを使っていないなら、conf.lua の中でジョイスティック用モジュールを無効化することで状況が変わるかもしれない、具体的には以下を記述せよ、とのことで。
-- at conf.lua function love.conf(t) t.modules.joystick = false end
試してみたところ、この対応で一応動作するようになった。でも、どうしてこんなことになるんだろう…。
◎ 今までアップロードしてたそれぞれをアップロードし直し。 :
今までアップロードしてたそれぞれを、conf.lua を修正した状態でアップロードしておいた。
_helloworld_like_tic80
_cubic_bezier
_snake_lovewebbuilder
_05_fake_rasterscroll_e
後で過去ページも修正しておかないと…。
_helloworld_like_tic80
_cubic_bezier
_snake_lovewebbuilder
_05_fake_rasterscroll_e
後で過去ページも修正しておかないと…。
[ ツッコむ ]
以上、1 日分です。