のつづきです
Elixirで作る「DDJ-FLX4のジョグ対応ブロックくずし」 の最終回です
DDJ-FLX4を毎回セッテイングがめんどくさい&DDJ-FLX4がなくても動作チェックしたい
結論はWebSocketで通信できれば、なんでも良いです
ライブラリの相性問題でWebSocket対応した為可能になりました
OSはUbuntu22.04で動かしていますが、ひょっとしたら他のOSでもライブラリさえ動けば動作するかも
方法ブラウザーから通信する
仕様
- ws://localhost:4000/socket/websocket?token=undefined&vsn=2.0.0'に接続
- 
["","","ddj:lobby","phx_join",{}]送信してサーバーに接続処理を行う
- aキーを押すと-1.0を送信- '["","","ddj:lobby","new_msg",{"body":-1.0"}]'
 
- dキーを押すと1.0を送信- '["","","ddj:lobby","new_msg",{"body":1.0"}]'
 
- データー受信時<div id="msg">に受信結果を表示
ソース
ddj_client/client_test.html
<html>
<script>
    const ws = new WebSocket('ws://localhost:4000/socket/websocket?token=undefined&vsn=2.0.0')
    // 接続後にphx_joinを送る
    ws.onopen = () => {
        ws.send('["","","ddj:lobby","phx_join",{}]');
    };
    const MOVE_LEFT_AMOUNT = "-1.0";
    const MOVE_RIGHT_AMOUNT = "1.0";
    const keyBindings = {
        a: MOVE_LEFT_AMOUNT,
        d: MOVE_RIGHT_AMOUNT,
    };
    // htmlロード後
    window.addEventListener('load', function () {
        document.addEventListener("keypress", event => {
            const value = keyBindings[event.key];
            if (value !== undefined) {
                send(value);
            }
        })
    });
    function send(msg) {
        data = '["","","ddj:lobby","new_msg",{"body":"' + msg + '"}]'
        ws.send(data)
    }
    // 受信時にdevタグの内容に追加
    ws.onmessage = (event) => {
        const msg = document.querySelector("#msg")
        msg.innerHTML = event.data + "<br>" + msg.innerHTML
    };
</script>
<div id="msg">
</div>
</html>
バグが見つかったので修正
一生消えないブロックができました
対策
- ボールを大きくする
- ボールの速度変更
- ボールがプレイヤーにあたった時のx軸は反射はしない修正
ddj_block/lib/block.ex
defmodule Block do
  def main(nil) do
    blocks =
      1..3
      |> Enum.flat_map(fn y -> creat_blocks(y) end)
    %{
      wall: [
        [0.0, 0.0, 10.0, 900.0],
        [790.0, 0.0, 10.0, 900.0],
        [0.0, 0.0, 900.0, 10.0],
        [0.0, 900.0, 900.0, 10.0]
      ],
      blocks: blocks,
      player: [[350.0, 790.0, 100.0, 10.0]],
-     ball: [[350.0, 400.0, 10.0, 10.0]],
-     ball_speed_x: -2.0,
-     ball_speed_y: -2.0
+     ball: [[350.0, 400.0, 50.0, 50.0]],
+     ball_speed_x: 0.5,
+     ball_speed_y: 4.0
    }
  end
  def main(%{} = data) do
    [[x, y, w, h]] = data.ball
    wall_lr = data.wall |> Enum.slice(0..1)
    wall_t = data.wall |> Enum.slice(2..3)
    {collided, blocks} = Game.collided_with_filter(x, y, w, h, data.blocks)
    ball_speed_y =
      if Game.collided?(x, y, w, h, wall_t ++ data.player) or collided,
        do: data.ball_speed_y * -1.0,
        else: data.ball_speed_y * 1.0
    ball_speed_x =
-     if Game.collided?(x, y, w, h, wall_lr ++ data.player) or collided,
+     if Game.collided?(x, y, w, h, wall_lr) or collided,
        do: data.ball_speed_x * -1.0,
        else: data.ball_speed_x * 1.0
    [[bx, by, bw, bh]] = data.ball
    ball = [[bx + ball_speed_x, by + ball_speed_y, bw, bh]]
    [[px, py, pw, ph]] = data.player
    player = [[px + DdjBlock.get_state() * 20, py, pw, ph]]
    DdjBlock.set_state(0.0)
    Map.merge(data, %{
      ball_speed_y: ball_speed_y,
      ball_speed_x: ball_speed_x,
      ball: ball,
      player: player,
      blocks: blocks
    })
  end
  def creat_blocks(y) do
    1..5
    |> Enum.map(fn x ->
      [120.0 * x, 100.0 * y, 100.0, 50.0]
    end)
  end
end
操作動画
ブラウザーにフォーカスしてからaキーとdキーで操作できます
github
気づいいる問題点:ddj_block起動時にたまに落ちる(理由不明)
おわり
コラム一覧
