はじめに
ブラウザゲームは、HTML5、Canvas、JavaScriptの組み合わせから始めると構造をつかみやすくなります。描画、入力、状態更新を分けることで、ゲーム開発に必要なプログラミングを小さな実装へ落とし込めます。
中心になるのは、一定間隔で状態を更新するゲームループです。JavaScriptではrequestAnimationFrameを使い、ブラウザの描画タイミングに合わせてupdateとrenderを呼び分けますし、ここがポイントです。
Canvas APIやWebGL対応ライブラリまで視野に入れると、2Dの練習用ゲームから3D表現まで段階的に広げられます。JavaScript初心者がつまずきやすいのは、入力、描画、状態管理を同じ場所へ詰め込む点です。
イベント処理は、JavaScriptイベントの使い方やイベントハンドラの実践例も合わせて確認すると整理しやすくなります。配列処理を敵や弾の管理に使う場合は、forEachでreturnを扱う考え方やforEachとmapの使い分けが役立ちますが、これは押さえたい点です。
ファイル名や画像パスを扱う場面では、JavaScriptで拡張子を活用する方法も補助になります。基礎を押さえると、ゲーム開発のプログラミングは部品の組み合わせとして理解できます。
- HTML Living Standard / ECMAScript 2024相当のブラウザ実装
- Google Chrome 126、Firefox 127、Safari 17.5を想定
- Canvas API、WebGL API、WebSocket API、Phaser 3系、Three.js r165系の記法を基準
- JavaScriptのゲームループを
requestAnimationFrameで組む考え方 - HTML5 Canvasでスプライト、図形、アニメーションを描画する方法
- マウスイベントとキーボードイベントで操作を受け取る実装
- Phaser、Three.js、WebGLを使ったゲーム開発の広げ方
- 公開、デプロイ、プロモーション時に確認したい実務上の注意点
JavaScriptでの基本的なゲーム構造
ゲームはstateを更新する処理と、更新後の状態を画面へ反映する処理に分けると崩れにくくなります。JavaScriptで小さなゲームを作る場合も、update、render、inputの境界を先に決めると機能を足しやすくなります。
結果: 期待される動作は、ブラウザの再描画タイミングに合わせてupdateとrenderが繰り返し呼ばれる状態です。
キャラクターの座標、スコア、残り時間などはupdate側で変化させ、Canvasへの描画はrender側へ集めます。JavaScriptで当たり判定やエフェクトを足すときも、処理の置き場所を判断しやすくなります。
ゲーム開発ではsetIntervalよりrequestAnimationFrameを優先するのが基本です。MDNのrequestAnimationFrameによれば、このAPIは次の再描画前に指定したコールバックを呼び出するのが基本です。
| 要素 | 主な役割 | 代表的なAPI | 注意点 |
|---|---|---|---|
| ゲームループ | 状態更新と描画を継続する | requestAnimationFrame | 処理が重いとフレーム落ちにつながります |
| 状態管理 | 座標やスコアを保持する | Object、class | 描画処理と混ぜすぎない設計が扱いやすいです |
| Canvas描画 | 2Dグラフィックを出す | getContext、drawImage | 毎フレームの消去範囲を意識します |
| 入力処理 | クリックやキー入力を受け取る | addEventListener | 押下中と単発入力を分けて考えます |
| 画像管理 | キャラクターや背景を読み込む | Image、onload | 読み込み前の描画を避けます |
| 物理表現 | 速度や重力を扱う | velocity、gravity | 単位と更新間隔をそろえます |
| 通信 | 複数プレイヤーを同期する | WebSocket | 遅延や切断を前提にします |
| 3D描画 | 立体的な画面を作る | WebGL、THREE.WebGLRenderer | 端末性能の差を考慮します |
サンプルコード1:ゲームループの設定
ゲームループは、入力の反映、状態更新、画面描画を続ける土台です。JavaScriptではループ内に全処理を書くより、役割ごとに関数を分けるほうが変更に耐えやすくなります。
結果: 期待される動作は、deltaTimeを受け取りながら状態更新と描画が繰り返される流れです。
timeから前回との差分を計算し、端末ごとの描画間隔の違いを吸収しやすくしています。複雑な物理演算を扱うJavaScriptゲームでは、固定タイムステップを採用する設計もあります。
サンプルコード2:スプライトの描画
スプライトは、キャラクター、敵、アイテム、弾などを画像として描く基本単位です。HTML5 CanvasではImageで読み込んだ画像をdrawImageへ渡し、画像の一部だけを切り出して配置できるのが目安です。
結果: 期待される表示は、画像の左上64ピクセル四方がCanvas上の座標100、100へ描かれる状態です。
sx、sy、sWidth、sHeightで元画像の範囲が決まり、dx、dy、dWidth、dHeightでCanvas上の位置と大きさが決まります。JavaScriptのスプライトシート処理では、この切り出し範囲をフレーム番号で切り替えます。
💡 Tips: 画像の読み込みは非同期なので、onloadより前にdrawImageを呼ぶと表示されない場合があるのがポイントです。複数画像を使うプログラミングでは、読み込み完了後にゲームループを開始すると安定します。
キャンバス操作の基本
CanvasはHTML5で提供される描画領域で、JavaScriptから線、矩形、画像、テキストを直接描けます。MDNのCanvas APIにもある通り、2D描画コンテキストを取得して命令を積み重ねますし、これが一つの目安です。
DOM要素を大量に動かすより、ゲーム画面全体を一枚の描画面として扱いやすくなります。一方、Canvasへ描いた内容は要素として残らないため、毎フレームの再描画をJavaScript側で組み立てます。
HTML5 Canvasの基礎
HTML側に<canvas>要素を置き、JavaScript側でdocument.getElementByIdにより取得するのが一般的です。続けてgetContext('2d')を呼ぶと、fillRectやstrokeなどの2D描画メソッドを利用できます。
結果: 期待される表示は、Canvas内の左上付近に赤い正方形が描かれる状態です。
fillStyleが塗り色を決め、fillRectが位置とサイズを決めます。Canvasの座標は左上が原点で、右方向がxの増加、下方向がyの増加です。
サンプルコード3:キャンバスに図形を描く
図形を組み合わせる場合は、beginPathで新しいパスを作り、arc、moveTo、lineToを順に使いるのが現実的です。円と直線を同じパスに含めることで、Canvas上に複合的な形を作れます。
結果: 期待される表示は、青い円と線で構成された図形がCanvas上へ描かれる状態です。
Math.PIで円周の角度を表し、strokeStyleで線の色を変えています。塗りつぶしが必要な場合はfillを組み合わせ、線と塗りの表現を分けると意図が明確になると整理できます。
サンプルコード4:アニメーションの実装
アニメーションは、前のフレームを消してから新しい位置へ描く処理を高速に繰り返すことで成立します。JavaScriptのゲーム開発では、clearRectで描画領域を消し、座標を変えながらfillRectなどで描き直します。
結果: 期待される表示は、緑色の四角形がCanvas上を横方向へ移動し、右端を越えると左端へ戻る動きです。
canvas.widthとcanvas.heightを消去範囲に使うため、描画面全体が毎回リセットされます。背景やUIを含むJavaScriptゲームでは、動く対象だけの再描画やレイヤー分割も選択肢です。
width、heightがずれると、描画がぼやける場合があります。高解像度ディスプレイではdevicePixelRatioを考慮した調整も検討すると理解できます。ゲームのインタラクションを管理する
プレイヤーが操作できるゲームにするには、マウス、タッチ、キーボードからの入力を状態へ反映させます。JavaScriptではaddEventListenerを使い、click、keydown、keyupなどを監視します。
入力処理は描画へ直接つなげず、座標や押下状態を更新する役割に限定すると整理しやすくなると覚えるとよいでしょう。押下中だけ移動させる場合は、キー状態を保持し、ゲームループ内で移動量を計算します。
サンプルコード5:マウスイベントの取り扱い
クリック位置へ反応を返す処理は、Canvasゲームの基本的な入力例です。JavaScriptの座標計算ではgetBoundingClientRectを使うと、スクロールやCanvasの表示位置を考慮しやすくなります。
結果: 期待される表示は、Canvasをクリックした位置を中心に青い四角形が描かれる状態です。
clientXとclientYからCanvasの表示位置を差し引き、Canvas内の座標へ変換しています。CSSでCanvasを拡大縮小している場合は、表示サイズと内部解像度の比率も計算に含めます。
サンプルコード6:キーボードイベントでキャラクターを動かす
キーボード操作では、矢印キーやWASDでキャラクターを動かす実装がよく使われますが、覚えておくと役立つでしょう。JavaScriptで滑らかな移動にするなら、押下状態をSetなどで管理する方法が向いています。
結果: 期待される動作は、矢印キーを押している間だけ赤い四角形の座標が変化する状態です。
キー入力の受け取りとキャラクター描画を分けられます。ジャンプ、攻撃、ポーズも入力状態を一度保持し、ゲームループ側で処理すると、ゲームパッドやタッチ操作へ広げやすくなります。
効率的なゲームエンジンの使用
小規模なプログラミング学習なら素のCanvasで十分ですが、シーン管理、物理演算、画像読み込み、サウンド再生をまとめるならゲームエンジンが役立ちますし、ここを基本と考えるとよいでしょう。JavaScriptの領域では、2DならPhaser、3DならThree.jsが代表的です。
HTML5 Canvas中心の2DアクションならPhaser、WebGLを使った立体表現や3D演出ならThree.jsを検討する流れが自然です。JavaScriptのゲーム開発では、画面要件から使い分けると選びやすくなります。
サンプルコード7:Phaserを使用したゲーム例
Phaserは、シーン、アセット読み込み、物理演算、入力処理をまとめて扱える2Dゲーム向けライブラリです。ゲーム開発で初期化処理を短く保ちたい場合、preload、create、updateの流れに沿って実装できます。
結果: 期待される表示は、Phaserのゲーム領域にassets/sky.pngの背景画像が配置される状態です。
Phaser.AUTOで利用可能な描画方式が選ばれ、arcade物理エンジンの重力も設定されています。画像パスが違うと読み込みに失敗するため、ブラウザのNetworkパネルで404を確認します。
サンプルコード8:Three.jsで3Dゲームを作成
Three.jsはWebGLの低レベルな記述を抽象化し、シーン、カメラ、メッシュ、マテリアル単位で3D表現を組み立てるライブラリです。WebGLを直接扱うより短いJavaScriptで立方体やライトを配置できると考えられます。
結果: 期待される表示は、WebGLレンダラー上で緑色の立方体が回転し続ける3Dシーンです。
THREE.SceneにTHREE.Meshを追加し、THREE.PerspectiveCameraから見える範囲をrenderer.renderで描画しています。WebGLは端末やブラウザの対応状況に影響を受けるため、JavaScript側で画質設定も検討します。
よくあるエラーと対処法
JavaScriptのゲーム開発で起きやすい問題は、読み込み順、スコープ、座標計算、非同期処理に集中すると言えるでしょう。どのオブジェクトがundefinedなのか、どのファイルが読み込まれていないのかを分けて確認します。
初心者がつまずきやすいのは、Canvas要素を取得する前にスクリプトが実行されるケースです。その場合、document.getElementByIdがnullを返し、続くgetContextでエラーになります。
エラー例とその解決策
Uncaught ReferenceErrorは、存在しない変数や関数を参照したときに発生するのが基本です。関数名のタイプミス、読み込み順の誤り、type="module"によるスコープの違いを順に見ます。
TypeError: Cannot read properties of undefinedは、未定義の値からプロパティを読もうとしたときに発生します。対象の変数をconsole.logで出し、初期化前の利用や配列添字の範囲外を確認するのが目安です。
画像関連では、drawImageの前に画像が読み込まれていない問題も起きます。onload、Promise、アセットローダーのいずれかで完了を管理し、描画開始のタイミングを制御します。
デバッグ技術の紹介
デバッグでは、console.logだけでなく、ブラウザのDevToolsにあるSourcesパネルも使いるのがポイントです。ブレークポイントを置くと、posX、posY、pressedKeysなどをフレームごとに確認できます。
ゲームループ内へ大量のログを出すとコンソールが埋まり、動作も重くなります。必要なフレームだけ出す、条件付きで出す、debugフラグを用意するなど、JavaScriptの調査範囲を絞りますし、ここがポイントです。
ネットワーク越しの画像や音声を使う場合は、Networkパネルでstatus、Content-Type、CORSエラーを確認します。Canvas、WebGL、音声ファイルはセキュリティ制約を受けるため、開発サーバー経由で確認します。
高度なゲーム機能の実装
基本の描画と入力が整ったら、通信やAIを組み込むことでゲーム性を広げられますが、これは押さえたい点です。JavaScriptではWebSocketによるリアルタイム通信、classによる敵管理、Math.atan2による追跡処理を小さく実装できます。
高度な機能ほど、見た目より状態管理の設計が重要になります。サーバーから届いた位置をそのまま描くのか、補間するのか、敵の行動判断を毎フレーム行うのかでゲーム開発の難度は変わりますし、これが一つの目安です。
サンプルコード9:リアルタイムマルチプレイヤー機能の追加
リアルタイム通信では、クライアントが位置や操作をサーバーへ送り、サーバーが他のプレイヤーへ配信する構成がよく使われます。ブラウザ標準のWebSocketは、接続後に双方向通信を継続できるJavaScript APIです。
結果: 期待される動作は、接続が開いているときだけプレイヤー座標をJSON文字列としてサーバーへ送る状態です。
readyStateで接続状態を確認してからsendを呼びます。実際のマルチプレイヤーでは、サーバー側の検証、送信頻度の制限、遅延時の補間、切断時の再接続も設計します。
ws://ではなくwss://を使う構成が一般的です。HTTPSページから安全でないWebSocketへ接続すると、ブラウザ側でブロックされる場合があるのが一般的です。サンプルコード10:AIの敵キャラクターを作成
敵キャラクターのAIは、最初から複雑な探索アルゴリズムを使わなくても作れます。プレイヤー座標へ少しずつ近づく動きなら、角度を計算してxとyを更新するだけで表現できます。
結果: 期待される出力は、敵キャラクターの座標がプレイヤー座標へ近づく形でコンソールへ表示される状態です。
Math.atan2で方向を求め、Math.cosとMath.sinで移動量へ変換しています。Canvasへ描画する場合は、setIntervalではなくJavaScriptのゲームループ内のupdateへ組み込みます。
ゲーム公開とマーケティング
完成したゲームを公開する段階では、ビルド、配信、計測、告知を分けて考えますが、覚えておくと役立つでしょう。JavaScriptで作ったHTML5ゲームは静的ファイルとして配信できる場合が多く、dist内のindex.html、bundle.js、画像、音声をサーバーへ配置します。
WebGLや大きなアセットを含むゲームでは、初回読み込みの重さが離脱につながることがあります。画像圧縮、遅延読み込み、キャッシュヘッダー、スマートフォン向けの画質設定を公開前に確認するのが現実的です。
サンプルコード11:ゲームのビルドとデプロイ
開発中は、ファイル変更を監視してブラウザを更新する開発サーバーがあると確認が速くなります。GulpとBrowserSyncを使う例では、distを配信対象にし、HTMLの変更時にリロードします。
結果: 期待される動作は、distフォルダを配信する開発サーバーが起動し、HTML変更時にブラウザが更新される状態です。
このコードは開発サーバー用であり、本番デプロイそのものを完了させるものではありません。公開時はホスティング先の手順に合わせ、npm run build、静的ファイルのアップロード、Cache-Control、Content-Encodingを確認します。
プロモーション戦略とユーザー獲得
プロモーションでは、SNS投稿だけでなく、ゲームページの説明、スクリーンショット、操作方法、更新履歴を整えます。CanvasやWebGLに力を入れたゲーム開発でも、初回訪問者が内容を理解できなければプレイ開始まで進みにくくなると整理できます。
共有用のタイトル、説明文、OGP画像、短いプレイ動画を用意し、公開URLの読み込み速度も確認します。JavaScriptの初期ロードが重い場合は、不要なライブラリ削除、画像形式の見直し、アセットの段階読み込みを検討します。
結果: 期待される返り値は、権限とトークンが有効な場合に投稿IDなどを含むJSONレスポンスです。
この例はAPI連携の概念コードであり、実運用ではMeta for Developersの仕様、アクセストークンの期限、投稿権限、アプリ審査を確認します。個人アカウントへの自動投稿は制約を受けやすいため、公式の共有UIや管理画面からの投稿も選択肢です。
まとめ
JavaScriptでゲームを作る流れは、ゲームループ、Canvas描画、入力処理、状態管理を分けるところから始まります。HTML5 Canvasで2D表現を固め、必要に応じてPhaser、Three.js、WebGLへ広げると、学習用の小さな作品から公開を前提にしたゲーム開発まで進められます。
中心になるJavaScript APIは、requestAnimationFrame、drawImage、addEventListener、WebSocketなどです。読み込み順、undefined、画像パス、Canvas座標の問題は、DevToolsで値と通信状況を確認しながら切り分けますし、ここを基本と考えるとよいでしょう。
マルチプレイヤー、AI、3D表現、公開後の告知まで広げる場合も、JavaScriptの各要素を小さく保つことが重要です。描画、入力、通信、マーケティング用処理を混ぜすぎないことが、保守しやすいHTML5ゲームにつながります。
関連記事
- JavaScriptのforEachでreturnを活用する6つのテクニック
- 【保存版】JavaScriptエンジニア必見!forEach・mapの"目からウロコ"な使い分け術10選
- JavaScriptイベント徹底解説!30個の使い方と応用例
- JavaScriptにおけるイベントハンドラを完全ガイド!20選の実践サンプルコード付き
- JavaScriptで拡張子を活用する方法12選!初心者でも簡単にできる方法を紹介
※本記事は実在のエンジニア複数名で構成される Japanシーモア編集部が、AI支援を活用して作成・校正・公開しています。


