未知との出会い

PyCon mini Shizuoka 2024 Continue

2025.02.08

清水川 貴之

お前、誰よ

_images/face-dot.png

清水川 / @shimizukawa

  • 翻訳者、著者

    • エキスパートPythonプログラミング

    • 独学プログラマー/独学コンピューターサイエンティスト

  • 一般社団法人PyCon JP Assocation

    • 会計理事、PyCamp講師

  • 株式会社 BeProud 所属

    • 自社サービス開発

      • Python, Django, Celery, Vue3, Nuxt3, TypeScript, Node, AWS, Stripe, Sentry

    • 受託開発

1985年(10歳頃)

  • ファミコン

  • スーパーマリオブラザーズ

  • ファミリーベーシック

このときハマりすぎて、プログラマーになってしまった

1991年(16歳頃)

  • パソコン(PC-9801 DS)

  • MIKATYPE (タイピングゲーム)

    • 今も現役でアップデートされている模様

  • ゲーム作り

    • 高校生: N88-BASIC, C, ASM(制約の多さに挫折)

    • 大学生: DirectX (難しすぎて挫折)

  • 自宅サーバー

    • KENT WEB、Web日記(Perlが難しくて挫折)

2003年(28歳頃)

  • Zopeを使い始め

  • Pythonを使い始め

  • コミュニティー活動 ZopeやPythonイベントへ参加

  • Pythonを使える環境へ転職

2010年前後

  • コミュニティー活動 (#pyhack, #sphinxjp)

  • 本の翻訳、執筆

  • Sphinxコミッター

  • PyCon JP、PyCamp講師

  • 結婚し、伊豆高原 (静岡) で挙式

2020年から

  • 函南町 (静岡) にセカンドハウス

  • 伊豆の国市 (静岡) で川遊び

  • 落ち葉集め、草むしり、ペンキ塗り

  • 三島の焚き火スポットで焚き火

2025年

  • 小学校支給のパソコンにはScratchが

    • 何か作ろうかと思った

    • Scratchだと作りたいものが思い浮かばず...

  • Pyxelでゲームを作って子供に遊ばせる

  • MIKATYPE 風タイピングゲーム作ってみた

ゲーム、今なら作れそう?

MIKATYPE風タイピングゲームを作ってみた

MIKATYPE 風タイピングゲーム

約60語、60 秒タイムアタック

_images/typinggame.png

実際にプレイしてみる

_images/typinggame.png

作っていて地味に苦労したところ

  • 単語を用意(ChatGPTに約900用意してもらった)

  • どこまで入力したか判るように文字を装飾

  • 単語エリアぴったりに単語を詰め込みたい

_images/typinggame2.png

40文字 x 8行に、きれいに詰め込みたい

最初の(素朴な)実装

  1. 全 900 単語をシャッフル

  2. 先頭から各行に順次詰めてみる

課題

  • 毎回、各行に入るかを判定してしまい、全探索

  • 空きが1文字でもあると完了判定できず、全単語チェック

  • 完了判定の閾値を増やすと、右端がガタガタしてしまう

40文字 x 8行に、きれいに詰め込みたい

_images/typinggame-algo1.png

単語詰め込みアルゴリズムの見直し

適用できそうな有名どころの解法

  • 力任せ探索(バックトラッキング)

  • 動的計画法(大学生のとき聞いたような...)

  • 最短経路探索(Dijkstra)

  • 組み合わせ最適化(何か難しいやつ)

今回は、力任せ探索の延長でちょっとだけ改良してみました。

力任せ探索の改善案

仮説と改善案

  • 長い単語は後になると入れづらい

    • 長い文字から詰め込んでみる

  • 先頭行に長い文字が集中するとつらい

    • 一番空いてる行から詰め込むと良さそう

修正したアルゴリズム

  1. 対象単語リスト を作る

    • 全 900 単語をシャッフル

    • 先頭から必要文字数+αの単語を取得

  2. 対象単語リスト を長い単語順にソート

  3. for 単語 in 対象単語リスト

    • 全行を空きの多い順(確定文字列の短い順)にソート

    • 先頭行に単語を追加

  4. 行毎の単語をシャッフル

修正したアルゴリズム

_images/typinggame-algo2.png

修正したアルゴリズムの評価

  • 明らかにステップ数が減っていて、良い感じ

  • アルゴリズムは簡易だが、計算資源は節約できた

  • 右端のガタガタは、多少改善

  • 他のアルゴリズムで実装したら綺麗な矩形になるだろうか?

今回の改良はここまで。

タイピングゲームを作ってみて

  • Pyxelは表現上の制約が多いので、やりすぎず、ゴールが近い

  • APIが少ないので、覚えるハードルが低い

  • やってみる気になれる、ほどよい難易度

  • 最後に立ちはだかるのは、アルゴリズムとデータ構造

  • 最短経路探索が使えるの?

    • 実装してみたからこそ調べて出てきた「未知」

    • もはやタイピングゲームはどうでもよい

      • 明日にでもちょっと実装してみるかな..

多人数同時、今なら作れそう?

高校時代に挫折したやつ

_images/15_tiled_map_file.png

多人数同時プレイの(昔)難しかったところ

  • PC-9801で2人同時プレイのアクションゲームに挑戦

    • N88-BASICやQuick Cでは難題だった

  • C言語の標準関数は同時押しに対応できない

    • アセンブラでキーボード割込検知を実装

  • ゲーム実装の手前で力尽きた

    • キーボードの同時押しでキャラクターは動いた!

Pyxel は、そのあたりの仕組みを提供している。
これなら作れるかも..!

多人数で操作してみよう

_images/15_tiled_map_file.png

技術スタック

  • Python

    • pyxel: ゲームエンジン

    • websocket-client: WSクライアント

    • websockets: WSサーバー(EC2で実行)

  • Pyodide

    • js.WebSocket: WSクライアント

PyodideとWebSocket

  • Pyxel標準で、ブラウザ版がPyodideで動作

  • しかし、Pyodideに WebSocket が 無い!

  • Issueにワークアラウンドが書いてあった

  • こういう、出来るか分からないことをやるのが、めっちゃ楽しい

WebSocket Echo Server

  • メッセージをエコーバックするだけ

  • shimizukawa/pyxel-app/02-multiplay/server.py

    async def echo(websocket):
        clients.add(websocket)
        async for message in websocket:
            data = json.loads(message)
            for client in clients:
                if client != websocket:
                    await client.send(json.dumps(data))
    
  • コードの大枠は GitHub Copilot が書いた

  • (検証は、Sphinx JP Hack-a-thonでご協力頂いた)

多人数同時プレイに改造してみて

  • 実際に作ってみて、分かっていなかった事が分かった

    • 「不知」が「未知」に転換した

  • 初めて触れるWebSocket処理は Copilot が書いてくれた

    • バグを直す過程で、WebSocketの使い方を把握

    • WebSocketの本番用意は大変だった(まだ未解決)

  • イベントで見せて、フィードバックを元に発想を広げた

    • 人に見せる、反応をもらう、そういう場は有り難い

「WebSocketの勉強しよう」では動けていなかった。 飛び込んでみてから、必要な知識を身に着けるスタイル。

スーパーマリオの壁抜け

をPyxelで再現

スーパーマリオ

  • 知ってる人~?

スーパーマリオブラザーズ(NES)

  • 1986年頃、ひたすら遊び続けたゲーム

  • 自分がプログラマーを目指したきっかけの1つ

  • 当時のゲームの中では別格に遊びやすかった

  • よくよく観察すると、どんなコードを書いたら実現できるか分からないことが多い

ここで、本物の映像をご覧ください

スーパーマリオの当たり判定

  • マリオ(小)は16x16ピクセル

  • 四角形同士(マリオとブロック)の当たり判定は比較的簡単

  • マリオ側を小さくしておかないと当たりすぎてゲームが難しくなる

  • マリオ側を小さくすると、端っこで落ちやすくなる

_images/mario1.png

どうする?

頭の当たり判定を小さくする

頭は小さく、足元は大きく、判定するには

  • 三角形(マリオ)と四角形(ブロック)で当たり判定を行う

  • マリオの頭を小さくして、頭をぶつけづらく

  • マリオの足はフルサイズにして、落ちづらく

_images/mario2.png

そんな当たり判定、
実装できる?

半ブロックずれを再現: jumpman

_images/jumpman.png

壁抜けをPyxelで再現してみて

  • いくつかの「未知」が解決した

    • 当たり判定はY軸が先、X軸が後

    • ハマりの検出方法

  • 新しい「未知」を見つけた

    • 実装コードをもっとシンプルにできる気がする

    • もっとうまい仕様にまとめられる気がする

    • 代数、幾何、の知識があれば解決できる気がする

  • 図書館でちょっと探してみたい

まとめ

未知との出会いを楽しもう!

プログラミングは、未知の宝庫!

今回登場した未知

  • Pyxel

  • Pyodide

  • WebSocket通信、本番デプロイ

  • 最短経路探索で単語詰込み

  • 当たり判定のうまい設計

  • キーボード同時押し検出

何が楽しい?

やってみて理解出来たときにめちゃくちゃ楽しい!

  • ハードウェアレベルでのキーの同時押し判定できた!

  • タイピングゲームの単語詰込みがきれいにできた!

  • マリオの当たり判定、それっぽく動くようになった!

  • PyxelにWebSocket通信を組み込んだぞ!

  • プレゼンスライドをPyxelで実装したぞ!

判らない事だらけになるとツラい

  • 壁抜け、まだハマるのが解決できない

  • WebSocket、API Gatewayで動かせなかった

  • DirectX は一生理解できなそう

  • ペンキ塗り立てなのに雨降ってきたんだけど!?

相談できる場が助けになる

コミュニティイベント参加がお勧め。

  • 誰かと話をしたり、教え合ったりするとモチベーションが上がる

  • 仲間と同じ場で雑談したり相談することが刺激になる

  • アウトプットすることで自分の知識が定着する

  • イベント本編だけでなく懇親会もすごい楽しい

    • 私は、初参加したイベントでそれを実感

コミュニティイベントは、

未知との出会い、理解、失敗、新しい未知、が高速回転する

  • 参加者同士の相互作用

  • 場のダイナミズム

  • フィルターバブルからの脱出作用

  • 中毒性

がある

プログラミングは楽しい

  • 未知に出会える(無限に)

  • 未知は解決できる

未知を問い、解決することで「世界が一変する瞬間」を体験できる

未知に効率よく遭遇するには

  • 本を読もう。驚きに遭遇できる本が良い

  • 手を動かして体験しよう。自分なりの何かを作ってみる。

  • 人と交流しよう。相互作用が思いがけない流れを作る

ありがとうございました

¿QUESTION?