Created a simple math (addition/subtraction) game to practice my JavaScript. Any feedback on the JavaScript appreciated.
Can play in: CodePen
Instructions: A math equation will show up and simply press the corresponding number on your keyboard to answer. Speed game so no need to press enter or anything, but also means no deleting/going back if press wrong key.
Note: The formula to create the equation could be easily change to make different levels. I made it simple to understand/program. This one allows for subtracting a negative number, which people have complained about, and I could easily prevent but I like the extra layer.
// set HTML shortcut variables
const startButton = document.getElementById('start');
const questionDiv = document.getElementById('question');
const score = document.getElementById('score');
const red = document.getElementById('red-light');
const green = document.getElementById('green-light');
const timer = document.getElementById('timer');
const slideDiv = document.getElementById('timer-slide');
const timerLabel = document.getElementById('timer-label');
// helper functions
function setHTML(el, text){
el.innerHTML = text;
}
function light(light){
window.clearTimeout(reset);
red.style.background = "black";
green.style.background = "black";
if (light === "red") red.style.background = "white";
if (light === "green") green.style.background = "white";
reset = setTimeout(resetLights, 500);
}
let reset;
function resetLights(){
light("");
}
function slide(bool){
if(bool){
slideDiv.classList.add('slid-up');
} else {
slideDiv.classList.remove('slid-up');
// slideDiv.style.webkitTransform = "translateY(0)";
}
}
// listener functions
document.addEventListener('keypress', (event) => {
const keyName = event.key;
const number = parseInt(keyName);
if (isNaN(number)) return;
ob.enteredAnswer = number;
ob.checkAnswer();
});
startButton.addEventListener('click', (event) => {
ob.start();
});
// create Object
const ob = new Object;
ob.score = 0;
ob.inProgress = false;
ob.countDown = false;
ob.countDownStart = Date.now();
ob.startTime = Date.now();
// Object Methods
ob.start = function(){
if (ob.inProgress) return;
if (ob.countDown) return;
setHTML(timerLabel, "Starting in");
slide(false);
ob.countDownStart = Date.now();
ob.countDown = true;
}
ob.begin = function(){
if (ob.inProgress) return;
ob.score = 0;
setHTML(score, ob.score);
ob.countDown = false;
ob.startTime = Date.now()
ob.inProgress = true;
ob.newQuestion();
}
ob.newQuestion = function(){
const a = Math.floor(Math.random() * 10);
const r1 = Math.floor(Math.random() * 10);
const r2 = Math.floor(Math.random() * 10);
const r3 = r1 + r2 - a;
const string = `${r1} + ${r2} - ${r3}`;
this.correctAnswer = a;
setHTML(questionDiv, string);
}
ob.checkAnswer = function(){
if (!ob.inProgress) return;
if (ob.correctAnswer === ob.enteredAnswer){
// setHTML(result, "Correct!");
light("green");
ob.scoreChange(100);
} else {
// setHTML(result, "Incorrect!");
ob.scoreChange(-50);
light("red");
}
ob.newQuestion();
}
ob.scoreChange = function(change){
ob.score += change;
setHTML(score, ob.score);
}
ob.end = function(){
ob.inProgress = false;
setHTML(questionDiv, "");
slide(true);
}
// Timer functions
function checkTimers(){
if (ob.countDown){
const diff = 3 - Math.floor((Date.now() - ob.countDownStart) / 1000);
if (diff > 0){
setHTML(timer, diff);
} else {
ob.begin();
}
}
if (ob.inProgress){
const diff = 15 - Math.floor((Date.now() - ob.startTime) / 1000);
if (diff > -1){
setHTML(timerLabel, "Remaining");
setHTML(timer, diff);
} else {
ob.end();
}
}
}
setInterval(checkTimers, 100);
body{
display: flex;
flex-flow: column;
justify-content: center;
align-items: center;
text-align: center;
min-height: 70vh;
background: #1d1f20;
color:white;
}
div{
display: flex;
justify-content: center;
align-items: center;
flex-flow: column nowrap;
}
section{
border: 2px solid white;
}
section > div{
margin: 5px;
height: 4em;
width: 10em;
border-radius: 5px;
}
.score-container{
background: #568bbd;
}
div.problem{
background: #86b38a;
}
p.main{
font-size: 1.4rem;
margin: 5px;
}
p.label{
font-size: 0.8rem;
margin: 2px;
}
.lights{
flex-flow: row nowrap;
}
.light{
height: 20px;
width: 20px;
border-radius: 50%;
margin: 5px;
}
#green-light::after{
content: '';
width: 100%;
height: 100%;
background: #00ff00aa;
border-radius: 50%;
position: relative;
z-index: 2;
}
#red-light::after{
content: '';
width: 100%;
height: 100%;
background: #ff0000aa;
border-radius: 50%;
position: relative;
z-index: 2;
}
.white{
background: white;
}
button{
border: 2px solid #42964c;
background-color: #86b38a;
color: white;
border-radius: 10px;
padding: 0.5em;
font-size: 1.4rem;
cursor: pointer;
box-shadow: 0 5px 0 #42964c;
transition-duration: 0.2s;
text-shadow: 2px 2px 0 #42964c;
outline: 0;
}
button:hover{
transform: translateY(5px);
box-shadow: 0 0 0 #42964c;
}
button:active{
transform: scale(0.8);
}
.slide-container{
position: relative;
overflow: hidden;
}
.slide-cover{
position: absolute;
height: 100%;
width: 100%;
top: 0;
left: 0;
transition-duration: 0.2s;
transform: translateY(0);
}
.slid-up{
transform: translateY(-120%);
}
#timer-slide{
background: #d0782a;
}
<section>
<div class='start-container slide-container'>
<button id="start">START</button>
<div id="timer-slide" class='timer slide-cover slid-up'>
<p id="timer-label" class='label'>Timer</p>
<p id="timer" class='main'></p>
</div>
</div>
<div class='problem'>
<p class='label'>PROBLEM</p>
<p id="question" class='main'></p>
</div>
<div class='lights'>
<div id='green-light' class='light'></div>
<div id='red-light' class='light'></div>
</div>
<div class='score-container'>
<p class='label'>SCORE</p>
<p id="score" class='main'></p>
</div>
</section>
<p class='label'>(Use Numbers on Keyboard)</p>
Feel free to fork and add to it!