2022/08/19(金) [n年前の日記]
#1 [ruby][windows] Ruby/SDLでスクリーンセーバを作成
Windows10 x64 21H2上で、Ruby 1.8.7, 1.9.3 + Ruby/SDL (rubysdl) 2.1.1.1 を使って、Windows用のスクリーンセーバ(の雛形)を作成してみた。
動作させている様子は以下。解像度が低いけど雰囲気ぐらいは伝わるかと。
Windows用スクリーンセーバに求められる仕様については、pygame でスクリーンセーバを作った際にメモしたソレが多少は参考になるかと。
_Windows用スクリーンセーバについてのおさらい。
動作させている様子は以下。解像度が低いけど雰囲気ぐらいは伝わるかと。
Windows用スクリーンセーバに求められる仕様については、pygame でスクリーンセーバを作った際にメモしたソレが多少は参考になるかと。
_Windows用スクリーンセーバについてのおさらい。
◎ 動作確認環境。 :
動作確認環境は以下。
セットアップファイル名も一応列挙。
_ActiveScriptRuby and Other packages
_Download Archives - RubyInstaller
Ruby は32bit版を利用。
Ruby は32bit版を利用。
大事なことなので2回言いました。
Ruby/SDLのバイナリが32bitなので、64bit版のRubyに入れて使おうとしても動かないです。たぶん。
ちなみに、Windows用のRuby/SDLは Ruby 1.8 / 1.9用しか存在しないので、Ruby 2.0以降でこういったことはできないと思われます。
利用できるRubyのバージョンや、Ruby/SDL のインストール方法は、以下を参照のこと。
_Ruby/SDLでスクリーンセーバを作れないものか
_Ruby/SDLをインストールしようとしてハマった
- Windows10 x64 21H2
- RubyInstaller 1.9.3 p551 i386-mingw32 + rubysdl 2.1.1.1 + ocra 1.3.10
- ActiveScriptRuby 1.8.7 p330 i386-mswin32 + rubysdl 2.1.1.1 + ocra 1.3.1
- RyubyInstaller 1.8.7 p330 i386-mingw32 + rubysdl 1.3.1.1 + ocra 1.3.1
セットアップファイル名も一応列挙。
- rubyinstaller-1.9.3-p551.exe
- rubysdl-2.1.1.1-mswin32-1.9.1-p243.zip
- ActiveRuby.msi
- rubysdl-2.1.1.1-mswin32-1.8.7-p174.zip
- rubyinstaller-1.8.7-p330.exe
- rubysdl-1.3.1.1-mswin32-1.8.6-p36.zip
_ActiveScriptRuby and Other packages
_Download Archives - RubyInstaller
Ruby は32bit版を利用。
Ruby は32bit版を利用。
大事なことなので2回言いました。
Ruby/SDLのバイナリが32bitなので、64bit版のRubyに入れて使おうとしても動かないです。たぶん。
ちなみに、Windows用のRuby/SDLは Ruby 1.8 / 1.9用しか存在しないので、Ruby 2.0以降でこういったことはできないと思われます。
利用できるRubyのバージョンや、Ruby/SDL のインストール方法は、以下を参照のこと。
_Ruby/SDLでスクリーンセーバを作れないものか
_Ruby/SDLをインストールしようとしてハマった
◎ ソース。 :
ソースは以下。処理内容は、画面内をRubyのロゴ画像が跳ね回るだけの処理。
_rbsdlsav.rb
使用画像は以下。.rb と同じ階層に res というフォルダを作って、その中に入れておく。
_ruby_logo.png
_rbsdlsav.rb
require "sdl" require "Win32API" APPLI_NAME = "Screensaver sample by using Ruby/SDL" APPLIT_VER = "0.0.1" IMG_FILE = "res/ruby_logo.png" MUTEX_NAME = { "None" => "screensaver_rubysdl_sample_fullscreen", "fullscreen" => "screensaver_rubysdl_sample_fullscreen", "config" => "screensaver_rubysdl_sample_config", "preview" => "screensaver_rubysdl_sample_preview", } ERROR_ALREADY_EXISTS = 183 # Draw fullscreen def draw_fullscreen SDL.init(SDL::INIT_VIDEO) screen = SDL::Screen.open(0, 0, 0, SDL::FULLSCREEN | SDL::HWSURFACE | SDL::DOUBLEBUF) img = SDL::Surface.load(get_resource_path(IMG_FILE)).display_format x, y = screen.w / 2, screen.h / 2 dx, dy = screen.w / (60.0 * 3), screen.h / (60.0 * 4) count = 0 looping = true SDL::Mouse.hide # hide mouse cursor # main loop while looping while event = SDL::Event2.poll case event when SDL::Event2::Quit looping = false when SDL::Event2::KeyUp looping = false when SDL::Event2::MouseMotion if count >= 120 rx = event.xrel ry = event.yrel r = 10 looping = false if (rx * rx + ry * ry >= r * r) end end end # update sprite position x += dx y += dy dx *= -1 if (x <= 0 or x >= screen.w - img.w) dy *= -1 if (y <= 0 or y >= screen.h - img.h) count += 1 screen.fill_rect(0, 0, screen.w, screen.h, [0, 0, 0]) # fill bg screen.put(img, x, y) # draw sprite screen.flip # update screen SDL.delay(16) # wait end SDL::Mouse.show # show mouse cursor end # Draw preview def draw_preview(hwnd) if hwnd > 0 # /p xxxxxx scrw, scrh = get_window_size(hwnd) SDL.putenv("SDL_VIDEODRIVER=windib") SDL.putenv("SDL_WINDOWID=#{hwnd}") else # /p 0 scrw, scrh = 152, 112 end SDL.init(SDL::INIT_VIDEO) screen = SDL::Screen.open(scrw, scrh, 0, SDL::SWSURFACE) img = SDL::Surface.load(get_resource_path(IMG_FILE)).display_format # main loop frames = 180 * 5 frames.times do |t| while event = SDL::Event2.poll case event when SDL::Event2::Quit return when SDL::Event2::KeyDown return if event.sym == SDL::Key::ESCAPE end end x = (screen.w - img.w) / 2 y = 12 * Math.sin((t * 4) * Math::PI / 180.0) + ((screen.h - img.h) / 2) screen.fill_rect(0, 0, screen.w, screen.h, [235, 108, 0]) # fill bg screen.fill_rect(8, 8, screen.w - 16, screen.h - 16, [255, 128, 0]) # fill bg screen.put(img, x, y) screen.flip SDL.delay(16) end end def draw_config s = "#{APPLI_NAME}\nVer. #{APPLIT_VER}" title = "Information" msg_box(s, title) end def get_resource_path(filepath) # return File.dirname(__FILE__) + "/" + filepath return File.join(File.dirname(__FILE__), filepath) end # Display messagebox dialog def msg_box(msg, title) msgbox = Win32API.new("user32", "MessageBoxA", %w(p p p i), "i") msgbox.call(0, msg, title, 0x40) end # Get window size def get_window_size(hwnd) get_window_rect = Win32API.new("user32", "GetWindowRect", "lp", "i") buf = "\0" * 256 get_window_rect.call(hwnd, buf) x0, y0, x1, y1 = buf.unpack("l4") w, h = (x1 - x0), (y1 - y0) return w, h end # parse command line option kind = "None" hwnd = 0 if ARGV.size >= 1 s = ARGV[0].downcase.slice(0..1) case s when "/s" kind = "fullscreen" when "/c" kind = "config" when "/p" kind = "preview" hwnd = ARGV[1].to_i end end # Mutex create_mutex = Win32API.new("kernel32", "CreateMutex", "llp", "l") get_last_error = Win32API.new("kernel32", "GetLastError", "", "l") release_mutex = Win32API.new("kernel32", "ReleaseMutex", "l", "l") close_handle = Win32API.new("kernel32", "CloseHandle", "l", "l") mutex = create_mutex.call(0, 1, MUTEX_NAME[kind]) err = get_last_error.call() exit if (mutex == 0 or err == ERROR_ALREADY_EXISTS) # main job case kind when "config" draw_config when "preview" draw_preview(hwnd) else # fullscreen draw_fullscreen end if mutex != 0 release_mutex.call(mutex) close_handle.call(mutex) end exit
- draw_fullscreen() が、フルスクリーン表示モードの処理。
- draw_config() が、設定画面モードの処理。
- draw_preview() が、プレビューモードの処理。
- Mutex 云々が、多重起動抑止処理。
使用画像は以下。.rb と同じ階層に res というフォルダを作って、その中に入れておく。
_ruby_logo.png
◎ テストで実行。 :
実行は以下。
ruby rbsdlsav.rb /s ruby rbsdlsav.rb /c ruby rbsdlsav.rb /p 0 ruby rbsdlsav.rb
- /s : フルスクリーン表示で実行。
- /c : 設定画面を表示。ここではアプリ名をメッセージボックスで表示するだけ。
- /p 0 : プレビューモード。スクリーンセーバ設定画面を表示した際に、プレビュー窓内に表示されるモード。ウインドウハンドルとして 0 を指定すると、小さいウインドウを表示してテスト描画する。本番では0より大きい数値(10進数)が渡されるはず。
- コマンドラインオプション無し : フルスクリーン表示で実行するようにしておいた。
◎ exe化する。 :
Windows用スクリーンセーバのファイル拡張子は .scr だけど、実体は .exe ファイル。.exe を .scr にリネームして、スクリーンセーバとして利用する。
今回、Rubyスクリプトのexe化には ocra を利用した。
ocra のインストールは以下。
以下で exe ファイルが生成される。
今回、Rubyスクリプトのexe化には ocra を利用した。
- Ruby 1.8.7 の場合、ocra 1.3.1 が利用できる。ocra 1.3.2 以降はエラーが出る。
- RUby 1.9.3 の場合、ocra 1.3.10 が利用できる。ocra 1.3.11 はエラーが出る。
ocra のインストールは以下。
# Ruby 1.8.7 gem install ocra -v 1.3.1 # Ruby 1.9.3 gem install ocra -v 1.3.10
以下で exe ファイルが生成される。
ocra --windows rbsdlsav.rb res
- --windows : GUIアプリとして実行する指定。
- *.rb : 変換したいスクリプトファイル名。
- res : 画像ファイル等が入ってるフォルダ。*.rb と一緒にフォルダ名を列挙すると exe に同梱される。
◎ スクリーンセーバとして利用する。 :
.exe が生成されたら、.scr にリネームする。以下の場所に .scr をコピーすれば、スクリーンセーバとして利用できるようになる。
今回作ったスクリーンセーバは、32bit版 Ruby で作ったので、C:\Windows\SysWOW64\ 以下にコピーして動作確認した。
- Windows が64bit版、スクリーンセーバが32bit版のプログラムなら、C:\Windows\SysWOW64\ 以下に .scr をコピーする。
- Windows が64bit版、スクリーンセーバが64bit版のプログラムなら、C:\Windows\System32\ 以下に .scr をコピーする。
- Windows が32bit版なら、C:\Windows\System32\ 以下に .scr をコピーする。
今回作ったスクリーンセーバは、32bit版 Ruby で作ったので、C:\Windows\SysWOW64\ 以下にコピーして動作確認した。
◎ exerbではexe化できない。 :
[ ツッコむ ]
以上です。