未知との出会い
PyCon mini Shizuoka 2024 Continue
2025.02.08
清水川 貴之
お前、誰よ

清水川 / @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 秒タイムアタック

実際にプレイしてみる

作っていて地味に苦労したところ
単語を用意(ChatGPTに約900用意してもらった)
どこまで入力したか判るように文字を装飾
単語エリアぴったりに単語を詰め込みたい

40文字 x 8行に、きれいに詰め込みたい
最初の(素朴な)実装
全 900 単語をシャッフル
先頭から各行に順次詰めてみる
課題
毎回、各行に入るかを判定してしまい、全探索
空きが1文字でもあると完了判定できず、全単語チェック
完了判定の閾値を増やすと、右端がガタガタしてしまう
40文字 x 8行に、きれいに詰め込みたい

単語詰め込みアルゴリズムの見直し
適用できそうな有名どころの解法
力任せ探索(バックトラッキング)
動的計画法(大学生のとき聞いたような...)
最短経路探索(Dijkstra)
組み合わせ最適化(何か難しいやつ)
今回は、力任せ探索の延長でちょっとだけ改良してみました。
力任せ探索の改善案
仮説と改善案
長い単語は後になると入れづらい
長い文字から詰め込んでみる
先頭行に長い文字が集中するとつらい
一番空いてる行から詰め込むと良さそう
修正したアルゴリズム
対象単語リスト を作る
全 900 単語をシャッフル
先頭から必要文字数+αの単語を取得
対象単語リスト を長い単語順にソート
for 単語 in 対象単語リスト
全行を空きの多い順(確定文字列の短い順)にソート
先頭行に単語を追加
行毎の単語をシャッフル
修正したアルゴリズム

修正したアルゴリズムの評価
明らかにステップ数が減っていて、良い感じ
アルゴリズムは簡易だが、計算資源は節約できた
右端のガタガタは、多少改善
他のアルゴリズムで実装したら綺麗な矩形になるだろうか?
今回の改良はここまで。
タイピングゲームを作ってみて
Pyxelは表現上の制約が多いので、やりすぎず、ゴールが近い
APIが少ないので、覚えるハードルが低い
やってみる気になれる、ほどよい難易度
最後に立ちはだかるのは、アルゴリズムとデータ構造
最短経路探索が使えるの?
実装してみたからこそ調べて出てきた「未知」
もはやタイピングゲームはどうでもよい
明日にでもちょっと実装してみるかな..
多人数同時、今なら作れそう?
高校時代に挫折したやつ

多人数同時プレイの(昔)難しかったところ
PC-9801で2人同時プレイのアクションゲームに挑戦
N88-BASICやQuick Cでは難題だった
C言語の標準関数は同時押しに対応できない
アセンブラでキーボード割込検知を実装
ゲーム実装の手前で力尽きた
キーボードの同時押しでキャラクターは動いた!
Pyxel は、そのあたりの仕組みを提供している。
これなら作れるかも..!
多人数で操作してみよう

技術スタック
Python
pyxel
: ゲームエンジンwebsocket-client
: WSクライアントwebsockets
: WSサーバー(EC2で実行)
Pyodide
js.WebSocket
: WSクライアント
PyodideとWebSocket
Pyxel標準で、ブラウザ版がPyodideで動作
しかし、Pyodideに WebSocket が 無い!
Issueにワークアラウンドが書いてあった
from js import WebSocket
refs: pyodide#574
こういう、出来るか分からないことをやるのが、めっちゃ楽しい
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ピクセル
四角形同士(マリオとブロック)の当たり判定は比較的簡単
マリオ側を小さくしておかないと当たりすぎてゲームが難しくなる
マリオ側を小さくすると、端っこで落ちやすくなる

どうする?
頭の当たり判定を小さくする
頭は小さく、足元は大きく、判定するには
三角形(マリオ)と四角形(ブロック)で当たり判定を行う
マリオの頭を小さくして、頭をぶつけづらく
マリオの足はフルサイズにして、落ちづらく

そんな当たり判定、
実装できる?
半ブロックずれを再現: jumpman

壁抜けをPyxelで再現してみて
いくつかの「未知」が解決した
当たり判定はY軸が先、X軸が後
ハマりの検出方法
新しい「未知」を見つけた
実装コードをもっとシンプルにできる気がする
もっとうまい仕様にまとめられる気がする
代数、幾何、の知識があれば解決できる気がする
図書館でちょっと探してみたい
まとめ
未知との出会いを楽しもう!
プログラミングは、未知の宝庫!
今回登場した未知
Pyxel
Pyodide
WebSocket通信、本番デプロイ
最短経路探索で単語詰込み
当たり判定のうまい設計
キーボード同時押し検出
何が楽しい?
やってみて理解出来たときにめちゃくちゃ楽しい!
ハードウェアレベルでのキーの同時押し判定できた!
タイピングゲームの単語詰込みがきれいにできた!
マリオの当たり判定、それっぽく動くようになった!
PyxelにWebSocket通信を組み込んだぞ!
プレゼンスライドをPyxelで実装したぞ!
判らない事だらけになるとツラい
壁抜け、まだハマるのが解決できない
WebSocket、API Gatewayで動かせなかった
DirectX は一生理解できなそう
ペンキ塗り立てなのに雨降ってきたんだけど!?
相談できる場が助けになる
コミュニティイベント参加がお勧め。
誰かと話をしたり、教え合ったりするとモチベーションが上がる
仲間と同じ場で雑談したり相談することが刺激になる
アウトプットすることで自分の知識が定着する
イベント本編だけでなく懇親会もすごい楽しい
私は、初参加したイベントでそれを実感
コミュニティイベントは、
未知との出会い、理解、失敗、新しい未知、が高速回転する
参加者同士の相互作用
場のダイナミズム
フィルターバブルからの脱出作用
中毒性
がある
プログラミングは楽しい
未知に出会える(無限に)
未知は解決できる
未知を問い、解決することで「世界が一変する瞬間」を体験できる
未知に効率よく遭遇するには
本を読もう。驚きに遭遇できる本が良い
手を動かして体験しよう。自分なりの何かを作ってみる。
人と交流しよう。相互作用が思いがけない流れを作る
ありがとうございました
¿QUESTION?