# SimonSays
Simon says is a game of copycat. The pattern becomes more complex with each round.
This module is a work in progress.
To do:- Speed up starting animation
- Animate colored icons
- Adjust copy positioning
- Buttons animate in after game round
# Example
<template>
<SimonSays
:boxes="boxes"
:answerOne="answerOne"
:answerTwo="answerTwo"
:answerThree="answerThree"
:loseOne="loseOne"
:loseTwo="loseTwo"
:loseThree="loseThree"
:simonHeadline="simonHeadline"
:simonContent="simonContent"
/>
</template>
<script>
import SimonSays from '~/components/SimonSays.vue';
export default {
components: {
SimonSays,
},
data() {
return {
simonHeadline: 'Repeat every move',
simonContent:
'Watch the pattern below and see how well you can copy each move. Ready?',
answerOne:
"Nice work. You copied each move just like the little ones around you copy your moves. <br /><span class='test'>Fact:</span> Teens are more likely to smoke cigarettes if their older siblings smoke cigarettes.",
answerTwo:
'You’ve got moves others respect. You copied each move just like the little ones copy what you do. Fact: Teens are more likely to smoke cigarettes if they have friends who smoke cigarettes.',
answerThree:
'You’re on pace to break the cycle. You copied each move just like the little ones copy you. Fact: If smoking continues at this rate, 5.6 million children in the U.S. today will die at a younger age because of smoking.',
loseOne:
'Distractions happen. Next time watch a little closer just like the little ones around you watch your moves closely. Fact: Your younger siblings are more likely to smoke cigarettes if you smoke cigarettes',
loseTwo:
'Nice try. Watch a little closer just like the little ones around you watch your moves closely. Fact: Teens are more likely to smoke cigarettes if they have friends who smoke cigarettes',
loseThree:
'Nice try. Next time follow as closely as little ones do. Fact: If smoking continues at this rate, 5.6 million children in the U.S. today will die at a younger age because of smoking',
boxes: [
{
boxNumber: '0',
image: '/simonsays/siblings.png',
imageAltAttr: 'siblings',
},
{
boxNumber: '1',
image: '/simonsays/friends.png',
imageAltAttr: 'friends',
},
{
boxNumber: '2',
image: '/simonsays/break-the-cycle.png',
imageAltAttr: 'break the cycle',
},
],
};
},
};
</script>
# props
answerOne (Optional) (String) Copy for the correct answer for round one.
answerTwo (Optional) (String) Copy for the correct answer for round two.
answerThree (Optional) (String) Copy for the correct answer for round three.
loseOne (Optional) (String) Copy for the incorrect answer for round one.
loseTwo (Optional) (String) Copy for the incorrect answer for round two.
loseThree (Optional) (String) Copy for the incorrect answer for round three.
image (Optional) (String) icon image.
imageAltAttr (Optional) (String) alt attribute for images.
simonHeadline (Optional) (String) Game headline text.
simonContent (Optional) (String) paragraph content.
boxes (Optional) (Array) Array of objects for icons and their respective content (boxNumber, image,imageAltAttr).
# Source Code
<template>
<div class="container">
<div class="main-simon-wrapper">
<h1 class="simon-headline">{{simonHeadline}}</h1>
<div class="simon-rules">{{simonContent}}</div>
<div class="top-row simon-row">
<div class="box" :id="'box' + box.boxNumber" v-for="(box, index) in boxes" :key="index">
<img :src="box.image" :alt="box.imageAltAttr" />
</div>
</div>
<div id="running-score"></div>
<div id="final-score"></div>
<div id="score-lose"></div>
<div id="score-win"></div>
<div class="button-row">
<div class="button start">
<div>START</div>
</div>
<div class="next">
<div>Next</div>
</div>
<div class="reset">
<div>TRY AGAIN?</div>
</div>
<div class="spacer"></div>
</div>
</div>
</div>
</template>
<style scoped>
.reset {
display: none;
}
.next {
display: none;
}
.shake {
animation: shake 0.5s;
}
@keyframes shake {
0% {
transform: translate(1px, 1px) rotate(0deg);
}
10% {
transform: translate(-1px, -2px) rotate(-1deg);
}
20% {
transform: translate(-3px, 0px) rotate(1deg);
}
30% {
transform: translate(3px, 2px) rotate(0deg);
}
40% {
transform: translate(1px, -1px) rotate(1deg);
}
50% {
transform: translate(-1px, 2px) rotate(-1deg);
}
60% {
transform: translate(-3px, 1px) rotate(0deg);
}
70% {
transform: translate(3px, 1px) rotate(-1deg);
}
80% {
transform: translate(-1px, -1px) rotate(1deg);
}
90% {
transform: translate(1px, 2px) rotate(0deg);
}
100% {
transform: translate(1px, -2px) rotate(-1deg);
}
}
.main-simon-wrapper {
width: 100%;
justify-content: center;
align-items: center;
display: flex;
flex-direction: column;
}
.button-row {
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
}
.container {
display: flex;
flex-direction: column;
flex-wrap: nowrap;
justify-content: center;
align-items: center;
}
.simon-row {
display: flex;
flex-direction: row;
flex-wrap: nowrap;
justify-content: space-around;
align-items: center;
width: 100%;
max-width: 407px;
}
#score-win {
max-width: 407px;
width: 100%;
text-align: center;
display: flex;
justify-content: center;
align-items: center;
flex-direction: column;
}
#score-lose {
max-width: 407px;
width: 100%;
text-align: center;
display: flex;
justify-content: center;
align-items: center;
}
.box {
border-radius: 20px;
height: 90%;
width: 40%;
display: flex;
flex-direction: row;
justify-content: center;
align-items: center;
}
#box0:active {
animation: shake 0.5s;
}
#box1:active {
animation: shake 0.5s;
}
#box2:active {
animation: shake 0.5s;
}
.button:active {
background: rgba(0, 0, 0, 0.5);
}
.spacer {
width: 10%;
}
.button {
display: flex;
justify-content: center;
align-items: center;
background: white;
border-radius: 12px;
height: 90%;
width: 20%;
}
</style>
<script>
export default {
props: {
boxNumber: {
type: String,
required: false
},
answerOne: {
type: String,
required: false
},
answerTwo: {
type: String,
required: false
},
answerThree: {
type: String,
required: false
},
answerThree: {
type: String,
required: false
},
loseOne: {
type: String,
required: false
},
loseTwo: {
type: String,
required: false
},
loseThree: {
type: String,
required: false
},
image: {
type: String,
required: false
},
imageAltAttr: {
type: String,
required: false
},
boxes: {
type: Array,
required: false
},
simonHeadline: {
type: String,
required: false
},
simonContent: {
type: String,
required: false
}
},
data() {
return {
seen: false
};
},
mounted() {
let $vm = this;
const boxes = document.querySelectorAll(".box"); //array of all the divs with a class of .box
const start = document.querySelector(".start"); //selecting the start button
const reset = document.querySelector(".reset"); //selecting the reset button
const next = document.querySelector(".next"); //selecting the reset button
let gameHistory; //initializes game history variable
let userHistory = []; //User history
let currentHistory = []; //History for current game
let currentSteps = 0; //How many buttons have been pressed
let totalSteps = 1; //How many buttons can be pressed in the current game
let steps = 0; //steps for the setInterval
let playingGame = false; //Flag to check if game is running
let gameSteps = true; //Flag to make sure that colored buttons can only be pressed a # of times
let gameStarts = false; //Flag to start game
let gameReset = false; //Resets the game
//-------------------------------------------------------------------------------------------------------------------------
function gameCreator() {
//returns an array of 3 random moves
// return [...new Array(3)].map(() => Math.round(Math.random() * 2));
return [0, 2, 1];
}
function resetGame() {
//resets the values of the game
reset.style.display = "none";
start.style.display = "flex";
var lose = document.getElementById("score-lose");
var win = document.getElementById("score-win");
lose.innerHTML = "";
win.innerHTML = "";
steps = 0;
totalSteps = 1;
currentHistory = [];
userHistory = [];
playingGame = false;
console.log("Game variables reset");
}
function jiggleButton(num) {
let shake = ["shake", "shake", "shake"];
//array of colors to use for when the buttons are pressed or shown
let dark = false; //flag for turning a button dark
var colored = setInterval(function() {
var element = document.getElementById("box" + num);
//interval for changing the colors on the buttons
if (dark) {
//checks the flag to see if the button should shake
element.classList.remove("shake");
clearInterval(colored); // stops the interval
return;
}
element.classList.add("shake");
dark = !dark; //set flag to true
}, 600);
return;
}
function gameMove() {
start.style.display = "none";
reset.style.display = "none";
next.style.display = "flex";
//function that visualizes the moves that the user has to press
if (!playingGame) {
//checks to see if the game has already started or is starting
gameHistory = gameCreator(); //creates an array for the game
console.log(gameHistory);
totalSteps = 1;
currentHistory = [];
userHistory = [];
playingGame = true;
console.log("current history: " + currentHistory);
}
let currentMoves = gameHistory.slice(0, totalSteps);
console.log(currentMoves);
steps = 0;
let lightUp = setInterval(function() {
if (steps >= currentMoves.length) {
currentSteps = 0;
gameSteps = true;
clearInterval(lightUp);
} else if (steps < currentMoves.length) {
jiggleButton(currentMoves[steps]);
}
steps++;
}, 1200);
console.log("steps: " + steps);
console.log("current Moves: " + steps);
console.log("game steps: " + gameSteps);
}
function onWin(winAnswer, score) {
var win = document.getElementById("score-win");
var currentScore = document.getElementById("running-score");
win.innerHTML += winAnswer;
currentScore.innerHTML += "Score " + score + "/3";
next.addEventListener("click", function() {
gameMove;
win.innerHTML = "";
currentScore.innerHTML = "";
});
}
function onLose(loseAnswer, score) {
var lose = document.getElementById("score-lose");
var win = document.getElementById("score-win");
var finalScore = document.getElementById("final-score");
var runningScore = document.getElementById("running-score");
finalScore.innerHTML += "Final score: " + score + "/3.";
runningScore.innerHTML = "";
playingGame = !playingGame;
lose.innerHTML += loseAnswer + userHistory.length;
win.innerHTML = "";
reset.style.display = "flex";
next.style.display = "none";
reset.addEventListener("click", function() {
finalScore.innerHTML = "";
});
}
function resetLose() {
reset.style.display = "flex";
next.style.display = "none";
}
function resetLoseThird() {
reset.style.display = "flex";
next.style.display = "none";
}
function onClick() {
//function for when the user clicks on one of the colored buttons
if (playingGame && gameSteps) {
//Checks the playingGame & gameSteps flag
for (var i = 0; i < 4; i++) {
//Checks what colored button was pressed and adds it to the currentHistory
if (this === boxes[i]) {
currentHistory.push(i);
currentSteps++; //adds to the number of moves done
if (currentSteps === totalSteps) {
//checks if the player made all the steps
userHistory.push(currentHistory); //updates the user game history
currentHistory = [];
gameSteps = false;
totalSteps++;
//round one
if (userHistory.length === 1) {
var firstAnswer = $vm.answerOne;
onWin(firstAnswer, 1);
//if round one is wrong
if (i !== 0) {
var firstLose = $vm.loseOne;
onLose(firstLose, 0);
}
}
//round two
else if (userHistory.length === 2) {
var secondAnswer = $vm.answerTwo;
onWin(secondAnswer, 2);
//if round two is wrong
if (i !== 2) {
var secondLose = $vm.loseTwo;
onLose(secondLose, 1);
}
} //round three
else if (userHistory.length === 3) {
var win = document.getElementById("score-win");
var currentScore = document.getElementById("running-score");
win.innerHTML += $vm.answerThree;
currentScore.innerHTML += "Score: 3/3. You Win!";
reset.addEventListener("click", function() {
gameMove;
win.innerHTML = "";
currentScore.innerHTML = "";
});
reset.style.display = "flex";
next.style.display = "none";
//if round three is wrong
if (i !== 1) {
//if user presses wrong colored button, game over
var thirdLose = $vm.loseThree;
onLose(thirdLose, 2);
}
}
}
}
}
}
}
function rename() {
let name = document.querySelector(".start");
name.innerHtml = "Next";
}
reset.addEventListener("click", resetGame); //resets the variables for the game
start.addEventListener("click", gameMove); //sets and event listener to the start button
next.addEventListener("click", gameMove); //sets and event listener to the start button
boxes.forEach(box => box.addEventListener("click", onClick)); //sets an event listener to the letters
}
};
</script>