How to decrease the count of life after each turn using Javascript - javascript

I have been developing a memory game and it working perfect. I wanted to add a life function in the game where after each wrong match , the player loses one of the hearts on the screen . I have attached the image below:
What i have achieved till now is, when i make the first unmatch, the life decrease by one but after that there is no decrease in life. I have attached the snippet code below :
function unmatched() {
openedCards[0].classList.add("unmatched");
openedCards[1].classList.add("unmatched");
life();
}
function life(){
for(let i=0; i<5; i++) {
if(i=4) {
starElementsArray[i].style.opacity = 0.1;
}
}
}
In the above code, when the function unmatch is executed it checks for the life function where the life is inside the array and i m reducing the opacity of one heart. when i make the first unmatch, it works , but after that I could not reduce the opacity of other hearts one by one. I m kin of stuck in this iteration part. Can someone help me fix this .

The issue is that because you define your life in the function, every time you call the life() function, its like resetting your life... and then looping.. continuously till i=4 and then decreasing opacity of square 4.
You need to store life outside the function and then you dont need to loop at all.. just reduce
var currentLife = 4;
function life(){
starElementsArray[currentLife].style.opacity = 0.1;
currentLife--;
if(currentLife < 0){
// do whatever happens when they run out of life because it continuously decreases as life() is ran
}
}

I'm going to recommend utilizing setTimeout() to invoke once the user gets a wrong answer and reset it when they get it right.
https://developer.mozilla.org/en-US/docs/Web/API/WindowOrWorkerGlobalScope/setTimeout

Related

How to stop a timer from counting when a Javascript memory game finishes?

I have a question on how to stop the timer in a "find the pair" game, built in javascript for a school project.
While trying to look for help online I noticed other javascript projects for a similar game.
However, the ones I found had more use of CSS functionalities, while the one I am trying to finish has practically all the functionalities built in javascript.
To give a description, there is a board (6x8) with random logos, let's call them 'cards'.
The game starts and all the cards are sorted randomly and then hidden.
For 60 seconds all the cards remain in the same position while the player tries to match them.
After that time, only the cards that have not been paired are sorted again, and the player will have to try to pair them again.
One of the things that the code must do is to stop the time when all the cards are correctly paired, i.e. when the game is finished.
Below there is the last version of the code made to end the game.
The function tempo() is supposed to define the time.
The temporizador is the time progress bar.
The contador is the variable used to count the time.
function tempo(){ //function that controls our time progress bar, uses 60 seconds (maxCount) for its cycle
let contador=0;
let maxCount=60;
temporizador=null;
if (temporizador != null) clearInterval(temporizador)
else
temporizador=setInterval(()=>{
contador++;
document.getElementById("time").value=contador;
if(contador===maxCount-5)document.getElementById("time").classList.add("warning"); //when it takes 5 seconds to end the 60 seconds
if(contador===maxCount) { //in the time bar, you can see the bar in red, blinking
clearInterval(temporizador);
document.getElementById("time").classList.remove("warning"); //when cycle finished the red blinking stops
scramblerEscondidas(); //and the function scramblerEscondidas() to sort the unmatched pairs, is executed
}
},1000)
for (let i=0; i<6; i++) { //cycle to iterate the rows of the board
for(let j=0; j<8; j++){ //cycle to iterate the columns of the board
if (game.board[i][j].virada=true) tempo.stop(); //'virada' is a property of each card of the board, if true it displays the logo. defined in the 'const' for the card
game.sounds.win.play();
}
}
}
The last cycle for in this function is supposed to check if all the cards are turned to the player, meaning the game is finished.
It is supposed to stop the time (the progress in the time bar) when this happens, but the timer doesn't stop.
Sorry for my noobness. Can anyone give any tips on how to find a solution for this?
I also tried different approaches but I fear they all used the same logic, which is likely faulty.
Any simple tip would help as I just recently started using javascript.
I didn't see what are you trying to do with these code.
But I got your point in stopping the timer.
To make a timer stop, you just have to make a boolean variable called isHaveWinner set it with with default false value.
Then wrap your counter function with
if (!isHaveWinner) {
...your timer iteration
}
In your game logic, if the game finished set the isHaveWinner to true. So your timer won't run no more

How do you slow down the execution of a for loop in JavaScript?

I am making a basic image slider (press the next/prev button and the picture changes). I am also trying to implement a very simple fade effect; to do this I have a for loop which changes the class of the image, cycling through classes that change the opacity. The code works fine and does what I want it to do, but the for loop executes so quickly that you don't notice the change in opacity. I have looked all over and everywhere people are mentioning setTimeout, but that only causes a delayed start of a function.. I just want to slow my for loop so you can visually notice each iteration.
function nextphoto(){
for(var x = 0; x < 5; x++){
photo.className = fade[x];
}
i++;
if(i>19){
i=0;
}
photo.src = image[i];
for(var y = 4; y >= 0; y--){
photo.className = fade[y];
}
}
You might be misunderstanding the concept of synchronous code execution. All of your code has to finish running before anything can be updated or "rendered" to the screen. So your for loop will run until it's done, then the screen will update, but it will of course only have the final view of the image to render.
You should either trigger a CSS transform, by dynamically adding a class to the element via javascript, or if you were desperate to do it all in code, had some reason not to use CSS, and do not want to write a custom per frame animation system, or use a library, then inside each iteration of the for loop, fire an asynchronous function that will update at a later and later time, outside of the current synchronous for loop code.
ie:
var aThing;
for(var i = 0; i < someNumber; i++){
setTimeout(function(){
aThing.someValue = aThing.someValue * .9;
}, 500 * i);
}
You should consider using JQuery's animate() function to animate css values like opacity. Even better you could be using CSS animations.
What you're doing is NOT a good way to achieve your goal. If you really want it that way you should use setInterval or setTimeout.

Javascript Timing for playing beeps

I am building a grid that will be playing sounds in HTML5/Javascript, and essentially I want it to keep repeating by looping through so I set:
window.setInterval(playMusic,INTERVAL);
This works all good and fine so far, but its when I try to add setTimeout events on each column:
function playMusic(){
for(var i=0;i<GRID_SIZE;i++){
setTimeout(playCol(i),INTERVAL/GRID_SIZE*i);
}
}
The reason I do it this way is so that from left to right it will play the sounds one after the other in increments. In the developer console I can see the individual timer events firing at the right times, but the sounds aren't being played. Then at the end of the interval all the sounds play at the same time. So there is something I'm not understanding about why each beep isn't playing one after the other like I want it to. Does setInterval stop the code from each timeout being run until the end of the interval? If so is there some work around for this where I can get the beeps to play at the right times?
You could make your playMusic a recursive function having your counter outside:
var i = 0;
function playMusic(){
if( i < GRID_SIZE ){
playCol(i);
i++;
setTimeout( playMusic, INTERVAL/GRID_SIZE );
}
}
Doing this way the playMusic() function will keep calling itself until the if condition is false. The i variable is updated and will be used to select a different sound for your playCol function.

variable doesn't update when function restarts (javascript)

I'm going to try my best to ask this question without a huge wall of code. Basically I have written a very simple math quiz game. In this game you select a difficulty, the number of questions you want, and the game starts. It asks that number of questions and then you get a score and then the game is over. However, you can restart the game. When you restart, it simply returns you to the home screen, then you can select your options again. The only problem is, we need to keep track of the number of questions remaining in the quiz, the first time around, it works well. We pass numQuestions to the game function. The second time, however, even if I pass numQuestions=10, the value remains 0 from the first time I played the game. Here is the game function:
function startGame(difficulty,numQuestions,score){
// begins game, excluded that come its just some acsii art
// asks question
var q = new question(difficulty);
$("#gameInside").html(q.string);
$("#gameInside").data('answer',q.answer);
// gives answer options
for (var ii=0;ii<=3;ii++){
$("#answers").append("<button class='answerButton'>"+q.answerArray[ii]+"</button>")
}
// starts timer
var b = document.getElementById("timer");
timer = new stopWatch(b, {delay: 100});
timer.start();
},5500)
// when answer is clicked, go here
$("#gameScreen").on("click",".answerButton",function() {
// this seems to be the problem: on the second time I play the game, numQuestions remains the value from the first game and continues to go down (-1,-2) and since my selector is (>0), the else statement fires.
numQuestions--;
var time = parseFloat($("#timer span").html());
var correct = parseFloat($("#gameInside").data('answer'));
var userAnswer = parseFloat($(this).html());
if (correct==userAnswer)
tempScore = Math.round(calculateScore(time)*100)/100;
else
tempScore = 0;
score += tempScore;
$("#score").html(Math.round(score*100)/100);
if (numQuestions > 0) {
var q = new question(difficulty);
$("#gameInside").html(q.string);
$("#gameInside").data('answer',q.answer);
$("#answers").empty();
for (var ii=0;ii<=3;ii++){
$("#answers").append("<button class='answerButton'>"+q.answerArray[ii]+"</button>")
}
timer.reset();
} else {
$("#answers").empty();
$("#gameInside").html('Game Over! Thanks for Playing!');
timer.stop();
}
});
}
any ideas? Thanks
edit:
$(".numberQButton").click(function(){
numQuestions = parseFloat($(this).html());
$("#numQuestionsScreen").hide();
$("#gameScreen").show();
$("#score").html(0);
startGame(difficulty,numQuestions,score);
});
You're problem (I think) lies in closures. When you declare a function in javascript, any accessing of a variable from outside it's own scope generates what is called a closure. In this case, numQuestions is accessed from inside your event function, creating a closure. The effect of this is that any accessing of the variable numQuestions inside your event functions references the variable as it was from the moment your javascript interpreter came across the event function itself- ie, the first time you play your game.
Have a look at these to get an idea of where it's going wrong.
It sounds like you need to instantiate a new Game object when the game is restarted.
Where do you define the on click listener? If it triggers two times, it seems like you are defining the on click listener in such way, that after you completed one game and start all over, a new listener will be registered so you got 2 in the end.

Javascript, object with set lifetime?

I have run in to a problem I do not know how to code in JavaScript really. The thing is I would like to be able to create a lot of objects added to an Array. when objects are created to be added to this array they will have a "lifetime". When this lifetime runs out this object should be removed from the array.
What Im trying to build here is a particle system where particles will vanish from being rendered after the particles lifetime in question have expired.
Anyone who have a good idea or example for this?
I have thought about using setTimeout, setInterval and clearInterval but not sure how this would be most effective.
Something like this?
Update for Felix Kling:
var a = [], next = function() {
a = a.slice(0,-1);
document.body.innerHTML += a.length + "<br />";
if (a.length != 0)
setTimeout(next, 100);
};
for (var i = 0; i < 100; i++) {
a.push({hi: 1});
}
setTimeout(next, 100);​
You can use the code sample of micha. On every call of "next" function you can update the state of you particles (position, velocity, etc). Also you can track the time of the creation of the particles and on every "next" call check if the current time minus the creation time exceeds certain constant and if it does then remove the particles. Depending on the required quality of the animation you may want to reduce the time between timeouts, e.g. setTimeout(next, 25);
Good luck :)

Categories

Resources