100コインで1UPするデーモン
何かのコマンドが標準出力に"Error"と出力したら音を鳴らすプログラムには多々問題がありました。
- コインをゲットする音を再生するのにmplayerを起動しているので、大変重い。`yes ok`とやってしまうと大変なことになる。
- それ以前にmplayerを起動するのはカッコ悪い
- コインの音が「コイン、コイン、コイン」とぎこちなく、「ココココイーン」と気持ちよく鳴らない
- 100コインで1UPしない
というわけで、音を鳴らす部分をRuby/SDLにしてみました。それからコインをゲットするプログラムをデーモン化して、確実に100コインで1UPするようにしてみました。
- Ruby/SDLを初期化
- 音声ファイルをロード
- SIGUSR1を受け取ったら…
- コインをゲット
- SIGUSR2を受け取ったら…
- ノコノコにやられる
という寸法で動きます。
適当なプログラムでシグナルを送ってやれば、コインをゲットできます。for((i=0; i<100; i++)); do killall -USR1 ruby; sleep 0.1; done など(bash拡張文法)。
- coind.rb
#!/usr/bin/env ruby require 'rubygems' require 'sdl' require 'pp' # Ruby/SDLのAudioだけ初期化 SDL.init(SDL::INIT_AUDIO) SDL::Mixer.open sound_coin = SDL::Mixer::Wave.load("coin.wav") # コイン sound_up = SDL::Mixer::Wave.load("up.wav") # 1UP sound_fail = SDL::Mixer::Wave.load("fail.wav") # ノコノコにやられる # デーモン化 ## IO.daemon # Ruby 1.9 #exit! 0 if fork #Process.setsid #exit! 0 if fork #Dir.chdir('/') #File.umask(0) #STDIN.reopen '/dev/null', 'r' #STDOUT.reopen '/dev/null', 'a' #STDERR.reopen '/dev/null', 'a' COIN_CHANNEL = 0 UP_CHANNEL = 1 FAIL_CHANNELNNEL = 2 coin = 0 # コインの数 Signal.trap(:USR1) { # SIGUSR1 coin += 1 if coin % 100 == 0 # 100コインごとに1UP SDL::Mixer.play_channel(UP_CHANNEL, sound_up, 0) else unless SDL::Mixer.play?(UP_CHANNEL) # 1UP中はコインの音を鳴らさない SDL::Mixer.play_channel(COIN_CHANNEL, sound_coin, 0) end end } Signal.trap(:USR2) { # SIGUSR2 SDL::Mixer.play_channel(FAIL_CHANNEL, sound_fail, 0) } while 1 sleep end
Mac OS Xでデーモン化すると「The process has forked and you cannot use this CoreFoundation functionality safely.」と怒られてしまうので、コメントアウトしてあります。