公開: 2026年10月25日 ・ 筆者: Toshi(開発者)
バズ走には画像ファイルが1枚もありません。東京タワーも、ピラミッドも、月も太陽も、棒人間も、すべて Canvas 2D API の円弧・直線・ベジェ曲線で描いています。「素材を持たない」という制約から生まれた描き方と、その結果として手に入った軽さについて書きます。
最初の目的は読み込み時間をゼロに近づけることでした。画像を1枚でも読み込むと、回線によっては表示までに1〜2秒かかり、その間に離脱されます。全部コードで描けば、HTMLが届いた瞬間に描画が始まります。
やってみて分かった副次的な利点が2つあります。1つは統一感。線の太さ・色・ゆらぎをコードで共通化しているので、どのステージも同じ「落書き帳」の世界に見えます。もう1つは追加コストの低さ。新しい都市を足すのに素材を探す必要がなく、数十行の描画関数を書くだけで済みます。
完全な円を1本描くと、どうしてもCGらしい硬さが出ます。太陽は「中心をわずかにずらした円弧を3本重ねる」だけで、手でぐるぐる描いたような質感になりました。この考え方は他の要素にも応用しています。
重要なのは、ゆらぎを Math.random() で毎フレーム変えないことです。毎フレーム変えると線がチラついて「ノイズ」になります。ゆらぎは描画位置から決まる固定値にして、同じ場所は常に同じ形に描いています。
| 用途 | 色 |
|---|---|
| 背景(紙) | #f4f2ec クリーム色 |
| 線画・地面・棒人間 | #111111 ほぼ黒 |
| アクセント(鉢巻・★・強調) | #d32f2f 赤 |
| 遠景の建物 | #8f8b80 灰色 |
色数を絞ると、ステージが変わっても世界観が崩れません。赤は「主人公の鉢巻」「三段ジャンプの★」「自己ベスト更新中」など、プレイヤーが注目すべきものだけに使う、というルールにしています。宇宙ステージでも背景は黒ではなく同じクリーム色で、星や惑星を線で描くことで「夜空の落書き」として表現しました。
全22ステージには、それぞれ一目でどこか分かる建造物を置いています。描画はすべて「基準点(x, y)とスケール」を受け取る関数で、ステージ切り替え時に遠景として描かれます。
どれも「描き込まない」のがコツです。情報量を減らすほど、見る側が記憶の中の形で補完してくれます。
主人公は drawPlayer 関数が描いています。頭は塗りのない円、体と手足は線幅一定・端が丸い線。走りは「脚の角度を距離に応じて周期的に振る」だけですが、鉢巻を速度に応じて後ろへ長くなびかせることでスピード感を出しています。三段ジャンプでは胴体ごと回転させ、何段目かを見た目で分かるようにしました。ジャンプの軌跡や着地の土煙は drawFx が担当し、こちらも円弧と短い線だけです。
スマートフォンの縦画面では、横長のパソコン画面に比べて前方の視認距離が短く、障害物が見えた瞬間には避けられません。解決策はゲーム内部の座標はそのままに、描画だけ縮小することでした。画面幅が狭いときは全体を約1.7倍引いて描き、見える範囲を広げます。物理計算には一切手を入れていないので、端末による有利不利はほぼありません。
実装は、画面幅に応じて決めた倍率(900px以上で1.0、600px以上で0.8、それ未満で0.62)を描画座標に掛けるだけです。ただし文字やUIまで縮むと読めなくなるので、UIはCanvasの外にHTMLで重ねています。ゲーム画面はCanvas、ボタンや文字はHTML、という分担が結果的に多言語対応でも役に立ちました。
dist * 0.5)、少ない描画で奥行きを出す(視差)devicePixelRatio に合わせたCanvasサイズの設定は、リサイズ時のみ行うshadowBlur はモバイルで重いので一切使わず、半透明の重ね描きも演出の数か所に限定この結果、ゲーム本体のHTMLは約100KBに収まりました。画像ゼロなので、通信が細い環境でもタップした次の瞬間に走り始められます。
次の記事:サーバーを1台も持たずに5人対戦 — Durable Objectsの使い方と落とし穴
⚽ いますぐ走る