chore: update readme; add link to source code
This commit is contained in:
parent
62abaf6290
commit
b110cc5d87
3 changed files with 47 additions and 19 deletions
24
README.md
24
README.md
|
@ -6,14 +6,38 @@ This is the classic game **Minesweeper** built as a single page application with
|
||||||
Stack:
|
Stack:
|
||||||
- HTML, JS, and CSS
|
- HTML, JS, and CSS
|
||||||
- Webpack for bundling
|
- Webpack for bundling
|
||||||
|
- Firebase for leader board store
|
||||||
|
- Netlify for hosting
|
||||||
|
|
||||||
## Development
|
## Development
|
||||||
To start development, you need node v16 (the dev server doesn't work on v18 *yet*). Once you know you have this, you can do the following:
|
To start development, you need node v16 (the dev server doesn't work on v18 *yet*). Once you know you have this, you can do the following:
|
||||||
1. Install dependencies: `npm i`
|
1. Install dependencies: `npm i`
|
||||||
2. Start the dev server: `npm run dev`
|
2. Start the dev server: `npm run dev`
|
||||||
|
|
||||||
|
*Sorry there's no hot reloading. You have to reload the app after making a change. OR contribute to enable HMR? ;)*
|
||||||
|
|
||||||
## Running Locally
|
## Running Locally
|
||||||
After running the commands to start development, open in a browser: `http://localhost:4200`
|
After running the commands to start development, open in a browser: `http://localhost:4200`
|
||||||
|
|
||||||
## Live Demo
|
## Live Demo
|
||||||
The live site is here: [Minesweeper](https://mnswpr.com)
|
The live site is here: [Minesweeper](https://mnswpr.com)
|
||||||
|
|
||||||
|
## Project motivation
|
||||||
|
One day, while working in my home office, I heard loud and fast mouse clicks coming from our bedroom. It's my wife, playing her favorite game (Minesweeper) on a crappy website full of advertisements.
|
||||||
|
|
||||||
|
I can't allow this, it's a security issue. 🤣
|
||||||
|
|
||||||
|
But it is also an opportunity.
|
||||||
|
|
||||||
|
I wanted to give her the same game, with a similar leader board she can dominate. But I also saw it as a chance to dig deeper into vanilla JS.
|
||||||
|
|
||||||
|
Can I make page with complex interactions (more on this later) without any dependency?
|
||||||
|
|
||||||
|
## What I have learned:
|
||||||
|
✨ We don't always necessarily *need* JS frameworks (or TS) ✨
|
||||||
|
|
||||||
|
✨ Even subtle UI changes *can improve* user experience ✨
|
||||||
|
|
||||||
|
✨ There's more ways to break you're app than you are initially aware of ✨
|
||||||
|
|
||||||
|
✨ Competition motivates users to use your app more ✨
|
||||||
|
|
|
@ -30,7 +30,6 @@
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<script type='text/javascript' src='https://ko-fi.com/widgets/widget_2.js'></script><script type='text/javascript'>kofiwidget2.init('Buy me a coffee', '#29abe0', 'ayoayco');kofiwidget2.draw();</script>
|
<script type='text/javascript' src='https://ko-fi.com/widgets/widget_2.js'></script><script type='text/javascript'>kofiwidget2.init('Buy me a coffee', '#29abe0', 'ayoayco');kofiwidget2.draw();</script>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<script type="module" src="main.bundle.js"></script>
|
<script type="module" src="main.bundle.js"></script>
|
||||||
|
|
|
@ -6,7 +6,7 @@ import {
|
||||||
} from './modules';
|
} from './modules';
|
||||||
import { levels } from './levels.js';
|
import { levels } from './levels.js';
|
||||||
|
|
||||||
const TEST_MODE = true; // set to true if you want to test the game with visual hints and separate leaderboard
|
const TEST_MODE = false; // set to true if you want to test the game with visual hints and separate leaderboard
|
||||||
const VERSION = "0.3.12";
|
const VERSION = "0.3.12";
|
||||||
const MOBILE_BUSY_DELAY = 250;
|
const MOBILE_BUSY_DELAY = 250;
|
||||||
const PC_BUSY_DELAY = 500;
|
const PC_BUSY_DELAY = 500;
|
||||||
|
@ -69,20 +69,27 @@ export const Minesweeper = function(appId) {
|
||||||
let minesArray = [];
|
let minesArray = [];
|
||||||
|
|
||||||
this.initialize = function() {
|
this.initialize = function() {
|
||||||
|
|
||||||
appElement.innerHTML = '';
|
|
||||||
const heading = `Minesweeper v${VERSION}`;
|
|
||||||
const headingElement = document.createElement('h1');
|
const headingElement = document.createElement('h1');
|
||||||
headingElement.innerText = heading;
|
|
||||||
|
|
||||||
const gameBoard = document.createElement('div');
|
const gameBoard = document.createElement('div');
|
||||||
|
|
||||||
|
headingElement.innerText = `Minesweeper v${VERSION}`;
|
||||||
gameBoard.setAttribute('id', 'game-board');
|
gameBoard.setAttribute('id', 'game-board');
|
||||||
|
|
||||||
gameBoard.append(initializeToolbar(), grid, initializeFootbar());
|
gameBoard.append(initializeToolbar(), grid, initializeFootbar());
|
||||||
|
appElement.innerHTML = '';
|
||||||
appElement.append(headingElement, gameBoard);
|
appElement.append(headingElement, gameBoard);
|
||||||
generateGrid()
|
appElement.append(initializeSourceLink());
|
||||||
// appElement.append(gameWrapper);
|
|
||||||
|
generateGrid();
|
||||||
|
}
|
||||||
|
|
||||||
|
function initializeSourceLink() {
|
||||||
|
const sourceLink = document.createElement('a');
|
||||||
|
sourceLink.href = 'https://github.com/ayoayco/mnswpr';
|
||||||
|
sourceLink.innerText = 'Source code';
|
||||||
|
sourceLink.target = '_blank';
|
||||||
|
sourceLink.style.color = 'white';
|
||||||
|
|
||||||
|
return sourceLink;
|
||||||
}
|
}
|
||||||
|
|
||||||
function initializeLeaderBoard() {
|
function initializeLeaderBoard() {
|
||||||
|
@ -114,22 +121,21 @@ export const Minesweeper = function(appId) {
|
||||||
levelsDropdown.add(levelOption, null);
|
levelsDropdown.add(levelOption, null);
|
||||||
});
|
});
|
||||||
|
|
||||||
const customOption = document.createElement('option');
|
// custom level
|
||||||
customOption.onmousedown = () => {}
|
// const customOption = document.createElement('option');
|
||||||
customOption.value = 'custom';
|
// customOption.onmousedown = () => {}
|
||||||
customOption.text = 'Custom';
|
// customOption.value = 'custom';
|
||||||
|
// customOption.text = 'Custom';
|
||||||
// levelsDropdown.add(customOption);
|
// levelsDropdown.add(customOption);
|
||||||
|
|
||||||
if (TEST_MODE) {
|
if (TEST_MODE) {
|
||||||
const testLevel = document.createElement('span');
|
const testLevel = document.createElement('span');
|
||||||
testLevel.innerText = 'Test Mode';
|
testLevel.innerText = 'Test Mode';
|
||||||
footBar.append(testLevel);
|
footBar.append(testLevel);
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
footBar.append(levelsDropdown);
|
footBar.append(levelsDropdown);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
return footBar;
|
return footBar;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -257,7 +263,6 @@ export const Minesweeper = function(appId) {
|
||||||
appElement.style.width = `${grid.offsetWidth + 40}px`;
|
appElement.style.width = `${grid.offsetWidth + 40}px`;
|
||||||
appElement.style.margin = '0 auto';
|
appElement.style.margin = '0 auto';
|
||||||
|
|
||||||
|
|
||||||
if (!CASUAL_MODE) {
|
if (!CASUAL_MODE) {
|
||||||
initializeLeaderBoard();
|
initializeLeaderBoard();
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue