I have a tetris game that I am trying to finish but saving the high score after a game is over is causing me some issues. When the game ends, if the score is higher than what was previously saved as a highscore, it is supposed to save that new score as the high score locally and display that new highscore. I can not figure out why this is not happening. Below are the three different areas of my code that pertain to the high score. Any help would be appreciated.
creates the menu on the side of the game
<div id="tetris">
<div id="menu">
<p id="start">Press Space to Play.</p>
<p><canvas id="upcoming"></canvas></p>
<p>score <span id="score">00000</span></p>
<p>rows <span id="rows">0</span></p>
<p>high score <span id="highscore">0</span></p>
</div>
<canvas id="canvas">
Sorry, this example cannot be run because your browser does not support the <canvas> element
</canvas>
sets the high score when the game is over
var highscore = localStorage.getItem("highscore");
if (playing == false){
if(highscore !==null){
if(vscore > highscore) {
localStorage.setItem("highscore", vscore);
}
}
else{
localStorage.setItem("highscore", vscore);
}
}
else{
null;
}
updates the scores to display them
function play() { hide('start'); reset(); playing = true; }
function lose() { show('start'); setVisualScore(); playing = false; }
function setVisualScore(n) { vscore = n || score; invalidateScore(); }
function setScore(n) { score = n; setVisualScore(n); }
function addScore(n) { score = score + n; }
function clearScore() { setScore(0); }
function clearRows() { setRows(0); }
function setRows(n) { rows = n; step = Math.max(speed.min, speed.start - (speed.decrement*rows)); invalidateRows(); }
function addRows(n) { setRows(rows + n); }
function setHighScore(n) { highscore = n; }
function addHighScore(n) { setHighScore(highscore); }
function getBlock(x,y) { return (blocks && blocks[x] ? blocks[x][y] : null); }
function setBlock(x,y,type) { blocks[x] = blocks[x] || []; blocks[x][y] = type; invalidate(); }
function clearBlocks() { blocks = []; invalidate(); }
function clearActions() { actions = []; }
function setCurrentPiece(piece) { current = piece || randomPiece(); invalidate(); }
function setNextPiece(piece) { next = piece || randomPiece(); invalidateNext(); }
function reset() {
dt = 0;
clearActions();
clearBlocks();
clearRows();
clearScore();
setCurrentPiece(next);
setNextPiece();
}
function update(idt) {
if (playing) {
if (vscore < score)
setVisualScore(vscore + 1);
handle(actions.shift());
dt = dt + idt;
if (dt > step) {
dt = dt - step;
drop();
}
}
}
I can add the full game code if needed but these are the three areas that directly pertain to the high score issue.
Try the following:
function update(idt) {
if (playing) {
if (vscore < score)
setVisualScore(vscore + 1);
handle(actions.shift());
dt = dt + idt;
if (dt > step) {
dt = dt - step;
drop();
}
// Add the following to update the highscore while playing.
if (score > highscore) {
setHighScore(score);
}
}
}
setHighScore = (score) => {
// update highscore
highscore = score;
// update it visually?
document.getElementById('highscore').text = highscore;
}
Then somewhere you'd want a check once the game is over -- I'd assume immediately where you set the playing boolean to false.
if (playing === false){
if(vscore > highscore) {
// For future games.
localStorage.setItem("highscore", vscore);
}
}
edit :
I'm typing this on my phone, so apologies if format is wonky.
See example : https://codepen.io/anon/pen/pVEJJW
Related
I am learning DOM from udemy and stuck here without any hint that why when I am formatting my code and trying to use a function in event listener function value then it stops working.
This is the original Code
let secretNumber = Math.round(Math.random() * 99) + 1;
let score = 20;
let highscore = 0;
document.querySelector(".check").addEventListener("click", function () {
const guess = Number(document.querySelector(".guess").value);
//Main Function used for DOM queryselection
const displayFunct = function (className, message) {
document.querySelector(className).textContent = message;
};
//When there is no input
if (!guess) {
displayFunct(".message", "No Value๐ฎ๐ฎ๐ฎ๐ฎ๐ฎ");
}
//When player Wins
else if (guess === secretNumber) {
displayFunct(".message", "Correct Number ๐๐๐");
document.querySelector("body").style.backgroundColor = "#60b347";
document.querySelector(".number").style.width = "30rem";
if (score > highscore) {
highscore = score;
}
displayFunct(".highscore", highscore);
}
// When guess is wrong
else if (guess !== secretNumber) {
if (score > 1) {
displayFunct(".message", guess > secretNumber ? "Too HIGH" : " Too LOW");
score--;
displayFunct(".score", score);
} else {
displayFunct(".message", "You Lose!!!!");
displayFunct(".score", 0);
}
}
});
//Coding Challenge 1
document.querySelector(".again").addEventListener("click", function () {
secretNumber = Math.round(Math.random() * 99) + 1;
score = 20;
//Messages Default
document.querySelector(".number").textContent = "?";
document.querySelector(".message").textContent = "Start guessing...";
document.querySelector(".score").textContent = score;
document.querySelector(".guess").value = "";
//CSS Default
document.querySelector("body").style.backgroundColor = "#222";
document.querySelector(".number").style.width = "15rem";
});
In the Coding Challenge 1 section under Message default whenever I am using DisplayFunc()
instead of first 3 code lines then again button stops resetting my code.
This is how I want it to be but It is not happening.
//Coding Challenge 1
document.querySelector(".again").addEventListener("click", function () {
secretNumber = Math.round(Math.random() * 99) + 1;
score = 20;
//Messages Default
DisplayFunc("number", "?" )
DisplayFunc(".message", "Start guessing..." )
DisplayFunc(".score",score)
document.querySelector(".guess").value = "";
//CSS Default
document.querySelector("body").style.backgroundColor = "#222";
document.querySelector(".number").style.width = "15rem";
});
The problem is the location of your displayFunct.
You defined it inside document.querySelector(".check").addEventListener("click", function () { but you are trying to use it inside another function document.querySelector(".again").addEventListener("click", function () {.
That will never work.Move it outside the first function and both functions will be able to use it.
In the second function you are calling DisplayFunc instead of displayFunct, so that's also wrong.
let secretNumber = Math.round(Math.random() * 99) + 1;
let score = 20;
let highscore = 0;
//Main Function used for DOM queryselection
const displayFunct = function (className, message) {
document.querySelector(className).textContent = message;
};
document.querySelector(".check").addEventListener("click", function () {
...
Newbie here! Apologies if I have not formatted this correctly.
I have a whack-a-mole game and want to keep score in local storage. The function at the bottom called 'highscore' is not working - it updates the 'highscore' regardless of whether it is in fact higher than the previous score or not!
I'm sure I'm missing something super obvious, like I say, very new to this! Only using Vanilla Javascript at this stage so hints or solutions in keeping would be ideal.
Any help or pointers in the right direction much appreciated!
Thank you!
window.onload = function() {
setUp();
count = 0;
myDiv = document.getElementById("mole");
myDiv.addEventListener("click", function() {});
};
function setUp() {
let img = document.createElement("img");
img.src = "mole.png";
img.onclick = function(event) {
whackedMole();
};
img.className = "mole";
img.id = "mole";
document.getElementById("moleMap")
.rows[randomNumber()].cells[randomNumber()].appendChild(img);
}
function randomNumber() {
return Math.floor(Math.random() * 5);
}
function whackedMole() {
let mole = document.getElementById("mole");
let audio = new Audio('whack-audio.wav');
audio.play();
document.getElementById("counter").innerHTML = (++count);
mole.parentNode.removeChild(mole);
setUp();
}
let myTimer = 0;
function clock() {
myTimer = setInterval(myClock, 1000);
var c = 10;
function myClock() {
document.getElementById("countdown").innerHTML = --c;
if (c <= 0) {
clearInterval(myTimer);
alert("Your score is " + count + "!");
highscore();
document.getElementById("counter").innerHTML = 0;
count = 0;
}
}
}
//This is the function in question;
function highscore() {
document.getElementById("highscore").innerHTML = count;
let highscore = count;
if (count <= highscore) {
return;
} else if (count > highscore) {
localStorage.setItem('highscore', count);
}
}
If i understood correctly the problem lies in this code:
function highscore() {
document.getElementById("highscore").innerHTML = count;
let highscore = count;
if (count <= highscore) {
return;
} else if (count > highscore) {
localStorage.setItem('highscore', count);
}
}
and specifically on these two lines:
document.getElementById("highscore").innerHTML = count;
and
let highscore = count;
Everytime you call highscore(); you are updating your DOM regardless of if the count is > than the highscore. Then on the second line of code that i have hinted highscore gets the value of count so the first statement in the if clause will always evaluate to true. What i would do is modify the code as following:
function highscore() {
// Just in case the highscore is not yet initialized.
if (!localstorage.getItem('highscore')) {
localstorage.setItem('highscore', count);
}
let highscore = localstorage.getItem('highscore');
if (count <= highscore) {
return;
} else if (count > highscore) {
document.getElementById("highscore").innerHTML = count;
localStorage.setItem('highscore', count);
}
}
Hi I made a js script for coin tossing and when I press the button to start it nothing appears
<script>
var coin = Math.random();
if(coin <= 0.5){
return "H";
}
else{
return "T";
}
var coinFlip = function(){
document.getElementById("flip").innerHTML = coin;
}
</script>
This is the button
<button onClick="coinFlip()">Flip</button>
Thank you for reading
coin is a random number the return is not doing what you think.
var coinFlip = function() {
var coin,
chance = Math.random();
if (chance <= 0.5) {
coin = "H";
} else {
coin = "T";
}
document.getElementById("flip").innerHTML = coin;
}
document.getElementById("btn").addEventListener("click", coinFlip);
<div id="flip"></div>
<button id="btn">Flip</button>
Click this link, after around 2 seconds you will see some ships coming at you. Now go to a different window for like 15-20 seconds. then come back, you will see a huge wall of enimes coming at you. Now obviously this is because canvas keeps the loops going but is just not letting the came continue on?
So any help would be great, I know this is not an issue during gameplay but if anyone goes off the window then it kind of messes things up...
I tried to solve this by adding these listeners:
window.onblur = function() {
// Add logic to pause the game here...
stopLoop();
};
window.onfocus = function() {
// Add logic to pause the game here...
startLoop();
};
But it does not solve the issue...
The actual loops:
function init()
{
isPlaying = true;
drawBackground();
drawBars();
setUpListeners();
startLoop();
}
and then...
function Loop()
{
if (isPlaying == true)
{
Player1.draw();
requestAnimFrame(Loop);
drawAllEnemies();
}
}
function startLoop()
{
isPlaying = true;
Loop();
startSpawningEnemies();
}
function stopLoop()
{
isPlaying = false;
stopSpawningEnemies();
}
function spawnEnemy(n) //total enemies starts at 0 and every-time you add to array
{
for (var x = 0; x < n; x++)
{
enemies[totalEnemies] = new Enemy();
totalEnemies++;
}
}
function drawAllEnemies()
{
ClearEnemyCanvas();
for(var i = 0; i < enemies.length; i++)
{
enemies[i].draw();
}
}
function startSpawningEnemies()
{
stopSpawningEnemies();
spawnInterval = setInterval(function() {spawnEnemy(spawnAmount);}, spawnRate); //this calls spawnEnemy every spawnRate
/////////spawn 'spawnAmount' enemies every 2 seconds
}
function stopSpawningEnemies()
{
clearInterval(spawnInterval);
}
Actual methods for the enemy:
function Enemy() //Object
{
//////Your ships values
this.EnemyHullMax = 1000;
this.EnemyHull = 1000;
this.EnemyShieldMax = 1000;
this.EnemyShield = 347;
this.SpaceCrystalReward = 2684;
this.EnemySpeed = 2; //should be around 6 pixels every-time draw is called by interval, directly linked to the fps global variable
////////////
////Pick Ship
this.type = "Hover";
this.srcX = EnemySrcXPicker(this.type);
this.srcY = EnemySrcYPicker(this.type);
this.enemyWidth = EnemyWidthPicker(this.type);
this.enemyHeight = EnemyHeightPicker(this.type);
this.drawX = EnemydrawXPicker(this.type);
this.drawY = EnemydrawYPicker(this.type);
////
}
Enemy.prototype.draw = function()
{
this.drawX -= this.EnemySpeed;
ctxEnemy.globalAlpha=1;
ctxEnemy.drawImage(spriteImage,this.srcX,this.srcY,this.enemyWidth,this.enemyHeight,this.drawX,this.drawY,this.enemyWidth,this.enemyHeight);
}
function EnemySrcXPicker(type)
{
if (type == "Hover")
{
return 906;
}
}
function EnemySrcYPicker(type)
{
if (type == "Hover")
{
return 616;
}
}
function EnemydrawXPicker(type)
{
if (type == "Hover")
{
return Math.floor(Math.random() * 1000) + canvasWidthEnemy;
}
}
function EnemydrawYPicker(type)
{
if (type== "Hover")
{
return Math.floor(Math.random() * (canvasHeightEnemy - 72));
}
}
function EnemyWidthPicker(type)
{
if (type == "Hover")
{
return 90;
}
}
function EnemyHeightPicker(type)
{
if (type == "Hover")
{
return 72;
}
}
Depends on the loop.
If you use setTimeOut or setInterval, then yes. The loop will continue even when the window loses focus.
If you use requestFrameAnimation, then no, the loop will stop when the window loses focus.
requestFrameAnimation was created to solve issues like this. Having you PC burn CPU cycles for something not active is just silly.
I am trying to draw enemy ships to the canvas that will come from the right at a random x being the height of the canvas and a random y past the right side + 1000.
This works fine however I am trying to make it automated and the code runs run it just does not work on screen, only 1 is drawn? Any more info that you need just ask, It's really frying my brain I went line by line for around 3 hours and can't see an issue.
Before I added this code and just called one manually: http://www.taffatech.com/DarkOrbit.html
After I added this code for automatic: (it kinda looks like its overlapping)
http://www.taffatech.com/test.html
Globals:
var spawnInterval;
var totalEnemies = 0; //leave as is
var enemies = []; //array of enemy objects
var spawnRate = 2000; //every 2 seconds
var spawnAmount = 3; //amount of enemies spawned
Then my init() calls a startLoop:
function startLoop()
{
isPlaying = true;
Loop();
startSpawningEnemies();
}
function stopLoop()
{
isPlaying = false;
stopSpawningEnemies();
}
function Loop()
{
if (isPlaying == true)
{
Player1.draw();
requestAnimFrame(Loop);
drawAllEnemies();
}
then they use these functions:
function spawnEnemy(n) //total enemies starts at 0 and every-time you add to array
{
for (var x = 0; x < n; x++)
{
enemies[totalEnemies] = new Enemy();
totalEnemies++;
}
}
function drawAllEnemies()
{
ClearEnemyCanvas();
for(var i = 0; i < enemies.length; i++)
{
enemies[1].draw();
}
}
function startSpawningEnemies()
{
stopSpawningEnemies();
spawnInterval = setInterval(function() {spawnEnemy(spawnAmount);}, spawnRate); //this calls spawnEnemy every spawnRate
/////////spawn 'spawnAmount' enemies every 2 seconds
}
function stopSpawningEnemies()
{
clearInterval(
spawnInterval);
}
which in turn calls the Enemy class:
function Enemy() //Object
{
//////Your ships values
this.EnemyHullMax = 1000;
this.EnemyHull = 1000;
this.EnemyShieldMax = 1000;
this.EnemyShield = 347;
this.SpaceCrystalReward = 2684;
this.EnemySpeed = 2; //should be around 6 pixels every-time draw is called by interval, directly linked to the fps global variable
////////////
////Pick Ship
this.type = "Hover";
this.srcX = EnemySrcXPicker(this.type);
this.srcY = EnemySrcYPicker(this.type);
this.enemyWidth = EnemyWidthPicker(this.type);
this.enemyHeight = EnemyHeightPicker(this.type);
this.drawX = EnemydrawXPicker(this.type);
this.drawY = EnemydrawYPicker(this.type);
////
}
Enemy.prototype.draw = function()
{
this.drawX -= this.EnemySpeed;
ctxEnemy.globalAlpha=1;
ctxEnemy.drawImage(spriteImage,this.srcX,this.srcY,this.enemyWidth,this.enemyHeight,this.drawX,this.drawY,this.enemyWidth,this.enemyHeight);
}
function EnemySrcXPicker(type)
{
if (type == "Hover")
{
return 906;
}
}
function EnemySrcYPicker(type)
{
if (type == "Hover")
{
return 616;
}
}
function EnemydrawXPicker(type)
{
if (type == "Hover")
{
return Math.floor(Math.random() * 1000) + canvasWidthEnemy;
}
}
function EnemydrawYPicker(type)
{
if (type== "Hover")
{
return Math.floor(Math.random() * (canvasHeightEnemy - 72));
}
}
function EnemyWidthPicker(type)
{
if (type == "Hover")
{
return 90;
}
}
function EnemyHeightPicker(type)
{
if (type == "Hover")
{
return 72;
}
}
for(var i = 0; i < enemies.length; i++)
{
enemies[1].draw();
}
should probably be
for(var i = 0; i < enemies.length; i++)
{
enemies[i].draw();
}
...or you'll draw the same enemy over and over.
In your drawAllEnemies function, shouldn't
enemies[1].draw();
be
enemies[i].draw();
?
When you loop the enemies array you should use the index i that you setup so that it doesn't continually draw the same element:
for(var i = 0; i < enemies.length; i++)
{
enemies[i].draw();
}