Skip to content

Instantly share code, notes, and snippets.

@risc12
Created October 11, 2019 08:15
Show Gist options
  • Save risc12/a516c522c18a2ee2a309588d2e73795e to your computer and use it in GitHub Desktop.
Save risc12/a516c522c18a2ee2a309588d2e73795e to your computer and use it in GitHub Desktop.
xxxGmPO
<div class="goals">
<div class="goal goal-red" data-goal="red" ></div>
<div class="goal goal-green" data-goal="green"></div>
<div class="goal goal-blue" data-goal="blue"></div>
<div class="goal goal-yellow" data-goal="yellow"></div>
</div>
<div class="start" onClick="start()">START</div>
<h1 id="score"></h1>
<div class="track"></div>
/*
* TODO:
* - Actual Styling
* - Endgame (based on errors and misses?)
* - Speed up game over time?
*
*/
const start = () => {
sideEffects.startButton.remove();
sideEffects.scoreDisplay.render(0);
roundOfGameLoop();
}
const levelTimeDecrease = {
0: 1,
1: 500,
2: 600,
3: 700,
4: 800,
5: 1000,
6: 1200
}
const roundOfGameLoop = () => {
const generatedLetter = sideEffects.track.addLetter(gameState.getNextGoal());
setTimeout(() => {
if(generatedLetter.parentNode) {
sideEffects.letter(generatedLetter).remove();
}
}, 4000)
setTimeout(() => {
roundOfGameLoop()
}, 2000 - (levelTimeDecrease[Math.floor(gameState.score/10)] || 1300));
}
const goals = document.querySelectorAll('.goal');
const track = document.querySelector('.track');
const scoreDisplay = document.querySelector('#score');
const startButton = document.querySelector('.start');
const gameState = {
score: 0,
currentLetter: undefined,
availableGoals: ['red', 'green', 'blue', 'yellow'],
getNextGoal: () => {
const randomIndex = Math.floor(Math.random() * gameState.availableGoals.length);
return gameState.availableGoals[randomIndex];
},
incrementScore: () => {
gameState.score = gameState.score + 1;
return gameState.score;
},
};
const sideEffects = {
scoreDisplay: {
render: score => scoreDisplay.innerHTML = `Score: ${score} Level: ${Math.floor(score/10)}`
},
track: {
addLetter: expectedGoal => {
const newLetter = document.createElement('div');
newLetter.setAttribute('data-goal', expectedGoal);
newLetter.innerHTML = expectedGoal;
newLetter.classList.add('letter');
newLetter.draggable = true;
track.appendChild(newLetter);
return newLetter;
},
},
letter: element => ({
freeze: touchPoint => {
element.style.opacity = '0.001';
element.style.left = `${Math.floor(element.getBoundingClientRect().left)}px`;
element.classList.add('dragging');
},
remove: () => element.parentNode.removeChild(element)
}),
startButton: {
remove: () => startButton.parentNode.removeChild(startButton)
}
};
const handlers = {
letter: {
dragStart: e => {
if (!e.target.classList.contains("letter")) return;
gameState.currentLetter = e.target;
sideEffects.letter(gameState.currentLetter).freeze(e.x);
e.dataTransfer.effectAllowed = 'move';
e.dataTransfer.setData("text", gameState.currentLetter.getAttribute('data-goal'));
},
},
goal: {
dragOver: e => e.preventDefault(),
dragEnter: e => e.target.classList.add("over"),
dragLeave: e => e.target.classList.remove("over"),
drop: e => {
const expectedGoal = e.dataTransfer.getData("text");
const actualGoal = e.target.getAttribute('data-goal');
if(expectedGoal === actualGoal) {
sideEffects.scoreDisplay.render(gameState.incrementScore());
}
e.target.classList.remove("over");
sideEffects.letter(gameState.currentLetter).remove();
gameState.currentLetter = undefined;
}
}
};
document.addEventListener("dragstart", handlers.letter.dragStart);
goals.forEach(goal => {
goal.addEventListener("dragenter", handlers.goal.dragEnter, false);
goal.addEventListener("dragover", handlers.goal.dragOver, false);
goal.addEventListener("dragleave", handlers.goal.dragLeave, false);
goal.addEventListener("drop", handlers.goal.drop, false);
});
<script src="https://cdn.jsdelivr.net/gh/Bernardo-Castilho/dragdroptouch@master/DragDropTouch.js"></script>
h1 {
color: white;
text-align: center;
font-family: 'Helvetica Neue', sans-serif;
}
body {
width: 100vw;
height: 100vh;
background-color: #333;
margin: 0;
padding: 0;
overflow: hidden;
font-family: sans-serif;
}
.goals {
display: flex;
width: 100%;
height: 200px;
}
.goal {
width: 100%;
height: 100%;
}
.goal-red { background-color: red; }
.goal-green { background-color: green; }
.goal-blue { background-color: blue; }
.goal-yellow { background-color: yellow; }
.over {
opacity: 0.2;
}
.track {
padding-top: 15px;
position: absolute;
bottom: 50px;
height: 200px;
width: 100%;
background-color: black;
}
.letter {
text-align: center;
background-color: #ccc;
width: 200px;
height: 75px;
position: absolute;
padding: 15px;
font-weight: 800;
font-size: 2em;
text-transform: uppercase;
}
.letter:not(.dragging) {
animation-duration: 4s;
animation-name: moving;
}
.start {
width: 200px;
margin-left: auto;
margin-right: auto;
background-color: orange;
text-align: center;
padding: 15px;
box-shadow: 0 0 5px black;
margin-top: 25px;
font-weight: 800;
}
.start:hover {
opacity: 0.8;
cursor: pointer;
}
@keyframes moving {
from {
left: -10%;
}
to {
left: 110%;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment