[Tutorial] So erstellen Sie Ihr erstes inkrementelles IDLE-JavaScript-Spiel

Heute werde ich Ihnen erklären, wie Sie die einfachste ToDo-Liste erstellen, die das einfachste inkrementelle IDLE-Spiel in JavaScript enthält, nachdem Sie weniger als einen Tag Urlaub pro Jahr verbracht haben. Um dies zu tun, schlage ich vor, ein Eulenspiel einfacher auszuwählen und keine Schritte zwischen der ovalen und der fertigen Eule, einem leeren Projekt und dem fertigen Spiel zu überspringen.


Leute, die wissen, wie man solche Spiele macht, werden sich langweilen; Menschen, die JS kennen, empfehle ich, den Code mit den Fingern zu betrachten (um Verletzungen zu vermeiden) und nur über Mechanik zu lesen. Unter dem Schnitt eine einheitliche Anleitung für Anfänger.

Inkrementelle Spiele sind Spiele, die auf dem [endlosen] Hauptzyklus basieren und aus der Anhäufung von Ressourcen, ihren konstanten Ausgaben und der Beschleunigung des Einkommens bestehen. Ihr Hauptmerkmal ist das ständige Wachstum der Zahlen. In den Anweisungen erfahren Sie, wie Sie ein IDLE-Spiel (faul) erstellen, bei dem Ressourcen nicht mit einem aktiven Klick, sondern mit einem Timer aufgefüllt werden.

Erstellen Sie zunächst eine Textdatei mit dem Namen index.html und schreiben Sie Folgendes hinein:
<html> <head> <meta http-equiv="Content-Type" content="text/html;charset=utf-8"><!--    ,     --> <title>     </title> <style> </style> </head> <body>  : 0<br> </body> </html> 

Im Moment gibt es noch kein Spiel, aber es gibt nur eine statische Inschrift.

Link zum Spiel im aktuellen Status: 0df7a27 .

Alle Spiele in diesem Genre basieren auf zwei bedingt unendlichen Spielzyklen.
Der erste Zyklus ist die Anhäufung von Ressourcen.
Der zweite Zyklus ist eine Verschwendung von Ressourcen.

Lassen Sie uns den ersten Zyklus implementieren.

   : <span id="spnCoppersValue">0</span><br> <script> let coppers = 0; let copperGrowth = 1; myTimer = setInterval(endOfTurnCalc, 2000); function endOfTurnCalc() { coppers = coppers+copperGrowth; document.getElementById("spnCoppersValue").innerHTML = coppers; } </script> 

Erste Zeile

 <span id="spnCoppersValue">0</span><br> 

bietet uns die Möglichkeit, über die ID darauf zuzugreifen und den Inhalt der Tags zu ändern, in unserem Fall den Wert von Geldmünzen.

Zweitens erschien ein Skript.

Wir erstellen die Variable coppers und legen ihren Gültigkeitsbereich mit dem Schlüsselwort let fest. Ähnlich wie bei der Ankündigung von Kupferwachstum, das für die Wachstumsrate von Kupfermünzen verantwortlich sein wird.

Erstellen Sie als Nächstes ein Objekt, in das wir unseren Timer einfügen, der alle 2000 ms (2 Sekunden) die Funktion endOfTurnCalc aufruft. Die Funktion bietet eine Erhöhung der Kupfermünzen und eine Aktualisierung der Benutzeroberfläche. Hurra, das halbe Spiel ist geschafft: Wir haben einen Zyklus, in dem sich Ressourcen ansammeln. Die nächste Aufgabe besteht darin, zu lernen, wie man es ausgibt.

Link zum Spiel im aktuellen Status: e5d96e1 .

Fügen wir einen Knopf hinzu, mit dem wir Kupfermünzen für die Verbesserung der Kupfermine ausgeben können. Ich schlage vor, ihn mit Münzen vor unsere Linie zu stellen. Eine Schaltfläche, ihr Name, die Funktion, die die Schaltfläche aufruft, der Name der Schaltfläche ist der Inhalt der Tags.

 <button id="btnUpgCopperMine" onclick="upgCopperMine()">  , 10  </button><br> 

Fügen Sie einen Code hinzu, mit dem die Upgrade-Schaltfläche funktioniert:

  let coppersUpgCost = 10; let coppersUpgLevel = 1; function upgCopperMine() { if (coppers>coppersUpgCost){ coppers = coppers-coppersUpgCost; coppersUpgLevel = coppersUpgLevel + 1; coppersUpgCost = coppersUpgCost*2; document.getElementById("spnCoppersValue").innerHTML = coppers; document.getElementById("btnUpgCopperMine").innerHTML = "  , "; document.getElementById("btnUpgCopperMine").innerHTML += coppersUpgCost.toString(); document.getElementById("btnUpgCopperMine").innerHTML += "  "; } } 

und einen Code, der die Extraktionsrate neuer Münzen beeinflusst:

  function endOfTurnCalc() { coppers = coppers+copperGrowth*coppersUpgLevel;; document.getElementById("spnCoppersValue").innerHTML = coppers; } 

Wir legen den Preis für die Verbesserung der Mine fest, definieren die Standard-Minenstufe und schreiben in die Funktion die Überprüfung der ausreichenden Anzahl von Münzen für das Minen-Upgrade.

Wenn genügend Geld vorhanden ist, schreiben Sie den Preis für das Upgrade ab, erhöhen Sie das aktuelle Minenniveau und berechnen Sie den Preis für die nächste Verbesserung. Zeigen Sie die aktuellen Werte von Kupfermünzen und die Kosten für die nächste Verbesserung an.

Link zum Spiel im aktuellen Status: c731ec5 .

Nun, Sie können bereits spielen - Sie können sparen und angenehmer das angesammelte ausgeben. Aber wir müssen den Erfolg verstärken - der Spieler berechnet nicht nur die Zunahme der Akkumulationsrate von Münzen, indem er vom neuen Wert der alten abzieht, sondern sieht auf gute Weise sofort die aktuelle Akkumulationsrate von Münzen. Wird es tun?

Fügen Sie der Benutzeroberfläche eine weitere Zeile hinzu:

    : <span id="spnCoppersRate">1</span>  2 <br> 

Nun wird unsere Schnittstelle durch die folgenden Zeilen beschrieben:

  <button id="btnUpgCopperMine" onclick="upgCopperMine()" style="width: 240px;">  , 10  </button><br>  : <span id="spnCoppersValue">0</span><br>    : <span id="spnCoppersRate">1</span>  2 <br> 

Wir nehmen eine Änderung am Skript und an der Funktion upgCopperMine () vor:

  if (coppers>coppersUpgCost){ coppers = coppers-coppersUpgCost; coppersUpgLevel = coppersUpgLevel + 1; coppersUpgCost = coppersUpgCost*2; document.getElementById("spnCoppersValue").innerHTML = coppers; document.getElementById("btnUpgCopperMine").innerHTML = "  , "; document.getElementById("btnUpgCopperMine").innerHTML += coppersUpgCost.toString(); document.getElementById("btnUpgCopperMine").innerHTML += "  "; document.getElementById("spnCoppersRate").innerHTML = copperGrowth*coppersUpgLevel; } 

Link zum Spiel im aktuellen Status: 3ac06b6 .

Großartig! Wir haben ein bedingt unendliches Spiel. Jetzt müssen wir eine Sekunde innehalten und darüber nachdenken - manche Leute mögen es, wenn es kein endgültiges Ziel gibt, und Sie können spielen, bis Sie müde werden. Der andere Teil glaubt, dass die Bedingungen für Endlichkeit und Erreichbarkeit des Spiels sein sollten. Wir haben bereits ein Spiel für das erstere gemacht, aber was hindert uns daran, eine kleine Änderung vorzunehmen, damit das Spiel ein Ziel und eine Siegbedingung hat? Lass es uns tun.

  let win_condition = 50; myTimer = setInterval(endOfTurnCalc, 2000); function endOfTurnCalc() { if (coppers < win_condition) { coppers = coppers+copperGrowth*coppersUpgLevel; document.getElementById("spnCoppersValue").innerHTML = coppers; } else { clearTimeout(myTimer); alert("  !   "+win_condition.toString()); } } 

Wir haben eine Variable hinzugefügt, in die wir den Wert setzen, den wir erreichen müssen, und die Funktion aus der Schleife heraus ändern. Dabei haben wir eine Prüfung hinzugefügt, um das Ziel zu erreichen. Bei Erreichen des Ziels löschen wir das Intervall von unserem Objekt mit einem Timer und zeigen eine Popup-Meldung im Browser an.

Es gibt einen kleinen Punkt: Einige Virenschutzprogramme mögen keine Warnungen und blockieren die Seite für ihre Verwendung.

Link zum Spiel im aktuellen Status: 8fa4041 .

Die nächste Funktionalität, die Benutzer von einem Spiel erwarten, das länger als fünf Minuten dauert, ist das Speichern und Laden des Spiels. Geben wir sie ihr!

Wir fügen der Benutzeroberfläche zwei Zeilen hinzu, wobei wir nicht vergessen, das Zeilenvorschub-Tag zur vorherigen Zeile hinzuzufügen:

  <button id="btnSaveGame" onclick="saveGame()" style="width: 240px;"> </button><br> <button id="btnLoadGame" onclick="loadGame()" style="width: 240px;"> </button><br> 

und jetzt werden wir unsere Skripte erweitern, damit die Schaltflächen funktionieren:

  function saveGame() { localStorage.setItem('coppers', coppers); localStorage.setItem('coppersUpgCost', coppersUpgCost); localStorage.setItem('coppersUpgLevel', coppersUpgLevel); } function loadGame() { coppers = parseInt(localStorage.getItem('coppers')); coppersUpgCost = parseInt(localStorage.getItem('coppersUpgCost')); coppersUpgLevel = parseInt(localStorage.getItem('coppersUpgLevel')); document.getElementById("spnCoppersValue").innerHTML = coppers; document.getElementById("btnUpgCopperMine").innerHTML = "  , "; document.getElementById("btnUpgCopperMine").innerHTML += coppersUpgCost.toString(); document.getElementById("btnUpgCopperMine").innerHTML += "  "; document.getElementById("spnCoppersRate").innerHTML = copperGrowth*coppersUpgLevel; } 

Wir speichern alle veränderbaren Ressourcen beim Speichern im lokalen Speicher des Browsers und lesen sie beim Lesen zurück und aktualisieren die Benutzeroberfläche.

Link zum Spiel im aktuellen Status: 54b1ea0 .

Alles, der Hauptteil des Spiels ist fertig.

Bisher haben wir überprüft:

- Schaffung einer Ressource;
- Rohstoffgewinnung;
- Verschwendung von Ressourcen bei einem Upgrade seines Produktionssystems;
- Reflexion der Geschwindigkeit der Gewinnung der Ressource;
- Siegbedingung;
- Schreiben und Lesen Speichern Sie das Spiel im lokalen Speicher des Browsers.

Weiter? Bevor wir mit dem nächsten Thema fortfahren, nämlich dem Hinzufügen einer zweiten Ressource zu unserem System (Silber), empfehle ich, ein kleines Refactoring des aktuellen Codes durchzuführen.

Was muss im Rahmen des Refactorings getan werden?

Zuerst erstellen wir ein Spielobjekt und legen Kupfermünzen, das Niveau der Kupferminen usw. als Eigenschaften dieses Objekts hinein. Dies wird in Zukunft sehr hilfreich sein, da wir den Speicher und das Laden auf neue Spieleinheiten erweitern.

Zweitens werden wir die Berechnung des Upgrade-Preises dynamisch gestalten.

Drittens beseitigen wir die Vervielfältigung von Code, der für die Aktualisierung der Schnittstelle verantwortlich ist.

Der Code hat folgende Form:

  let game = { coppers: 1, copperGrowth: 1, coppersUpgCost: 10, coppersUpgLevel: 1, } let win_condition = 50; myTimer = setInterval(endOfTurnCalc, 2000); function endOfTurnCalc() { if (game.coppers < win_condition) { game.coppers = game.coppers+game.copperGrowth*game.coppersUpgLevel; document.getElementById("spnCoppersValue").innerHTML = game.coppers; } else { clearTimeout(myTimer); alert("  !   "+win_condition.toString()); } } function upgCopperMine() { if (game.coppers>game.coppersUpgCost){ game.coppers = game.coppers-game.coppersUpgCost; game.coppersUpgLevel = game.coppersUpgLevel + 1; game.coppersUpgCost = game.coppersUpgCost*2; document.getElementById("spnCoppersValue").innerHTML = game.coppers; document.getElementById("btnUpgCopperMine").innerHTML = "  , "; document.getElementById("btnUpgCopperMine").innerHTML += game.coppersUpgCost.toString(); document.getElementById("btnUpgCopperMine").innerHTML += "  "; document.getElementById("spnCoppersRate").innerHTML = game.copperGrowth*game.coppersUpgLevel; } } function saveGame() { localStorage.setItem('coppers', game.coppers); localStorage.setItem('coppersUpgCost', game.coppersUpgCost); localStorage.setItem('coppersUpgLevel', game.coppersUpgLevel); } function loadGame() { game.coppers = parseInt(localStorage.getItem('coppers')); game.coppersUpgCost = parseInt(localStorage.getItem('coppersUpgCost')); game.coppersUpgLevel = parseInt(localStorage.getItem('coppersUpgLevel')); document.getElementById("spnCoppersValue").innerHTML = game.coppers; document.getElementById("btnUpgCopperMine").innerHTML = "  , "; document.getElementById("btnUpgCopperMine").innerHTML += game.coppersUpgCost.toString(); document.getElementById("btnUpgCopperMine").innerHTML += "  "; document.getElementById("spnCoppersRate").innerHTML = game.copperGrowth*game.coppersUpgLevel; } </script> 

Es ist ziemlich offensichtlich, dass wir das Spielobjekt erstellt und innerhalb des Objekts seine Eigenschaften und Eigenschaftswerte registriert haben. Wo immer wir früher direkt auf Variablen zugegriffen haben, beziehen wir uns jetzt auf dieselben Eigenschaften des Spielobjekts.

Link zum Spiel im aktuellen Status: 8a07f4d .

Lassen Sie uns nun das Save and Load-System aktualisieren.

  function saveGame() { localStorage.setItem('gameTutorial', JSON.stringify(game)); } function loadGame() { game = JSON.parse(localStorage.getItem('gameTutorial')); document.getElementById("spnCoppersValue").innerHTML = game.coppers; document.getElementById("btnUpgCopperMine").innerHTML = "  , "; document.getElementById("btnUpgCopperMine").innerHTML += game.coppersUpgCost.toString(); document.getElementById("btnUpgCopperMine").innerHTML += "  "; document.getElementById("spnCoppersRate").innerHTML = game.copperGrowth*game.coppersUpgLevel; } 

Anstatt einzelne Eigenschaften zu speichern, speichern wir jetzt das gesamte Objekt als Ganzes. Aber seien Sie vorsichtig: Wenn Sie dem Objekt Methoden hinzufügen, werden diese nicht auf diese Weise gespeichert, und beim anschließenden Umschreiben des Objekts aus dem Speicher werden alle Methoden gelöscht ...

Link zum Spiel im aktuellen Status: 8eba059 .

Entfernen wir die unnötige Eigenschaft - den Preis des Minen-Upgrades - und erstellen eine Funktion zur Berechnung des Upgrades. Wir werden sie an den erforderlichen Stellen aufrufen.

  function coppersUpgCost() { return game.coppersUpgLevel*10; } function upgCopperMine() { if (game.coppers>=coppersUpgCost()){ game.coppers = game.coppers-coppersUpgCost(); game.coppersUpgLevel = game.coppersUpgLevel + 1; document.getElementById("spnCoppersValue").innerHTML = game.coppers; document.getElementById("btnUpgCopperMine").innerHTML = "  , "; document.getElementById("btnUpgCopperMine").innerHTML += coppersUpgCost().toString(); document.getElementById("btnUpgCopperMine").innerHTML += "  "; document.getElementById("spnCoppersRate").innerHTML = game.copperGrowth*game.coppersUpgLevel; } } function saveGame() { localStorage.setItem('gameTutorial', JSON.stringify(game)); } function loadGame() { game = JSON.parse(localStorage.getItem('gameTutorial')); document.getElementById("spnCoppersValue").innerHTML = game.coppers; document.getElementById("btnUpgCopperMine").innerHTML = "  , "; document.getElementById("btnUpgCopperMine").innerHTML += coppersUpgCost().toString(); document.getElementById("btnUpgCopperMine").innerHTML += "  "; document.getElementById("spnCoppersRate").innerHTML = game.copperGrowth*game.coppersUpgLevel; } 

Link zum Spiel im aktuellen Status: 4007924 .

Schließlich haben wir die sich wiederholenden Teile des Schnittstellenaktualisierungscodes in einer separaten Funktion veröffentlicht.

  function updateUI() { document.getElementById("spnCoppersValue").innerHTML = game.coppers; document.getElementById("btnUpgCopperMine").innerHTML = "  , "; document.getElementById("btnUpgCopperMine").innerHTML += coppersUpgCost().toString(); document.getElementById("btnUpgCopperMine").innerHTML += "  "; document.getElementById("spnCoppersRate").innerHTML = game.copperGrowth*game.coppersUpgLevel; } 

An allen anderen Stellen, an denen wir auf bestimmte DOM-Objekte zugegriffen haben, rufen wir jetzt die Funktion updateUI () auf:

  function endOfTurnCalc() { if (game.coppers < win_condition) { game.coppers = game.coppers+game.copperGrowth*game.coppersUpgLevel; updateUI(); } else { clearTimeout(myTimer); alert("  !   "+win_condition.toString()); } } function upgCopperMine() { if (game.coppers>=coppersUpgCost()){ game.coppers = game.coppers-coppersUpgCost(); game.coppersUpgLevel = game.coppersUpgLevel + 1; updateUI(); } } function loadGame() { game = JSON.parse(localStorage.getItem('gameTutorial')); updateUI(); } 

Link zum Spiel im aktuellen Status: 2245f97 .

Jetzt schlage ich vor, eine zweite Ressource einzuführen: Silber, Bau und Verbesserung von Silberminen.

  <button id="btnUpgCopperMine" onclick="upgCopperMine()" style="width: 240px;">  , 10  </button><br>  : <span id="spnCoppersValue">0</span><br>    : <span id="spnCoppersRate">1</span>  2 <br> <button id="btnUpgSilverMine" onclick="upgSilverMine()" style="width: 240px;">  , 50  </button><br>  : <span id="spnSilversValue">0</span><br>    : <span id="spnSilversRate">1</span>  2 <br> <button id="btnSaveGame" onclick="saveGame()" style="width: 240px;"> </button><br> <button id="btnLoadGame" onclick="loadGame()" style="width: 240px;"> </button><br> <script> let game = { coppers: 1, copperGrowth: 1, coppersUpgLevel: 1, silvers: 0, silverGrowth: 1, silversUpgLevel: 0, } let win_condition = 50; let silverMineBasePriceCoppers = 100; myTimer = setInterval(endOfTurnCalc, 2000); function endOfTurnCalc() { if (game.silvers < win_condition) { game.coppers = game.coppers+game.copperGrowth*game.coppersUpgLevel; game.silvers = game.silvers+game.silverGrowth*game.silversUpgLevel; updateUI(); } else { clearTimeout(myTimer); alert("  !   "+win_condition.toString()); } } function coppersUpgCost() { return game.coppersUpgLevel*10+5; } function silversUpgCost() { return game.silversUpgLevel*10+5; } function upgCopperMine() { if (game.coppers>=coppersUpgCost()){ game.coppers = game.coppers-coppersUpgCost(); game.coppersUpgLevel = game.coppersUpgLevel + 1; updateUI(); } } function upgSilverMine() { if (game.silversUpgLevel===0){ if (game.coppers>=silverMineBasePriceCoppers){ game.coppers = game.coppers-silverMineBasePriceCoppers; game.silversUpgLevel = 1; updateUI(); } } else { if (game.silvers>=silversUpgCost()){ game.silvers = game.silvers-silversUpgCost(); game.silversUpgLevel = game.silversUpgLevel + 1; updateUI(); } } } function updateUI() { document.getElementById("spnCoppersValue").innerHTML = game.coppers; document.getElementById("btnUpgCopperMine").innerHTML = "  , "; document.getElementById("btnUpgCopperMine").innerHTML += coppersUpgCost().toString(); document.getElementById("btnUpgCopperMine").innerHTML += "  "; document.getElementById("spnCoppersRate").innerHTML = game.copperGrowth*game.coppersUpgLevel; document.getElementById("spnSilversValue").innerHTML = game.silvers; if (game.silversUpgLevel===0) { document.getElementById("btnUpgSilverMine").innerHTML = "  , "; document.getElementById("btnUpgSilverMine").innerHTML += silverMineBasePriceCoppers.toString(); document.getElementById("btnUpgSilverMine").innerHTML += "  "; } else { document.getElementById("btnUpgSilverMine").innerHTML = "  , "; document.getElementById("btnUpgSilverMine").innerHTML += silversUpgCost().toString(); document.getElementById("btnUpgSilverMine").innerHTML += "  "; } document.getElementById("spnSilversRate").innerHTML = game.silverGrowth*game.silversUpgLevel; } function saveGame() { localStorage.setItem('gameTutorial', JSON.stringify(game)); } function loadGame() { game = JSON.parse(localStorage.getItem('gameTutorial')); updateUI(); } </script> 

Was wird gemacht? Felder zur Anzeige von Silbermünzen, der Geschwindigkeit ihrer Entnahme, einer Schaltfläche zum Bauen oder Verbessern einer Silbermine wurden der Benutzeroberfläche hinzugefügt.

Die Eigenschaften silvers, silverGrowth und silversUpgLevel werden im Spielobjekt dupliziert, letzteres wird jedoch auf 0 gesetzt, da wir standardmäßig keine Silbermine haben.
Die Variable silverMineBasePriceCoppers wurde hinzugefügt, die den Preis für den Bau einer Silbermine in Kupfermünzen widerspiegelt (da wir für eine Silbermine mit Silber, die wir noch nicht haben, nicht bezahlen können).

Die Funktion coppersUpgCost wurde geändert und als silversUpgCost dupliziert, sodass der Upgrade-Preis ungleich Null ist, wenn die aktuelle Minenstufe 0 ist.
Wir haben die Funktion zur Berechnung des Rundenendes geändert, die Berechnung des Einkommens aus der dortigen Silbermine hinzugefügt und auch die Siegbedingung geändert - jetzt müssen wir nicht die Anzahl der Kupfermünzen, sondern die Anzahl der Silbermünzen vergleichen.

Wir haben die Funktion upgSilverMine erstellt, in der wir die Logik der Abbuchung von Geldern widerspiegeln (wenn es noch keine Mine gibt, schreiben wir die Kupfermünzen ab, wenn die Mine bereits gebaut ist, schreiben wir Silber ab, um die Mine zu verbessern).
Die erforderlichen Zeilen für Silber wurden der updateUI-Funktion hinzugefügt, und die Logik der Textausgabe wurde in eine Schaltfläche unterteilt, um eine Silbermine zu verbessern, sodass eine Schaltfläche zum Erstellen und Verbessern einer Mine dient.

Die Funktionen zum Speichern und Laden blieben unverändert.

Link zum Spiel im aktuellen Status: 03eb0eb .

Es kann vorkommen, dass viel mehr Kupfermünzen angesammelt werden müssen als nötig, während Silber noch verdient werden muss. Dafür besteht in solchen Spielen in der Regel die Möglichkeit, unterschiedliche Ressourcen gegeneinander auszutauschen.

Fügen wir der Benutzeroberfläche einige Schaltflächen hinzu:

 <button id="btnUpgCopperMine" onclick="upgCopperMine()" style="width: 240px;">  , 15  </button><br>  : <span id="spnCoppersValue">0</span><br>    : <span id="spnCoppersRate">1</span>  2 <br> <button id="btnBuySilver" onclick="buySilver()" style="width: 240px;"> 1   100 </button><br> <hr> <button id="btnUpgSilverMine" onclick="upgSilverMine()" style="width: 240px;">  , 50  </button><br>  : <span id="spnSilversValue">0</span><br>    : <span id="spnSilversRate">0</span>  2 <br> <button id="btnBuySilver" onclick="buyCoppers()" style="width: 240px;"> 100   1  </button><br> <hr> <button id="btnSaveGame" onclick="saveGame()" style="width: 240px;"> </button><br> <button id="btnLoadGame" onclick="loadGame()" style="width: 240px;"> </button><br> 

Fügen Sie diesen Schaltflächen einige Funktionen hinzu:

  function buySilver() { if (game.coppers>=100) { game.coppers = game.coppers - 100; game.silvers = game.silvers + 1; updateUI(); } } function buyCoppers() { if (game.silvers>=1) { game.coppers = game.coppers + 100; game.silvers = game.silvers - 1; updateUI(); } } 

Link zum Spiel im aktuellen Status: 92219b2 .

Was kann dem inkrementellen Spiel noch hinzugefügt werden? Prestige-Ausrüstung! Natürlich ist dies jetzt eher ein Übermaß, aber wenn sich das Spiel weiterentwickelt, wird es nützlich sein. Spieler lieben ihn!

In verschiedenen Spielen wird es anders gemacht, aber im Allgemeinen - der Mechanismus gibt Prestige-Punkte entweder nach erfolgreichem Abschluss (Bestehen) des Spiels oder wird während des Spiels nach Erreichen einer bestimmten Zielschwelle freigeschaltet.

Mit Hilfe von Prestige-Punkten erhält der Spieler die Möglichkeit, schnell zu beginnen oder einen dauerhaften Bonus im selben Spiel zu erhalten (es ist möglich, dass in der nächsten Mission, wenn das Spiel in diese unterteilt ist), andere Taktiken auszuprobieren, verbringt aber weniger Zeit damit, erneut zu vergehen . Somit ist es möglich, mehrere Gabeln zu untersuchen, verschiedene Lösungen getestet zu haben und weniger Zeit damit zu verbringen, als wenn es keinen solchen Mechanismus gäbe.

Was brauchen wir dafür? Benötigen Sie einen Spielneustartmechanismus mit Standardwerten. Als permanenten Bonus werden wir Prestige-Punkte zu den bisher unveränderten Eigenschaften von Kupfer- und Silberwachstum hinzufügen.

Fügen Sie die folgenden Funktionen winGame, restartGameDialog, restartGame hinzu und ändern Sie endOfTurnCalc, um neue Funktionen aufzurufen und updateUI zu aktualisieren:

  function endOfTurnCalc() { if (game.silvers < win_condition) { game.coppers = game.coppers+game.copperGrowth*game.coppersUpgLevel; game.silvers = game.silvers+game.silverGrowth*game.silversUpgLevel; updateUI(); } else { winGame(); } } function winGame() { clearTimeout(myTimer); alert("  !   "+win_condition.toString()); myRestartTimer = setInterval(restartGameDialog, 2000); } function restartGameDialog() { if (confirm('      ?')) { restartGame(); } else { clearTimeout(myRestartTimer); } } function restartGame() { game.coppers = 1; game.copperGrowth = game.copperGrowth+1; game.coppersUpgLevel = 1; game.silvers = 0; game.silverGrowth = game.silverGrowth+1; game.silversUpgLevel = 0; clearTimeout(myRestartTimer); myTimer = setInterval(endOfTurnCalc, 2000); updateUI(); } function updateUI() { ... if (game.copperGrowth!==1) { document.getElementById("divLblPrestige").innerHTML = "     "+game.copperGrowth.toString(); document.getElementById("divLblPrestige").style.display = "block"; } else { document.getElementById("divLblPrestige").style.display = "none"; } } 

Die winGame-Funktion startet einen Timer, woraufhin ein Bestätigungsdialog aufgerufen wird. Im Falle einer Bestätigung wird die Neustartfunktion aufgerufen, die alle Werte auf den Standardwert zurücksetzt, aber die Eigenschaften des Grundwachstums von Münzen erhöht.

Im Allgemeinen ist das Spiel fertig:

- Schaffung einer Ressource;
- Rohstoffgewinnung;
- Verschwendung von Ressourcen bei einem Upgrade seines Produktionssystems;
- Reflexion der Geschwindigkeit der Gewinnung der Ressource;
- Siegbedingung;
- Schreiben und Lesen Speichern Sie das Spiel im lokalen Speicher des Browsers.
- Hinzufügen einer weiteren Ressource mit Produktion und Aufrüstung ihrer Produktion;
- Austausch von Ressourcen;
- Spielneustartmechanismus und Prestige-Mechanismus.

Link zum Spiel im aktuellen Status: 92219b2 .

Das Letzte, was ich in diesem Artikel zeigen möchte, ist ein anderer Speichermechanismus, da der aktuelle Mechanismus einen hat, aber ein erhebliches Problem.

Stellen Sie sich vor, Sie entwickeln ein Spiel, veröffentlichen es auf einem Webserver (möglicherweise auf Github-Seiten) und die Leute spielen es. Im Laufe der Zeit nehmen Sie Änderungen am Spiel vor, die dem Spielobjekt des Spiels neue Eigenschaften hinzufügen.

Beobachten Sie jetzt Ihre Hände.

Der Spieler tritt mit dem alten Save ein, der alle Eigenschaften von Kupfer und Silber hat, aber nicht etwa die Goldeigenschaft. Unser Spielobjekt wird geladen und überschreibt das Objekt, das beim Laden der Webseite erstellt wurde. Jetzt befinden sich im Objekt nur noch die Eigenschaften, die darin gespeichert wurden. Und wir haben den Code bereits aktualisiert! Und dieser Code bezieht sich auf aktualisierte Eigenschaften, die nicht vorhanden sind. Somit beginnt der Code mehrere Fehler zu erhalten, bis das Spiel vollständig funktionsunfähig ist. Um dieses Problem zu beheben, müssen Sie überraschenderweise nur zwei Zeilen in der Download-Funktion des Spiels neu schreiben:

  function loadGame() { gameTemp = JSON.parse(localStorage.getItem('gameTutorial')); for (var propertyName in gameTemp) { game[propertyName] = gameTemp[propertyName]; } updateUI(); } 

Wenn Sie nun in game = {gold: 1,} hinzufügen und von Ihrem alten Speicher booten, in dem noch kein Gold vorhanden war, bleibt das Gold im Objekt und die Spiellogik wird nirgendwo brechen.
Link zum Spiel im aktuellen Status: 83c258d .

Noch eine Sache. Wenn Sie Speicher zwischen Browsern übertragen, speichern wir sie auch.

  <hr> <button id="btnSaveGame" onclick="saveGame()" style="width: 240px;"> </button><br> <br> <button id="btnExportGame" onclick="exportGame()" style="width: 240px;"> </button><br> <div id="divLblExport" style="display: none"></div> <br> <hr> <button id="btnLoadGame" onclick="loadGame()" style="width: 240px;"> </button><br> <br> <button id="btnImportGame" onclick="importGame()" style="width: 240px;"> </button><br> 

Aktualisieren Sie die Schnittstelle.

  let countdown = 30; let showExport = 0; function updateUI() { ... if (showExport===1){ document.getElementById("divLblExport").style.display = "block"; } else { document.getElementById("divLblExport").style.display = "none"; } } function exportGame() { exportTimer = setInterval(exportCountdown, 1000); document.getElementById("divLblExport").innerHTML = btoa(JSON.stringify(game)); showExport = 1; updateUI(); } function exportCountdown() { if (countdown > 0) { countdown = countdown - 1; } else { clearTimeout(exportTimer); countdown = 30; showExport = 0; updateUI(); } } function importGame() { let importString = prompt('   '); gameTemp = JSON.parse(atob(importString)); for (var propertyName in gameTemp) { game[propertyName] = gameTemp[propertyName]; } updateUI(); } 

Wir haben zwei Dienstprogrammvariablen hinzugefügt, updateUI () aktualisiert und drei Funktionen geschrieben - Exportieren, Importieren und eine Funktion, die das Exportanzeigeflag ändert, sodass der „alte“ Export 30 Sekunden nach seiner Erstellung ausgeblendet wird.

Das ist alles für heute.

Source: https://habr.com/ru/post/de465829/


All Articles