diff --git a/6-space-game/4-collision-detection/translations/README.ja.md b/6-space-game/4-collision-detection/translations/README.ja.md new file mode 100644 index 00000000..99bb8f26 --- /dev/null +++ b/6-space-game/4-collision-detection/translations/README.ja.md @@ -0,0 +1,298 @@ +# スペースゲーム構築プロジェクト その 4: レーザーを追加して衝突を検出する + +## レッスン前の小テスト + +[レッスン前の小テスト](https://nice-beach-0fe9e9d0f.azurestaticapps.net/quiz/35) + +このレッスンでは、JavaScript でレーザーを撃つ方法を学びます! 私たちはゲームに2つのものを追加します。 + +- **レーザー**: このレーザーはあなたのヒーローの宇宙船から垂直に上向きに撃たれます +- **衝突検出**、発射する能力を実装する一環として、我々はまたいくつかの素敵なゲームのルールを追加します + - **レーザーが敵に当たる**: レーザーが当たると敵が破壊される + - **レーザーがトップ画面に当たる**: 画面上部に当たるとレーザーが破壊されます + - **敵とヒーローの衝突**: 敵とヒーローがぶつかると破壊されます + - **敵が画面の下に当たる**: 敵が画面下に当たると敵とヒーローが破壊されます + +要するに、あなた - *ヒーロー* - は画面の下部に移動するために管理する前に、レーザーですべての敵をヒットする必要があります。 + +✅ これまでに書かれた最初のコンピュータゲームについて少し調べてみてください。その機能は何だったのでしょうか? + +一緒にヒーローになりましょう! + +## 衝突検出 + +どのようにして衝突を検出するのか? ゲームオブジェクトを移動する長方形と考える必要があります。なぜでしょうか? ゲームオブジェクトの描画に使われる画像は矩形です。`x`、`y`、`width`、`height` を持っています。 + +2 つの長方形、つまりヒーローと敵が交差すると、衝突します。そのときに何が起こるかは、ゲームのルール次第です。したがって、衝突検出を実装するためには以下のものが必要です。 + +1. ゲームオブジェクトの矩形表現を取得する方法。こんな感じです + + ```javascript + rectFromGameObject() { + return { + top: this.y, + left: this.x, + bottom: this.y + this.height, + right: this.x + this.width + } + } + ``` + +2. 比較関数で、この関数は次のようになります + + ```javascript + function intersectRect(r1, r2) { + return !(r2.left > r1.right || + r2.right < r1.left || + r2.top > r1.bottom || + r2.bottom < r1.top); + } + ``` + +## オブジェクトをどうやって破壊するか + +ゲーム内のオブジェクトを破壊するには、一定の間隔で発生するゲームループの中で、このアイテムをペイントしないようにゲームに知らせる必要があります。これを行うには、以下のように、何かが起こったときにゲームオブジェクトを *dead* としてマークする方法があります。 + +```javascript +// 衝突が発生します +enemy.dead = true +``` + +その後、画面を再描画する前に、このように、*dead* オブジェクトをソートしていきます。 + +```javascript +gameObjects = gameObject.filter(go => !go.dead); +``` + +## レーザーの撃ち方 + +レーザーを発射することは、キーイベントに反応して、特定の方向に移動するオブジェクトを作成することになります。そのため、以下のような作業を行う必要があります。 + +1. **レーザーオブジェクトを作成します**: ヒーローの船の上部から、作成時に画面の上部に向かって上向きに移動を開始します +2. **キーイベントにコードを添付します**: レーザーを撮影しているプレイヤーを表すキーボードのキーを選択する必要があります +3. キーを押すと**レーザーのように見えるゲームオブジェクトを作成します** + +## レーザーのクールダウン + +レーザーは、例えば*スペース*のように、キーを押すたびに発射する必要があります。短時間で多くのレーザーが発射されるのを防ぐために、この問題を解決する必要があります。これを修正するには、いわゆる *クールダウン*、タイマーを実装することで、レーザーはそれほど頻繁にしか発射することができないことを保証します。以下の方法で実装できます。 + +```javascript +class Cooldown { + constructor(time) { + this.cool = false; + setTimeout(() => { + this.cool = true; + }, time) + } +} + +class Weapon { + constructor { + } + fire() { + if (!this.cooldown || this.cooldown.cool) { + // レーザーを作る + this.cooldown = new Cooldown(500); + } else { + // 何もしない-まだクールダウンしていない。 + } + } +} +``` + +✅ スペースゲームシリーズのレッスン1を参照して、*クールダウン*について思い出してください。 + +## 何を構築するか + +前回のレッスンで使用した既存のコード (クリーンアップしてリファクタリングしたはずのコード) を使用して、それを拡張します。 +パート II のコードから始めるか、[パートIII - スターター](../../your-work)のコードを使用してください。 + +> ヒント: 作業に使用するレーザーはすでにアセットフォルダにあり、コードで参照されています。 + +- **衝突検出を追加します**、レーザーが何かに衝突するときは、次のルールを適用する必要があります + 1. **レーザーが敵に当たる**: レーザーが当たると敵が破壊される + 2. **レーザーが画面上部に当たる**: レーザーが画面の上部に当たると破壊される + 3. **敵とヒーローの衝突**: 敵とヒーローがぶつかると破壊される + 4. **画面下に敵が当たる**: 敵が画面下部に当たると敵とヒーローが破壊される + +## 推奨される手順 + +あなたのために作成されたファイルを `your-work` サブフォルダ内で探します。以下のファイルが含まれているはずです。 + +```bash +-| assets + -| enemyShip.png + -| player.png + -| laserRed.png +-| index.html +-| app.js +-| package.json +``` + +次のコマンドをタイピングして、あなたのプロジェクトを `your_work` フォルダから開始します。 + +```bash +cd your-work +npm start +``` + +上記は、`http://localhost:5000` というアドレスで HTTP サーバを起動します。ブラウザを開いてそのアドレスを入力すると、今はヒーローと全ての敵が表示されるはずですが、まだ何も動いていません。 + +### コードの追加 + +1. **衝突を処理するためにゲームオブジェクトの矩形表現を設定する** 以下のコードでは、`GameObject` の矩形表現を取得することができます。GameObject クラスを編集して拡張します + + ```javascript + rectFromGameObject() { + return { + top: this.y, + left: this.x, + bottom: this.y + this.height, + right: this.x + this.width, + }; + } + ``` + +2. **衝突をチェックするコードの追加** これは、2 つの矩形が交差するかどうかをテストする新しい関数になります + + ```javascript + function intersectRect(r1, r2) { + return !( + r2.left > r1.right || + r2.right < r1.left || + r2.top > r1.bottom || + r2.bottom < r1.top + ); + } + ``` + +3. **レーザー発射機能の追加** + 1. **キーイベントメッセージを追加します**。*スペース*キーはヒーローの宇宙船の真上にレーザーを作成する必要があります。Messages オブジェクトに3つの定数を追加します + + ```javascript + KEY_EVENT_SPACE: "KEY_EVENT_SPACE", + COLLISION_ENEMY_LASER: "COLLISION_ENEMY_LASER", + COLLISION_ENEMY_HERO: "COLLISION_ENEMY_HERO", + ``` + + 1. **スペースキーを処理します**。スペースを扱うために、`window.addEventListener` のキーアップ関数を編集します + + ```javascript + } else if(evt.keyCode === 32) { + eventEmitter.emit(Messages.KEY_EVENT_SPACE); + } + ``` + + 1. **リスナーを追加します**。スペースバーがヒットした時にヒーローが発射できるように `initGame()` 関数を編集します + + ```javascript + eventEmitter.on(Messages.KEY_EVENT_SPACE, () => { + if (hero.canFire()) { + hero.fire(); + } + ``` + + そして、敵がレーザーに衝突したときの動作を保証するために、新しい `eventEmitter.on()` 関数を追加します + + ```javascript + eventEmitter.on(Messages.COLLISION_ENEMY_LASER, (_, { first, second }) => { + first.dead = true; + second.dead = true; + }) + ``` + + 1. **オブジェクトを移動させ**、レーザーが徐々に画面上部に移動するようにします。先ほどと同じように `GameObject`を継承した Laser クラスを新たに作成します + + ```javascript + class Laser extends GameObject { + constructor(x, y) { + super(x,y); + (this.width = 9), (this.height = 33); + this.type = 'Laser'; + this.img = laserImg; + let id = setInterval(() => { + if (this.y > 0) { + this.y -= 15; + } else { + this.dead = true; + clearInterval(id); + } + }, 100) + } + } + ``` + + 1. **衝突の処理**、レーザーの衝突ルールの実装 衝突したオブジェクトのヒットをテストする `updateGameObjects()` 関数を追加します + + ```javascript + function updateGameObjects() { + const enemies = gameObjects.filter(go => go.type === 'Enemy'); + const lasers = gameObjects.filter((go) => go.type === "Laser"); + // レーザーが当たる + lasers.forEach((l) => { + enemies.forEach((m) => { + if (intersectRect(l.rectFromGameObject(), m.rectFromGameObject())) { + eventEmitter.emit(Messages.COLLISION_ENEMY_LASER, { + first: l, + second: m, + }); + } + }); + }); + + gameObjects = gameObjects.filter(go => !go.dead); + } + ``` + + 必ず `window.onload` のゲームループに `updateGameObjects()` を追加してください。 + + 4. レーザーに**クールダウンを実装**して、それがそんなに頻繁にしか発射できないようにします + + 最後に、Hero クラスをクールダウンできるように編集します + + ```javascript + class Hero extends GameObject { + constructor(x, y) { + super(x, y); + (this.width = 99), (this.height = 75); + this.type = "Hero"; + this.speed = { x: 0, y: 0 }; + this.cooldown = 0; + } + fire() { + gameObjects.push(new Laser(this.x + 45, this.y - 10)); + this.cooldown = 500; + + let id = setInterval(() => { + if (this.cooldown > 0) { + this.cooldown -= 100; + } else { + clearInterval(id); + } + }, 200); + } + canFire() { + return this.cooldown === 0; + } + } + ``` + +この時点で、あなたのゲームはいくつかの機能を持っています! 矢印キーで移動したり、スペースバーでレーザーを発射したり、敵はあなたがそれらを打つときに消えることができます。よくできました! + +--- + +## 🚀 チャレンジ + +爆発を追加しましょう! [スペースアートレポ](../../solution/spaceArt/readme.txt)のゲームアセットを見て、レーザーがエイリアンに当たったときに爆発を追加してみてください。 + +## レッスン後の小テスト + +[レッスン後の小テスト](https://nice-beach-0fe9e9d0f.azurestaticapps.net/quiz/36) + +## 復習と自己学習 + +これまでのゲームの間隔を実験してみてください。それらを変更するとどうなるでしょうか? [JavaScript のタイミングイベント](https://www.freecodecamp.org/news/javascript-timing-events-settimeout-and-setinterval/)についての詳細はこちら。 + +## 課題 + +[衝突を調べる](assignment.ja.md) diff --git a/6-space-game/4-collision-detection/translations/assignment.ja.md b/6-space-game/4-collision-detection/translations/assignment.ja.md new file mode 100644 index 00000000..9bedefdd --- /dev/null +++ b/6-space-game/4-collision-detection/translations/assignment.ja.md @@ -0,0 +1,11 @@ +# 衝突を調べる + +## 説明書 + +衝突がどのように機能するかを理解するために、衝突するいくつかのアイテムで非常に小さなゲームを構築します。キープレスやマウスクリックでアイテムを移動させ、アイテムが当たったときに何かが起こるようにします。隕石が地球に衝突したり、バンパーカーに衝突したりします。創造力を発揮してください。 + +## ルーブリック + +| 基準 | 模範的な例 | 適切な | 改善が必要 | +| -------- | ------------------------------------------------------------------------------------------------------------------------ | ------------------------------ | ----------------- | +| | アイテムがキャンバスに描画され、基本的な衝突が発生し、反応が発生する完全な動作コードサンプルが作成されます。 | コードが不完全な場合 | コードの誤動作 | \ No newline at end of file