Nokia Snake ゲーム
ReactとHTML5 Canvasで作った、懐かしのNokia 3310 Snakeゲーム。ブラウザでそのまま遊べる。
Nokia 3310、覚えてる?あの壊れない携帯。スマホもタッチスクリーンもない時代、Snakeがあった。
ゼロから作り直した。同じシンプルなルール。同じ中毒性。ブラウザで遊べる。
ゲームをプレイ
オリジナル
Snakeが最初にNokiaの携帯に登場したのは1998年。ルールはシンプル。伸びていくヘビを操作して、ドットを食べて、壁や自分自身にぶつからないようにする。チュートリアルなし。課金なし。純粋にゲームだけ。
Nokia 3310版は伝説になった。1億台以上に搭載されて、一世代まるごとモバイルゲームの入口になった。グレーのLCD画面、太いピクセル、ドットを食べたときのビープ音。これが何年もの間、携帯ゲームの代名詞だった。
再現の構築
Canvas レンダリング
ピクセル単位で制御するためにHTML5 Canvasを使った。各フレームでやること:
- テーマに合わせた背景で画面をクリア(ライト:
#fafafa、ダーク:#171717) - 薄いグリッドを描画
- スネークを塗りつぶした四角の連続としてレンダリング
- 餌を小さな色付きの円として描画
頭は体より少し大きくして、向きがわかりやすいようにした。
ゲームループ
ゲームループはrequestAnimationFrameじゃなくてsetTimeoutベース。これで速度を正確にコントロールできる。オリジナルと同じように、スネークは一定間隔で動く。
Game Loop:
1. キューに入れられた方向変更を処理
2. 新しい頭の位置を計算
3. 衝突をチェック(壁、自分自身)
4. 餌との衝突を処理 → 成長 + 加速
5. スネークの位置を更新
6. フレームをレンダリング
7. 次のtickをスケジュール
速度は150msからスタートして、餌を食べるたびに5msずつ速くなる。最速で50ms。この「だんだん速くなる」感じが、オリジナルの中毒性を生み出してた。
操作方法
PC:
- 矢印キーかWASDで移動
- スペースキーでポーズ
スマホ:
- 画面上の方向ボタンをタップ
- 十字キー風のタッチ操作に対応
180度ターンはできない仕様にした。いきなり逆方向には曲がれない。オリジナルと同じ挙動。
State管理
パフォーマンスが重要な状態(スネークの位置、方向、餌)にはReact refs、UI要素(スコア、ゲーム状態)にはReact stateを使い分けている。このハイブリッド方式で、Reactにスコア表示の再レンダリングを任せつつ、ゲームループは高速に保てる。
ハイスコアはlocalStorageに保存。ブラウザを閉じても残る。
デザイン
テーマ対応デザイン
システムのカラースキームに合わせて、ミニマルでモダンな配色に切り替わる:
ライトモード:
- 背景:
#fafafa(オフホワイト) - スネーク:
#171717(ほぼ黒) - 餌:
#3b82f6(ブルー)
ダークモード:
- 背景:
#171717(ほぼ黒) - スネーク:
#fafafa(オフホワイト) - 餌:
#60a5fa(ライトブルー)
角丸とシャドウで、昔のごついプラスチック携帯の雰囲気を出した。
グリッドサイズ
オリジナルのNokia 3310は84×48ピクセルのディスプレイだった。今回は12pxのセルで20×20のグリッドにした:
- 今の画面サイズにちょうどいい
- ストレスなく遊べる難易度
- スマホでもちゃんとスケールする
サウンドなし
サウンドはあえて入れなかった。オリジナルにはビープ音があったけど、Webサイトで急に音が鳴るのは邪魔になる。見た目のフィードバックで十分。スネークが伸びるのが見えれば、それでいい。
学んだこと
Canvasで十分。 シンプルなグラフィックのゲームなら、WebGLやゲームエンジンは要らない。Canvasで全部できる。
ゲームループにはrefsがstateより向いてる。 React stateは再レンダリングを起こす。毎秒10回以上動くゲームループには遅すぎる。refsならレンダリングなしで値を更新できる。
モバイル操作はちゃんと設計しないとダメ。 タッチターゲットは押しやすい大きさにする。十字キーのレイアウトは、ゲームコントローラーと同じ配置だから直感的。
今後やりたいこと
- Snake IIの要素を追加(障害物、ボーナスアイテム)
- WebSocketでマルチプレイヤー対応
- ミュート付きでサウンドを追加
- 難易度設定を追加
- バックエンドでリーダーボードを実装
とりあえず今は、懐かしさに浸ってほしい。何点取れる?
Outcomes
- •ライト/ダークモード対応のミニマルデザイン
- •だんだん速くなる、スムーズなゲームループ
- •スマホでもタッチ操作でプレイ可能
- •localStorageでハイスコアを保存
- •どんな画面サイズでも動くレスポンシブ対応