转弯之间的Javascript延迟

时间:2017-11-15 19:44:49

标签: javascript

我试图在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。

3 个答案:

答案 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);
}

您的代码存在的问题是setTimeoutsetInterval是异步函数 - 即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)