From 9bcd2df563d6ba1e7fe8eabb2d0b3f467dec6b15 Mon Sep 17 00:00:00 2001 From: John Edvard Reiten Date: Sat, 27 Aug 2022 22:17:58 +0900 Subject: [PATCH] feat: Add main menu and level selector --- src/Game.js | 10 ++++-- src/Rope.js | 5 +-- src/VerletNode.js | 1 - src/assets/img/close icon.svg | 1 + src/gameEvents.js | 1 + src/index.html | 19 ++++++++--- src/index.js | 2 ++ src/menu.js | 63 +++++++++++++++++++++++++++++++++++ src/near/nearLogin.js | 2 +- src/styles.css | 62 ++++++++++++++++++++++++++++++++-- 10 files changed, 149 insertions(+), 17 deletions(-) create mode 100644 src/assets/img/close icon.svg create mode 100644 src/menu.js diff --git a/src/Game.js b/src/Game.js index 42bf667..94fe213 100644 --- a/src/Game.js +++ b/src/Game.js @@ -1,5 +1,5 @@ import { init, initPointer, initInput, GameLoop, onPointer, on } from 'kontra'; -import { LEVEL_COMPLETE } from './gameEvents'; +import { LEVEL_COMPLETE, START_LEVEL } from './gameEvents'; import { Level } from './Level'; import { playSong } from './sound'; import { setGameHeight, setGameWidth } from './store'; @@ -24,13 +24,13 @@ export class Game { setGameWidth(canvas.width); this.addPointerListeners(); - this.loadLevel(1); - let loop = GameLoop({ update: function () { + if (!game.level) return; game.level.update(); }, render: function () { + if (!game.level) return; game.level.render(game.context); }, }); @@ -55,9 +55,13 @@ export class Game { listenForGameEvents() { on(LEVEL_COMPLETE, this.onLevelComplete); + on(START_LEVEL, this.onStartLevel); } onLevelComplete = () => { this.level.destroy(); this.loadLevel(this.level.levelId + 1); }; + onStartLevel = ({ levelId }) => { + this.loadLevel(levelId); + }; } diff --git a/src/Rope.js b/src/Rope.js index fc27041..f29dbab 100644 --- a/src/Rope.js +++ b/src/Rope.js @@ -23,13 +23,12 @@ export class Rope { }) ); } - console.log(this.nodes); + for (let i = 0; i < this.nodes.length - 1; i++) { const n1 = this.nodes[i]; const n2 = this.nodes[i + 1]; this.links.push(new VerletLink(n1, n2)); } - console.log('links', this.links); } update() { @@ -62,10 +61,8 @@ export class Rope { updateLinks() { this.links.forEach((l) => { const dxy = l.n2.pos.subtract(l.n1.pos); - // console.log(l.n1.pos); const distance = dxy.length(); const diff = l.restingDistance - distance; - // console.log(distance); const percent = diff / distance / 2; const offset = Vector(dxy.x * percent, dxy.y * percent); l.n1.pos = l.n1.pos.subtract(offset); diff --git a/src/VerletNode.js b/src/VerletNode.js index 127a4e1..4a96e4f 100644 --- a/src/VerletNode.js +++ b/src/VerletNode.js @@ -7,7 +7,6 @@ export class VerletNode { height = 2; constructor({ x, y }) { this.pos = Vector(x, y); - console.log(this.pos); this.oldPos = Vector(x, y); } diff --git a/src/assets/img/close icon.svg b/src/assets/img/close icon.svg new file mode 100644 index 0000000..93a5f87 --- /dev/null +++ b/src/assets/img/close icon.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/gameEvents.js b/src/gameEvents.js index 7fd0fe6..b3d915b 100644 --- a/src/gameEvents.js +++ b/src/gameEvents.js @@ -3,3 +3,4 @@ export const ARCADIAN_ADDED = 'aa'; export const LEVEL_COMPLETE = 'lc'; export const HEART_PICKUP = 'hp'; export const CUT_ROPE = 'cr'; +export const START_LEVEL = 'sl'; diff --git a/src/index.html b/src/index.html index 93c0de0..a4a1745 100644 --- a/src/index.html +++ b/src/index.html @@ -12,11 +12,20 @@ - +
+ + + +
+
+ +
+
+ +
+
- -
diff --git a/src/index.js b/src/index.js index 814b8d8..3dd064a 100644 --- a/src/index.js +++ b/src/index.js @@ -5,10 +5,12 @@ import { ARCADIAN_ADDED } from './gameEvents'; import { queryArcadian } from './arcadianApi'; import { initLoginLogout } from './near/nearLogin'; import { NearConnection } from './near/nearConnection'; +import { initMenu } from './menu'; const init = () => { new Game(); initNear(); + initMenu(); // fetchArcadianHeads(); }; diff --git a/src/menu.js b/src/menu.js new file mode 100644 index 0000000..ddc50b2 --- /dev/null +++ b/src/menu.js @@ -0,0 +1,63 @@ +import { emit } from 'kontra'; +import { START_LEVEL } from './gameEvents'; + +const overlayIds = ['main', 'bonus', 'levels']; +const levels = 12; +export const initMenu = () => { + addButtonListeners(); + initLevels(); + initBonusContent(); +}; + +const initLevels = () => { + const levelsGridEl = document.getElementById('levels-grid'); + for (let i = 1; i < levels + 1; i++) { + const levelEl = document.createElement('div'); + levelEl.textContent = i; + levelEl.classList.add('level-item'); + levelsGridEl.appendChild(levelEl); + } +}; +const initBonusContent = () => {}; + +const addButtonListeners = () => { + const containerEl = document.getElementById('container'); + containerEl.addEventListener('click', onContainerClick); +}; + +const onContainerClick = (e) => { + const id = e.target.id; + const classList = e.target.classList; + switch (id) { + case 'levelBtn': + showOverlay('levels'); + break; + case 'bonusBtn': + showOverlay('bonus'); + break; + case 'hamburger': + showOverlay('main'); + default: + break; + } + + if (classList.contains('close-icon')) { + showOverlay('main'); + } + if (classList.contains('level-item')) { + showOverlay(); + emit(START_LEVEL, { levelId: e.target.textContent }); + } +}; + +const showOverlay = (id) => { + overlayIds.forEach((o) => { + const overlayEl = document.getElementById(o); + if (!overlayEl.classList.contains('hide')) { + overlayEl.classList.add('hide'); + } + if (o === id) { + overlayEl.classList.remove('hide'); + } + }); +}; diff --git a/src/near/nearLogin.js b/src/near/nearLogin.js index ec4bcd8..75552e8 100644 --- a/src/near/nearLogin.js +++ b/src/near/nearLogin.js @@ -10,7 +10,7 @@ export const loginout = (loginoutEl, nearConnection) => { }; export const initLoginLogout = (nearConnection) => { - const loginoutEl = document.getElementById('loginout'); + const loginoutEl = document.getElementById('loginoutBtn'); if ( nearConnection && nearConnection.walletConnection && diff --git a/src/styles.css b/src/styles.css index e8a4c53..b596c73 100644 --- a/src/styles.css +++ b/src/styles.css @@ -21,7 +21,6 @@ body, flex-flow: column; justify-content: center; align-items: center; - overflow: hidden; } canvas { background-color: var(--bgc); @@ -38,7 +37,7 @@ canvas { flex-direction: row-reverse; align-content: center; align-items: center; - padding: 5px 10px; + padding: 10px 20px; } #hamburger { @@ -46,7 +45,7 @@ canvas { display: flex; flex-direction: column; align-items: center; - line-height: 0.3; + line-height: 0.4; cursor: pointer; } #hamburger:hover { @@ -57,3 +56,60 @@ canvas { #hamburger::before { content: '––'; } + +button { + width: 240px; + height: 50px; + margin: 20px 0px 0px 0px; + background-color: var(--fgc2); + color: var(--bgc); + border: none; + border-radius: 4px; + font-size: large; + font-weight: bolder; +} + +.overlay { + position: absolute; + width: 100%; + height: 100%; + background-color: var(--bgc); + display: flex; + align-content: center; + flex-direction: column; + justify-content: center; + align-items: center; +} +.close-icon { + position: absolute; + top: 100px; + right: 100px; +} +.close-icon:hover { + filter: drop-shadow(0 0 12px var(--acc)) brightness(2); +} + +.level-item { + display: flex; + align-items: center; + justify-content: center; + width: 80px; + height: 80px; + border-radius: 4px; + background-color: var(--fgc2); +} +#levels-grid { + width: 640px; + height: 440px; + min-height: 440px; + overflow-y: scroll; + grid-template-columns: repeat(4, 150px); + justify-content: center; + row-gap: 60px; + display: grid; + justify-items: center; +} + +.hide { + display: none !important; /* XXX Override any other display settings on the element */ +}