Ich werde Sie durch die Erstellung eines von Megaman inspirierten Shooter / Plattform-Spiels führen. Wir werden uns mehr auf das Schießen als auf das Plattforming konzentrieren. In diesem Tutorial werde ich Construct 2 als Werkzeug verwenden, um das Spiel zu erstellen, aber ich werde die Logik anhand von Pseudocode erklären, so dass Sie dieses Tutorial in jeder Sprache oder Engine Ihrer Wahl verfolgen können.
zusammenhängende PostsUm mich auf die Gameplay-Implementierung zu konzentrieren, werde ich nicht jedes Construct 2-Feature erklären. Ich gehe davon aus, dass Sie die Grundlagen kennen, wie das Laden eines Sprites, eine grundlegende Kollision oder das Spielen von Sounds. Lass uns mit dem Spiel beginnen.
Zuerst müssen wir Sprites für unser Spiel haben. Zum Glück hat uns opengameart mit ihrer wundervollen Sammlung legaler Spielkunst bedeckt. Wir brauchen vier Spritesätze; Ein Held, ein Feind und Plättchen für Plattformen.
Um sie in Construct 2 zu verwenden, schneide ich die Sprites des Helden mithilfe von GIMP in einzelne Frames.
Ich werde das Verhalten der Plattform von Construct 2 für den Rest des Tutorials verwenden, damit ich mich auf das Schießen und den AI-Teil des Spiels konzentrieren kann, der Hauptfokus dieses Tutorials war.
Wenn Sie in einer anderen Sprache arbeiten oder Ihre eigenen grundlegenden Plattformbewegungen ausführen möchten, anstatt das integrierte Verhalten zu verwenden. Sie müssen den Code in diesem Abschnitt nur verwenden, wenn Sie nicht das integrierte Verhalten von Construct 2 verwenden.
Um zu beginnen, müssen wir drei Möglichkeiten in Betracht ziehen, wie sich unser Held bewegen kann. nach rechts gehen, nach links gehen oder springen. Bei jedem Frame aktualisieren wir die Spielsimulation.
Anzahl moveSpeed = 50; function update () moveHero ();
Um den Charakter des Spielers zu aktualisieren, führen wir grundlegende Bewegungen wie folgt aus:
function moveHero () // Der Spieler drückt diese Taste, wenn (keyDown (KEY_LEFT)) hero.x - = moveSpeed * deltaTime; hero.animate ("walkLeft"); if (keyDown (KEY_RIGHT)) hero.x + = moveSpeed * deltaTime; hero.animate ("walkRight"); if (keyDown (KEY_UP)) hero.jump (); hero.animate ("Sprung"); // ein Schlüssel, der gerade nicht gedrückt wurde if (keyReleased (KEY_LEFT)) hero.animate ("standLeft"); if (keyReleased (KEY_RIGHT)) hero.animate ("standRight");
Ich verwende eine andere Funktion zum Springen, da beim Springen nicht nur der y-Wert geändert wird, sondern auch die Schwerkraft berechnet wird. Wir haben auch eine Funktion, die darauf wartet, ob gerade eine Taste freigegeben wurde oder nicht, um die Animation des Helden in eine stehende Animation umzuwandeln.
Lassen Sie uns darüber sprechen, wie der Spieler springen kann. Der Held muss wissen, ob er gerade springt oder nicht, und auch, ob er gerade fällt oder nicht. Wir werden also zwei neue Variablen deklarieren: isJumping und isFalling. Standardmäßig sind beide falsch, dh der Held steht auf einer Plattform.
Um einen Sprung auszuführen, müssen wir zuerst prüfen, ob beide Werte falsch sind oder nicht, und dann den Wert von isJump auf true setzen.
Funktion jump () if (! IsJumping &&! IsFalling) isJumping = True
Damit der Held springen kann, benötigen wir eine Variable namens jumpPower und Schwerkraft. Der voreingestellte Wert von jumpPower ist -20 und die Schwerkraft ist 1. Die Logik besteht darin, den Wert der Sprungkraft zur Y-Position des Helden und die Schwerkraft zum Wert der Sprungkraft hinzuzufügen.
Wir machen das jeden Augenblick. Vielleicht ist dies nicht die realistischste Schwerkraftphysik, die es gibt, aber Spiele müssen nicht realistisch sein, sie müssen nur glaubwürdig sein. Deshalb haben einige Spiele einen super menschlichen Sprung und einen doppelten Sprung. Der folgende Code gehört zur Update-Funktion.
If (isJumping || isFalling) hero.y + = hero.jumpPower; hero.jumpPower + = hero.gravity; // schließlich ist die Sprungkraft größer als Null, und das bedeutet, dass der Held fällt, wenn (hero.jumpPower> = 0) isJumping = False; isFalling = True; // Um dem Absturz ein Ende zu setzen, tun Sie etwas, wenn der Held die Plattform überlappt, wenn (hero.isOverlapping (platform1)) // Plattform1 die Plattform ist, auf die unser Held treten kann, // setzt die Variable auf ihren Standardwert zurück isJumping = False; isFalling = False; hero.jumpPower = -20; // und dann der freie Fall, wenn der Spieler über den Rand einer Plattform fällt, wenn (! hero.isOverlapping (platform1) && hero.jumpPower) < 0 && !isJumping) // !hero.isOverlapping(platform1) checks whether or not our hero is standing on a platform // and if jumpPower is less than zero and the player is not currently jumping, then that means // he's falling // setting these two values like this will make the player fall. hero.jumpPower = 0; isFalling = true;
Das integrierte Plattformverhalten von Construct 2 repliziert den obigen Beispielcode, der nur die Hilfe für Personen bietet, die in einer anderen Sprache arbeiten.
Jetzt kommt der Drehteil des Spiels. In der Megaman-Serie gibt es drei Arten von Schüssen: normale Schüsse, geladene Schüsse und Boss-Energieschüsse.
Normale Aufnahmen sind selbsterklärend. Bei aufgeladenen Schüssen handelt es sich um Schüsse, die vor dem Loslassen aufgeladen werden. Diese aufgeladenen Schüsse sind in zwei Arten erhältlich: halb aufgeladen und voll aufgeladen. Diese aufgeladenen Angriffe sind stärker als normale Schüsse, wobei die vollständig aufgeladenen Angriffe die stärksten werden.
Boss Energy Shots sind Schläge mit einer Kraft, die der Spieler nach dem Sieg über jeden Boss erwirbt. Der Schaden ist derselbe wie normal, aber sie haben besondere Eigenschaften, die normale Schüsse nicht haben.
Nun, da wir den Typ der einzelnen Schüsse kennen, beginnen wir damit, sie zu machen. Lassen Sie uns zunächst die Logik sehen, wie wir jeden Schuss verwenden. Hier nehmen wir an, dass die Z-Taste auf der Tastatur verwendet wird, um einen Schuss abzufeuern. Wir werden zwei verschiedene Verhaltensweisen implementieren:
Jetzt fangen wir mit dem Code an. Da unser Held nach links und rechts schießen kann, müssen wir wissen, in welche Richtung er gerade schaut. Lassen Sie uns eine neue Variable mit dem Namen Verkleidung deklarieren, die einen Zeichenfolgewert speichert, ob der Held nach links oder rechts gerichtet ist.
Zeichenfolge = "rechts"; // in welche Richtung sich der Held gerade auf die Funktion bewegt. moveHero () // Der Spieler drückt diese Taste, wenn (keyDown (KEY_LEFT)) hero.x - = moveSpeed * deltaTime; hero.animate ("walkLeft"); Einfassung = "links"; if (keyDown (KEY_RIGHT)) hero.x + = moveSpeed * deltaTime; hero.animate ("walkRight"); Einfassung = "rechts"; //… die Fortsetzung der Funktion moveHero () geht hier function update () //… der Update-Code, den wir zuvor geschrieben haben, wird hier angezeigt… // Der Spieler drückt diese Taste einmal, wenn (keyPressed (KEY_Z)) wenn (Einblendung == "rechts") hero.animate ("Shoot"); // wir werden später eine Schießfunktion hinzufügen else if (gegenüber == "links") hero.animate ("Shoot"); hero.mirrorSprite (); // Diese Funktion kippt das Sprite horizontal if (keyReleased (KEY_Z)) if (gegenüber == "right") hero.animate ("standRight"); else if (gegenüber == "links") hero.animate ("standLeft"); hero.mirrorSprite (); // Wir müssen das erneut aufrufen, da das Sprite gespiegelt wurde. // Wenn wir das Sprite nicht erneut spiegeln, wird standLeft wie standRight aussehen.
Bevor wir eine Kugel abschießen, müssen wir uns die Eigenschaften der Kugel ansehen:
Diese Eigenschaften unterscheiden sich für jedes Aufzählungszeichen. Insbesondere wird die Leistungseigenschaft unterschiedlich sein. Die Winkeleigenschaft ist normalerweise nur einer von zwei Werten. ob die Kugel nach rechts oder links geschossen wird, es sei denn, es handelt sich um eine Boss-Energiekugel, die in einem bestimmten Winkel schießen kann.
Schussvariationen werden später besprochen, so dass ich jetzt nur noch Grundaufnahmen behandeln werde. Das Folgende ist der Code, der eine Kugel schießt.
// Zuerst erstellen wir eine Funktion, die ein neues Aufzählungszeichen erstellt. Funktion shoot (String pathToSprite, number bulletPower, number bulletSpeed, number bulletAngle) myBullet = new Bullet (pathToSprite); myBullet.power = bulletPower; // Die Aufzählungsklasse oder das Objekt verfügt über zwei private Variablen, die es entsprechend seinem Winkel verschieben. // Weitere Erläuterungen zu diesen beiden Zeilen benötigen mehr Mathematik. Daher entscheide ich mich nicht für die Erklärung // Ich gehe davon aus, dass Ihre Engine eine Wahl hat, um eine zu verschieben Objekt entsprechend seinem Winkel ySpeed = Math.sin (bulletAngle) * bulletSpeed; xSpeed = Math.cos (bulletAngle) * bulletSpeed; // Dies ist die Funktion der Bullet-Klasse, die jeden Frame genannt wird. Dadurch wird das Aufzählungszeichen entsprechend seiner Winkelfunktion verschoben. moveBullet () x + = xSpeed * deltaTime; y + = ySpeed * deltaTime; // und dies ist die Modifikation unserer vorherigen update () - Funktion function update () //… der Update-Code, den wir zuvor geschrieben haben, wird hier angezeigt… // Der Spieler drückt diese Taste einmal, wenn (keyPressed (KEY_Z)) if ( vor == "rechts") hero.animate ("Shoot"); hero.shoot ("path / to / sprite.png", 10, 400, 0); else if (gegenüber == "links") hero.animate ("Shoot"); hero.mirrorSprite (); // Mit dieser Funktion wird das Sprite horizontal umgedreht. hero.shoot ("path / to / sprite.png", 10, 400, 180); // der Winkel ist 180, so dass die Kugel nach links geht //… die Fortsetzung des Aktualisierungscodes geht hier weiter…
Einige Kugeln können mächtiger sein als andere. Um einen aufgeladenen Schuss zu erstellen, benötigen wir eine Variable mit dem Namen 'chargeTime', die jede Sekunde erhöht, in der der Spieler Z gedrückt hält, und beim Abschuss der Kugel auf Null zurückkehrt. Die Änderungen am Aktualisierungscode lauten wie folgt:
// Spieler hat gerade die Taste z freigegeben if (keyReleased (KEY_Z)) if (chargedTime> 0 && chargedTime <= 5) if (facing == "right") hero.animate("Shoot"); hero.shoot("path/to/halfChargedBullet.png", 20, 400, 0); chargedTime = 0; else if (facing == "left") hero.animate("Shoot"); hero.mirrorSprite(); // this function flips the sprite horizontally hero.shoot("path/to/halfChargedBullet.png", 20, 400, 180); chargedTime = 0; else if (chargedTime > 5) if (gegenüber == "rechts") hero.animate ("Shoot"); hero.shoot ("path / to / fullChargedBullet.png", 40, 400, 0); chargeTime = 0; else if (gegenüber == "links") hero.animate ("Shoot"); hero.mirrorSprite (); // Diese Funktion dreht das Sprite horizontal. hero.shoot ("path / to / fullChargedBullet.png", 40, 400, 180); chargeTime = 0; if (gegen == "rechts") hero.animate ("standRight"); else if (gegenüber == "links") hero.animate ("standLeft"); hero.mirrorSprite (); // wir müssen das erneut aufrufen, da das Sprite gespiegelt wurde // Wenn das Sprite nicht erneut gespiegelt wird, wird standLeft wie standRight aussehen. // Der Spieler drückt diese Taste, wenn (keyDown (KEY_Z)) // Dies ist die Funktion, die den Wert von chargedTime jede Sekunde addiert. // Dieser keyDown-Codeblock wird bei jedem Frame ausgeführt. Dies ist weniger als eine Sekunde. // Ihre Engine sollte eine Möglichkeit haben, festzustellen, ob eine Sekunde vergangen ist oder nicht addChargedTime ();
Unser Heldencharakter bewegt sich nach links und rechts und springt entsprechend unserer Eingabe und schießt auch Kugeln, ob normal, halb aufgeladen oder voll aufgeladen.
Wir haben jetzt einen kontrollierbaren Helden. Nennen wir es der Einfachheit halber Xeon. Er kann einige grundlegende Bewegungen wie Gehen, Springen und Schießen ausführen. Das ist großartig! Aber was ist die Fähigkeit, ohne etwas zu schießen, richtig? Deshalb werden wir dieses Mal zum ersten Feind.
Lassen Sie uns die Attribute unseres Feindes entwerfen, bevor wir ihn codieren.
Gesundheit: Wie viele Gesundheit unser Feind hat, bestimmt, wie viele Schüsse (und welche Art) benötigt werden, um ihn zu zerstören.
Macht: Die Angriffskraft des Feindes, wie viel Schaden verursacht er unserem Spieler.
ShotAngle: In welche Richtung der Feind die Kugel abschießt, kann es links oder rechts oder an einem beliebigen Ort sein.
Das ist so ziemlich das, was wir für unseren Feind brauchen. Nun machen wir den Feind Klasse / Objekt.
Die Klasse / das Objekt des Feindes ist fast das gleiche wie die Klasse / das Objekt des Spielers, es sei denn, der Feind hört den Spielereingaben nicht zu. Aus diesem Grund müssen wir die Teile ersetzen, an denen der Held die Spielereingaben hört, die feindliche KI / Logik.
Beginnen wir mit der grundlegenden schießenden KI des Gegners. Der Feind schießt auf den Spieler, wenn er den Spieler sieht.
Um zu bestimmen, ob der Feind den Spieler "sieht", müssen wir eine Variable für das feindliche Objekt mit der Bezeichnung "Ausrichten" definieren. Dies ist eine Zeichenfolge, die einen der beiden Werte "links" oder "rechts" speichert..
Der Feind braucht auch eine Sichtweite, weshalb wir eine weitere Variable mit der Bezeichnung Reichweite erstellen. Wenn sich der Spieler in diesem Bereich befindet, "sieht" der Gegner den Spieler. Der Pseudocode lautet wie folgt:
function boolean checkSees () if (gegenüber == "links" && hero.x> = enemy.x - range) return true; if (vor == "rechts" && hero.x <= enemy.x + range) return true; return false;
Funktion checkSees ()
Vielleicht haben Sie in diesem Pseudocode etwas bemerkt: Die y-Position des Helden wird nicht berücksichtigt, sodass der Feind auf den Helden schießt, auch wenn er sich auf Plattformen mit unterschiedlichen Höhen befindet.
Fürs Erste genügt dies, denn das Erstellen eines Sichtlinienalgorithmus liegt außerhalb des Rahmens dieses Tutorials. In Ihrem eigenen Spiel möchten Sie vielleicht eine Y-Toleranz oberhalb dieser Funktion hinzufügen, um zu prüfen, ob die Position des Helden zwischen zwei Punkten liegt, die die Höhe des Gegners definieren.
Der Pseudocode für das Feindschießen lautet wie folgt:
// kann in update () oder woanders ausgeführt werden, wo jede Frame-Funktion update () ausgeführt wird. if (checkSees ()) shoot ("path / to / bulletSprite.png", enemyPower, 400, shotAngle);
Wie Sie sehen können, ähnelt die feindliche Schießfunktion der Funktion des Spielers. Als Parameter werden der Pfad, die Angriffskraft, die Geschossgeschwindigkeit und der Schusswinkel des Sprites verwendet.
Wann wechselt der Feind von links nach rechts? Für unseren Helden verwenden wir Spielereingaben, um die Richtung zu ändern, in die unser Held schaut. Für unseren Feind haben wir zwei Möglichkeiten: Verwenden Sie einen Timer, um alle paar Sekunden die Blickrichtung zu wechseln, während der Feind stillsteht, oder den Feind an eine bestimmte Stelle zu gehen und dann die Blickrichtung zu ändern und an eine andere Stelle zu gehen um die Blickrichtung wieder zu ändern.
Diese zweite Methode kann als patrouillierende KI verwendet werden. Natürlich können wir den Feind einfach in eine Richtung laufen lassen und niemals zurückkehren.
Der Pseudocode für die erste Methode lautet wie folgt:
function testingAI () // elapsedTime () ist eine Funktion, die zählt, wie viele Sekunden seit dem Zurücksetzen des Werts vergangen sind. // Ich gehe davon aus, dass Ihre Engine diese Wahlmöglichkeiten hat, wenn (elapsedTime ()> 4.0) if (gesicht) == "links") gegenüberliegend = "rechts"; shotAngle = 0; if (gegenüber == "rechts") gegenüber = "links"; shotAngle = 180; enemy.mirrorSprite (); // dreh auch das Sprite horizontal zurück resetTime (); // setzt die Zeit zurück, die in der abgelaufenen Zeit () zählt
Um die patrouillierende KI zu erstellen, müssen wir zwei unsichtbare Objekte herstellen, die sich am Ende beider Wege der patrouillierenden Route des Feindes befinden, und den Feind dazu bringen, sich in eine andere Richtung zu bewegen, wenn er mit ihnen kollidiert.
Nun schreiben wir unseren Pseudocode für die patrouillierende KI des Feindes:
function patrollingAI () if (gegenüber == "rechts") walkRight (); // dasselbe wie das Objekt in der Objekt- / Klasse des Spielers if (collidesWith (rightPatrolBorder)) gesicht = "left"; enemy.mirrorSprite (); if (gegenüber == "links") walkLeft (); if (collidesWith (leftPatrolBorder)) gesicht = "rechts"; enemy.mirrorSprite ();
Danach patrouilliert der Feind zwischen zwei Punkten, so wie wir es wollen.
Um festzulegen, welche KI der Feind verwendet, fügen wir eine weitere Variable mit einem String-Typ für unseren Feind hinzu: die feindliche KI. Dies bestimmt, welche KI jeden Frame verwenden soll:
if (enemyAI == "Schalten") ChangingAI (); else if (enemyAI == "patrouillieren") patrollingAI ();
Natürlich können Sie weitere feindliche KI-Typen hinzufügen, wenn Sie möchten.
Lassen Sie uns darüber sprechen, wie wir sowohl für den Spieler als auch für den Feind Schlagvariationen machen können. Wir machen Schussvariationen, indem wir zwei Dinge ändern: den Schusswinkel und die Anzahl der Kugeln.
Auf diese Weise können wir einen einfachen Kugelschuss oder einen Kugelschuss in drei Richtungen machen. Bevor wir dies tun, machen wir eine weitere Variable für das gegnerische Objekt / Klasse namens shotAI, die eine Zeichenfolge ist. Wir werden dies in unseren checkSees () verwenden, um zu prüfen, ob der Feind blockiert. Die Änderungen an diesem Codeblock werden wie folgt aussehen:
// kann in update () oder woanders ausgeführt werden, wo jede Frame-Funktion update () ausgeführt wird (if (checkSees ()) if (shotAI == "simple") shoot ("path / to / bulletSprite.png", enemyPower) 400 (shotAngle); if (shotAI == "threeBullets") shootThreeBullets ();
Der Name der KI und der Schuss, den der Feind feuern würde, liegt natürlich bei Ihnen. Dies ist nur ein Beispiel.
Lassen Sie uns nun tiefer in die Funktion shootThreeBullets () eintauchen.
Funktion shootThreeBullets () if (gegenüber == "rechts") shoot ("Pfad / nach / bulletSprite.png", enemyPower, 400, 0); // Diese Kugel geht direkt nach rechts ("path / to / bulletSprite.png", enemyPower, 400, 330); // Dies geht um 30 Grad höher ("path / to / bulletSprite.png", enemyPower, 400, 30); // das geht um 30 Grad nach unten if (gegenüber == "links") shoot ("path / to / bulletSprite.png", enemyPower, 400, 180); // Diese Kugel geht direkt zum linken Trieb ("path / to / bulletSprite.png", enemyPower, 400, 210); // Dies geht um 30 Grad höher ("path / to / bulletSprite.png", enemyPower, 400, 150); // das geht um 30 Grad nach unten
Wenn Sie nicht sicher sind, warum 0 nach rechts und 180 nach links geht, liegt dies daran, dass die Richtung von 0 Grad auf die rechte Seite des Bildschirms, 90 Grad auf die untere Seite des Bildschirms usw. gerichtet sind, bis sie trifft 360 Grad. Sobald Sie wissen, welcher Wert wo liegt, können Sie Ihre eigene Schussvariation erstellen.
Wir können auch eine ShotAI-Variable für den Spieler erstellen, aber ich bevorzuge es, dass wir es "Shot" nennen, weil unser Spieler das Geschoss wählen wird, anstatt von Anfang an zu programmieren. T
Die Logik in Megaman ist, jedes Mal, wenn Megaman einen Boss besiegt, erhält er die Kraft dieses Bosses als neuen Schuss. Ich werde versuchen, diese Logik neu zu erstellen. Dazu benötigen wir ein Array, das Spielerschüsse enthält, einschließlich normaler Schüsse. Der Pseudocode sieht so aus:
var shotArr = ["normalShot", "boss1", "boss2"]; var shotIndex = 0; var selectedShot = "normalShot"; function update () // Dies ist der Codeblock in der Update-Funktion des Spielers, bei dem der Spieler eine Kugel abschießt // Diese Funktion ändert die Kugel, die der Spieler schießt changeBullet (); // Spieler diese Taste einmal drücken if (keyPressed (KEY_Z)) if (gegenüber == "rechts") hero.animate ("Shoot"); if (selectedShot == "normalShot") hero.shoot ("Pfad / zu / sprite.png", 10, 400, 0); else if (selectedShot == "boss1") // füge Codes hinzu, um die Art des Schusses zu schießen, die der Spieler nach dem Besiegen von Boss 1 erhalten hat Funktion changeBullet () // ändert den ShotIndex basierend auf der gedrückten Schaltfläche if (keyPressed (KEY_E)) shotIndex + = 1; if (keyPressed (KEY_Q)) shotIndex - = 1; // ShotIndex korrigieren, wenn es außerhalb der Arraylänge ist, wenn (ShotIndex == ShotArr.length) ShotIndex = 0; if (shotIndex < 0) shotIndex = shotArr.length -- 1; selectedShot = shotArr[shotIndex];
Wir müssen zwei neue Variablen im Auge behalten:
Wir werden neue Elemente zu shotArr bringen, wenn der Spieler einen Boss besiegt.
Genau wie der Feind shootThreeBullet () können Sie kreativ sein und Ihre eigenen Schussvariationen erstellen. Da dies die Kugel des Helden ist, geben wir ihm etwas Besonderes.
Lassen Sie uns eine Art von Schuss machen, um gegen einen bestimmten Boss wirksam zu sein, damit er mehr Schaden anrichtet. Zu diesem Zweck erstellen wir eine Variable für das Aufzählungsobjekt namens strongAgainst, bei der es sich um eine weitere Zeichenfolgentypvariable handelt, die den Namen des Bosses enthält, gegen den dieses Aufzählungszeichen wirksam ist. Wir werden hinzufügen, dass diese Funktion mehr Schaden verursacht, wenn wir den Bossteil des Spiels besprechen.
An diesem Punkt beginnen alle Variationen, die wir machen, wirklich zu spielen. Hier beschädigt und tötet unser Held den Feind und umgekehrt.
Lassen Sie uns zunächst eine Variable für den Helden und das gegnerische Objekt erstellen, die Gesundheit genannt wird, die ein Int ist, und eine weitere Variable nur für den Helden mit dem Namen Leben. Schauen wir uns den Pseudocode an:
if (bullet.collidesWith (hero)) hero.health - = bullet.power; createExplosion (); // Im Moment haben wir kein Explosionssprite, daher wird dies als Erinnerung dienen. // // Prüfen Sie, ob der Held tot ist if (hero.health <= 0) hero.lives -= 1; // decreases hero's total number of lives. destroyHero();
Wir werden den gleichen Pseudocode erstellen, um Feinde zu beschädigen, wie folgt:
if (bullet.collidesWith (Feind)) enemy.health - = bullet.power; createExplosion (); if (Feind.gesundheit <= 0) destroyEnemy();
Wenn ich es dabei belasse, wäre es nicht interessant. Ich werde also ein Rechtecksprite in der oberen linken Ecke des Bildschirms erstellen, das als Gesundheitsleiste für unseren Helden dient.
Die Länge dieser Leiste wird sich je nach aktueller Gesundheit unseres Helden ändern. Die Formel zum Ändern der Länge der Gesundheitsleiste lautet:
// Dies ist in der Update-Funktion healthBar.width = (hero.health / hero.maxHealth) * 100;
Wir brauchen eine weitere Variable für unseren Helden namens maxHealth. der volle gesundheitswert unseres helden. Momentan kann dieser Wert nicht geändert werden, aber möglicherweise können wir in Zukunft einen Gegenstand erstellen, der die Menge an maxHealth des Helden erhöht.
Jetzt, da wir unsere Helden-, Feind- und Schussvariationen erstellt haben, müssen wir mehrere Ebenen und Bosse erstellen.
Mehrere Stufen zu haben bedeutet, dass der Spieler zu einem bestimmten Zeitpunkt im Spiel einen oder mehrere Kontrollpunkte erreichen wird, die das Spiel von Stufe 1-1 über Stufe 1-2 auf Stufe 1-3 usw. umschalten, bis sie den Boss erreichen.
Wenn der Spieler irgendwo in Level 1-2 stirbt, muss er oder sie nicht den ganzen Weg zurück vom Anfang von Level 1-1 wiederholen. Wie mache ich das? Zuerst werden wir das Level erstellen, ich werde nicht viel über das Leveldesign erklären, aber hier ist das Beispiellevel in Construct 2.
Das Bild in der oberen linken Ecke ist die HUD-Ebene. Es folgt dem Helden, wenn das Spiel gespielt wird.
Ein Sprite, auf das Sie achten sollten, ist das grüne Sprite im oberen rechten Teil des Levels. Es ist der Kontrollpunkt in diesem Level, wenn der Held damit kollidiert, und wir werden das Spiel auf Level 1-2 übertragen.
Um mit mehreren Ebenen umgehen zu können, benötigen wir drei Variablen: currentLevel, levelName und nextLevel.
Die Variable currentLevel wird im Heldenobjekt / in der Klasse erstellt. Der levelName wird für jede Ebene im Spielszenenobjekt (level) erstellt. Die nextLevel-Variable wird im grünen Sprite-Objekt erstellt.
Die Logik ist wie folgt: Wenn der Held mit dem grünen Sprite kollidiert (ich nenne es greenDoor), ändern wir unser Level in die Spielszene, in der levelName mit der nextLevel-Variablen identisch ist. Nachdem wir das Level geändert haben, ändern wir den Wert der currentLevel-Variablen des Helden in den gleichen Namen wie LevelName der Spielszene. Hier ist der Pseudocode:
// Dies ist in der Aktualisierungsfunktion des Spiels. if (hero.collidesWith (greenDoor)) changeLevelTo (greenDoor.nextLevel);
Hier ist der Pseudocode, der angibt, wann das nächste Level geladen und spielbereit ist.
// Dies ist die Funktion, die ausgelöst wird, wenn die neue Ebene geladen wird. Funktion onStart () hero.currentLevel = scene.LevelName; hero.x = startPos.x; hero.y = startPos.y;
Nun, da wir zu einem neuen Level gewechselt sind, werde ich das orangefarbene Sprite hinter unserem Helden im Leveldesign-Image oben erklären. Dieses orange Sprite ist ein Objekt, das ich startPos nenne. Hiermit wird die Startposition jeder Ebene markiert.
Wir beziehen uns auf dieses Objekt, wenn der Held gerade das Level gewechselt hat oder gestorben ist, so dass wir wissen, wo wir ihn spawnen können.
Hier ist der Pseudocode für die Handhabung, wenn der Held stirbt:
// die Funktion, die ausgelöst wird, wenn der Held zerstört wird Funktion onDestroyed () // erweckt den Helden wieder, wenn der Held noch Leben hat. If (hero.lives> 0) var newHero = neuer Held (); newHero.x = startPos.x; newHero.y = startPos.y;
Jetzt können wir mehrere Level haben und den Helden auch nach seinem Tod respawnen.
Sie können beliebig viele Level erstellen oder sogar zwei greenDoor-Objekte in einem Level erstellen, von denen eines auf Level 1-1 zurückgeht, wenn der Spieler ein Rätsel falsch löst.
Endlich ist es an der Zeit, den Chef selbst umzusetzen. Ein Boss-Level zu schaffen ist so einfach wie das Erstellen eines anderen Levels, bei dem ein Boss statt normaler Gegner erscheint.
Der schwierige Teil besteht darin, eine KI für den Boss zu erstellen, da jeder Boss eine eigene KI haben wird. Damit es für viele Bosse einfach zu verstehen und zu duplizieren ist, werde ich die Boss-KI von der Zeit abhängig machen, nachdem sie aufgetaucht sind. Was bedeutet, dass sie A für x Sekunden tun, dann für B Sekunden für B wechseln, dann C für Z Sekunden machen, bevor sie wieder zu A zurückkehren. Der Pseudocode sieht etwa so aus:
// Dieser Code befindet sich in der Boss-Aktualisierungsfunktion, also wird er bei jedem Frame ausgeführt, wenn (elapsedTime ()> 2.0) // dieser if-Block für 3 Sekunden ausgeführt wird, da der Zeitunterschied zum if-Block unter // drei ist Sekunden. BossShot1 (); // Shot-Variante, die dieses Mal ausgeführt werden soll else if (elapsedTime ()> 5.0) bossShot2 (); else if (elapsedT