我试图在RPG I建筑物中制作回合制战斗系统。我希望玩家能够(通过CSS)看到他自己和敌人的生命如何在整个战斗中降低。 这是我目前的代码:
// Defining the variables globally for accessibility.
var enemy_max_hp = 0;
var enemy_hp = 0;
var enemy_atk_dmg = 0;
var enemy_def_pwr = 0;
var enemy_crit_chance = 0;
var enemy_crit_pwr = 0.0;
function battle() {
while(current_hp > 0 || enemy_current_hp <= 0){
//setTimeout(function(){
current_hp -= enemy_atk_dmg*enemy_crit_pwr*crit_chance/100 + def_pwr/2;
enemy_hp -= attack_dmg*crit_power*crit_chance/100 - enemy_def_pwr/2;
if(current_hp < 0){ current_hp = 0; }
if(enemy_hp < 0){ enemy_hp = 0; }
if (current_hp == 0){
// Die
}
if (enemy_current_hp == 0){
// Win battle, proceed.
spawnenemy();
}
//}, 1000);
}
}
function spawnenemy() {
enemy_max_hp = 150;
enemy_hp = 150;
enemy_atk_dmg = 5;
enemy_def_pwr = 3;
enemy_crit_chance = 0;
enemy_crit_pwr = 0;
}
我通过其他脚本更新用户的数据:
var max_hp = 100;
var current_hp = 100;
var attack_dmg = 5;
var defense_power = 4;
var crit_chance = 0;
var crit_power = 0.0;
function showStats(){
document.getElementById("max_hp").innerHTML = max_hp;
document.getElementById("current_hp").innerHTML = current_hp;
document.getElementById("attack_dmg").innerHTML = attack_dmg;
document.getElementById("defense_power").innerHTML = defense_power;
document.getElementById("crit_chance").innerHTML = crit_chance + '%';
document.getElementById("crit_power").innerHTML = crit_power;
}
setInterval(showStats, 5);
如果我按原样运行代码,则战斗以眼睛链接结束,健康状况在实例中从100运行到0。我想添加setTimeout()函数会起作用,但它只会崩溃网页。我该怎么办?
此外,通过按钮点击呼叫(现在)调用战斗功能。我试过制作一个turn()函数,但我失败了。
另一方面,我尽量避免使用外部包。我从未接触过jQuery或Angular2,而且现在我还没有使用它。但是,如果您有任何人知道使用它的解决方案,请随时分享。我也不太关心向后兼容性,tbh。
答案 0 :(得分:2)
将battle
功能更改为以下内容:
function battle() {
var t = setInterval(function() {
if(current_hp > 0 || enemy_current_hp <= 0) {
// code to update battle stats
} else {
clearInterval(t);
}
}, 1000);
}
您的代码存在的问题是setTimeout
和setInterval
是异步函数 - 即JavaScript不会等待它们完成,因此您的while循环创建了无限数量的它们并崩溃你的程序。因为停止完成超时。
此修改后的程序将每秒在setInterval
块内运行代码,而不会创建无限循环。战斗结束后,它将清除setInterval
。
答案 1 :(得分:2)
SetTimeout(kindof)产生一个单独的进程,它启动它自己的生命。调用此代码的代码不会停止。
你应该这样做:
function battle(){
if(current_hp > 0 || enemy_current_hp <= 0){
// do your win thing
} else {
// do your fight thing
// next round in 1 second
setTimeout(battle, 1000);
}
}
为了这样的目的使用setTimeout比setInterval更好,因为你不必清除它们并且它们不会变得拥挤 - 如果你的战斗时间比周期长,那么这将不会进入下一场战斗。 / p>
关于jQuery,而不是像这样的长js选择器:
document.getElementById("max_hp").innerHTML = max_hp;
在jQuery中你可以写:
$('#max_hp').html(max_hp);
此外,具有5毫秒周期的setInterval有点危险,特别是在速度较慢的计算机上。使用至少17 ms间隔,甚至100 ms。无论如何,普通人不会看到小于100毫秒的更新。
答案 2 :(得分:1)
使用该决定将新超时设置为程序中的流控制,而不是function battleStep() {
current_hp -= enemy_atk_dmg*enemy_crit_pwr*crit_chance/100 + def_pwr/2;
enemy_hp -= attack_dmg*crit_power*crit_chance/100 - enemy_def_pwr/2;
if(current_hp < 0){ current_hp = 0; }
if(enemy_hp < 0){ enemy_hp = 0; }
// now update the DOM with the new values
showStats();
if (current_hp == 0){
// Die
} else if (enemy_current_hp == 0){
// Win battle, proceed.
spawnenemy();
} else {
setTimeout(battleStep, 1000);
}
}
function battle() {
// initialize anything you need for the battle to start
battleStep();
}
循环。此外,我认为不需要每5毫秒更新一次统计数据。当事情发生变化时,只需在战斗中加入showStats()。类似的东西:
import os
from django.conf import settings
from django.apps import apps
conf = {
'INSTALLED_APPS': [
'Demo'
],
'DATABASES': {
'default': {
'ENGINE': 'django.db.backends.sqlite3',
'NAME': os.path.join('.', 'db.sqlite3'),
}
}
}
settings.configure(**conf)
apps.populate(settings.INSTALLED_APPS)