Utilize the combination of a While Loop and setTimeout for optimal

I'm currently working on developing a text-based space RPG game. One of the challenges I'm facing is creating a battle system where the player and AI take turns firing at each other. I've been struggling to implement a while loop in a way that doesn't crash the browser due to an infinite loop. Here's a snippet of my code:

function battle(enemy) {
var battleOver = false;
console.log(enemy.name + " appears!");
//The problem arises here with the loop implementation.
while(battleOver === false){
console.log("This enemy has " + enemy.health + " health.");
for (var i = 0; i < userWeapons.length; i++) {
    var ibumped = i + 1;
    console.log("Press " + ibumped + " to fire the " + userWeapons[i].name + ".");
}
var weaponChosen;
setTimeout(function() {
    var weaponChoice = prompt("Which weapon do you choose?");
    switch (weaponChoice) {
        case 1:
            weaponChosen = userWeapons[0];
            console.log(userWeapons[0].name + " chosen.");
            break;
        case 2:
            weaponChosen = userWeapons[1];
            console.log(userWeapons[1].name + " chosen.");
            break;
        default:
            weaponChosen = userWeapons[0];
            console.log(userWeapons[0].name + " chosen.");

    };
}, 1000);
setTimeout(function() {
    if (enemy.shields > 0 && weaponChosen.ignoreShield === false) {
        enemy.shields = enemy.shields - weaponChosen.damage;
        weaponChosen.fire(enemy);
        if (enemy.shields < 0) {
            enemy.health = enemy.health + enemy.shields;
            console.log("Enemy shields destroyed and enemy took " + -1 * enemy.shields + " damage!")
        } else {
            console.log("Enemy shields have been reduced to " + enemy.shields + ".");
        }
    } else {
        enemy.health = enemy.health - weaponChosen.damage;
        weaponChosen.fire(enemy);
        console.log("Enemy takes " + weaponChosen.damage + " damage!");
    }
    if (enemy.health <= 0 && battleOver === false) {
        console.log("Enemy destroyed!");
        battleOver = true;
    }
}, 3000);
setTimeout(function() {
    if (enemy.health > 0 && battleOver === false) {
        if (enemy.weapons != null) {
            console.log(enemy.weapons.name + " fired at you.");
            health = health - enemy.weapons.damage;
            console.log("You have " + health + " health left.");
            if (health <= 0) {
                console.log("Game over... You were destroyed");
                battleOver = true;
            }
        } else {
            console.log("The enemy did nothing...");
        }
    };
}, 5000);
}
}

Any insights or suggestions would be highly valued!

Answer №1

It can get quite complex when incorporating setTimeout into your game development process. Most games have a designated "main game loop" that executes 60 times per second.

Consider implementing a main game loop and cooldowns for better control.

Check out this example to see how you could reorganize your code:

var timeForOneFrame = 1000/60; // 60 FPS
var enemy;
var battleOver;

function initGame() {
    /*
      Set up the enemy and other components.
    */
}

function gameLoop() {
  battle(enemy);
}

function battle(enemy) {

  /*
    Handle all things related to battles - this function is called every 60 times per second,
    removing the need for setTimeout!
  */

  // To limit an enemy's attack interval to every 2 seconds, implement a cooldown system...
  if (enemy.cooldown <= 0) {
    // Attack!
    enemy.cooldown += 2000;
  } else {
    enemy.cooldown -= timeForOneFrame;
  }

  if (enemy.health <= 0 && !battleOver) {
    console.log("Enemy defeated!");
    battleOver = true;
    clearInterval(gameLoopInterval);
  }
}

initGame();
var gameLoopInterval = setInterval(gameLoop, timeForOneFrame);

Answer №2

The entire page is halted by a while loop until it completes, and since your loop never ends, it becomes infinite. Consider replacing it with a faster interval method:

const loop = setInterval( function(){
   if( battleOver ) return clearInterval(loop);
   console.log("This enemy has " + enemy.health + " health.");
   for (var i = 0; i < userWeapons.length; i++) {
     console.log("Press " + (i + 1) + " to fire the " + userWeapons[i].name + ".");
   }
},10);

Answer №3

Instead of keeping that loop, I recommend implementing a recursive call at the end of the interactions.
For example:

function engageBattle(enemy) {
   //Your code goes here
   if (HeroSurvives) {
     engageBattle(enemy);
   }
}

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Providing an aggregate outcome from an array

There's a puzzle for you: data = [ '2016-12-12 pass [pass]', '2016-12-12 pass [pass]', '2016-12-12 fail [fail]', '2016-12-13 fail [fail]', '2016-12-14 fail [fail]', '2016-12-14 pass [pa ...

Retrieve the chosen items from a Syncfusion listview

I'm looking to display the selected items from a listview in a grid on the home page, but I'm having trouble figuring out how to do it. I've included the code from the js file and a screenshot of the popup. var subItemsLoaded = false, ...

Using jQuery to assign the value of a selected list item to an input field

I'm struggling with implementing a jQuery function to achieve the following: When a list item is clicked, it should add a 'select' class and remove any other selected list items The selected list item's data value should be set as ...

Deliver search findings that are determined by matching criteria, rather than by identification numbers

I am seeking to return a JSON match upon form submission, rather than simply searching for a specific ID. However, I am uncertain about how to structure this. I have the ability to search for the necessary match in a JavaScript document within one of my n ...

Is there a way to print the entire Bootstrap modal even if the content in the modal body is scrolled beyond visibility?

An issue arises when a user needs to scroll down to see all of the content in the modal body. When printing the modal, only the visible part is printed rather than the entire content. Various code snippets from different sources have been tried with no suc ...

Troubleshooting JavaScript's onchange Function Dysfunction

Here is the code snippet I am working with: <!DOCTYPE html> <html> <head> <link rel="stylesheet" type="text/css" href="style.css"> <script src="jquery-2.2.1.min.js"></script> <script src="slike.js"></script> ...

Include a future date with a date extracted from a JSON response

I have retrieved a date from a JSON response. After confirming that the date is indeed a valid date type, I am having trouble setting it to a future date. The snippet of code below shows my attempt: $rootScope.until = response.data.data.dateReceived; //r ...

Unveiling the Truth about Svelte Transitions

Recently, I attempted to incorporate the guidance provided in this repl () for implementing flying and fading effects on divs. However, it seems that I may have a slight misunderstanding regarding the concept... To tackle this, I designed a component rese ...

What could be the reason for the malfunction of Twitter Bootstrap's typeahead feature in this case?

Struggling to implement typeahead.js into my current project. Despite having bootstrap loaded, the source code does not mention anything about typeahead. As a result, I included the standalone js file with hopes of making it work. Upon implementation, the ...

Having trouble with installing NPM and ng commands, neither of them is working. I may have to uninstall everything and begin from scratch

Learning Angular and how to use the terminal is all new to me. I recently installed NPM and attempted to use ng serve, but encountered a series of issues. At this point, I am considering completely uninstalling everything so I can start fresh. I've d ...

What is the best way to create dynamic .env files that can easily adapt to different environments instead of

Having multiple .env files (one for Vue and one for Laravel) with 'localhost' hard coded in them is causing accessibility issues from other computers on my network. It would be beneficial to have this set up dynamically, except for production. F ...

PHP displays the array returned by Ajax as "[object Object],[object Object]"

When working with Jquery, I am creating two arrays - one embedded inside the other. Here is an example of what it looks like: arrayOne = [{name:'a',value:1}, {name:'b',value:2}] var arrayTwo = [{name:'foo',value:'blah&ap ...

The axios GET request suddenly transforms into an Options request, returning a 401 Unauthorized status. Miraculously, Post

I am well-versed in the concept of "preflight request" and my server does indeed support options requests. What perplexes me is that I have tested various online API tools like Postman and reqbin, which work perfectly fine. However, when I attempt to use ...

Why does my console refuse to log the input entered for the search?

Looking to become proficient in web development, I am attempting to record HTML search queries in the console after storing them in a variable. However, when I try running the search procedure, nothing seems to be displaying in my browser's inspect co ...

Enhancing TypeScript with Generic Proxyify Functionality

I'm attempting to enclose a basic interface provided through a type generic in order to alter the return value of each function within the interface. For instance: interface IBaseInterface { test(a?: boolean, b?: number): Promise<boolean>; ...

The rc-form package in npm is issuing a Warning for the getFieldDecorator method when `defaultValue` is not being used as an option

Currently, I am on the rc-form 2.4.8 version and I am utilizing the getFieldDecorator method in my codebase. However, an issue has arisen: Warning: defaultValue is not a valid property for getFieldDecorator; the correct use is to set value, so please uti ...

The animation speed of the jQuery hashchange event is set to zero, causing the animation

I'm facing an issue with jQuery where my animation inside a hashchange event is not smooth; it happens instantly when triggered. I'm looking for a way to make the animation smoother. jQuery( document ).ready(function() { jQuery(window).on(&a ...

Switch between various components using multiple buttons in Next.js

I am in the process of creating a component that will display different components depending on which button the user selects. Here are the available “pages”: ` const navigation = [ { name: "EOQ", return: "<EOQgraph />" }, { nam ...

Enabling client-side access to collections without the need for meteor startup

Whenever I define my Meteor collections on the server and attempt to access them in the client without being within any of the predefined Meteor methods such as rendered, events, created, or helpers, I consistently encounter an error stating Meteor colle ...

Issue encountered during execution of a mongodb function within a while loop in nodejs

To ensure that a generated id doesn't already exist in the database, I have implemented the following code: let ssid; while ( ssid == undefined ) { let tempSId = assets.makeid(30); MongoClient.connect(mongoUrl, function(err, db) { if ( ...