今天,我将告诉您如何用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秒被隐藏。今天就这些了。