スイッチ以外をクリックしたときにエラーになるのを修正
Circuit#find_switch_by_position
を修正。
クリックした位置にスイッチがない場合に nil を返すように。
もっと早く直しておけばよかった……。
--- a/circuit.rb +++ b/circuit.rb @@ -328,5 +328,7 @@ class Circuit .find { |switch| switch.pos == pos } return pushed_switch if pushed_switch } + + nil end end
タッチ操作対応
これまで PC メインで作業してきてタッチ操作対応は後回しでもいいかなと思ってたんですが、 ブログに貼ったりするとやはりスマホやタブレットで触りたくなってきました。
マウスの場合とほとんど同じで大丈夫でした。 これももっと早くやっとけばよかったですね。
# main.rb tx = (Input.touch_x / PPC).floor ty = (Input.touch_y / PPC).floor if Input.touch_push? tpos = Point(tx, ty) pushed_switch = circuit.find_switch_by_position(tpos) if pushed_switch Sound[:click].play pushed_switch.toggle() end end
以下の iframe で実際に試せます。
ファイルが増えたためロード時間がだいぶ長くなってきました(特にモバイル環境)。 これはこれでなんとかしたい……。
こちらも同じものです。
https://sonota88.github.io/kairo-gokko/pages/20/index.html
動くことが分かったのでリファクタリングします。
スイッチをクリック、またはタッチしたときの処理をメソッドに抽出。
def on_push(pushed_switch) Sound[:click].play pushed_switch.toggle() end
無駄な通電判定を抑制
気づいてはいましたが、 通電判定は重い処理ですから、毎フレーム実行するのはかなり無駄です。 スイッチの状態が変わらなければ通電の状態を更新する必要はないはずです。
まあこれは明らかに無駄だと思うので、 測定せずにやってしまいます。
まずはスイッチが変更されたことを示す変数 switch_changed
を導入して、スイッチが押されたときだけ true になるようにします。
--- a/main.rb +++ b/main.rb @@ -50,6 +50,8 @@ Window.load_resources do Window.bgcolor = C_BLACK Window.loop do + switch_changed = false + mx = (Input.mouse_x / PPC).floor my = (Input.mouse_y / PPC).floor @@ -61,6 +63,7 @@ Window.load_resources do if pushed_switch on_push(pushed_switch) + switch_changed = true end end @@ -75,6 +78,7 @@ Window.load_resources do if pushed_switch on_push(pushed_switch) + switch_changed = true end end
この switch_changed
を見て通電判定処理を実行するか決めるようにします。
if switch_changed circuit.child_circuits.each { |child_circuit| child_circuit.update_edges() } end
これだけだと、アプリケーションの実行が開始されて最初にスイッチが押されるまで 通電判定が行われないことになってしまうので、 初回に一度実行するようにします。
--- a/main.rb +++ b/main.rb @@ -40,6 +40,10 @@ end circuit = Circuit.from_plain(parse_json($data_json)) +circuit.child_circuits.each { |child_circuit| + child_circuit.update_edges() +} + view = View.new(PPC) Sound.register(:click, "click.wav")
さらに、この子回路をイテレートして通電判定する部分は、責務的に Circuit に移した方がよさそうなので、 Circuit#update_tuden_state
に抽出しました。
def update_tuden_state @child_circuits.each { |child_circuit| child_circuit.update_edges() } end
んー、メインループ部分が長くなってきたのでこれもメソッドに抽出しましょうか。
main_loop()
自体は長いままなんですが、呼び出し側の部分はすっきりしました。
circuit = Circuit.from_plain(parse_json($data_json)) circuit.update_tuden_state() view = View.new(PPC) Sound.register(:click, "click.wav") Window.load_resources do hide_loading() Window.bgcolor = C_BLACK Window.loop do main_loop(circuit, view) end end
今回はここまで。