This question already has an answer here:
Why is my window.setInterval function overlapping itself in the DOM when called multiple times?
(1 answer)
Closed 1 year ago.
I'm new to JS, and decided to start of learning by a making a small game. I am using a setInterval to automate the enemy's attack. For their first attack the interval is correct, but after the second attack it speeds up to attacking almost three times, or more, a second. I'm also having trouble stopping the interval once either the player's or the enemy's health reaches 0.
here is pretty much all the code pertaining my problem. The whole code can be found here
function deadFunct(){
if(yourHealth <= 0){
window.alert("You dead");
clearInterval(fightAuto);
clearInterval(deadAuto);
}
if(enemyHealth <= 0){
window.alert("The enemy is dead");
clearInterval(fightAuto);
clearInterval(deadAuto);
}
}
function nextFunct(){
document.getElementById("nextBtn").disabled=true;
document.getElementById("swordBtn").disabled=false;
document.getElementById("bowBtn").disabled=false;
document.getElementById("hamBtn").disabled=false;
var a=Math.random();
if(a>0.66){
enemy="Knight";
eAcc=.75;
eDmg=5;
eAttackSpeed=2000;
y= "Your health = " + yourHealth + " || "+ enemy +" = " + enemyHealth + "<br>";
document.getElementById("attack").innerHTML=y;
}else if(a>0.33){
enemy="Archer";
eAcc=.80;
eDmg=3;
eAttackSpeed=1750;
y= "Your health = " + yourHealth + " || "+ enemy +" = " + enemyHealth + "<br>";
document.getElementById("attack").innerHTML=y;
}else{
enemy="Berserker";
eAcc=.66;
eDmg=7;
eAttackSpeed=2500;
y= "Your health = " + yourHealth + " || "+ enemy +" = " + enemyHealth + "<br>";
document.getElementById("attack").innerHTML=y;
}
}
function enemyAttackFunct(){
for(var i=0; i<1;i++){
if(enemy == "Archer"){
fightAuto = setInterval(function(){aAttackFunct()},eAttackSpeed);
document.getElementById("test").innerHTML=eAttackSpeed;
}else if(enemy == "Knight"){
fightAuto = setInterval(function(){kAttackFunct()},eAttackSpeed);
document.getElementById("test").innerHTML=eAttackSpeed;
}else{
fightAuto = setInterval(function(){bAttackFunct()},eAttackSpeed);
document.getElementById("test").innerHTML=eAttackSpeed;
}
}
}
You keep calling 'setInterval' again again. Each call is running in parallel.
If you have more than one warrior peer type (archer, knight, etc), create an array that will have a separate set interval for each.
If, as seems the case, you only have one and they play at random each turn, add clearInterval before every setInterval
you should never use setInterval for animations!
Just use requestAnimationFrame instead!
https://developer.mozilla.org/en/docs/Web/API/window.requestAnimationFrame
http://www.paulirish.com/2011/requestanimationframe-for-smart-animating/
http://css-tricks.com/using-requestanimationframe/
Related
I am working on a sort of clicker game where the user is able to buy upgrades. One such upgrade involves the user earning a certain amount of in-game currency per second, in this case 0.1. Unfortunately if the user decides to buy more than one of this upgrade it appears to rise exponentially. I feel like this might be because the setInterval() function is stacking each time, so that the first time it is 0.1 then the next its 0.1 + 0.2 so 0.3, then 0.3 + 0.2 + 0.1 so 0.6 and so on.
upgradePerSec1.onclick = function() {
if (presents >= cost1) {
presents -= cost1;
upgrade1Amount += 1;
totalPresentsSpent += cost1;
cost1 = Math.ceil(cost1Base *= 1.03 ** upgrade1Amount);
perSec += 0.1;
displayScore.innerHTML = format(presents) + " Presents delivered.";
cost1Disp.innerHTML = "<hr>Cost: " + format(cost1);
title.innerHTML = format(presents) + " Presents";
perSecDisp.innerHTML = formatPerSec(perSec) + " presents /s";
totalPresentsSpentDisp.innerHTML = format(totalPresentsSpent) + " Total presents spent";
setInterval(increment1, 1000);
} else {
alert("You don't have enough presents! Still need: " + format(cost1 - presents));
}
}
function increment1() {
presents += perSec;
totalPresents += perSec;
displayScore.innerHTML = format(presents) + " Presents delivered.";
totalPresentsDisp.innerHTML = format(totalPresents) + " Total presents delivered";
title.innerHTML = format(presents) + " Presents";
}
Here is some clarification for this code:
upgradePerSec1 = HTML button element
cost1 = the cost of this upgrade
perSec = variable to store the amount of "presents" per second
displayScore = an HTML label element
cost1Disp = an HTML label element
title = the browser tab title
format() = a function to format large numbers by adding in commas
totalPresents = the total presents without taking away costs (used for a statistics section)
I have tried replacing the perSec variable with just the number(obviously did not work) I have tried making the timing also rise but could not get the correct timing. Ive also searched many places on the web and could not find any helpful results. I saw one on stack overlfow but it did not apply to me.
You're right, the setInterval calls are stacking. To fix the issue, you should make sure you only call setInterval() once (e.g. by adding an if statement before that line checking if perSec === 0).
e.g.
upgradePerSec1.onclick = function() {
if (presents >= cost1) {
if (perSec === 0) {
setInterval(increment1, 1000);
}
presents -= cost1;
upgrade1Amount += 1;
totalPresentsSpent += cost1;
cost1 = Math.ceil(cost1Base *= 1.03 ** upgrade1Amount);
perSec += 0.1;
displayScore.innerHTML = format(presents) + " Presents delivered.";
cost1Disp.innerHTML = "<hr>Cost: " + format(cost1);
title.innerHTML = format(presents) + " Presents";
perSecDisp.innerHTML = formatPerSec(perSec) + " presents /s";
totalPresentsSpentDisp.innerHTML = format(totalPresentsSpent) + " Total presents spent";
} else {
alert("You don't have enough presents! Still need: " + format(cost1 - presents));
}
}
function increment1() {
presents += perSec;
totalPresents += perSec;
displayScore.innerHTML = format(presents) + " Presents delivered.";
totalPresentsDisp.innerHTML = format(totalPresents) + " Total presents delivered";
title.innerHTML = format(presents) + " Presents";
}
I am using tracking.js for facedetection and sending the result of facedetection to server through websocket. In the following code in if(event.data.length != 0) of setInterval runs for some iterations even after clearInterval command.Could anyone explain why is it happening?
var mainfunc = setInterval( function() {
ctx.drawImage(video, 0, 0, 400, 300);
tracking.track('#canvas', tracker);
tracker.on('track', function(event){
if (event.data.length != 0 ){
var center_x = event.data[0].x + (event.data[0].width/2);
var center_y = event.data[0].y +(event.data[0].height/2);
var str = center_x + " " + center_y +" " + center_image_x + " " + center_image_y + " " + flag ;
webSocket.send( str );
// dunno why it is executing number of times ??????????
clearInterval(mainfunc);
}
});
} , 0);
The probable reason you're getting multiple executions is that your code is registering "many" event handlers inside the interval callback (tracker.on(... happens in every callback). Then, only when that event arrives with the condition satisfying data do you clear the interval. That's probably a basic flaw in your logic that should be changed. Only register to the 'track' event 1 time.
It looks like there's a missunderstanding how tracking and the setInterval functions.
setInterval is meant to run a piece of code over and over again with a set interval (in milliseconds).
According to the tracking.js' website, you only start the tracking once and it'll keep tracking things.
Try changing your code to this:
var trackerTask = tracking.track('#canvas', myTracker);
myTracker.on('track', function(event){
if (event.data.length != 0 ){
var center_x = event.data[0].x + (event.data[0].width/2);
var center_y = event.data[0].y +(event.data[0].height/2);
var str = center_x + " " + center_y +" " + center_image_x + " " + center_image_y + " " + flag ;
webSocket.send( str );
trackerTask.stop(); // stopping the tracking
}
});
And now I'm not certain but I think you want to continously draw the video feed. You can do this in this way:
function drawVideo() {
requestAnimationFrame(drawVideo); //this will make sure it's redrawn as soon as the browser is ready
ctx.clearRect(0,0,canvas.width,canvas.height);
ctx.drawImage(video, 0, 0, 400, 300);
}
drawVideo(); //this call is needed to initiate drawing of the video.
How do I have a button appear after a certain function is executed?
I'm trying to create a simple game and it has 2 buttons which lead to function 2 and 3 when the program first runs.
After pressing one of the two buttons and executing one of the functions, the button disappears. I then want to create another button on the second and third function that will allow player to replay the game and exit the game. The problem is that I don't know how to make the button only appear on the second function or third functions.
<HTML>
<!Foundation Page for building our Javascript programs>
<HEAD>
<TITLE>The Foundation Page </TITLE>
<SCRIPT LANGUAGE="JavaScript">
var score;
score = 0
function mainmenu() {
var start
name = prompt("What is your name?")
document.write("Welcome " + name + " for playing game" + "<BR>")
}
function game() {
var ask
var repeat
var again
again = "yes"
while (again == "yes") {
document.write("Hello " + name + " Welcome to the game, you will decide on what action you will take depending on the situation. You will either gain or loose score depending on your decision made. GLHF!" + "<br>" + "<BR>")
document.write(" You enter the dungeon and its pitch black, you can barely see your hand infront of your face. You have a pair of flint inside your pocket and you can attempt to make a torch by ripping a piece of your cloth. What do you do?" + "<BR>")
decision1 = (" Option 1) You brave the darkness" + "<br>")
document.write(decision1)
/* dont need to use all these's variables for decision 1-16*/
decision2 = ("Option 2) You attempt to make a torch" + "<BR>")
document.write(decision2)
decision3 = ("Option 3) You attempt to find a wall and let it guide you" + "<BR>")
document.write(decision3)
decision4 = ("Option 4) You run like an animal, screaming like an animal" + "<BR>")
document.write(decision3)
ask = prompt("Which decision do you choose? Choose from 1,2,3 and 4" + "<BR>")
if (ask == "1") {
document.write("You walk for a few minute without any event but you suddenly step onto a pot-hole and loose your grip. You injured your right knee. You'll live but its gonna hurt for a while" + "<BR>")
score = score + 20
}
if (ask == "2") {
document.write("You tore off a piece of cloth from your sholder and you write it around a stick you found nearby but ask you reach into your pocket to grab your flint, you dropped it. As you attempt to find it, you accidentally felt something sharp and you started to bleed from your left hand. Tought luck m8" + "<BR>")
score = score - 30
}
if (ask == "3") {
document.write("You glide your hand agaist the wall, after half and hour of nothing happening. You finally found a ray of light at the end of the tunnel" + "<BR>")
score = score + 50
}
if (ask == "4") {
document.write("You started running and you scream your lungs out. You took 3 steps and you fell down face first. What the hell were you thinking?" + "<BR>")
score = score - 50
}
document.write("Your current score is " + score + "<BR>")
document.write(" As you finally walk past the darkness, you stumble upon a bright litted room. In the middle of the room, filled a chest. You took a survey around the room and you notice there's nothing in the room except the chest. What to do you?" + "<BR>" + "<BR>")
decision5 = ("Option 1) You rush towards the treasure chest and open it. Gotta get dat bootie!" + "<br>")
document.write(decision5)
/* dont need to use all these's variables for decision 1-16*/
decision6 = ("Option 2) You take a more carefull look around the room." + "<BR>")
document.write(decision6)
decision7 = ("Option 3) You leave the chest alone and walk straight past it and into the next room" + "<BR>")
document.write(decision7)
decision8 = ("Option 4) You kick the chest" + "<BR>")
document.write(decision8)
ask = prompt("Which decision do you choose? Choose from 5,6,7 and 8" + "<BR>")
if (ask == "1") {
document.write("You rush towards the chest with full speed and suddenly, half a dozen arrow wizzez past you. Unfortunatly, you've been hit around the sholder. You decided its too dangerous and you cut your losses and enter the next room" + "<BR>")
score = score - 50
}
if (ask == "2") {
document.write("As you walk to the side of the room, you notice there are dozens of small holes placed infront of the the treasure chest. You also notice there are pressure plates suinfront of the chest. You walk behind the chest and opened it and you fond that its completely empty!. So much for bootie." + "<BR>")
score = score + 50
}
if (ask == "3") {
document.write("You decided to play it safe and walk past the treasure chest. Nothing happens" + "<BR>")
score = score + 0
}
if (ask == "4") {
document.write("You decided to kick the chest for whatever reason. You hurt your foot during the process. Why would you do that?" + "<BR>")
score = score - 20
}
document.write("Your current score is " + score + "<BR>")
document.write(" As you continue along your journey, you stumble upon an injured adventurer! You rush to his side and he claims that his right leg is broken. He's seems to be carrying a rather heavy rucksack. You cant carry him with you because he's simply too heavy. " + "<BR>" + "<BR>")
decision9 = (" Option 1) You perform some medical treatment on him. Though you dont have much experience on medicine." + "<br>")
document.write(decision9)
/* dont need to use all these's variables for decision 1-16*/
decision10 = ("Option 2) You ignore him." + "<BR>")
document.write(decision10)
decision11 = ("Option 3) You search for his bag and see if there is anything useful to help him" + "<BR>")
document.write(decision11)
decision12 = ("Option 4) You end his misery. He's not gonna last long here anyway." + "<BR>")
document.write(decision12)
ask = prompt("Which decision do you choose? Choose from 9,10,11 and 12" + "<BR>")
if (ask == "1") {
document.write("you attempt to fix the adventurer's leg by applying some ointment onto his leg. It wont help much but at least it's something" + "<BR>")
score = score + 10
}
if (ask == "2") {
document.write("You walk past him and ignore his plea of him. There's nothing you can do to help him" + "<BR>")
score = score + 0
}
if (ask == "3") {
document.write("As you run through his bad you found a stick! Looks like he's in a sticky situation :D, you tied the stick to the adventurer's leg. It seems to be sturdy enough to hold him. He thanks you and he goes to his merry ways." + "<BR>")
score = score + 40
}
if (ask == "4") {
document.write("You decide to end his misery by knocking him in the back. He falls dead on the ground the moment your hand make contact. How this work i will nover know. Just roll with it" + "<BR>")
score = score - 20
}
document.write(" At the end of the room a giant lion statue gazes upon you. He ask you a quiz. What walks on 4 legs, then 2 and finally 3. " + "<BR>" + "<BR>")
decision13 = (" Option 1) AN ANIMAL!" + "<br>")
document.write(decision13)
/* dont need to use all these's variables for decision 1-16*/
decision14 = ("Option 2) A CHAIR!" + "<BR>")
document.write(decision14)
decision15 = ("Option 3) A MAN!" + "<BR>")
document.write(decision15)
decision16 = ("Option 4) I dunno" + "<BR>")
document.write(decision16)
ask = prompt("Which decision do you choose? Choose from 13,14,15 and 16" + "<BR>")
if (ask == "1") {
document.write("NOPE, the lion statue slowly disapears and behind it leads to the outside world" + "<BR>")
score = score - 10
}
if (ask == "2") {
document.write("NOPE, the lion statue slowly disapears and behind it leads to the outside world" + "<BR>")
score = score - 10
}
if (ask == "3") {
document.write("Correct!, the lion statue slowly disapears and behind it leads to the outside world." + "<BR>")
score = score + 10
}
if (ask == "4") {
document.write("Your not even gonna try? The lion's head shook in disapointment and slowly disapears. Behind it leads to the outside world" + "<BR>")
score = score - 20
}
document.write("Your current score is " + score)
again = prompt("would you like to play again?")
}
leaderboard()
}
function leaderboard() {
var n, temp;
ok = false;
var leaderboardarray = new Array(5);
leaderboardarray[0] = 50;
leaderboardarray[1] = 60;
leaderboardarray[2] = 130;
leaderboardarray[3] = 120;
leaderboardarray[4] = score;
leaderboardarray.sort(function (a, b) {
return b - a
});
var myContent = '';
for (var n = 0; n < 5; n++)
myContent += "score: " + leaderboardarray[n] + "<br>";
document.getElementById("leaderBoard").innerHTML = myContent;
document.write("Your current score is " + score)
}
leaderboard()
</SCRIPT>
</HEAD>
<BODY style="background-color:#cccccc;">
<INPUT NAME="dobutton" TYPE="button" value="Start game" onclick=game()>
<INPUT NAME="dobutton" TYPE="button" value="Leaderboard" onclick=leaderboard()>
<H2>The Foundation Page </H2>
<HR>
<div id="leaderBoard">
<script type="text/javascript">mainmenu();</script>
</div>
<BR>
</BODY>
</HTML>
You may assign ad ID to both buttons, and hide the second one:
<INPUT ID="btn1" NAME="dobutton" TYPE="button" value="Start game" onclick="game()">
<INPUT ID="btn2" NAME="dobutton" TYPE="button" value="Leaderboard" onclick="leaderboard()" style="display:none;">
Then you can show or hide them in this way:
document.getElementById("btn1").style.display = "none"; /// first button disappear
document.getElementById("btn2").style.display = "inline"; /// second button appear
I'm making a chopsticks game, and this is my first app I'm making (really new to javascript) and I want it to restart whenever it reaches a certain point until either both the enemy's or your hands have 5 chopsticks. Here's my code:
var nocLeft = 1;
var nocRight = 1;
var handChoice = prompt("You now have " + nocLeft + " chopstick(s) on your left hand, and " + nocRight+ " chopstick(s) on your right hand, which hand do you want to use?").toLowerCase();
if (handChoice === right){
var ehc = prompt("Which hand are you attacking? The enemy's left hand has " + noceLeft + ", and their right hand has " + noceRight + " chopsticks.").toLowerCase();
switch(ehc) {
case 'right':
console.log("You chose the right hand!");
break;
case 'left':
console.log("You chose the right hand!");
break;
default:
console.log("please answer with 'left' or 'right', thanks!");
}
}
else if (handChoice === left){
var ehc = prompt("Which hand are you attacking? The enemy's left hand has " + noceLeft + ", and their right hand has " + noceRight + " chopsticks.").toLowerCase;
}
else {
}
Here's one way to do it:
var exit = false;
while (exit != true) {
// Your code
// Use the next line to get out of the loop
// exit = true;
}
The above method will exit the loop after it reaches the end. If you'd like to exit immediately you can use break.
This code is supposed prompt for two player names and generate a random number between 1 and 6 for each player. It is then supposed to compare those two numbers and provide the output of which player has the higher number or display tie if there is a tie. Sometimes this works and sometimes it does the opposite other times it says both numbers match when they don't.
Anyone have any ideas for me?
var playerOne = " "
var playerTwo = " "
var rollWinner = " "
var p1number = 0;
var p2number = 0;
var end = " "
main()
function main()
{
do {
getNames()
rollDice()
displayResults()
endProgram()
}
while (end == "yes")
}
function getNames()
{
playerOne = prompt("Please enter the name of Player One: ")
playerTwo = prompt("Please enter the name of Player Two: ")
}
function rollDice()
{
p1Number = Math.floor((Math.random()*6)+1)
p2Number = Math.floor((Math.random()*6)+1)
if (p1Number > p2Number)
{
return playerOne
}
else if (p1Number < p2Number)
{
return playerTwo
}
else
{
return "Sorry no winner, there was a tie"
}
}
function displayResults()
{
window.alert(playerOne + " rolled a " + p1Number)
window.alert(playerTwo + " rolled a " + p2Number)
window.alert("The winner is! " + rollDice())
}
function endProgram()
{
end = prompt("Do you want to play again? Enter yes or no")
if (end == "no")
window.alert("Thank you for playing");
else if (end == "yes")
return end;
}
window.alert("The winner is! " + rollDice())
This line calls rollDice again for a 2nd time. You display the results of the first call then you re-roll and display the return value of the 2nd call (which may be different).
// display p1Number and p2Number from first roll
window.alert(playerOne + " rolled a " + p1Number)
window.alert(playerTwo + " rolled a " + p2Number)
// recall rollDice
window.alert("The winner is! " + rollDice())
In displayResults(), you are showing the values of p1Number and p2Number before assigning values to them (since that happens within rollDice()).
So your program is working, but your diagnostic output is misleading you.