PUZZLE TROUBLE - trying to save initial board [closed] - javascript

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 8 years ago.
Improve this question
I wrote this Javascript application for a 15-puzzle. The entire application is contained in the file below. Whenever I render a new board, I'm trying to store the initial configuration in the initialBoard variable so I can replay the same game later. However, initialBoard variable always seems to equal the currentBoard variable. I'm new to Javascript and any help will be greatly appreciated.
<html>
<head>
<title>15 Puzzle</title>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap.min.css">
<style type="text/css">
#puzzle-board {
border: 5px solid;
}
.puzzle-tile {
background:#fff;
background: -moz-linear-gradient(top, #fff, #eee);
background: -webkit-gradient(linear,0 0, 0 100%, from(#fff), to(#eee));
box-shadow: inset 0 0 0 1px #fff;
-moz-box-shadow: inset 0 0 0 1px #fff;
-webkit-box-shadow: inset 0 0 0 1px #fff;
font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
font-size:60px;
height: 100px;
text-align: center;
text-decoration: none;
text-shadow:0 1px #fff;
user-select: none;
-moz-user-select: none;
-webkit-user-select: none;
-ms-user-select: none;
vertical-align:middle;
width: 100px;
}
#start-stop {
float: left;
}
#timer {
float: left;
margin-left: 10px;
}
#counter {
float: left;
margin-left: 10px;
}
</style>
</head>
<body>
<div class="container-fluid">
<div class="row">
<br />
</div>
<div class="row">
<div class="col-md-5 col-md-offset-1">
<table id="puzzle"></table>
</div>
<div class="col-md-6">
<div class="row">
<br />
<button type="button" class="btn btn-lg btn-success" id="start-stop">START</button>
<button type="button" class="btn btn-lg btn-default" id="timer"></button>
<button type="button" class="btn btn-lg btn-default" id="counter"></button>
</div>
</div>
</div>
</div>
<script src="http://code.jquery.com/jquery-1.11.0.min.js"></script>
<script src="http://code.jquery.com/ui/1.11.1/jquery-ui.min.js"></script>
<!--<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.2.0/js/bootstrap.min.js"></script>-->
<script>
/**
* Puzzle Object
*/
puzzle = function(targetId) {
/************************************************************
* Private members
************************************************************/
var
currentBoard,
initialBoard,
orderedBoard = [[1,2,3,4],[5,6,7,8],[9,10,11,12],[13,14,15,'']];
function canSwapTiles(source, target) {
var sourceTileRow = source.attr("data-row");
var sourceTileCol = source.attr("data-col");
var sourceTileValue = source.text();
var targetTileRow = target.attr("data-row");
var targetTileCol = target.attr("data-col");
var targetTileValue = target.text();
if (sourceTileValue != '' && targetTileValue != '') {
return false;
} else if (Math.abs(targetTileRow - sourceTileRow) > 1) {
return false;
} else if (Math.abs(targetTileCol - sourceTileCol) > 1) {
return false;
} else {
return true;
}
}
function swapTiles(source, target) {
var sourceTileRow = source.attr("data-row");
var sourceTileCol = source.attr("data-col");
var sourceTileValue = source.text();
var targetTileRow = target.attr("data-row");
var targetTileCol = target.attr("data-col");
var targetTileValue = target.text();
source.text(targetTileValue);
currentBoard[sourceTileRow][sourceTileCol] = parseInt(targetTileValue);
target.text(sourceTileValue);
currentBoard[targetTileRow][targetTileCol] = parseInt(sourceTileValue);
$(targetId).trigger('moved');
console.log("swapped tiles");
console.log(initialBoard);
if (isSolved())
{
console.log('solved puzzle');
console.log(initialBoard);
$(targetId).trigger('solved', {
board: initialBoard
});
}
}
function renderBoard(board) {
$("#puzzle-board").empty();
currentBoard = board;
//initialBoard = board;
console.log('rendering board');
console.log(initialBoard);
for (i = 0; i < 4; i++) {
$("#puzzle-board").append('<tr class="puzzle-row" id="puzzle-row-' + i + '"></tr><br />');
for (j = 0; j < 4; j++) {
var tile = '<td class="puzzle-tile" data-row="' + i + '" data-col="' + j + '">' +
board[i][j] +
'</td>';
$("#puzzle-row-" + i).append(tile);
}
}
$(".puzzle-tile").draggable(
{
revert: true,
snap: true,
snapMode: "inner",
zIndex: 100
}
).droppable(
{
drop: function (event, ui) {
var sourceTile = ui.draggable;
var targetTile = $(this);
if (canSwapTiles(sourceTile, targetTile)) {
swapTiles(sourceTile, targetTile);
}
}
}
);
}
function randomBoard() {
var tileValues = [];
for (i = 0; i < 15; i++) {
tileValues[i] = i + 1;
}
var randomlyOrderedTileValues = [''];
do {
randomlyOrderedTileValues[(16 - tileValues.length)] = tileValues.splice(Math.floor(Math.random() * tileValues.length), 1).pop();
} while (tileValues.length > 0);
var board = [];
for (i = 0; i < 4; i++) {
board[i] = [];
for (j = 0; j < 4; j++) {
board[i][j] = randomlyOrderedTileValues.pop();
}
}
return board;
}
function isSolved() {
for (i = 0; i < 4; i++) {
for (j = 0; j < 4; j++) {
if (isNaN(currentBoard[i][j]))
{
continue;
}
if (parseInt(currentBoard[i][j]) != parseInt(orderedBoard[i][j]))
{
return false;
}
}
}
return true;
}
/************************************************************
* Constructor
************************************************************/
/*
* Initialize board
*/
$(targetId).append('<tbody id="puzzle-board"></tbody>');
renderBoard(orderedBoard);
/************************************************************
* Public data and methods
************************************************************/
return {
reset: function() {
renderBoard(orderedBoard);
},
shuffle: function() {
//initialBoard = randomBoard();
initialBoard = [[1,2,3,4],[5,6,7,8],[9,10,11,12],[13,14,'',15]];
renderBoard(initialBoard);
}
}
};
/**
* Timer Object
*/
timer = function(targetId) {
/************************************************************
* Private members
************************************************************/
var
intervalId,
totalSeconds = 0;
function pad(val) {
var valString = val + "";
if (valString.length < 2) {
return "0" + valString;
} else {
return valString;
}
}
function setTime()
{
++totalSeconds;
$("#seconds").html(pad(totalSeconds % 60));
$("#minutes").html(pad(parseInt(totalSeconds / 60)));
}
/************************************************************
* Constructor
************************************************************/
/*
* Initialize timer
*/
$(targetId).append('<i>Time: </i><i id="minutes">00</i>:<i id="seconds">00</i>');
/************************************************************
* Public data and methods
************************************************************/
return {
reset: function() {
window.clearInterval(intervalId);
totalSeconds = 0;
$("#minutes").text('00');
$("#seconds").text('00');
},
start: function () {
intervalId = window.setInterval(setTime, 1000);
},
getTime: function () {
return pad(parseInt(totalSeconds / 60)) + ':' + pad(totalSeconds % 60);
}
}
};
/**
* Counter Object
*/
counter = function(targetId) {
/************************************************************
* Private members
************************************************************/
var
steps = 0;
/************************************************************
* Constructor
************************************************************/
/*
* Initialize timer
*/
$(targetId).append('<i id="steps-title">Steps: </i><i id="steps-count">0</i>');
/************************************************************
* Public data and methods
************************************************************/
return {
reset: function() {
steps = 0;
$("#steps-count").text(steps);
},
incr: function () {
steps++;
$("#steps-count").text(steps);
},
getSteps: function () {
return steps;
}
}
};
$(document).ready(function() {
var Puzzle = puzzle("#puzzle");
var Timer = timer("#timer");
var Counter = counter("#counter");
localStorage["games"] = '[]';
$("#start-stop").click(function() {
switch ($(this).text()) {
case 'START':
$(this).removeClass("btn-success").addClass("btn-danger").text("STOP");
Puzzle.shuffle();
Timer.start();
Counter.reset();
break;
case 'STOP':
$(this).removeClass("btn-danger").addClass("btn-success").text("START");
Puzzle.reset();
Timer.reset();
Counter.reset();
break;
}
});
$("#puzzle").bind('moved',
function(e, data) {
Counter.incr();
}
).bind('solved',
function(e, data) {
console.log(data);
$("#start-stop").removeClass("btn-danger").addClass("btn-success").text("START");
Puzzle.reset();
Timer.reset();
Counter.reset();
}
);
});
</script>
</body>

When you invoke the Puzzle.shuffle() here:
$("#start-stop").click(function() {
switch ($(this).text()) {
case 'START':
$(this).removeClass("btn-success").addClass("btn-danger").text("STOP");
Puzzle.shuffle();
Timer.start();
Counter.reset();
break;
case 'STOP':
$(this).removeClass("btn-danger").addClass("btn-success").text("START");
Puzzle.reset();
Timer.reset();
Counter.reset();
break;
}
});
It initializes the board and passes it to renderBoard here
shuffle: function() {
//initialBoard = randomBoard();
initialBoard = [[1,2,3,4],[5,6,7,8],[9,10,11,12],[13,14,'',15]];
renderBoard(initialBoard);
}
Then renderBoard does this:
currentBoard = board;
Which causes both variables point to the same object. If you want them to be separated, then in renderBoard you should clone the object, instead of assigning it. Something along the lines of this if you use jQuery:
currentBoard = [];
$.extend(currentBoard, board);

Related

How to save time value in dynamically created li to input box with javascript

How to save a time value in dynamically created li to input box with javascript
I have a simple timer, that starts, stops, pauses, takes a time snap and resets the time snap.
The timesnap in generated and displayed in the webpage inside a li. It all works fine what I am struggling with is trying to click on a displayed time snap and have the value placed in an input box so I can later save a selected value to a database.
This is the script I am using to place the clicked on li item into the input box
var items = document.querySelectorAll("#list li");
for (var i = 0; i < items.length; i++) {
items[i].onclick = function () {
document.getElementById("inptSnap").value = this.innerHTML;
};
}
This is the html
<div class="container">
<!-- Different App -->
<div class="timeDisplay">00:00:00</div>
<button id="begin">Start</button>
<button id="hold">Pause</button>
<button id="end">Stop</button>
<button id="timeSnap">Time Snap</button>
<button id="resetSnap">Reset Time Snap</button>
<ul id="list" class="laps"></ul>
<div>
<input type="text" id="inptSnap" />
</div>
</div>
This is the full timer script with the attempted select value onclick
var begin = document.getElementById("begin");
begin.addEventListener("click", start);
var end = document.getElementById("end");
end.addEventListener("click", stop);
var hold = document.getElementById("hold");
hold.addEventListener("click", pause);
var timeSnap = document.getElementById("timeSnap");
timeSnap.addEventListener("click", snap);
var timeSnap = document.getElementById("timeSnap");
timeSnap.addEventListener("click", pause);
var resetSnap = document.getElementById("resetSnap");
resetSnap.addEventListener("click", resetSnaps);
var ms = 0,
s = 0,
m = 0;
var timeCounter;
var displayEl = document.querySelector(".timeDisplay");
var lapsContainer = document.querySelector(".laps");
function start() {
if (!timeCounter) {
timeCounter = setInterval(run, 10);
}
}
function run() {
displayEl.textContent = displayTimeCount();
ms++;
if (ms == 100) {
ms = 0;
s++;
}
if (s == 60) {
s = 0;
m++;
}
}
function stop() {
stopTimer();
ms = 0;
s = 0;
m = 0;
displayEl.textContent = displayTimeCount();
}
function stopTimer() {
clearInterval(timeCounter);
timeCounter = false;
}
function pause() {
stopTimer();
}
function displayTimeCount() {
return (
(m < 10 ? "0" + m : m) +
":" +
(s < 10 ? "0" + s : s) +
":" +
(ms < 10 ? "0" + ms : ms)
);
}
function snap() {
if (timeCounter) {
var li = document.createElement("li");
li.innerText = displayTimeCount();
lapsContainer.appendChild(li);
}
}
function resetSnaps() {
lapsContainer.innerHTML = "";
}
// Script to put lap into input box
var items = document.querySelectorAll("#list li");
for (var i = 0; i < items.length; i++) {
items[i].onclick = function () {
document.getElementById("inptSnap").value = this.innerHTML;
};
}
This is the CodePen Link
I would be very grateful for any pointers and advice, thanks
You can do somthing like that...
PS: I think that the ergonomics of your button is to be reviewed, I did a kind of revision.
const
btStartPause = document.querySelector('#container button:nth-of-type(1)')
, btStopClear = document.querySelector('#container button:nth-of-type(2)')
, btSnap = document.querySelector('#container button:nth-of-type(3)')
, snapList = document.querySelector('ol')
, inptSnap = document.querySelector('input#inptSnap')
, chrono = ((dZTime='#container time') =>
{
const
displZone = document.querySelector(dZTime)
, chronoZero = '00:00:00.000'
, one_Sec = 1000
//, one_Min = one_Sec * 60
//, one_Hrs = one_Min * 60
, n_Dgts = (n,t) => `${t}`.padStart(n,'0')
;
let startTime = null
, timeElapsed = 0
, pausedTime = 0
, reqRef = null
, reqPause = false
, stoped = false
;
displZone.textContent = chronoZero
function reqLoop(timeStamp) // timeStamp is float
{
startTime ??= timeStamp // Logical nullish assignment (??=)
if (stoped)
{
cancelAnimationFrame(reqRef)
return
}
if (reqPause)
{
pausedTime = (timeStamp - startTime) - timeElapsed;
}
else
{
timeElapsed = ((timeStamp - startTime) - pausedTime) | 0 // get integer part of float
let
Tms = timeElapsed % one_Sec
, tim = (timeElapsed - Tms) / one_Sec
, T_s = tim % 60
, T_m = 0
, T_h = 0
;
tim = (tim - T_s) / 60
T_m = tim % 60
T_h = (tim - T_m) / 60
displZone.textContent = `${n_Dgts(2,T_h)}:${n_Dgts(2,T_m)}:${n_Dgts(2,T_s)}.${n_Dgts(3,Tms)}`
}
requestAnimationFrame( reqLoop )
}
const jso =
{ dispSz: chronoZero.length
, getVal: ()=> displZone.textContent
, start() { reqRef = requestAnimationFrame(reqLoop) }
, pause(OnOff) { reqPause = OnOff }
, stop() { stoped = true }
, RaZ()
{
startTime = null
timeElapsed = 0
pausedTime = 0
reqRef = null
reqPause = false
stoped = false
displZone.textContent = chronoZero
}
}
Object.freeze(jso)
return jso
})()
;
btStartPause.onclick =_=>
{
if (btStartPause.classList.toggle('pause') )
{
btStopClear.disabled = false
if ( btStartPause.dataset.lib !== 'continue' )
{
btStartPause.dataset.lib = 'continue'
chrono.start()
}
else
chrono.pause(false)
}
else
{
btStopClear.disabled = true
btStopClear.classList.remove('clear')
chrono.pause(true)
}
}
btStopClear.onclick =_=>
{
if (btStopClear.classList.toggle('clear') )
{
btStartPause.disabled = true
btStartPause.dataset.lib = 'start'
btStartPause.classList.remove('pause')
chrono.stop()
}
else
{
btStartPause.disabled = false
btStopClear .disabled = true
chrono.RaZ()
}
}
btSnap.onclick =_=>
{
snapList
.appendChild( document.createElement('li'))
.innerHTML = chrono.getVal()
+ '<span title="delete"> ✖ </span>'
+ '<span title="copy"> &#x2398 </span>'
}
snapList.onclick =({target}) =>
{
if (!target.matches('li > span'))
{
inptSnap.value = target.closest('li').textContent.substring(0, chrono.dispSz)
inptSnap.focus()
return
}
if (target.matches('span[title=delete]'))
{
target.closest('li').remove()
}
if (target.matches('span[title=copy]'))
{
let origin = target.closest('li')
copySomething ( origin.textContent.substring(0, chrono.dispSz), origin )
}
}
async function copySomething(toCopy, el )
{
try
{
await navigator.clipboard.writeText(toCopy);
el.classList.add('copyOK')
setTimeout(() => { el.classList.remove('copyOK')}, 1200);
}
catch (err)
{
el.classList.add('copyBad')
setTimeout(() => { el.classList.remove('copyBad')}, 1200);
console.error('Failed to copy :/', err);
}
}
body {
font-family : Arial, Helvetica, sans-serif;
font-size : 16px;
}
time {
display : block;
font-size : 1.4rem;
margin : .6rem 1rem;
letter-spacing : .2rem;
}
ol {
list-style : none;
font-size : 1.6rem;
padding : 0;
margin : 1.5rem;
width : 15rem;
list-style-type: decimal;
}
li {
border : 1px solid lightblue;
padding : .3rem .6rem;
position : relative;
cursor : pointer;
}
li::marker {
font-size : .9rem;
color : darkslategray;
}
li span {
float : right;
margin : 0 0 0 .3em;
font-size : 1.2rem;
color : darkslategray;
}
li span[title=delete]:hover {
color : crimson;
}
li span[title=copy]:hover {
background : white;
color : darkblue;
}
#container button {
min-width : 4.4rem;
text-transform : capitalize;
}
#container button:before {
content : attr(data-lib)
}
#container button.pause:before {
content : 'pause'
}
#container button.clear:before {
content : 'clear'
}
li:hover {
background : lightblue;
}
li.copyOK::after,
li.copyBad::after {
position : absolute;
display : block;
font-size : .8rem;
top : 1.2rem;
left : 11rem;
padding : .1rem .2rem;
}
li.copyOK::after {
content : 'copied';
background : lightgreen;
}
li.copyBad::after {
left : 1rem;
content : 'Failed to copy :/';
background : lightcoral;
}
<input type="text" id="inptSnap" >
<hr>
<div id="container">
<time datetime="00:00:00.000">00:00:00.000</time>
<button data-lib="start"><!-- start / continue / pause --></button>
<button data-lib="stop" disabled><!-- stop / clear --></button>
<button>snap</button>
</div>
<ol></ol>
for info :
Fastest way to cast a float to an int in javascript?
So I understand that you need a place value kind of thing.
var begin = document.getElementById("begin");
begin.addEventListener("click", start);
var end = document.getElementById("end");
end.addEventListener("click", stop);
var hold = document.getElementById("hold");
hold.addEventListener("click", pause);
var timeSnap = document.getElementById("timeSnap");
timeSnap.addEventListener("click", snap);
var timeSnap = document.getElementById("timeSnap");
timeSnap.addEventListener("click", pause);
var resetSnap = document.getElementById("resetSnap");
resetSnap.addEventListener("click", resetSnaps);
var ms = 0,
s = 0,
m = 0;
var timeCounter;
var displayEl = document.querySelector(".timeDisplay");
var lapsContainer = document.querySelector(".laps");
function start() {
if (!timeCounter) {
timeCounter = setInterval(run, 10);
}
}
function run() {
displayEl.textContent = displayTimeCount();
ms++;
if (ms == 100) {
ms = 0;
s++;
}
if (s == 60) {
s = 0;
m++;
}
}
function stop() {
stopTimer();
ms = 0;
s = 0;
m = 0;
displayEl.textContent = displayTimeCount();
}
function stopTimer() {
clearInterval(timeCounter);
timeCounter = false;
}
function pause() {
stopTimer();
}
function displayTimeCount() {
return (
(m < 10 ? "0" + m : m) +
":" +
(s < 10 ? "0" + s : s) +
":" +
(ms < 10 ? "0" + ms : ms)
);
}
function snap() {
if (timeCounter) {
var input = document.createElement("input");
input.value = displayTimeCount();
lapsContainer.appendChild(input);
}
}
function resetSnaps() {
lapsContainer.innerHTML = "";
}
// Script to put lap into input box
var items = document.querySelectorAll("#list li");
for (var i = 0; i < items.length; i++) {
items[i].onclick = function () {
document.getElementById("inptSnap").value = this.innerHTML;
};
}
.timeDisplay {
font-size: 32px;
}
ul li {
list-style: none;
font-size: 32px;
}
.container {
width: 400px;
margin: auto;
}
<div class="container">
<!-- Different App -->
<div class="timeDisplay">00:00:00</div>
<button id="begin">Start</button>
<button id="hold">Pause</button>
<button id="end">Stop</button>
<button id="timeSnap">Time Snap</button>
<button id="resetSnap">Reset Time Snap</button>
<ul id="list" class="laps">
</ul>
<div>
<input type="text" id="inptSnap" />
</div>
</div>

Cant figure out how to implement a 3 strike feature in Javascript game

I need to allow the user to make 2 mistakes before they lose the game. I need to:
-Create a global variable to track the number of mistakes
-Initialize that variable during startGame
-Edit the guess function so that it updates the mistake counter when the user makes and mistake, and adds a check of that variable before calling the loseGame function
Im having trouble implementing this into the JS file. How can I do it?
JS File:
const cluePauseTime = 333; //how long to pause in between clues
const nextClueWaitTime = 1000; //how long to wait before starting playback of the clue sequence
//Global variables
var clueHoldTime = 200; //how long to hold each clue's light/sound
// var pattern = [2, 3, 1, 4, 6, 1, 2, 4, 3, 5];
var pattern = [];
var clueLength = 10;
///////////////////////////////
var progress = 0;
var gamePlaying = false;
var tonePlaying = false;
var volume = 0.5;
var guessCounter = 0;
function startGame() {
progress = 0;
pattern = []; // reset so array doesn't get longer then 10 if we restart game
for (var i = 0; i < clueLength; i++) {
pattern.push(getRandomInt(5));
}
console.log("pattern: " + pattern);
gamePlaying = true;
document.getElementById("startBtn").classList.add("hidden");
document.getElementById("stopBtn").classList.remove("hidden");
playClueSequence();
}
function stopGame() {
gamePlaying = false;
document.getElementById("startBtn").classList.remove("hidden");
document.getElementById("stopBtn").classList.add("hidden");
}
function getRandomInt(max) {
return Math.floor(Math.random() * Math.floor(max) + 1);
}
function lightButton(btn) {
document.getElementById("button" + btn).classList.add("lit");
}
function clearButton(btn) {
document.getElementById("button" + btn).classList.remove("lit");
}
function playSingleClue(btn) {
if (gamePlaying) {
lightButton(btn);
playTone(btn, clueHoldTime);
setTimeout(clearButton, clueHoldTime, btn);
}
}
function playClueSequence() {
guessCounter = 0;
let delay = nextClueWaitTime; //set delay to initial wait time
for (let i = 0; i <= progress; i++) {
// for each clue that is revealed so far
console.log("play single clue: " + pattern[i] + " in " + delay + "ms");
setTimeout(playSingleClue, delay, pattern[i]); // set a timeout to play that clue
delay += clueHoldTime;
delay += cluePauseTime;
}
}
function loseGame() {
stopGame();
alert("Game Over. You lost.");
}
function winGame() {
stopGame();
alert("Yayyyyy, you win!!");
}
function guess(btn) {
console.log("user guessed: " + btn);
if (!gamePlaying) {
return;
}
if (pattern[guessCounter] == btn) {
if (guessCounter == progress) {
if (progress == pattern.length - 1) {
winGame();
} else {
progress++;
playClueSequence();
}
} else {
guessCounter++;
}
//guessCounter++;
} else {
loseGame();
}
}
// Sound Synthesis Functions
const freqMap = {
1: 261.6,
2: 329.6,
3: 392,
4: 466.2,
5: 432.8,
6: 336.2
};
function playTone(btn, len) {
o.frequency.value = freqMap[btn];
g.gain.setTargetAtTime(volume, context.currentTime + 0.05, 0.025);
tonePlaying = true;
setTimeout(function() {
stopTone();
}, len);
}
function startTone(btn) {
if (!tonePlaying) {
o.frequency.value = freqMap[btn];
g.gain.setTargetAtTime(volume, context.currentTime + 0.05, 0.025);
tonePlaying = true;
}
}
function stopTone() {
g.gain.setTargetAtTime(0, context.currentTime + 0.05, 0.025);
tonePlaying = false;
}
//Page Initialization
// Init Sound Synthesizer
var context = new AudioContext();
var o = context.createOscillator();
var g = context.createGain();
g.connect(context.destination);
g.gain.setValueAtTime(0, context.currentTime);
o.connect(g);
o.start(0);
HTML:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>Hello!</title>
<!-- import the webpage's stylesheet -->
<link rel="stylesheet" href="/style.css" />
<!-- import the webpage's javascript file -->
<script src="/script.js" defer></script>
</head>
<body>
<h1>Memory Game</h1>
<p>
Welcome to the game that will test your memory!
</p>
<button id="startBtn" onclick="startGame()">
Start
</button>
<button id="stopBtn" class="hidden" onclick="stopGame()">
Stop
</button>
<div id="gameButtonArea">
<button
id="button1"
onclick="guess(1)"
onmousedown="startTone(1)"
onmouseup="stopTone()"
></button>
<button
id="button2"
onclick="guess(2)"
onmousedown="startTone(2)"
onmouseup="stopTone()"
></button>
<button
id="button3"
onclick="guess(3)"
onmousedown="startTone(3)"
onmouseup="stopTone()"
></button>
<button
id="button4"
onclick="guess(4)"
onmousedown="startTone(4)"
onmouseup="stopTone()"
></button>
<button
id="button5"
onclick="guess(5)"
onmousedown="startTone(5)"
onmouseup="stopTone()"
></button>
<button
id="button6"
onclick="guess(6)"
onmousedown="startTone(6)"
onmouseup="stopTone()"
></button>
</div>
</body>
</html>
CSS:
body {
font-family: helvetica, arial, sans-serif;
margin: 2em;
background-color: slategrey;
color: white;
}
h1 {
font-family: verdana, arial, sans-serif;
color: yellow;
}
button {
padding: 15px;
border-radius: 15px;
}
#gameButtonArea > button {
width: 200px;
height: 200px;
margin: 2px;
}
.hidden {
display: none;
}
#button1 {
background: lightgreen;
}
#button1:active,
#button1.lit {
background: green;
}
#button2 {
background: lightblue;
}
#button2:active,
#button2.lit {
background: blue;
}
#button3 {
background: pink;
}
#button3:active,
#button3.lit {
background: red;
}
#button4 {
background: lightyellow;
}
#button4:active,
#button4.lit {
background: yellow;
}
#button5 {
background: lightgray;
}
#button5:active,
#button5.lit {
background: black;
}
#button6 {
background: white;
}
#button6:active,
#button6.lit {
background: purple;
}
Add a variable let lostCount = 0;.
Change guess else block to:
else {
if (lostCount < 2) lostCount++;
else loseGame();
}
const cluePauseTime = 333; //how long to pause in between clues
const nextClueWaitTime = 1000; //how long to wait before starting playback of the clue sequence
//Global variables
var clueHoldTime = 200; //how long to hold each clue's light/sound
// var pattern = [2, 3, 1, 4, 6, 1, 2, 4, 3, 5];
var pattern = [];
var clueLength = 10;
///////////////////////////////
var progress = 0;
var gamePlaying = false;
var tonePlaying = false;
var volume = 0.5;
var guessCounter = 0;
let lostCount = 0;
function startGame() {
progress = 0;
pattern = []; // reset so array doesn't get longer then 10 if we restart game
for (var i = 0; i < clueLength; i++) {
pattern.push(getRandomInt(5));
}
console.log("pattern: " + pattern);
gamePlaying = true;
document.getElementById("startBtn").classList.add("hidden");
document.getElementById("stopBtn").classList.remove("hidden");
playClueSequence();
}
function stopGame() {
gamePlaying = false;
document.getElementById("startBtn").classList.remove("hidden");
document.getElementById("stopBtn").classList.add("hidden");
}
function getRandomInt(max) {
return Math.floor(Math.random() * Math.floor(max) + 1);
}
function lightButton(btn) {
document.getElementById("button" + btn).classList.add("lit");
}
function clearButton(btn) {
document.getElementById("button" + btn).classList.remove("lit");
}
function playSingleClue(btn) {
if (gamePlaying) {
lightButton(btn);
playTone(btn, clueHoldTime);
setTimeout(clearButton, clueHoldTime, btn);
}
}
function playClueSequence() {
guessCounter = 0;
let delay = nextClueWaitTime; //set delay to initial wait time
for (let i = 0; i <= progress; i++) {
// for each clue that is revealed so far
console.log("play single clue: " + pattern[i] + " in " + delay + "ms");
setTimeout(playSingleClue, delay, pattern[i]); // set a timeout to play that clue
delay += clueHoldTime;
delay += cluePauseTime;
}
}
function loseGame() {
stopGame();
alert("Game Over. You lost.");
}
function winGame() {
stopGame();
alert("Yayyyyy, you win!!");
}
function guess(btn) {
console.log("user guessed: " + btn);
if (!gamePlaying) {
return;
}
if (pattern[guessCounter] == btn) {
if (guessCounter == progress) {
if (progress == pattern.length - 1) {
winGame();
} else {
progress++;
playClueSequence();
}
} else {
guessCounter++;
}
//guessCounter++;
} else {
if (lostCount < 2) lostCount++;
else loseGame();
}
}
// Sound Synthesis Functions
const freqMap = {
1: 261.6,
2: 329.6,
3: 392,
4: 466.2,
5: 432.8,
6: 336.2,
};
function playTone(btn, len) {
o.frequency.value = freqMap[btn];
g.gain.setTargetAtTime(volume, context.currentTime + 0.05, 0.025);
tonePlaying = true;
setTimeout(function () {
stopTone();
}, len);
}
function startTone(btn) {
if (!tonePlaying) {
o.frequency.value = freqMap[btn];
g.gain.setTargetAtTime(volume, context.currentTime + 0.05, 0.025);
tonePlaying = true;
}
}
function stopTone() {
g.gain.setTargetAtTime(0, context.currentTime + 0.05, 0.025);
tonePlaying = false;
}
//Page Initialization
// Init Sound Synthesizer
var context = new AudioContext();
var o = context.createOscillator();
var g = context.createGain();
g.connect(context.destination);
g.gain.setValueAtTime(0, context.currentTime);
o.connect(g);
o.start(0);

code does not work outside jsfiddle

There is a jsfiddle code that I'd like to use on my page.
I copied css and put it into <style> tag on my page. Then I separate part that starts with
$(function(){
$('.anyClass').liEqualizer({
and put it into custom.js. And the first part that starts with (function ($) { I put into audio_frequency.js. I added its imports to head tag. The page looks like this
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8"/>
<style>
.sampleWrap {
margin-left: 6%;
margin-top: 5%;
}
.eqCol {
width: 80px;
margin: 0 0 0 2px;
float: left;
}
.eqItem {
height: 20px;
width: 100%;
background: transparent;
margin: 1px 0 0 0;
opacity: 0;
box-shadow: 15px 20px 0px rgba(0,0,0,0.1);
}
.eqCol .eqItem:last-child {
opacity:1 !important
}
</style>
<script src="jquery-3.2.1.slim.min.js"></script>
<script src="audio_frequency.js"></script>
<script src="custom.js"></script>
</head>
<body>
<div class="sampleWrap d-flex">
<div class="anyClass"></div>
<div style="clear:both; padding:15px 0">
<button class="start">start</button>
<button class="stop">stop</button>
</div>
</div>
</div>
</body>
</html>
custom.js looks like this
$(document).ready(function() {
$('.anyClass').liEqualizer({
row:7,
col:20,
speed:20,
freq:400,
on:true
});
$('.start').click(function(){
$('.anyClass').liEqualizer('start');
return false;
})
$('.stop').click(function(){
$('.anyClass').liEqualizer('stop');
return false;
})
});
and audio_frequency looks like this
(function ($) {
var methods = {
init: function (options) {
var p = {
row: 7,
col: 6,
speed: 20,
freq: 400,
on: true
};
if (options) {
$.extend(p, options);
}
var eqWrap = $(this).addClass('eqWrap');
for (c = 0; c < p.col; c++) {
var eqColEl = $('<div>').addClass('eqCol').appendTo(eqWrap);
for(r = 0; r < p.row; r++){
$('<div>').addClass('eqItem').appendTo(eqColEl);
}
}
var
eqCol = $('.eqCol', eqWrap),
eqItem = $('.eqItem', eqWrap),
randomNumber = function (m, n){
m = parseInt(m);
n = parseInt(n);
return Math.floor(Math.random() * (n - m + 1)) + m;
},
eqUp = function(colEl, val) {
var
speed = p.speed,
v = p.row - val,
i = p.row,
j = 0,
flag2 = true,
eachItemUp = function(){
$('.eqItem', colEl).eq(i - 1).nextAll().stop().css({ opacity:'1' });
if ($('.eqItem', colEl).eq(i - 1).css('opacity') == 1) { flag2 = false }
else { flag2 = true }
$('.eqItem', colEl).eq(i - 1).stop(true).animate({ opacity:'1' }, p.speed, function() {
if ($('.eqItem', colEl).index(this) == v) {
if(flag2) {
eqDown(colEl,val);
}
} else {
i--;
j++;
if(i>v){
eachItemUp()
}
}
})
}
eachItemUp()
},
eqDown = function(colEl,val){
var
v = p.row - val,
i = (p.row-val),
j = 0,
speed = p.speed * 2,
eachItemDown = function(){
if (i == (p.row - val)) {
$('.eqItem', colEl).eq(i).animate({ opacity:'0' }, speed * 10)
setTimeout(function() {
i++;
j++;
if(i < p.row){
eachItemDown();
}
}, speed)
} else {
$('.eqItem', colEl).eq(i).animate({ opacity:'0' }, speed, function(){
i++;
j++;
if(i < p.row){
eachItemDown();
}
})
}
}
eachItemDown();
},
eqInterval = function(){
eqCol.each(function(){
eqUp($(this), randomNumber(0, p.row))
})
}
eqInterval()
if (p.on) {
var eqIntervalId = setInterval(eqInterval, p.freq)
$(this).data({
'eqIntId': eqIntervalId,
'eqInt': eqInterval,
'freq': p.freq,
'on': p.on
})
} else {
$(this).data({
'eqIntId':eqIntervalId,
'eqInt':eqInterval,
'freq':p.freq,
'on':p.on
})
}
}, start: function () {
if (!$(this).data('on')) {
$(this).data('eqInt')();
var eqIntervalId = setInterval($(this).data('eqInt'), $(this).data('freq'));
$(this).data ({
'eqIntId':eqIntervalId,
'on':true
})
}
},
stop: function () {
if($(this).data('on')) {
clearInterval($(this).data('eqIntId'));
$('.eqItem', $(this)).animate({opacity:0})
$(this).data({
'on':false
})
}
}
};
$.fn.liEqualizer = function (method) {
if (methods[method]) {
return methods[method].apply(this, Array.prototype.slice.call(arguments, 1));
} else if (typeof method === 'object' || !method) {
return methods.init.apply(this, arguments);
} else {
$.error('Method ' + method + ' in jQuery.liEqualizer does not exist');
}
};
})(jQuery);
But when I load page I get
TypeError: $(...).eq(...).nextAll(...).stop is not a function[Learn More]
What is the problem? Is it trying to evaluate something before all the components are ready on the page?
This $(...).eq(...).nextAll(...).stop error is because of jquery-3.2.1.slim.min.js this ist not complete.
Note:
In the jquery.slim.js, the following functions of code are removed:
jQuery.fn.extend
jquery.fn.load
jquery.each // Attach a bunch of functions for handling common AJAX events
jQuery.expr.filters.animated
ajax settings like jQuery.ajaxSettings.xhr, jQuery.ajaxPrefilter, jQuery.ajaxSetup, jQuery.ajaxPrefilter, jQuery.ajaxTransport,
jQuery.ajaxSetup
xml parsing like jQuery.parseXML,
animation effects like jQuery.easing, jQuery.Animation, jQuery.speedIn the jquery.slim.js, the following function of code are removed:
Here is the complete code, you need jquery lib <script type="text/javascript" src="//code.jquery.com/jquery-1.10.1.js"></script>
<style>
/*Layout css*/
body {
margin: 0;
padding: 20px 10px;
text-align: center
}
.sampleWrap {
height: 290px
}
/*plugin css*/
.eqWrap {
margin: -1px 0 0 -2px;
overflow: hidden;
display: inline-block; //display:inline; //zoom:1;}
.eqCol {
width: 37px;
margin: 0 0 0 2px;
float: left;
}
.eqItem {
height: 10px;
width: 100%;
background: #e7aa3b;
margin: 1px 0 0 0;
opacity: 0
}
.eqCol .eqItem:last-child {
opacity: 1 !important
}
</style>
<script type="text/javascript" src="//code.jquery.com/jquery-1.10.1.js"></script>
<div class="sampleWrap">
<div class="anyClass"></div>
<div style="clear:both; padding:15px 0">
<button class="start">start</button>
<button class="stop">stop</button>
</div>
<div class="anyClass2"></div>
<div style="clear:both; padding:15px 0">
<button class="start2">start</button>
<button class="stop2">stop</button>
</div>
</div>
<script>
/*код плагина*/
(function($) {
var methods = {
init: function(options) {
var p = {
row: 7, //кол-во столбцов
col: 6, //кол-во колонок
speed: 20, //скорость подсветки кубиков
freq: 400, //частота сигнала
on: true //включено по умолчанию (true,false)
};
if (options) {
$.extend(p, options);
}
var eqWrap = $(this).addClass('eqWrap');
for (c = 0; c < p.col; c++) {
var eqColEl = $('<div>').addClass('eqCol').appendTo(eqWrap);
for (r = 0; r < p.row; r++) {
$('<div>').addClass('eqItem').appendTo(eqColEl);
}
}
var
eqCol = $('.eqCol', eqWrap),
eqItem = $('.eqItem', eqWrap),
randomNumber = function(m, n) {
m = parseInt(m);
n = parseInt(n);
return Math.floor(Math.random() * (n - m + 1)) + m;
},
eqUp = function(colEl, val) {
var
speed = p.speed,
v = p.row - val,
i = p.row,
j = 0,
flag2 = true,
eachItemUp = function() {
$('.eqItem', colEl).eq(i - 1).nextAll().stop().css({
opacity: '1'
});
if ($('.eqItem', colEl).eq(i - 1).css('opacity') == 1) {
flag2 = false
} else {
flag2 = true
}
$('.eqItem', colEl).eq(i - 1).stop(true).animate({
opacity: '1'
}, p.speed, function() {
if ($('.eqItem', colEl).index(this) == v) {
if (flag2) {
eqDown(colEl, val);
}
} else {
i--;
j++;
if (i > v) {
eachItemUp()
}
}
})
}
eachItemUp()
},
eqDown = function(colEl, val) {
var
v = p.row - val,
i = (p.row - val),
j = 0,
speed = p.speed * 2,
eachItemDown = function() {
if (i == (p.row - val)) {
$('.eqItem', colEl).eq(i).animate({
opacity: '0'
}, speed * 10)
setTimeout(function() {
i++;
j++;
if (i < p.row) {
eachItemDown();
}
}, speed)
} else {
$('.eqItem', colEl).eq(i).animate({
opacity: '0'
}, speed, function() {
i++;
j++;
if (i < p.row) {
eachItemDown();
}
})
}
}
eachItemDown();
},
eqInterval = function() {
eqCol.each(function() {
eqUp($(this), randomNumber(0, p.row))
})
}
eqInterval()
if (p.on) {
var eqIntervalId = setInterval(eqInterval, p.freq)
$(this).data({
'eqIntId': eqIntervalId,
'eqInt': eqInterval,
'freq': p.freq,
'on': p.on
})
} else {
$(this).data({
'eqIntId': eqIntervalId,
'eqInt': eqInterval,
'freq': p.freq,
'on': p.on
})
}
},
start: function() {
if (!$(this).data('on')) {
$(this).data('eqInt')();
var eqIntervalId = setInterval($(this).data('eqInt'), $(this).data('freq'));
$(this).data({
'eqIntId': eqIntervalId,
'on': true
})
}
},
stop: function() {
if ($(this).data('on')) {
clearInterval($(this).data('eqIntId'));
$('.eqItem', $(this)).animate({
opacity: 0
})
$(this).data({
'on': false
})
}
}
};
$.fn.liEqualizer = function(method) {
if (methods[method]) {
return methods[method].apply(this, Array.prototype.slice.call(arguments, 1));
} else if (typeof method === 'object' || !method) {
return methods.init.apply(this, arguments);
} else {
$.error('Метод ' + method + ' в jQuery.liEqualizer не существует');
}
};
})(jQuery);
/*инициализация плагина*/
$(function() {
$('.anyClass').liEqualizer({
row: 7, //кол-во столбцов
col: 6, //кол-во колонок
speed: 20, //скорость подсветки кубиков
freq: 400, //частота сигнала
on: true //включено по умолчанию (true,false)
});
$('.start').click(function() {
$('.anyClass').liEqualizer('start');
return false;
})
$('.stop').click(function() {
$('.anyClass').liEqualizer('stop');
return false;
})
$('.anyClass2').liEqualizer({
row: 7, //кол-во столбцов
col: 6, //кол-во колонок
speed: 20, //скорость подсветки кубиков
freq: 400, //частота сигнала
on: false //включено по умолчанию (true,false)
});
$('.start2').click(function() {
$('.anyClass2').liEqualizer('start');
return false;
})
$('.stop2').click(function() {
$('.anyClass2').liEqualizer('stop');
return false;
})
});
</script>

Javascript end game when click on image

Hey this is my first time on Stackoverflow!
I am building a small javascript html5 game where you click on objects kind of like whack-a-mole.. The goal is to kill as many "gem green" and " gem blue" as possible in 10 seconds, and when you click on the "gem red".. the game ends and plays a sound.
I got most things to work, except I can't find a way to make the game end when clicking on "gem red".. I have tried lots of functions and listeners.. but to no avail.. can anyone help me figure this out?
Here is the code:
<!DOCTYPE html>
<html lang="en">
<head>
<meta http-equiv="content-type" content="text/html; charset=utf-8">
<title>HTML 5 Gem Game</title>
<meta name="viewport" content="width=device-width, height=device-height, initial-scale=1">
<style>
section#game {
width: 480px;
height: 800px;
max-width: 100%;
max-height: 100%;
overflow: hidden;
position: relative;
background-image: url('img/Splash.png');
position: relative;
color: #ffffff;
font-size: 30px;
font-family: "arial,sans-serif";
}
section#game .score{
display: block;
position: absolute;
top: 10px;
left: 10px;
}
section#game .time{
display: block;
position: absolute;
top: 10px;
right: 10px;
}
section#game .start{
display: block;
padding-top: 40%;
margin: 0 auto 0 auto;
text-align: center;
width: 70%;
cursor: pointer;
}
section#game .start .high-scores{
text-align: left;
}
section#game .gem{
display: block;
position: absolute;
width: 40px;
height: 44px;
cursor: pointer;
}
section#game .gem.green{
background: url('img/Gem Green.png') no-repeat top left;
}
section#game .gem.blue{
background: url('img/Gem Blue.png') no-repeat top left;
}
section#game .gem.red{
background: url('img/Gem Red.png') no-repeat top left;
}
</style>
<script>
function addEvent(element, event, delegate ) {
if (typeof (window.event) != 'undefined' && element.attachEvent)
element.attachEvent('on' + event, delegate);
else
element.addEventListener(event, delegate, false);
}
function Game(){
var game = document.querySelector("section#game");
var score = game.querySelector("section#game span.score");
var high_scores = game.querySelector("section#game ol.high-scores");
var time = game.querySelector("section#game span.time");
var start = game.querySelector("section#game span.start");
function Gem(Class, Value, MaxTTL) {
this.Class = Class;
this.Value = Value;
this.MaxTTL = MaxTTL;
};
var gems = new Array();
gems[0] = new Gem('green', 10, 1.2);
gems[1] = new Gem('blue', 20, 1);
gems[2] = new Gem('red', 50, 0.75);
function Click(event)
{
if(event.preventDefault) event.preventDefault();
if (event.stopPropagation) event.stopPropagation();
else event.cancelBubble = true;
var target = event.target || event.srcElement;
if(target.className.indexOf('gem') > -1){
var value = parseInt(target.getAttribute('data-value'));
var current = parseInt( score.innerHTML );
var audio = new Audio('music/blaster.mp3');
audio.play();
score.innerHTML = current + value;
target.parentNode.removeChild(target);
}
return false;
}
function Remove(id) {
var gem = game.querySelector("#" + id);
if(typeof(gem) != 'undefined')
gem.parentNode.removeChild(gem);
}
function Spawn() {
var index = Math.floor( ( Math.random() * 3 ) );
var gem = gems[index];
var id = Math.floor( ( Math.random() * 1000 ) + 1 );
var ttl = Math.floor( ( Math.random() * parseInt(gem.MaxTTL) * 1000 ) + 1000 ); //between 1s and MaxTTL
var x = Math.floor( ( Math.random() * ( game.offsetWidth - 40 ) ) );
var y = Math.floor( ( Math.random() * ( game.offsetHeight - 44 ) ) );
var fragment = document.createElement('span');
fragment.id = "gem-" + id;
fragment.setAttribute('class', "gem " + gem.Class);
fragment.setAttribute('data-value', gem.Value);
game.appendChild(fragment);
fragment.style.left = x + "px";
fragment.style.top = y + "px";
setTimeout( function(){
Remove(fragment.id);
}, ttl)
}
<!-- parse high score keeper -->
function HighScores() {
if(typeof(Storage)!=="undefined"){
var scores = false;
if(localStorage["high-scores"]) {
high_scores.style.display = "block";
high_scores.innerHTML = '';
scores = JSON.parse(localStorage["high-scores"]);
scores = scores.sort(function(a,b){return parseInt(b)-parseInt(a)});
for(var i = 0; i < 10; i++){
var s = scores[i];
var fragment = document.createElement('li');
fragment.innerHTML = (typeof(s) != "undefined" ? s : "" );
high_scores.appendChild(fragment);
}
}
} else {
high_scores.style.display = "none";
}
}
function UpdateScore() {
if(typeof(Storage)!=="undefined"){
var current = parseInt(score.innerHTML);
var scores = false;
if(localStorage["high-scores"]) {
scores = JSON.parse(localStorage["high-scores"]);
scores = scores.sort(function(a,b){return parseInt(b)-parseInt(a)});
for(var i = 0; i < 10; i++){
var s = parseInt(scores[i]);
var val = (!isNaN(s) ? s : 0 );
if(current > val)
{
val = current;
scores.splice(i, 0, parseInt(current));
break;
}
}
scores.length = 10;
localStorage["high-scores"] = JSON.stringify(scores);
} else {
var scores = new Array();
scores[0] = current;
localStorage["high-scores"] = JSON.stringify(scores);
}
HighScores();
}
}
function Stop(interval) {
clearInterval(interval);
}
this.Start = function() {
score.innerHTML = "0";
start.style.display = "none";
var interval = setInterval(Spawn, 750);
var count = 10;
var counter = null;
function timer()
{
count = count-1;
if (count <= 0)
{
var left = document.querySelectorAll("section#game .gem");
for (var i = 0; i < left.length; i++) {
if(left[i] && left[i].parentNode) {
left[i].parentNode.removeChild(left[i]);
}
}
Stop(interval);
Stop(counter);
time.innerHTML = "Game Over!";
start.style.display = "block";
UpdateScore();
return;
} else {
time.innerHTML = count + "s left";
}
}
counter = setInterval(timer, 1000);
setTimeout( function(){
Stop(interval);
}, count * 1000)
};
addEvent(game, 'click', Click);
addEvent(start, 'click', this.Start);
HighScores();
}
addEvent(document, 'readystatechange', function() {
if ( document.readyState !== "complete" )
return true;
var game = new Game();
});
</script>
</head>
<body>
<div id="page">
<section id="game">
<span class="score">0</span>
<span class="time">0</span>
<span class="start">START!
<ol class="high-scores"></ol>
</span>
</section>
</div>
</body>
</html>
Alessio -
You only need a few minor changes to your code to make it work. The example below should help you get started in the right direction. Good luck.
Changes:
Add an endGame() function and move the stop game logic from the timer() function into it.
Add a line to the click() function to check for red gem clicks.
if (target.className.indexOf('red') > 0) endGame("Red Gem - You win!");
Declare the count, counter, and interval variables at the top of your Game object.
The code below also has a few minor CSS changes used for debugging which you can remove.
<!DOCTYPE html>
<html lang="en">
<head>
<meta http-equiv="content-type" content="text/html; charset=utf-8">
<title>HTML 5 Gem Game</title>
<meta name="viewport" content="width=device-width, height=device-height, initial-scale=1">
<style>
section#game {
width: 480px;
height: 800px;
max-width: 100%;
max-height: 100%;
overflow: hidden;
position: relative;
background-image: url('img/Splash.png');
border: 1px red dotted;
position: relative;
color: red;
font-size: 30px;
font-family: "arial,sans-serif";
}
section#game .score{
display: block;
position: absolute;
top: 10px;
left: 10px;
}
section#game .time{
display: block;
position: absolute;
top: 10px;
right: 10px;
}
section#game .start{
display: block;
padding-top: 40%;
margin: 0 auto 0 auto;
text-align: center;
width: 70%;
cursor: pointer;
}
section#game .start .high-scores{
text-align: left;
}
section#game .gem{
display: block;
position: absolute;
width: 40px;
height: 44px;
cursor: pointer;
}
section#game .gem.green{
background: url('img/Gem Green.png') no-repeat top left;
background-color: green;
}
section#game .gem.blue{
background: url('img/Gem Blue.png') no-repeat top left;
background-color: blue;
}
section#game .gem.red{
background: url('img/Gem Red.png') no-repeat top left;
background-color: red;
}
</style>
<script>
function addEvent(element, event, delegate ) {
if (typeof (window.event) != 'undefined' && element.attachEvent)
element.attachEvent('on' + event, delegate);
else
element.addEventListener(event, delegate, false);
}
function Game(){
var game = document.querySelector("section#game");
var score = game.querySelector("section#game span.score");
var high_scores = game.querySelector("section#game ol.high-scores");
var time = game.querySelector("section#game span.time");
var start = game.querySelector("section#game span.start");
var interval, counter, count;
function Gem(Class, Value, MaxTTL) {
this.Class = Class;
this.Value = Value;
this.MaxTTL = MaxTTL;
};
var gems = new Array();
gems[0] = new Gem('green', 10, 1.2);
gems[1] = new Gem('blue', 20, 1);
gems[2] = new Gem('red', 50, 0.75);
function Click(event)
{
if(event.preventDefault) event.preventDefault();
if (event.stopPropagation) event.stopPropagation();
else event.cancelBubble = true;
var target = event.target || event.srcElement;
if(target.className.indexOf('gem') > -1){
var value = parseInt(target.getAttribute('data-value'));
var current = parseInt( score.innerHTML );
var audio = new Audio('music/blaster.mp3');
audio.play();
score.innerHTML = current + value;
target.parentNode.removeChild(target);
if (target.className.indexOf('red') > 0) endGame("Red Gem - You win!");
}
return false;
}
function Remove(id) {
var gem = game.querySelector("#" + id);
if(typeof(gem) != 'undefined')
gem.parentNode.removeChild(gem);
}
function Spawn() {
var index = Math.floor( ( Math.random() * 3 ) );
var gem = gems[index];
var id = Math.floor( ( Math.random() * 1000 ) + 1 );
var ttl = Math.floor( ( Math.random() * parseInt(gem.MaxTTL) * 1000 ) + 1000 ); //between 1s and MaxTTL
var x = Math.floor( ( Math.random() * ( game.offsetWidth - 40 ) ) );
var y = Math.floor( ( Math.random() * ( game.offsetHeight - 44 ) ) );
var fragment = document.createElement('span');
fragment.id = "gem-" + id;
fragment.setAttribute('class', "gem " + gem.Class);
fragment.setAttribute('data-value', gem.Value);
game.appendChild(fragment);
fragment.style.left = x + "px";
fragment.style.top = y + "px";
setTimeout( function(){
Remove(fragment.id);
}, ttl)
}
<!-- parse high score keeper -->
function HighScores() {
if(typeof(Storage)!=="undefined"){
var scores = false;
if(localStorage["high-scores"]) {
high_scores.style.display = "block";
high_scores.innerHTML = '';
scores = JSON.parse(localStorage["high-scores"]);
scores = scores.sort(function(a,b){return parseInt(b)-parseInt(a)});
for(var i = 0; i < 10; i++){
var s = scores[i];
var fragment = document.createElement('li');
fragment.innerHTML = (typeof(s) != "undefined" ? s : "" );
high_scores.appendChild(fragment);
}
}
} else {
high_scores.style.display = "none";
}
}
function UpdateScore() {
if(typeof(Storage)!=="undefined"){
var current = parseInt(score.innerHTML);
var scores = false;
if(localStorage["high-scores"]) {
scores = JSON.parse(localStorage["high-scores"]);
scores = scores.sort(function(a,b){return parseInt(b)-parseInt(a)});
for(var i = 0; i < 10; i++){
var s = parseInt(scores[i]);
var val = (!isNaN(s) ? s : 0 );
if(current > val)
{
val = current;
scores.splice(i, 0, parseInt(current));
break;
}
}
scores.length = 10;
localStorage["high-scores"] = JSON.stringify(scores);
} else {
var scores = new Array();
scores[0] = current;
localStorage["high-scores"] = JSON.stringify(scores);
}
HighScores();
}
}
function Stop(interval) {
clearInterval(interval);
}
function endGame( msg ) {
count = 0;
Stop(interval);
Stop(counter);
var left = document.querySelectorAll("section#game .gem");
for (var i = 0; i < left.length; i++) {
if(left[i] && left[i].parentNode) {
left[i].parentNode.removeChild(left[i]);
}
}
time.innerHTML = msg || "Game Over!";
start.style.display = "block";
UpdateScore();
}
this.Start = function() {
score.innerHTML = "0";
start.style.display = "none";
interval = setInterval(Spawn, 750);
count = 10;
counter = null;
function timer()
{
count = count-1;
if (count <= 0)
{
endGame();
return;
} else {
time.innerHTML = count + "s left";
}
}
counter = setInterval(timer, 1000);
setTimeout( function(){
Stop(interval);
}, count * 1000)
};
addEvent(game, 'click', Click);
addEvent(start, 'click', this.Start);
HighScores();
}
addEvent(document, 'readystatechange', function() {
if ( document.readyState !== "complete" )
return true;
var game = new Game();
});
</script>
</head>
<body>
<div id="page">
<section id="game">
<span class="score">0</span>
<span class="time">0</span>
<span class="start">START!
<ol class="high-scores"></ol>
</span>
</section>
</div>
</body>
</html>
For starters, you shouldn't include a style sheet and your entire HTML file since neither is relevant and you should use a canvas element instead of this chaotic use of CSS and html elements, which would allow the size of your code to be halved. Furthermore, you should be able to fix this by just changing some global boolean variable to false when the red gem is clicked and when the boolean variable is false (this if statement belongs at the end of your game loop) you call Stop(arg)/clearInterval(arg). Given that your current code doesn't seem to have a global boolean variable indicating game state (using an enumeration would generally be a cleaner solution but a simple boolean seems to suit this case)

Count-up Timer required

I've been wanting to create a timer for my website that countsup, and displays alerts at certain intervals. So like, it starts from 0 and counts upwards when the user pushes a button. From there, it will display a a custom alert at certain intervals... (4 minutes for example)... 45 seconds before that interval, I need the number to change to yellow and 10 seconds before that interval, I need it to change to red... then back to the normal color when it passes that interval.
I've got a basic timer code but I am not sure how to do the rest. I am quite new to this. Any help? Thanks so much in advance.
var pad = function(n) { return (''+n).length<4?pad('0'+n):n; };
jQuery.fn.timer = function() {
var t = this, i = 0;
setInterval(function() {
t.text(pad(i++));
}, 1000);
};
$('#timer').timer();
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id='timer'></div>
You could do something like this
var pad = function (n) {
return ('' + n).length < 4 ? pad('0' + n) : n;
};
jQuery.fn.timer = function () {
var t = this,
i = 0;
setInterval(function () {
t.text(pad(i++));
checkTime(i, t);
}, 1000);
};
$('#timer').timer();
checkTime = function (time, t) {
switch (time -1) {
case 10:
t.css('color','red');
break;
case 20:
t.css('color','yellow');
break;
case 30:
t.css('color','green');
break;
case 40:
t.css('color','black');
break;
default:
}
};
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id='timer'></div>
Something like this should work:
Here is a jsFiddle DEMO
jQuery
$.fn.timer = function (complete, warning, danger) {
var $this = $(this);
var total = 0;
$this.text(total);
var intervalComplete = parseInt(complete, 10);
var intervalWarning = parseInt(intervalComplete - warning, 10);
var intervalDanger = parseInt(intervalComplete - danger, 10);
var clock = setInterval(function () {
total += 1;
$this.text(total);
if (intervalWarning === total) {
// set to YELLOW:
$this.addClass('yellow');
}
if (intervalDanger === total) {
// set to RED:
$this.removeClass('yellow').addClass('red');
}
if (intervalComplete === total) {
// reset:
clearInterval(clock);
$this.removeClass();
alert('COMPLETE!');
}
}, 1000);
};
$(function () {
$('#timer').timer(240, 45, 10);
});
CSS
.red {
background-color: red;
}
.yellow {
background-color: yellow;
}
An additional point:
You should place some error validation within the function to ensure your counter completion time is greater than both the warning and danger time intervals.
You can try something like this:
JSFiddle
This is a pure JS timer code. Also for popup you can use something like Bootbox.js.
Code
function timer() {
var time = {
sec: 00,
min: 00,
hr: 00
};
var finalLimit = null,
warnLimit = null,
errorLimit = null;
var max = 59;
var interval = null;
function init(_hr, _min, _sec) {
time["hr"] = _hr ? _hr : 0;
time["min"] = _min ? _min : 0;
time["sec"] = _sec ? _sec : 0;
printAll();
}
function setLimit(fLimit, wLimit, eLimit) {
finalLimit = fLimit;
warnLimit = wLimit;
errorLimit = eLimit;
}
function printAll() {
print("sec");
print("min");
print("hr");
}
function update(str) {
time[str] ++;
time[str] = time[str] % 60;
if (time[str] == 0) {
str == "sec" ? update("min") : update("hr");
}
print(str);
}
function print(str) {
var _time = time[str].toString().length == 1 ? "0" + time[str] : time[str];
document.getElementById("lbl" + str).innerHTML = _time;
}
function validateTimer() {
var c = "";
var secs = time.sec + (time.min * 60) + (time.hr * 60 * 60);
console.log(secs, finalLimit)
if (secs >= finalLimit) {
stopTimer();
} else if (secs >= errorLimit) {
c = "error";
} else if (secs >= warnLimit) {
c = "warn";
} else {
c = "";
}
var element = document.getElementsByTagName("span");
console.log(element, c)
document.getElementById("lblsec").className = c;
}
function startTimer() {
init();
if (interval) stopTimer();
interval = setInterval(function() {
update("sec");
validateTimer();
}, 1000);
}
function stopTimer() {
window.clearInterval(interval);
}
function resetInterval() {
stopTimer();
time["sec"] = time["min"] = time["hr"] = 0;
printAll();
startTimer();
}
return {
'start': startTimer,
'stop': stopTimer,
'reset': resetInterval,
'init': init,
'setLimit': setLimit
}
};
var time = new timer();
function initTimer() {
time.init(0, 0, 0);
}
function startTimer() {
time.start();
time.setLimit(10, 5, 8);
}
function endTimer() {
time.stop();
}
function resetTimer() {
time.reset();
}
span {
border: 1px solid gray;
padding: 5px;
border-radius: 4px;
background: #fff;
}
.timer {
padding: 2px;
margin: 10px;
}
.main {
background: #eee;
padding: 5px;
width: 200px;
text-align: center;
}
.btn {
-webkit-border-radius: 6;
-moz-border-radius: 6;
border-radius: 6px;
color: #ffffff;
font-size: 14px;
background: #2980b9;
text-decoration: none;
transition: 0.4s;
}
.btn:hover {
background: #3cb0fd;
text-decoration: none;
transition: 0.4s;
}
.warn {
background: yellow;
}
.error {
background: red;
}
<div class="main">
<div class="timer"> <span id="lblhr">00</span>
: <span id="lblmin">00</span>
: <span id="lblsec">00</span>
</div>
<button class="btn" onclick="startTimer()">Start</button>
<button class="btn" onclick="endTimer()">Stop</button>
<button class="btn" onclick="resetTimer()">Reset</button>
</div>
Hope it helps!

Categories