kairo-gokko (9) マウスと効果音



「マウス操作も効果音もまだ必要にはなってない」と前回書きましたが、 せっかく DXOpal にしたのでちょっとだけやっておきます。

マウス

とりあえずマウスカーソルの位置(x, y 座標)を取得して、表示に反映させてみます。

--- a/main.rb
+++ b/main.rb
@@ -22,6 +22,9 @@ Window.load_resources do
   Window.bgcolor = C_BLACK
 
   Window.loop do
+    mx = (Input.mouse_x / PPC).floor
+    my = (Input.mouse_y / PPC).floor
+
     view.draw_grid(8, 10)
 
     circuit.plus_poles.each { |pole|
@@ -35,5 +38,7 @@ Window.load_resources do
     circuit.edges.each { |edge|
       view.draw_edge(edge)
     }
+
+    view.draw_cursor_highlight(mx, my)
   end
 end

mx, my はセル座標です。マウスカーソルがある位置のセルがハイライトされるようにしてみました。

f:id:sonota88:20200224105905g:plain

効果音

効果音の音声ファイルを作ります。 とりあえず今は音が出れば何でもよいです。 wavefile gem を使って適当な三角波を作ってみました。

参考: Rubyで音(wav)を書き出してみた - Qiita

※ 作った後で気づきましたが、こういう場合は SoundEffect を使うのもよさそうです。
SoundEffectチュートリアル(DXRuby)

# coding: utf-8
require "wavefile"
include WaveFile

def osc_tri(ratio)
  if ratio < 0.25
    4 * ratio
  elsif ratio < 0.75
    -4 * ratio + 2
  else
    4 * ratio - 4
  end
end

# --------------------------------

params = {}

ARGV.map { |arg|
  md = /^(.+?)=(.+)/.match(arg)
  k = md[1].to_sym
  v = md[2]

  params[k] =
    case k
    when :msec, :hz, :amp
      v.to_f
    when :out
      v
    else
      raise "invalid key (#{k})"
    end
}

# --------------------------------

# サンプリングレート(サンプル数 / 秒)
srate = 44100

# 増幅率 (0.0 <= x <= 1.0)
amp = params[:amp] || 0.1

duration_msec = params[:msec] || 100.0

# 全体のサンプル数
num_samples = srate * (duration_msec.to_f / 1000)

hz = params[:hz] || 440.0

# 1周期あたりのサンプル数
num_samples_per_cycle = srate / hz

out_file = params[:out] || "output.wav"

# --------------------------------

samples = []

(0 ... num_samples).each { |t|
  t_in_cycle = t % num_samples_per_cycle
  ratio = t_in_cycle / num_samples_per_cycle
  samples << osc_tri(ratio) * amp
}

# --------------------------------

buffer_format = Format.new(:mono, :float, srate)
file_format = Format.new(:mono, :pcm_16, srate)

buffer = Buffer.new(samples, buffer_format)

Writer.new(out_file, file_format) do |writer|
  writer.write(buffer)
end

たかだか数十ミリ秒の小さなデータを生成するだけなので実行は 0.3 秒くらいで終わります。 なので、生成処理も富豪的run.sh で毎回実行するようにしました。

--- a/run.sh
+++ b/run.sh
@@ -2,6 +2,8 @@
 
 set -o errexit
 
+bundle exec ruby gen_sound.rb \
+  out=click.wav amp=0.1 msec=30 hz=1000
+
 ruby preprocess.rb "$@" > data.rb
 
 bundle exec dxopal server

ファイルが用意できたので main.rb で使ってみましょう。

--- a/main.rb
+++ b/main.rb
@@ -18,6 +18,8 @@ circuit = Circuit.from_plain(
 
 view = View.new(PPC)
 
+Sound.register(:click, "click.wav")
+
 Window.load_resources do
   Window.bgcolor = C_BLACK
 
@@ -25,6 +27,10 @@ Window.load_resources do
     mx = (Input.mouse_x / PPC).floor
     my = (Input.mouse_y / PPC).floor
 
+    if Input.mouse_push?(M_LBUTTON)
+      Sound[:click].play
+    end
+
     view.draw_grid(8, 10)
 
     circuit.plus_poles.each { |pole|

マウスの左ボタンをクリックしたときに効果音が鳴るようになりました。 お手軽ですね!


せっかくの DXOpal なので GitHub Pages に置いてみました。

スマホタブレットだと描画はされますがマウス操作はできません。 DXOpal 側ではタッチまわりの API が用意されていますが、いったんマウスのみの対応で進めます。

https://sonota88.github.io/kairo-gokko/pages/09/index.html

参考: DXOpalで作ったゲームを無料で公開する - Qiita