10DEC2020 - Update branch from master
to main
.
This project is an example project for the Interactive Front-End module of the Code Institute Full Stack Software Development course. The objective for this milestone project is to "build an interactive front-end site that should respond to users' actions, such as a data dashboard, a memory game, or use of an external API such as Google Maps".
"As a user, I would like to _______________"
- β read the instructions on how to play the game.
- β test my logical memory skills by matching a progressively difficult level of a series of colorful buttons.
- β play the game using either a mouse, the keyboard, or tapping on a touch screen.
- β play the game with both visual and audio effects from the buttons and sounds.
- β be notified when I've made a mistake from the sound of an error klaxon.
- β continue playing if I've made a mistake, but repeat the previous level a bit slower.
- β play the game in either standard mode, or strict mode (which ends the game immediately if I get one wrong answer).
- β restart the game at any point during my turn.
- β win the game after successfully matching 31 consecutive randomized colors.
- β hear the winning razz once I've completed all 31 levels successfully.
A standard layout that is fully responsive on mobile devices and larger screens has been utilized. The constant use of responsive CSS sizing elements such as vw
, vh
, %
, and calc()
helps to ensure the site responds to the appropriate user device.
There was no need to utilize any particular frameworks or libraries for this project, such as the following:
- Bootstrap / Materialize
- CSS Grid / Flexbox
- jQuery (exception: jasmine-jquery only for tests)
All of these colors are set at :root
level within my style.css file. This also allows me to reuse my colors as a class
across the site, instead of having to assign the colors each and every time.
- Font Awesome 5.12.1
- 2 Font Awesome icons were used, purely for social media icons on the Info Modal.
- 5 Google Fonts were used across the site:
- Original Surfer : main body text.
- Press Start 2P : button letters (RGBY).
- Quantico : counter and announcements.
- Sarpanch : game logo text.
- Luckiest Guy : all modal text.
I built mockup concept wireframes using Balsamiq Wireframes.
- Code Institute have provided all students with free access until the end of 2020.
My wireframes for this project can be found in the wireframes folder.
back to top
In accordance to the project brief, I have successfully implemented all of the required features, as well as a few additional features to improve user experience!
JavaScript Memory Game:
- Build a memory game using JavaScript to execute instructions to perform arithmetic, logic, controlling, and input/output operations to a user.
Progressive Difficulty:
- Players can progress through multiple levels if successfully matching Simon's moves each round. Levels get harder the further you manage to play.
- Levels 1-5 are EASY
- Levels 6-13 are MEDIUM
- Levels 14-31 are HARD
Strict Mode:
- To truly test their memory matching skills, players can choose to play in Strict Mode, but one wrong move will immediately end the game!
Restart Game:
- At any point during their turn, player's can opt to restart the game for a new randomized series of colors.
Player Timeout:
- If the player doesn't make a move within 5 seconds, a klaxon will sound to signify an error. This 5 second timer resets after each move. The level will repeat again at a slower playback speed only if Strict Mode is not active.
Automatic Console Shut-off:
- If the player does not interact with the game console for 45 consecutive seconds, the game console will automatically shut itself off. This 45 second timer does not apply when it is Simon's turn; this is to take in consideration when player's are at high levels and have made an error, Simon repeats the round at a slower speed, which nearly exhausts the entire 45 seconds of inactivity.
Winning Razz:
- If the player is successful enough to beat Simon's 31 levels, the traditional winning 'Razz' will trigger. This is a combination of rapid pulses of the final color, mixed with a round of applause in order from Red, Yellow, Blue, Green on repeat, followed by the losing klaxon to signify the player has won the game!
- Winning Modal will display length of time it took to beat Simon.
Leaderboard:
- Ideally, I'd like to implement a leaderboard of session users that have completed all 31 levels successfully, which can be displayed to anybody else.
back to top
-
- HTML5 - Used as the base for markup text.
-
- CSS3 - Used as the base for cascading styles.
-
- JavaScript ES6 - Used as the base for game interaction.
-
- Jasmine - Used for Test-Driven Development (TDD).
-
- jasmine-jquery - Used to simplify some of the automated Jasmine tests.
-
- VS Code - Used as my primary IDE for developing projects.
-
- GitHub - Used as remote storage of my projects online.
-
- Balsamiq - Used to bring my wireframes to life.
-
- Audacity - Used to record my own audio files.
back to top
A thorough mix of automated and manual testing have gone into building the project. In addition to tests, I have validated all files against online validation sites, and checked compatibilities across various modern browsers and devices.
HTML
- W3C HTML Validator
- Document checking completed. No errors or warnings to show.
CSS
- W3C CSS Validator
- The W3C Jigsaw validator does not yet recognize root variables, and therefore shows 110 Parse and Value Errors. These are used to set/use global CSS variables.
:root
var(--foo)
- I also received 2 Warnings:
- Imported style sheets are not checked in direct input and file upload modes.
-webkit-tap-highlight-color
is an unknown vendor extension.
- The W3C Jigsaw validator does not yet recognize root variables, and therefore shows 110 Parse and Value Errors. These are used to set/use global CSS variables.
JavaScript
- JShint
-
File: script.js
- METRICS:
- There are 57 functions in this file.
- Function with the largest signature take 1 arguments, while the median is 0.
- Largest function has 21 statements in it, while the median is 3.
- The most complex function has a cyclomatic complexity value of 12 while the median is 1.
- UNDEFINED VARIABLE:
KeyboardEvent
- METRICS:
-
File: simon-tests.js
- METRICS:
- There are 91 functions in this file.
- Function with the largest signature take 0 arguments, while the median is 0.
- Largest function has 16 statements in it, while the median is 3.
- The most complex function has a cyclomatic complexity value of 2 while the median is 1.
- UNDEFINED VARIABLES:
describe
beforeEach
it
expect
spyOn
jasmine
method
$
- METRICS:
-
- Esprima
- Code is syntactically valid.
Full details about compatibility tests can be found in my testing folder, which includes results from Chrome's DevTools Audit report as well.
To ensure a broad range of users can successfully use the site, I tested it across the 6 major browsers in both desktop and mobile configuration.
- Chrome (v.80.0.3987.116)
- Firefox (v.74.0b5 - Developer Edition)
- Edge (v.80.0.361.56)
- Safari (v.12.1.2)
- Opera (v.62.0.3331.99)
- Internet Explorer (v.11.885.17134.0)
I have also created a testing matrix (raw Excel file here).
Testing Matrix
Chrome's DevTools Audit Report
Performance | Accessibility | Best Practices | SEO | PWA |
---|---|---|---|---|
98% | 100% | 100% | 100% | - |
While passing my code through the online validators, I encountered one questionable issue. I opened an Issue on GitHub so I could revisit this problem and resolve it later.
- KeyboardEvent.keyCode depreciated
- This was fixed and pushed with commit a6eab2a.
I used Jasmine 3.5.0 in conjunction with jasmine-jquery 2.1.1 to build all automated tests (test-driven development). These tests can be found in the testing/automated folder.
There are 59 tests in my specs, all successfully passing, with 0 failures.
CLICK HERE to see tests on the Power Button
- should exist
- should be 'off' by default
- should not trigger Simon's turn (if power=off)
- should trigger the strictButton to be 'false' (during power off)
- should call the
disablePlayer()
function (during power off) - should call the
disableStart()
function after 500ms (during power off) - should call the
disableStrict()
function after 500ms (during power off) - should call the
disableColors()
function after 500ms (during power off) - should clear the gameSpeed interval after 500ms (during power off)
- should clear the playerTimer timeout after 500ms (during power off)
- should trigger the game console to turn 'on' if clicked
- should call the
enableStart()
function (during power on) - should call the
enableStrict()
function (during power on) - should call the
inactiveGame()
function (during power on) - should turn the Level Counter 'on' (during power on)
CLICK HERE to see tests on the Start Button
- should exist
- should be 'disabled' (if power=off)
- should have a default cursor (if power=off)
- should be 'enabled' (if power=on)
- should have a pointer cursor (if power=on)
- should call the
enablePlay()
function if clicked
CLICK HERE to see tests on the Strict Button
- should exist
- should be 'disabled' (if power=off)
- should have a default cursor (if power=off)
- should be 'enabled' (if power=on)
- should have a pointer cursor (if power=on)
- should end the game if 'enabled' and player is incorrect
CLICK HERE to see tests on the Level Counter
- should exist
- should show ON when the game is powered 'on'
- should show 01 when the game 'starts'
- should show NO if a player is 'incorrect'
- should show 13 when a player reaches the 'fastest' mode
- should show WIN if a player completes all '31 levels'
CLICK HERE to see tests on the Green Button
- should exist
- should not be 'enabled' if the
disablePlayer()
function is called - should call the
pushButton()
function if clicked during theenablePlayer()
function - should have class active if the
enableColors()
function is called - should not have class active if the
disableColors()
function is called - should play the greenAudio audio file if player isCorrect
CLICK HERE to see tests on the Red Button
- should exist
- should not be 'enabled' if the
disablePlayer()
function is called - should call the
pushButton()
function if clicked during theenablePlayer()
function - should have class active if the
enableColors()
function is called - should not have class active if the
disableColors()
function is called - should play the redAudio audio file if player isCorrect
CLICK HERE to see tests on the Yellow Button
- should exist
- should not be 'enabled' if the
disablePlayer()
function is called - should call the
pushButton()
function if clicked during theenablePlayer()
function - should have class active if the
enableColors()
function is called - should not have class active if the
disableColors()
function is called - should play the yellowAudio audio file if player isCorrect
CLICK HERE to see tests on the Blue Button
- should exist
- should not be 'enabled' if the
disablePlayer()
function is called - should call the
pushButton()
function if clicked during theenablePlayer()
function - should have class active if the
enableColors()
function is called - should not have class active if the
disableColors()
function is called - should play the blueAudio audio file if player isCorrect
CLICK HERE to see tests on the 'Lose' audio file
- should exist
- should play the lose audio file if player is not correct
back to top
My simon-game repository was developed locally using VS Code, and all commits were pushed to GitHub using Git.
In order to run this project locally on your own system, you will need the following installed (as a bare minimum):
- GIT for cloning and version control.
- Microsoft Visual Studio Code (or any suitable IDE) to develop your project.
Next, to proceed with local deployment, you can...
EITHER:
- Download this GitHub repository
- by clicking the green "Clone or download" button above,
- select Download Zip,
- this will download the project as a zip-file (remember to unzip it first).
OR:
- Clone this GitHub repository
- by entering the following command into the Git CLI terminal:
git clone https://github.com/TravelTimN/simon-game.git
- Troubleshooting for git cloning
- by entering the following command into the Git CLI terminal:
Congratulations! Your project should be completely setup and ready for local development! π
This site was deployed using GitHub Pages using the main branch.
Deployed Site:
Once you have the project setup locally, you can proceed to deploy it remotely with the following steps:
- Navigate to your GitHub repository:
https://github.com/USERNAME/REPO
- Click on the Settings tab at the top:
https://github.com/USERNAME/REPO/settings
- Scroll down on that page to the GitHub Pages section.
- The first drop-down field should be Source with None preselected.
- Select main branch from the list.
- The page should refresh.
- Scroll back down to the GitHub Pages section.
- You should now have a deployed link:
https://USERNAME.github.io/REPO
IMPORTANT NOTE:
- Please allow a few minutes to pass before opening your newly deployed link! Clicking this link too quickly may result in a failure to build the site, causing an Error 404 page instead.
Congratulations! Your project should be deployed successfully on GitHub Pages! π
back to top
- WaitingForFriday - Reverse Engineering a Simon Game. I wanted to keep the game as real to the original as possible.
- "How to Write a Git Commit Message" by Chris Beams (as recommended by Code Institute assessors).
- Szynalski - Online Tone Generator to create all sounds.
- TinyPNG - Online Image Compressor.
- Shields.io - Markdown badges for README.
All audio files were created by me. These files are not to be used without proper attribution, acknowledgment, and credit to this repository. You must specify that audio files were obtained from my repository, for example:
"Audio files were obtained with approval from https://github.com/TravelTimN/simon-game"
You are, however, welcome to generate your own audio files using the same methods and tools that I used, but the use of my files should be attributed if you use them for your own project(s).
- Jasmine QRG - My Quick Reference Guide as CI IFD_lead.
- Jasmine Cheatsheet - A helpful Jasmine cheatsheet.
- Jasmine 'setFixtures' - How to use
setFixtures
in Jasmine. - Jasmine 'spyOn' - How to use
spyOn
in Jasmine. - Jasmine 'createSpy' + 'createSpyObj' - How to use
createSpy
andcreateSpyObj
in Jasmine. - Jasmine 'timeouts' + 'intervals' - How to use
set
||clear
+Timeout
||Interval
in Jasmine. - Jasmine 'timeouts' + 'intervals' - How to use
set
||clear
+Timeout
||Interval
in Jasmine. - Jasmine 'addEventListener' - How to use
addEventListener
in Jasmine. - Jasmine 'removeEventListener' - How to use
removeEventListener
in Jasmine. - Jasmine audio files - How to test 'audio files' in Jasmine.
- Chris Quinn - My accountability partner on all projects.