[教程]如何创建您的第一个增量IDLE JavaScript游戏

今天,我将告诉您如何用JavaScript制作最简单的待办事项清单,该清单最简单的增量式IDLE游戏花费了不到一年的假期。 为此,我建议您更轻松地选择猫头鹰游戏,并且不要在椭圆形和完成的猫头鹰空项目以及完成的游戏之间跳过步骤。


知道如何制作此类游戏的人会感到无聊; 熟悉JS的人,我建议您用手指看一下代码(以避免受伤),并仅阅读有关机械的知识。 在削减下,为初学者提供了一致的指导。

增量游戏是基于[无尽]主周期的游戏,包括资源的积累,它们的固定支出和加速收入。 它们的主要特征是数字的持续增长。 这些说明将告诉您如何制作一个IDLE(懒惰)游戏,在该游戏中,资源是用计时器而不是有效的点击来补充的。

首先,创建一个名为index.html的文本文件,并将以下内容写入其中:
<html> <head> <meta http-equiv="Content-Type" content="text/html;charset=utf-8"><!--    ,     --> <title>     </title> <style> </style> </head> <body>  : 0<br> </body> </html> 

目前,尚无游戏,但只有静态题词。

链接到当前状态的游戏: 0df7a27

该类型的所有游戏均基于两个有条件的无限游戏周期。
第一个周期是资源的积累。
第二个周期浪费资源。

让我们实现第一个周期。

   : <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> 

第一行

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

使我们能够通过其ID来访问它,并更改标签内的内容(在我们的示例中为现金硬币的价值)。

其次,出现了脚本。

我们创建Coppers变量,并使用let关键字设置其范围。 类似于铜增长的公告,它将负责铜币的增长率。

接下来,创建一个放置计时器的对象,该计时器每2000毫秒(2秒)拉动一次endOfTurnCalc函数。 该功能增加了铜币并更新了界面。 好了,游戏完成了一半:我们有一个积累资源的周期。 下一个任务是学习如何花钱。

链接到当前状态的游戏: e5d96e1

让我们添加一个按钮,该按钮将使我们能够花费铜币来改善铜矿,我建议将其放置在带有硬币的生产线的前面。 按钮,其名称,按钮调用的功能,按钮的名称是标签内的内容。

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

添加一个使升级按钮可以工作的代码:

  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 += "  "; } } 

和将影响新硬币提取率的代码:

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

我们设定了改善矿井的价格,定义了默认的矿井等级,并在函数中写入了用于矿井升级的硬币充足性检查。

如果有足够的钱,则注销升级的价格,增加当前的地雷水平,计算出下一个改进的价格; 显示铜币的当前值和下一个改进的成本。

链接到当前状态的游戏: c731ec5

好了,您已经可以玩-您可以保存,更愉快地花费累积的时间。 但是我们需要加强成功-玩家不仅通过从旧值中减去新值来计算硬币累积率的增长,而且还可以很好地立即看到当前硬币累积率。 会吗?

在界面上再添加一行:

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

现在,我们的界面由以下几行描述:

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

我们对脚本进行更改,对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; } 

链接到当前状态的游戏: 3ac06b6

太好了! 我们有条件的无限游戏。 现在我们需要停下来思考一下-有些人在没有最终目标的情况下喜欢它,并且可以玩直到感到累为止,另一部分则认为应该限制游戏的局限性和可达到性。 我们已经为前者制作了游戏,但是是什么阻止了我们进行一些小的改动,以使游戏具有目标和胜利条件? 来吧

  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()); } } 

我们添加了一个变量,在其中放入了我们需要实现的值并从循环中更改了该函数,并添加了一个检查以实现目标。 达到目标后,我们使用计时器清除对象的时间间隔,并在浏览器中显示弹出消息。

有一点很重要:某些防病毒软件不喜欢警报并阻止其使用页面。

链接到当前状态的游戏: 8fa4041

人们期望游戏超过五分钟的下一个功能是能够保存和加载游戏。 让他们给她!

我们在界面中添加了两行,不要忘记在前一行中添加换行标记:

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

现在我们将扩展脚本,以使按钮起作用:

  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; } 

保存时,我们将所有可变资源放在浏览器的本地存储中,在读取时,我们将它们读回并更新界面。

链接到当前状态的游戏: 54b1ea0

一切准备就绪,游戏的主要部分已经准备就绪。

迄今为止,我们已经审查了:

-创建资源;
-资源提取;
-升级生产系统浪费资源;
-反映资源提取的速度;
-胜利条件;
-编写和读取游戏,并将其保存在浏览器的本地存储中。

继续吗 在继续下一个主题(即向我们的系统(银色)添加第二个资源)之前,我建议对当前代码进行少量重构。

重构的一部分需要做什么?

首先,我们创建一个游戏对象,并在其中放置铜币,铜矿的高度等作为该对象的属性。 随着我们将存储和加载扩展到新的游戏实体,这将在将来极大地帮助您。

其次,我们将使升级价格的计算动态化。

第三,我们摆脱了重复代码,它负责更新接口。

该代码将采用以下形式:

  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> 

很明显,我们创建了游戏对象,并且在对象内部注册了它的属性和属性值。 此外,无论我们以前直接访问变量的位置如何,我们现在都引用游戏对象的相同属性。

链接到当前状态的游戏: 8a07f4d

现在让我们更新保存和加载系统。

  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; } 

现在,我们不再保存单个属性,而是将整个对象保存为一个整体。 但是要小心:如果将方法添加到对象,则不会以这种方式保存它们,并且随后从保存中重写对象将删除所有方法...

链接到当前状态的游戏: 8eba059

让我们删除不必要的属性-矿山升级的价格,并创建一个计算升级的函数,我们将在必要的地方调用它。

  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; } 

链接到当前状态的游戏: 4007924

最后,我们将接口更新代码的重复部分放在单独的函数中。

  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; } 

反过来,在我们访问某些DOM对象的所有其他地方,我们现在将调用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(); } 

链接到当前状态的游戏: 2245f97

现在,我建议引入第二种资源:白银,银矿的建设和改良。

  <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> 

怎么办 界面中增加了显示银币的字段,提取速度,用于建造或改善银矿的按钮。

属性silvers,silverGrowth,silversUpgLevel在游戏对象中重复,但后者被设置为0,因为默认情况下我们没有银矿。
添加了silverMineBasePriceCoppers变量,该变量将反映使用铜币建造银矿的价格(因为我们无法用银来购买银矿,而我们还没有)。

CoppersUpgCost函数已被修改并复制为silversUpgCost,因此,如果当前矿山级别为0,则升级价格不为零。
我们更改了计算回合结束的功能,增加了从那里的银矿获得的收入的计算,还更改了获胜条件-现在我们需要比较的不是铜币的数量,而是银币的数量。

我们创建了upgSilverMine函数,在其中反映了借方资金的逻辑(如果还没有地雷,我们注销铜币,如果已经建造了地雷,那么就注销白银以改善地雷)。
Silver的必要行已添加到updateUI函数中,并且文本输出的逻辑被划分为一个按钮以改善Silver mine,因此一个按钮既可用于构建也可用于改进此mine。

保存和加载功能保持不变。

链接到当前状态的游戏: 03eb0eb

可能发生的是,积累的铜币多于所需的数量,而仍然需要赚取白银。 为此,通常在这种游戏中,有可能彼此交换不同的资源。

让我们在界面中添加几个按钮:

 <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> 

并向这些按钮添加一些功能:

  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(); } } 

链接到当前状态的游戏: 92219b2

那么还有什么可以添加到增量游戏中呢? 威望齿轮! 当然,现在这有点多余了,但是如果游戏进一步发展,它将对您派上用场。 玩家们爱他!

在不同的游戏中,其完成方式有所不同,但总的来说-该机制会在成功完成(通过)游戏后提供声望值,或者在达到某个目标阈值后在游戏过程中解锁。

借助Prestige积分,玩家有机会在同一游戏中快速开始游戏或获得永久奖励(有可能在下一个任务中,如果将游戏划分为多个任务),这样他可以尝试其他一些战术,但花费的时间更少。 因此,有可能研究多个分支,测试了不同的解决方案,并且比没有这种机制花费更少的时间。

为此我们需要什么? 需要使用默认值的游戏重启机制。 作为永久奖励,我们将Prestige点添加到CopperGrowth和silverGrowth先前未更改的属性中。

添加以下函数winGame,restartGameDialog,restartGame,还更改endOfTurnCalc以调用新函数并更新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"; } } 

winGame函数启动一个计时器,此后调用确认对话框。 在确认的情况下,将调用重新启动函数,该函数会将所有值重置为默认值,但会增加硬币基本增长的属性。

通常,游戏已准备就绪:

-创建资源;
-资源提取;
-升级生产系统浪费资源;
-反映资源提取的速度;
-胜利条件;
-编写和读取游戏,并将其保存在浏览器的本地存储中;
-在生产中增加一种资源并对其生产进行升级;
-交换资源;
-游戏重启机制和威望机制。

链接到当前状态的游戏: 92219b2

最后,我想展示的本文的最后一件事是一种不同的存储机制,因为当前的机制有一个,但存在很大的问题。

假设您正在开发游戏,然后将其发布到Web服务器上(可能在github页面上),并且人们正在玩它。 随着时间的流逝,您对游戏进行了更改,从而向游戏的游戏对象添加了新的属性。

现在注意你的手。

玩家进入旧的保存区,该保存区具有铜和银的所有属性,但没有金的属性。我们的游戏对象已加载并覆盖了网页加载时创建的对象,现在该对象内部仅保存了那些属性。并且我们已经更新了代码!并且此代码引用的更新属性不存在。因此,代码开始接收多个错误,直到游戏完全无法操作为止。出人意料的是,要解决此问题,您只需要重写游戏下载功能中的两行即可:

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

现在,如果您添加游戏= {gold:1,},并从尚未有黄金的旧存储中启动,那么黄金将保留在对象中,并且游戏逻辑不会在任何地方中断。
链接到当前状态的游戏:83c258d

还有一件事。在浏览器之间转移保存,我们也保存它。

  <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> 

更新界面。

  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(); } 

我们添加了两个实用程序变量,即更新的updateUI(),编写了三个函数-导出,导入和一个用于更改导出显示标志的函数,因此“旧”导出将在其形成后30秒被隐藏。

今天就这些了。

Source: https://habr.com/ru/post/zh-CN465829/


All Articles