mieki256's diary



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

#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 をインストールしてある環境だから動いているけれど、どの環境でも動作する形にして配布するのは結構難しそう。

以上です。

過去ログ表示

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