|
7 days ago | |
---|---|---|
.. | ||
solution | 2 weeks ago | |
your-work | 2 weeks ago | |
README.md | 7 days ago | |
assignment.md | 2 weeks ago |
README.md
Baue ein Weltraumspiel Teil 4: Hinzufügen eines Lasers und Erkennen von Kollisionen
Quiz vor der Lektion
In dieser Lektion lernst du, wie man mit JavaScript Laser abfeuert! Wir fügen zwei Dinge zu unserem Spiel hinzu:
- Einen Laser: Dieser Laser wird von dem Schiff deines Helden abgefeuert und bewegt sich vertikal nach oben.
- Kollisionserkennung: Im Rahmen der Implementierung der Schussfähigkeit fügen wir auch einige interessante Spielregeln hinzu:
- Laser trifft Gegner: Gegner stirbt, wenn er von einem Laser getroffen wird.
- Laser trifft oberen Bildschirmrand: Ein Laser wird zerstört, wenn er den oberen Teil des Bildschirms erreicht.
- Kollision zwischen Gegner und Held: Ein Gegner und der Held werden zerstört, wenn sie miteinander kollidieren.
- Gegner erreicht unteren Bildschirmrand: Ein Gegner und der Held werden zerstört, wenn der Gegner den unteren Bildschirmrand erreicht.
Kurz gesagt, du – der Held – musst alle Gegner mit einem Laser treffen, bevor sie es schaffen, den unteren Bildschirmrand zu erreichen.
✅ Recherchiere ein wenig über das allererste Computerspiel, das jemals geschrieben wurde. Welche Funktionalität hatte es?
Lasst uns gemeinsam heldenhaft sein!
Kollisionserkennung
Wie erkennen wir Kollisionen? Wir müssen unsere Spielobjekte als Rechtecke betrachten, die sich bewegen. Warum, fragst du dich vielleicht? Nun, das Bild, das verwendet wird, um ein Spielobjekt darzustellen, ist ein Rechteck: Es hat x
, y
, width
und height
.
Wenn sich zwei Rechtecke, z. B. ein Held und ein Gegner, überschneiden, liegt eine Kollision vor. Was dann passieren soll, hängt von den Spielregeln ab. Um die Kollisionserkennung zu implementieren, benötigst du Folgendes:
-
Eine Möglichkeit, eine Rechteckdarstellung eines Spielobjekts zu erhalten, etwa so:
rectFromGameObject() { return { top: this.y, left: this.x, bottom: this.y + this.height, right: this.x + this.width } }
-
Eine Vergleichsfunktion, die so aussehen kann:
function intersectRect(r1, r2) { return !(r2.left > r1.right || r2.right < r1.left || r2.top > r1.bottom || r2.bottom < r1.top); }
Wie zerstören wir Dinge
Um Dinge in einem Spiel zu zerstören, musst du dem Spiel mitteilen, dass es dieses Objekt nicht mehr im Spielzyklus zeichnen soll, der in einem bestimmten Intervall ausgelöst wird. Eine Möglichkeit, dies zu tun, besteht darin, ein Spielobjekt als tot zu markieren, wenn etwas passiert, etwa so:
// collision happened
enemy.dead = true
Dann kannst du tote Objekte aussortieren, bevor der Bildschirm neu gezeichnet wird, etwa so:
gameObjects = gameObject.filter(go => !go.dead);
Wie feuern wir einen Laser ab
Einen Laser abzufeuern bedeutet, auf ein Tastenevent zu reagieren und ein Objekt zu erstellen, das sich in eine bestimmte Richtung bewegt. Wir müssen daher die folgenden Schritte ausführen:
- Einen Laserobjekt erstellen: Vom oberen Teil des Schiffes unseres Helden aus, das bei der Erstellung beginnt, sich nach oben in Richtung des oberen Bildschirmrands zu bewegen.
- Code an ein Tastenevent anhängen: Wir müssen eine Taste auf der Tastatur auswählen, die das Abfeuern des Lasers durch den Spieler darstellt.
- Ein Spielobjekt erstellen, das wie ein Laser aussieht, wenn die Taste gedrückt wird.
Abkühlzeit für unseren Laser
Der Laser muss jedes Mal abgefeuert werden, wenn du eine Taste drückst, z. B. Leertaste. Um zu verhindern, dass das Spiel in kurzer Zeit zu viele Laser produziert, müssen wir dies beheben. Die Lösung besteht darin, eine sogenannte Abkühlzeit zu implementieren, einen Timer, der sicherstellt, dass ein Laser nur in bestimmten Abständen abgefeuert werden kann. Du kannst das folgendermaßen umsetzen:
class Cooldown {
constructor(time) {
this.cool = false;
setTimeout(() => {
this.cool = true;
}, time)
}
}
class Weapon {
constructor {
}
fire() {
if (!this.cooldown || this.cooldown.cool) {
// produce a laser
this.cooldown = new Cooldown(500);
} else {
// do nothing - it hasn't cooled down yet.
}
}
}
✅ Sieh dir Lektion 1 der Weltraumspiel-Serie an, um dich an Abkühlzeiten zu erinnern.
Was soll gebaut werden
Du wirst den bestehenden Code (den du bereinigt und refaktoriert haben solltest) aus der vorherigen Lektion erweitern. Entweder beginnst du mit dem Code aus Teil II oder verwendest den Code unter Teil III - Starter.
Tipp: Der Laser, mit dem du arbeiten wirst, befindet sich bereits in deinem Assets-Ordner und wird von deinem Code referenziert.
- Füge Kollisionserkennung hinzu, wenn ein Laser mit etwas kollidiert, sollten die folgenden Regeln gelten:
- Laser trifft Gegner: Gegner stirbt, wenn er von einem Laser getroffen wird.
- Laser trifft oberen Bildschirmrand: Ein Laser wird zerstört, wenn er den oberen Teil unseres Bildschirms erreicht.
- Kollision zwischen Gegner und Held: Ein Gegner und der Held werden zerstört, wenn sie miteinander kollidieren.
- Gegner erreicht unteren Bildschirmrand: Ein Gegner und der Held werden zerstört, wenn der Gegner den unteren Bildschirmrand erreicht.
Empfohlene Schritte
Finde die Dateien, die für dich im Unterordner your-work
erstellt wurden. Sie sollten Folgendes enthalten:
-| assets
-| enemyShip.png
-| player.png
-| laserRed.png
-| index.html
-| app.js
-| package.json
Starte dein Projekt im Ordner your_work
, indem du Folgendes eingibst:
cd your-work
npm start
Das obige startet einen HTTP-Server unter der Adresse http://localhost:5000
. Öffne einen Browser und gib diese Adresse ein, derzeit sollte der Held und alle Gegner angezeigt werden, aber nichts bewegt sich – noch nicht :).
Code hinzufügen
-
Richte eine Rechteckdarstellung deines Spielobjekts ein, um Kollisionen zu behandeln. Der folgende Code ermöglicht es dir, eine Rechteckdarstellung eines
GameObject
zu erhalten. Bearbeite deine GameObject-Klasse, um sie zu erweitern:rectFromGameObject() { return { top: this.y, left: this.x, bottom: this.y + this.height, right: this.x + this.width, }; }
-
Füge Code hinzu, der Kollisionen überprüft. Dies wird eine neue Funktion sein, die testet, ob sich zwei Rechtecke überschneiden:
function intersectRect(r1, r2) { return !( r2.left > r1.right || r2.right < r1.left || r2.top > r1.bottom || r2.bottom < r1.top ); }
-
Füge die Fähigkeit hinzu, Laser abzufeuern
-
Füge eine Key-Event-Nachricht hinzu. Die Leertaste sollte einen Laser direkt über dem Schiff des Helden erstellen. Füge drei Konstanten im Nachrichtenobjekt hinzu:
KEY_EVENT_SPACE: "KEY_EVENT_SPACE", COLLISION_ENEMY_LASER: "COLLISION_ENEMY_LASER", COLLISION_ENEMY_HERO: "COLLISION_ENEMY_HERO",
-
Bearbeite die Leertaste. Bearbeite die
window.addEventListener
-Funktion fürkeyup
, um die Leertaste zu behandeln:} else if(evt.keyCode === 32) { eventEmitter.emit(Messages.KEY_EVENT_SPACE); }
-
Füge Listener hinzu. Bearbeite die Funktion
initGame()
, um sicherzustellen, dass der Held schießen kann, wenn die Leertaste gedrückt wird:eventEmitter.on(Messages.KEY_EVENT_SPACE, () => { if (hero.canFire()) { hero.fire(); }
und füge eine neue
eventEmitter.on()
-Funktion hinzu, um das Verhalten zu gewährleisten, wenn ein Gegner mit einem Laser kollidiert:eventEmitter.on(Messages.COLLISION_ENEMY_LASER, (_, { first, second }) => { first.dead = true; second.dead = true; })
-
Bewege das Objekt, Stelle sicher, dass sich der Laser allmählich zum oberen Bildschirmrand bewegt. Du wirst eine neue Laser-Klasse erstellen, die
GameObject
erweitert, wie du es zuvor getan hast: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) } }
-
Behandle Kollisionen, Implementiere Kollisionsregeln für den Laser. Füge eine Funktion
updateGameObjects()
hinzu, die kollidierende Objekte auf Treffer testet:function updateGameObjects() { const enemies = gameObjects.filter(go => go.type === 'Enemy'); const lasers = gameObjects.filter((go) => go.type === "Laser"); // laser hit something 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); }
Stelle sicher, dass du
updateGameObjects()
in deinen Spielzyklus inwindow.onload
einfügst. -
Implementiere eine Abkühlzeit für den Laser, sodass er nur in bestimmten Abständen abgefeuert werden kann.
Bearbeite abschließend die Hero-Klasse, damit sie eine Abkühlzeit hat:
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; } }
-
An diesem Punkt hat dein Spiel einige Funktionalitäten! Du kannst dich mit deinen Pfeiltasten bewegen, mit der Leertaste einen Laser abfeuern, und Gegner verschwinden, wenn du sie triffst. Gut gemacht!
🚀 Herausforderung
Füge eine Explosion hinzu! Sieh dir die Spielassets im Space Art Repo an und versuche, eine Explosion hinzuzufügen, wenn der Laser einen Alien trifft.
Quiz nach der Lektion
Überprüfung & Selbststudium
Experimentiere mit den Intervallen in deinem Spiel bis jetzt. Was passiert, wenn du sie änderst? Lies mehr über JavaScript-Timing-Events.
Aufgabe
Haftungsausschluss:
Dieses Dokument wurde mit dem KI-Übersetzungsdienst Co-op Translator übersetzt. Obwohl wir uns um Genauigkeit bemühen, weisen wir darauf hin, dass automatisierte Übersetzungen Fehler oder Ungenauigkeiten enthalten können. Das Originaldokument in seiner ursprünglichen Sprache sollte als maßgebliche Quelle betrachtet werden. Für kritische Informationen wird eine professionelle menschliche Übersetzung empfohlen. Wir übernehmen keine Haftung für Missverständnisse oder Fehlinterpretationen, die sich aus der Nutzung dieser Übersetzung ergeben.