Aujourd'hui, je vais vous dire comment créer la
liste de tâches la plus simple, le jeu IDLE incrémentiel
le plus simple en JavaScript, après avoir passé moins d'une journée de vacances annuelles. Pour ce faire, je suggère de choisir un jeu de
hibou plus facilement et de ne pas sauter d'étape entre l'
ovale et le hibou fini, un projet vide et le jeu fini.
Les gens qui savent faire de tels jeux s'ennuieront; les gens qui connaissent JS, je vous recommande de regarder le code avec vos doigts (pour éviter les blessures) et de lire uniquement sur la mécanique. Sous la coupe, un guide cohérent pour les débutants.
Les jeux incrémentaux sont des jeux basés sur le cycle principal [sans fin], consistant en l'accumulation de ressources, leurs dépenses constantes et l'accélération des revenus. Leur principale caractéristique est la croissance constante des nombres. Les instructions vous diront comment créer un jeu IDLE (paresseux) dans lequel les ressources sont reconstituées avec un minuteur, plutôt qu'un clic actif.
Pour commencer, créez un fichier texte appelé index.html et écrivez-y:
<html> <head> <meta http-equiv="Content-Type" content="text/html;charset=utf-8"> <title> </title> <style> </style> </head> <body> : 0<br> </body> </html>
Pour le moment, il n'y a pas encore de jeu, mais il n'y a qu'une inscription statique.
Lien vers le jeu dans l'état actuel:
0df7a27 .
Tous les jeux de ce genre sont basés sur deux cycles de jeu conditionnellement infinis.
Le premier cycle est l'accumulation de ressources.
Le deuxième cycle est un gaspillage de ressources.
Implémentons le premier cycle.
: <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>
Première ligne
<span id="spnCoppersValue">0</span><br>
nous donne la possibilité d'y accéder par son identifiant, et de changer le contenu à l'intérieur des balises, dans notre cas, la valeur des pièces en espèces.
Deuxièmement, un script est apparu.
Nous créons la variable coppers et définissons sa portée avec le mot clé let. Semblable à l'annonce de CopperGrowth, qui sera responsable du taux de croissance des pièces en cuivre.
Ensuite, créez un objet dans lequel nous mettons notre minuterie, qui tirera la fonction endOfTurnCalc toutes les 2000 ms (2 secondes). La fonction fournit une augmentation des pièces en cuivre et une mise à jour de l'interface. Hourra, la moitié du jeu est terminée: nous avons un cycle d'accumulation de ressources. La prochaine tâche consiste à apprendre à le dépenser.
Lien vers le jeu dans l'état actuel:
e5d96e1 .
Ajoutons un bouton qui nous permettra de dépenser des pièces de cuivre pour améliorer la mine de cuivre, je suggère de le mettre devant notre ligne de pièces. Un bouton, son nom, la fonction que le bouton appelle, le nom du bouton est le contenu à l'intérieur des balises.
<button id="btnUpgCopperMine" onclick="upgCopperMine()"> , 10 </button><br>
Ajoutez un code qui permet au bouton de mise à niveau de fonctionner:
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 += " "; } }
et un code qui affectera le taux d'extraction des nouvelles pièces:
function endOfTurnCalc() { coppers = coppers+copperGrowth*coppersUpgLevel;; document.getElementById("spnCoppersValue").innerHTML = coppers; }
Nous fixons le prix de l'amélioration de la mine, définissons le niveau de mine par défaut et écrivons dans la fonction le contrôle de la suffisance des pièces pour la mise à niveau de la mine.
S'il y a assez d'argent, alors radiez le prix de la mise à niveau, augmentez le niveau actuel des mines, calculez le prix de la prochaine amélioration; afficher les valeurs actuelles des pièces de cuivre et le coût de la prochaine amélioration.
Lien vers le jeu dans l'état actuel:
c731ec5 .
Eh bien, vous pouvez déjà jouer - vous pouvez économiser et, plus agréablement, dépenser l'accumulé. Mais nous devons renforcer le succès - le joueur calcule non seulement l'augmentation du taux d'accumulation de pièces, en soustrayant de la nouvelle valeur de l'ancienne, mais, dans le bon sens, voit immédiatement le taux actuel d'accumulation de pièces. Fera l'affaire?
Ajoutez une ligne de plus à l'interface:
: <span id="spnCoppersRate">1</span> 2 <br>
Maintenant, notre interface est décrite par les lignes suivantes:
<button id="btnUpgCopperMine" onclick="upgCopperMine()" style="width: 240px;"> , 10 </button><br> : <span id="spnCoppersValue">0</span><br> : <span id="spnCoppersRate">1</span> 2 <br>
Nous apportons une modification au script, à la fonction 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 += " "; document.getElementById("spnCoppersRate").innerHTML = copperGrowth*coppersUpgLevel; }
Lien vers le jeu dans l'état actuel:
3ac06b6 .
Super! Nous avons un jeu conditionnellement infini. Maintenant, nous devons nous arrêter une seconde et y réfléchir - certaines personnes aiment quand il n'y a pas de but final, et vous pouvez jouer jusqu'à ce que vous soyez fatigué, l'autre partie pense que les conditions de finitude, d'accessibilité du jeu devraient être. Nous avons déjà fait un match pour le premier, mais qu'est-ce qui nous empêche de faire un petit changement pour que le match ait un but et une condition de victoire? Faisons-le.
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()); } }
Nous avons ajouté une variable dans laquelle nous mettons la valeur dont nous avons besoin pour atteindre et changer la fonction de la boucle, en ajoutant une vérification pour atteindre l'objectif. En atteignant l'objectif, nous effaçons l'intervalle de notre objet avec une minuterie et affichons un message contextuel dans le navigateur.
Il y a un petit point: certains antivirus n'aiment pas les alertes et bloquent la page pour leur utilisation.
Lien vers le jeu dans l'état actuel:
8fa4041 .
La prochaine fonctionnalité que les gens attendent d'un jeu de plus de cinq minutes est la possibilité d'enregistrer et de charger le jeu. Donnons-les-lui!
Nous ajoutons deux lignes à l'interface, sans oublier d'ajouter la balise de saut de ligne à la ligne précédente:
<button id="btnSaveGame" onclick="saveGame()" style="width: 240px;"> </button><br> <button id="btnLoadGame" onclick="loadGame()" style="width: 240px;"> </button><br>
et maintenant nous allons étendre nos scripts pour que les boutons fonctionnent:
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; }
Nous mettons toutes les ressources mutables dans le stockage local du navigateur lors de l'enregistrement et pendant la lecture, nous les relisons et mettons à jour l'interface.
Lien vers le jeu dans l'état actuel:
54b1ea0 .
Tout, la partie principale du jeu est prête.
À ce jour, nous avons examiné:
- création d'une ressource;
- extraction des ressources;
- gaspillage de ressources sur une mise à niveau de son système de production;
- reflet de la vitesse d'extraction de la ressource;
- condition de victoire;
- écrire et lire sauvegarder le jeu dans le stockage local du navigateur.
Continuez? Avant de passer au sujet suivant, à savoir l'ajout d'une deuxième ressource à notre système (argent), je suggère d'effectuer une petite refactorisation du code actuel.
Que faut-il faire dans le cadre de la refactorisation?
Tout d'abord, créons un objet de jeu et mettons à l'intérieur les pièces de cuivre, le niveau des mines de cuivre, etc., comme propriétés de cet objet. Cela nous sera très utile à l'avenir alors que nous étendons le stockage et le chargement à de nouvelles entités de jeu.
Dans un deuxième temps, nous allons dynamiser le calcul du prix de mise à jour.
Troisièmement, nous nous débarrassons de la duplication de code, qui est responsable de la mise à jour de l'interface.
Le code prendra la forme suivante:
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>
Il est assez évident que nous avons créé l'objet de jeu, et à l'intérieur de l'objet, nous avons enregistré ses propriétés et valeurs de propriété. De plus, partout où nous avons utilisé pour accéder directement aux variables, nous nous référons maintenant aux mêmes propriétés de l'objet de jeu.
Lien vers le jeu dans l'état actuel:
8a07f4d .
Mettons maintenant à jour le système de sauvegarde et de chargement.
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; }
Maintenant, au lieu d'enregistrer des propriétés individuelles, nous enregistrons l'intégralité de l'objet dans son ensemble. Mais attention: si vous ajoutez des méthodes à l'objet, elles ne seront pas enregistrées de cette façon, et la réécriture ultérieure de l'objet à partir de la sauvegarde supprimera toutes les méthodes ...
Lien vers le jeu dans l'état actuel:
8eba059 .
Supprimons la propriété inutile - le prix de la mise à niveau de la mine et créons une fonction pour calculer la mise à niveau et nous l'appellerons aux endroits nécessaires.
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; }
Lien vers le jeu dans l'état actuel:
4007924 .
Enfin, nous avons mis les parties répétitives du code de mise à jour de l'interface dans une fonction distincte.
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; }
À son tour, dans tous les autres endroits où nous avons accédé à certains objets DOM, nous allons maintenant appeler la fonction updateUI ():
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(); }
Lien vers le jeu dans l'état actuel:
2245f97 .
Je propose maintenant d'introduire une deuxième ressource: l'argent, la construction et l'amélioration des mines d'argent.
<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>
Que fait-on? Des champs pour afficher les pièces d'argent, la vitesse de leur extraction, un bouton pour construire ou améliorer une mine d'argent ont été ajoutés à l'interface.
Les propriétés silvers, silverGrowth, silversUpgLevel sont dupliquées à l'intérieur de l'objet de jeu, mais ce dernier est défini sur 0, car nous n'avons pas de mine d'argent par défaut.
Ajout de la variable silverMineBasePriceCoppers, qui reflétera le prix de la construction d'une mine d'argent en pièces de cuivre (car nous ne pouvons pas payer une mine d'argent avec de l'argent, ce que nous n'avons pas encore).
La fonction coppersUpgCost a été modifiée et dupliquée en tant que silversUpgCost afin que le prix de mise à niveau soit différent de zéro si le niveau de mine actuel est 0.
Nous avons changé la fonction de calcul de la fin du tour, en y ajoutant le calcul du revenu de la mine d'argent, et en changeant également la condition de victoire - maintenant nous devons comparer non pas le nombre de pièces de cuivre, mais le nombre de pièces d'argent.
Nous avons créé la fonction upgSilverMine, dans laquelle nous reflétons la logique de débit des fonds (s'il n'y a pas encore de mine, nous radions les pièces de cuivre, si la mine est déjà construite, alors nous radions l'argent pour améliorer la mine).
Les lignes nécessaires pour l'argent ont été ajoutées à la fonction updateUI, ainsi que la logique de la sortie de texte a été divisée en un bouton pour améliorer la mine d'argent, donc un bouton fonctionne à la fois pour construire et améliorer la mine.
Les fonctions de sauvegarde et de chargement sont restées inchangées.
Lien vers le jeu dans l'état actuel:
03eb0eb .
Il peut arriver qu'il y ait beaucoup plus de pièces de cuivre à accumuler que nécessaire, alors que l'argent doit encore être gagné. Pour cela, dans de tels jeux, en règle générale, il y a la possibilité d'échanger des ressources différentes.
Ajoutons quelques boutons à l'interface:
<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>
Et ajoutez quelques fonctions à ces boutons:
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(); } }
Lien vers le jeu dans l'état actuel:
92219b2 .
Alors quoi d'autre peut être ajouté au jeu incrémentiel? Prestige Gear! Bien sûr, maintenant c'est plus un excès, mais si le jeu se développe davantage, il vous sera utile. Les joueurs l'adorent!
Dans différents jeux, cela se fait différemment, mais en général - le mécanisme donne des points de Prestige soit après la réussite (réussite) du jeu, soit se déverrouille pendant le jeu après avoir atteint un certain seuil cible.
Avec l'aide de points Prestige, le joueur a la possibilité de démarrer rapidement ou un bonus permanent dans le même jeu (il est possible que dans la prochaine mission, si le jeu est divisé en ceux-ci), afin qu'il puisse essayer d'autres tactiques, mais passe moins de temps à repasser . Ainsi, il est possible d'étudier plusieurs fourches, ayant testé différentes solutions, et y consacrant moins de temps que s'il n'y avait pas un tel mécanisme.
De quoi avons-nous besoin pour cela? Besoin d'un mécanisme de redémarrage du jeu avec des valeurs par défaut. En bonus permanent, nous ajouterons des points Prestige aux propriétés précédemment inchangées de copperGrowth et silverGrowth.
Ajoutez les fonctions suivantes winGame, restartGameDialog, restartGame et modifiez également endOfTurnCalc pour appeler de nouvelles fonctions et mettre à jour updateUI:
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"; } }
La fonction winGame démarre une minuterie, après quoi une boîte de dialogue de confirmation est appelée. En cas de confirmation, la fonction de redémarrage est appelée, ce qui réinitialise toutes les valeurs par défaut, mais augmente les propriétés de la croissance de base des pièces.
En général, le jeu est prêt:
- création d'une ressource;
- extraction des ressources;
- gaspillage de ressources sur une mise à niveau de son système de production;
- reflet de la vitesse d'extraction de la ressource;
- condition de victoire;
- écrire et lire sauvegarder le jeu dans le stockage local du navigateur;
- l'ajout d'une ressource supplémentaire avec la production et la mise à niveau de sa production;
- échange de ressources;
- mécanisme de redémarrage du jeu et mécanisme Prestige.
Lien vers le jeu dans l'état actuel:
92219b2 .
Enfin, la dernière chose dans cet article que je veux montrer est un mécanisme de stockage différent, car le mécanisme actuel en a un, mais un problème important.
Imaginez que vous développez un jeu, que vous le publiez sur un serveur Web (éventuellement sur des pages github) et que des gens y jouent. Au fil du temps, vous apportez des modifications au jeu qui ajoutent de nouvelles propriétés à l'objet de jeu du jeu.
Regardez maintenant vos mains.
Le joueur entre avec l'ancienne sauvegarde, qui a toutes les propriétés des cuivres et des argent, mais pas, disons, la propriété d'or. Notre objet de jeu est chargé et remplace celui qui a été créé lors du chargement de la page Web, et maintenant à l'intérieur de l'objet il n'y a que les propriétés qui ont été enregistrées. Et nous avons déjà mis à jour le code! Et ce code fait référence à des propriétés mises à jour qui ne s'y trouvent pas. Ainsi, le code commence à recevoir de multiples erreurs, jusqu'à l'inopérabilité complète du jeu. Étonnamment, pour résoudre ce problème, vous devez réécrire seulement deux lignes dans la fonction de téléchargement du jeu: function loadGame() { gameTemp = JSON.parse(localStorage.getItem('gameTutorial')); for (var propertyName in gameTemp) { game[propertyName] = gameTemp[propertyName]; } updateUI(); }
Maintenant, si vous ajoutez game = {gold: 1,} et que vous démarrez à partir de votre ancienne sauvegarde là où il n'y avait pas encore d'or, alors l'or restera dans l'objet et la logique du jeu ne se cassera nulle part.Lien vers le jeu dans l'état actuel: 83c258d .Encore une chose. Transfert de sauvegardes entre les navigateurs, sauvegardons-le aussi. <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>
Mettez à jour l'interface. 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(); }
Nous avons ajouté deux variables utilitaires, mis à jour updateUI (), écrit trois fonctions - exportation, importation et une fonction qui modifie l'indicateur d'affichage d'exportation, de sorte que «l'ancienne» exportation sera masquée 30 secondes après sa formation.C'est tout pour aujourd'hui.