2021/02/04(木) [n年前の日記]
#1 [love2d] love2dでコマンドラインオプションを取得
love2dスクリプトで、コマンドラインオプション(コマンドライン引数)を取得できるか試してみたり。環境は Windows10 x64 20H2 + love2d 11.3。
ググったところ、arg というテーブルにコマンドラインオプションが入った状態で love2dスクリプトが実行されるらしい。
とりあえず、サンプルを書いてみる。今回、コマンドラインオプションを取得して画面に表示するサンプルを書いてみた。
getarg というフォルダを作成して、conf.lua と main.lua を置く。
_conf.lua
以下のようにループを回せば、arg テーブルのキーと値を順々に取り出すことができる。
動かしてみる。love フォルダ名、で実行できる。まずはコマンドラインオプションを付けない状態で試してみる。
コマンドラインオプションを付けて実行してみる。
ググったところ、arg というテーブルにコマンドラインオプションが入った状態で love2dスクリプトが実行されるらしい。
とりあえず、サンプルを書いてみる。今回、コマンドラインオプションを取得して画面に表示するサンプルを書いてみた。
getarg というフォルダを作成して、conf.lua と main.lua を置く。
_conf.lua
function love.conf(t) t.window.title = "get arg with love2d" t.window.vsync = true t.window.width = 640 t.window.height = 480 -- t.window.fullscreen = true -- t.window.fullscreentype = "exclusive" end_main.lua
-- get arg with love2d function love.load(arg) -- Check command line options ssmode = "" for k, v in pairs(arg) do lv = string.lower(v) if lv == "/s" then ssmode = "fullscreen" elseif lv == "/c" then ssmode = "config" elseif lv == "/p" then ssmode = "preview" elseif lv == "/a" then ssmode = "passwordlock" end end if ssmode == "" then ssmode = "none" end min_dt = 1 / 60 next_time = love.timer.getTime() end function love.update(dt) next_time = next_time + min_dt if dt > 0.75 then return end end function love.draw() love.graphics.setCanvas() love.graphics.clear(0, 0, 0.2, 1.0) love.graphics.setColor(1, 1, 1, 1) love.graphics.print("FPS: " .. tostring(love.timer.getFPS()), 10, 10) y = 32 for k, v in pairs(arg) do love.graphics.print(string.format("arg[%d] : %s", k, v), 10, y) y = y + 18 end y = y + 18 love.graphics.print("Mode : " .. ssmode, 10, y) if love.system.getOS() == "Windows" then -- wait local cur_time = love.timer.getTime() if next_time <= cur_time then next_time = cur_time else love.timer.sleep(next_time - cur_time) end end end function love.keypressed(key, isrepeat) if key == "escape" then -- ESC to exit love.event.quit() end end
以下のようにループを回せば、arg テーブルのキーと値を順々に取り出すことができる。
for k, v in pairs(arg) do -- key, value end
動かしてみる。love フォルダ名、で実行できる。まずはコマンドラインオプションを付けない状態で試してみる。
love getarg
arg[1] : getarg arg[-2] : love arg[-1] : embedded boot.lua Mode : none
- arg[1] にフォルダ名が入ってることがわかる。
- arg[-2] には、love が入っている。
- arg[-1] には、love2d を動かした際に、一番最初に呼び出されてる内蔵luaスクリプト名が表示されているのだろうと思われる。
コマンドラインオプションを付けて実行してみる。
love getarg /s
arg[1] : getarg arg[2] : /s arg[-2] : love arg[-1] : embedded boot.lua Mode : fullscreen
- arg[2] に「/s」が入ってる。
- love.load(arg) 内で、「/s」「/c」「/p」「/a」等が指定されてるかチェックしているが、「/s」が指定されてることを検出できている。(Mode : fullscreen になっている)
◎ .loveファイルを作成。 :
この love2dスクリプトを、.loveファイルに変換してみる。.loveファイルと言ってるけれど、実態は .zip ファイル。
動作確認してみる。
- conf.lua と main.lua を、1つのzipファイル、getarg.zip に圧縮する。(getargフォルダごとzip圧縮しないように注意。)
- getarg.zip の .zip を .love にリネームする。
動作確認してみる。
love getarg.love /s
arg[1] : getarg.love arg[2] : /s arg[-2] : love arg[-1] : embedded boot.lua Mode : fullscreen
- フォルダ名を指定した時と違って、arg[1] が getarg から getarg.love に変わっている。
- それ以外は、love getarg /s を動かしたときと同じ。
◎ exe化する。 :
getarg.love を exe化してみる。
love2dスクリプトの exe化は、love.exe の末尾に .love ファイルを結合するだけでいいらしい。
これで、getarg.exe を作ることができた。
getarg.exe を動かすためには、love.exe に同梱されているDLLファイル群が必要になる。こうして .exe化した exeファイルを配布する際は、それら .dll も一緒に配布しておかないと動作しないよ、ということになっているけれど…。
とりあえず、今回は love2d をインストールしてある環境で動作確認しているので ―― OSの環境変数PATHに love2d のインストールフォルダが登録してあるので、DLLが必要になったら PATH の中からDLLを探して呼び出して一応実行することはできるだろう、と。実際、getarg.exe をいきなり呼び出しても動いてくれた。
動作確認してみる。
とりあえず…。
love2dスクリプトの exe化は、love.exe の末尾に .love ファイルを結合するだけでいいらしい。
copy /b love.exe+getarg.love getarg.exe
これで、getarg.exe を作ることができた。
getarg.exe を動かすためには、love.exe に同梱されているDLLファイル群が必要になる。こうして .exe化した exeファイルを配布する際は、それら .dll も一緒に配布しておかないと動作しないよ、ということになっているけれど…。
とりあえず、今回は love2d をインストールしてある環境で動作確認しているので ―― OSの環境変数PATHに love2d のインストールフォルダが登録してあるので、DLLが必要になったら PATH の中からDLLを探して呼び出して一応実行することはできるだろう、と。実際、getarg.exe をいきなり呼び出しても動いてくれた。
動作確認してみる。
getarg.exe /s
arg[1] : /s arg[-2] : getarg.exe arg[-1] : embedded boot.lua Mode : fullscreen
- arg[1] が「/s」になった。
- arg[-2] が getarg.exe になった。
とりあえず…。
- love2dスクリプトのままでも、
- .loveファイルにしても、
- exe化しても、
[ ツッコむ ]
#2 [love2d] love2dでWindows用のスクリーンセーバを作成してみる
love2d を使って、Windows用のスクリーンセーバを作成してみる。環境は、Windows10 x64 20H2 + love2d 11.3。
◎ Windows用スクリーンセーバについてのおさらい。 :
Windows用のスクリーンセーバは、拡張子が .scr になっているけれど、実態は exeファイル。
以下のコマンドラインオプションを渡して実行した際に、それぞれ処理が変わるように作っておけばスクリーンセーバとして使える、らしい。
また、スクリーンセーバのファイル名は、8文字以下(拡張子を除く)にしておかないといけない、という話もどこかで見かけた。それって Windows 9x 時代の話じゃないのか、今も適用されるのか、という疑問も湧くけど、一応合わせておいたほうが無難だろうなと…。
以下、参考ページ。
_スクリーンセーバー
_Borland C++ 5.5 フリーでスクリーンセーバを作る
以下のコマンドラインオプションを渡して実行した際に、それぞれ処理が変わるように作っておけばスクリーンセーバとして使える、らしい。
- /s : フルスクリーン表示。スクリーンセーバとして動いている時はこの状態。
- /c : 設定ダイアログを表示する。
- /p xxxx : プレビューモード。スクリーンセーバの種類を選択する際に表示されている小さい窓部分を返す。xxxx はウインドウハンドルらしい。
- /a : パスワード設定。
また、スクリーンセーバのファイル名は、8文字以下(拡張子を除く)にしておかないといけない、という話もどこかで見かけた。それって Windows 9x 時代の話じゃないのか、今も適用されるのか、という疑問も湧くけど、一応合わせておいたほうが無難だろうなと…。
以下、参考ページ。
_スクリーンセーバー
_Borland C++ 5.5 フリーでスクリーンセーバを作る
◎ love2dスクリプトを書く。 :
とりえず、フルスクリーンで表示して、丸が画面の中で跳ね回るだけのlove2dスクリプトを書いてみた。
lovescr1 というフォルダを作って、中に conf.lua と main.lua を置く。
_conf.lua
_main.lua
動作確認。
フルスクリーン表示で、丸が動いた。
何かキーを押したり、マウスを勢いよく動かすと終了する。
lovescr1 というフォルダを作って、中に conf.lua と main.lua を置く。
_conf.lua
function love.conf(t) t.window.title = "Windows Screensaver with love2" t.window.vsync = true t.window.width = 1280 t.window.height = 720 t.window.fullscreen = true -- t.window.fullscreentype = "exclusive" end
- t.window.fullscreen = true を書いて、フルスクリーン表示を指定している。
_main.lua
-- Windows screensaver with love2d function love.load() love.graphics.setDefaultFilter("nearest", "nearest") -- get screen size wdw_w, wdw_h = love.graphics.getDimensions() -- Check command line options ssmode = "" for k, v in pairs(arg) do lv = string.lower(v) if lv == "/s" then ssmode = "fullscreen" elseif lv == "/c" then ssmode = "config" elseif lv == "/p" then ssmode = "preview" elseif lv == "/a" then ssmode = "passwordlock" end end if ssmode == "" then ssmode = "none" end if ssmode == "config" then love.event.quit() end if ssmode == "preview" then love.event.quit() end if ssmode == "passwordlock" then love.event.quit() end if ssmode == "none" then love.event.quit() end -- hide mouse cursor love.mouse.setVisible(false) min_dt = 1 / 60 next_time = love.timer.getTime() dx = wdw_w / 2 dy = dx / 3 x = wdw_w / 2 y = wdw_h / 2 r = wdw_w / 100 end function love.update(dt) next_time = next_time + min_dt if dt > 0.75 then return end -- move ball x = x + dx * dt y = y + dy * dt if (x - r) < 0 or (x + r) > wdw_w then dx = dx * -1 end if (y - r) < 0 or (y + r) > wdw_h then dy = dy * -1 end end function love.draw() -- clear screen love.graphics.setCanvas() love.graphics.clear(0, 0, 0, 1.0) -- draw ball love.graphics.setColor(0.1, 0.3, 1.0, 1.0) love.graphics.circle("fill", x, y, r) -- draw FPS love.graphics.setColor(0.5, 0.5, 0.5, 1.0) love.graphics.print("FPS: "..tostring(love.timer.getFPS()), 10, 10) if love.system.getOS() == "Windows" then -- wait local cur_time = love.timer.getTime() if next_time <= cur_time then next_time = cur_time else love.timer.sleep(next_time - cur_time) end end end function love.keypressed(key, isrepeat) -- Pressed any key to exit love.mouse.setVisible(true) love.event.quit() end function love.mousemoved( x, y, dx, dy, istouch ) -- Moved the mouse cursor a lot to exit if dx * dx + dy * dy >= 16 * 16 then love.mouse.setVisible(true) love.event.quit() end end
- コマンドラインオプションを取得して、/s の時だけ動作させる。
- /c、/p、/a、及び、コマンドラインオプション無しの場合は、いきなり終了させている。
- 何かキー入力があったら終了させる。love.keypressed(key, isrepeat) で検出。
- マウスカーソルが16ドット以上動いたら終了させる。love.mousemoved( x, y, dx, dy, istouch ) で検出。
動作確認。
love lovescr1 /s
フルスクリーン表示で、丸が動いた。
何かキーを押したり、マウスを勢いよく動かすと終了する。
◎ scr化する。 :
.loveファイルを作成。conf.lua と main.lua を、lovescr1.zip に圧縮して、.zip を .love にリネーム。
.loveファイルをexe化(scr化)する。
.loveファイルをexe化(scr化)する。
copy /b love.exe+lovescr1.love lovescr1.scrlovescr1.scr が出来上がった。
◎ 所定の場所にコピー。 :
出来上がった lovescr1.scr を、所定の場所にコピーしてみる。
今回の環境は、64bit版の Windows10。また、今回利用した love2d は 32bit版だったので、C:\Windows\SysWOW64\ に lovescr1.scr を置いてみた。
本来、lovescr1.scr と一緒に、love2d を動かすための以下のDLL群も C:\Windows\SysWOW64\ 以下にコピーしないといけないのだけど…。
こんなに大量の .dll を、C:\Windows\SysWOW64\ 以下にコピーするのはちょっとヤバイ気がするわけで。
なので、環境変数 PATH に、love2d のインストール場所を追加しておいて、.dll のコピーはしないことにする。love2d を利用する exe が実行されて、.dll が必要になったら、PATH の中から探して呼び出してくれるだろう…。たぶん。
- 32bit版 Windows の場合、C:\Windows\System32\
- 64bit版 Windows、かつ、スクリーンセーバが32bit版プログラムの場合、C:\Windows\SysWOW64\
- 64bit版 Windows、かつ、スクリーンセーバが64bit版プログラムの場合、C:\Windows\System32\
今回の環境は、64bit版の Windows10。また、今回利用した love2d は 32bit版だったので、C:\Windows\SysWOW64\ に lovescr1.scr を置いてみた。
本来、lovescr1.scr と一緒に、love2d を動かすための以下のDLL群も C:\Windows\SysWOW64\ 以下にコピーしないといけないのだけど…。
game.ico love.dll love.ico lua51.dll mpg123.dll msvcp120.dll msvcr120.dll OpenAL32.dll SDL2.dll
こんなに大量の .dll を、C:\Windows\SysWOW64\ 以下にコピーするのはちょっとヤバイ気がするわけで。
なので、環境変数 PATH に、love2d のインストール場所を追加しておいて、.dll のコピーはしないことにする。love2d を利用する exe が実行されて、.dll が必要になったら、PATH の中から探して呼び出してくれるだろう…。たぶん。
◎ 動作確認。 :
Windows10 のスクリーンセーバ設定を呼び出してみる。デスクトップ画面を右クリック → 個人用設定 → ロック画面 → スクリーンセーバー設定。
lovescr1 が選べるようになっている。
スクリーンセーバが実行されるまでの時間を1分に設定して、本当に呼びされるのか眺めてみたけれど、一応実行してくれた、ように見えている。
lovescr1 が選べるようになっている。
- プレビュー画面には、何も出てこない。/p xxxx を与えて実行した時は、即座に終了するようにしているので。
- 設定ボタンを押しても、何も出てこない。/c を与えて実行した時も、即座に終了するようにしているので。
- プレビューボタンを押すと(/s を与えて実行されると)、フルスクリーンで表示される。
スクリーンセーバが実行されるまでの時間を1分に設定して、本当に呼びされるのか眺めてみたけれど、一応実行してくれた、ように見えている。
◎ 試してみた感想。 :
何かの拍子にプロセスが残り続けたりしないか、等々が気になるし、プレビュー表示も設定画面も出せないあたりがちょっともやもやするけれど。でもまあ、一応、love2d を使って Windows用のスクリーンセーバを作れなくもないっぽい雰囲気ではあるな、と…。
ただ、動作に必要なDLL群をどこに置くか、という問題は残るなと。今回は love2d をインストールしてある環境だから動いているけれど、どの環境でも動作する形にして配布するのは結構難しそう。
ただ、動作に必要なDLL群をどこに置くか、という問題は残るなと。今回は love2d をインストールしてある環境だから動いているけれど、どの環境でも動作する形にして配布するのは結構難しそう。
[ ツッコむ ]
以上、1 日分です。