mieki256's diary



2021/02/04(木) [n年前の日記]

#1 [love2d] love2dでコマンドラインオプションを取得

love2dスクリプトで、コマンドラインオプション(コマンドライン引数)を取得できるか試してみたり。環境は Windows10 x64 20H2 + love2d 11.3。

ググったところ、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
getarg_ss01.png
arg[1] : getarg
arg[-2] : love
arg[-1] : embedded boot.lua

Mode : none

コマンドラインオプションを付けて実行してみる。
love getarg /s
getarg_ss02.png
arg[1] : getarg
arg[2] : /s
arg[-2] : love
arg[-1] : embedded boot.lua

Mode : fullscreen

.loveファイルを作成。 :

この love2dスクリプトを、.loveファイルに変換してみる。.loveファイルと言ってるけれど、実態は .zip ファイル。
  1. conf.lua と main.lua を、1つのzipファイル、getarg.zip に圧縮する。(getargフォルダごとzip圧縮しないように注意。)
  2. getarg.zip の .zip を .love にリネームする。
これで、getarg.love を作成できた。

動作確認してみる。
love getarg.love /s
getarg_ss03.png
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 ファイルを結合するだけでいいらしい。
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
getarg_ss04.png
arg[1] : /s
arg[-2] : getarg.exe
arg[-1] : embedded boot.lua

Mode : fullscreen
  • arg[1] が「/s」になった。
  • arg[-2] が getarg.exe になった。

とりあえず…。
  • love2dスクリプトのままでも、
  • .loveファイルにしても、
  • exe化しても、
love2d に渡されたコマンドラインオプションを取得することはできそうだ、ということが分かった。

#2 [love2d] love2dでWindows用のスクリーンセーバを作成してみる

love2d を使って、Windows用のスクリーンセーバを作成してみる。環境は、Windows10 x64 20H2 + love2d 11.3。

Windows用スクリーンセーバについてのおさらい。 :

Windows用のスクリーンセーバは、拡張子が .scr になっているけれど、実態は exeファイル。

以下のコマンドラインオプションを渡して実行した際に、それぞれ処理が変わるように作っておけばスクリーンセーバとして使える、らしい。
  • /s : フルスクリーン表示。スクリーンセーバとして動いている時はこの状態。
  • /c : 設定ダイアログを表示する。
  • /p xxxx : プレビューモード。スクリーンセーバの種類を選択する際に表示されている小さい窓部分を返す。xxxx はウインドウハンドルらしい。
  • /a : パスワード設定。

また、スクリーンセーバのファイル名は、8文字以下(拡張子を除く)にしておかないといけない、という話もどこかで見かけた。それって Windows 9x 時代の話じゃないのか、今も適用されるのか、という疑問も湧くけど、一応合わせておいたほうが無難だろうなと…。

以下、参考ページ。

_スクリーンセーバー
_Borland C++ 5.5 フリーでスクリーンセーバを作る

love2dスクリプトを書く。 :

とりえず、フルスクリーンで表示して、丸が画面の中で跳ね回るだけのlove2dスクリプトを書いてみた。

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
lovesr1_ss.png

フルスクリーン表示で、丸が動いた。

何かキーを押したり、マウスを勢いよく動かすと終了する。

scr化する。 :

.loveファイルを作成。conf.lua と main.lua を、lovescr1.zip に圧縮して、.zip を .love にリネーム。

.loveファイルをexe化(scr化)する。
copy /b love.exe+lovescr1.love lovescr1.scr
lovescr1.scr が出来上がった。

所定の場所にコピー。 :

出来上がった lovescr1.scr を、所定の場所にコピーしてみる。
  • 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 のスクリーンセーバ設定を呼び出してみる。デスクトップ画面を右クリック → 個人用設定 → ロック画面 → スクリーンセーバー設定。

lovesr1_ss02.png

lovescr1 が選べるようになっている。
  • プレビュー画面には、何も出てこない。/p xxxx を与えて実行した時は、即座に終了するようにしているので。
  • 設定ボタンを押しても、何も出てこない。/c を与えて実行した時も、即座に終了するようにしているので。
  • プレビューボタンを押すと(/s を与えて実行されると)、フルスクリーンで表示される。

スクリーンセーバが実行されるまでの時間を1分に設定して、本当に呼びされるのか眺めてみたけれど、一応実行してくれた、ように見えている。

試してみた感想。 :

何かの拍子にプロセスが残り続けたりしないか、等々が気になるし、プレビュー表示も設定画面も出せないあたりがちょっともやもやするけれど。でもまあ、一応、love2d を使って Windows用のスクリーンセーバを作れなくもないっぽい雰囲気ではあるな、と…。

ただ、動作に必要なDLL群をどこに置くか、という問題は残るなと。今回は love2d をインストールしてある環境だから動いているけれど、どの環境でも動作する形にして配布するのは結構難しそう。

以上、1 日分です。

過去ログ表示

Prev - 2021/02 - 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

カテゴリで表示

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


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

Powered by hns-2.19.6, HyperNikkiSystem Project