From f5d276e4164277ead8b516e6dd0a06e6c3989667 Mon Sep 17 00:00:00 2001 From: yehorbk Date: Sun, 2 Oct 2022 18:55:07 +0300 Subject: [PATCH 1/3] message box functionality implemented --- .eslintrc.json | 4 ++- assets/css/style.css | 10 +++++++ index.html | 12 +++++++- main.js | 24 +++++++++------- src/handlers/keyboard-handler.js | 12 ++++++++ src/message-box.js | 49 ++++++++++++++++++++++++++++++++ src/utils/event-emitter.js | 19 +++++++++++++ 7 files changed, 118 insertions(+), 12 deletions(-) create mode 100644 src/handlers/keyboard-handler.js create mode 100644 src/message-box.js create mode 100644 src/utils/event-emitter.js diff --git a/.eslintrc.json b/.eslintrc.json index b47d466..07911b3 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -4,7 +4,9 @@ "es6": true }, "extends": ["eslint:recommended", "airbnb"], - "globals": {}, + "globals": { + "EventEmiter": "readonly" + }, "parserOptions": { "ecmaVersion": 2018, "sourceType": "script" diff --git a/assets/css/style.css b/assets/css/style.css index 2f29d7d..4f4cfcb 100644 --- a/assets/css/style.css +++ b/assets/css/style.css @@ -8,6 +8,16 @@ body { font-size: 20px; } +#more-break { + background-color: grey; + color: black; + visibility: hidden; +} + +#more-break::before, #more-break::after { + content: "\00a0"; +} + #hud { font-size: 25px; font-weight: bold; diff --git a/index.html b/index.html index 63d03cd..5cdea33 100644 --- a/index.html +++ b/index.html @@ -10,11 +10,21 @@
-
Press any key to continue...
+
+ + More +
HP: 100
+ + + + + + + diff --git a/main.js b/main.js index 41cd2ed..9071b98 100644 --- a/main.js +++ b/main.js @@ -1,13 +1,17 @@ -const field = document.getElementById('game-field'); -const context = field.getContext('2d'); +const Elements = { + field: document.getElementById('field'), + message: document.getElementById('message'), + moreBreak: document.getElementById('more-break'), +}; -const menuTheme = new Audio('./assets/sound/menu-theme.mp3'); -menuTheme.loop = true; -menuTheme.play(); +// eslint-disable-next-line no-undef +const messageBox = new MessageBox( + Elements.message, + Elements.moreBreak, +); -const cover = new Image(); -cover.src = './assets/images/cover.png'; +// eslint-disable-next-line no-undef +const keyboardHandler = new KeyboardHandler(); +document.addEventListener('keydown', keyboardHandler); -cover.onload = () => { - context.drawImage(cover, 0, 0); -}; +messageBox.write('Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nunc sit amet molestie nisi, quis dictum nisl. Phasellus at tellus vulputate, placerat tortor suscipit, laoreet neque. Maecenas bibendum, justo in fermentum. Lorem lorem'); diff --git a/src/handlers/keyboard-handler.js b/src/handlers/keyboard-handler.js new file mode 100644 index 0000000..04ec316 --- /dev/null +++ b/src/handlers/keyboard-handler.js @@ -0,0 +1,12 @@ +/* eslint-disable no-undef */ + +function KeyboardHandler() { + this.keys = [ + 'Space', + ]; +} + +KeyboardHandler.prototype.handleEvent = function ({ code }) { + if (!this.keys.includes(code)) return; + EventEmiter.emit(`key:${code}`); +}; diff --git a/src/message-box.js b/src/message-box.js new file mode 100644 index 0000000..6d72e8a --- /dev/null +++ b/src/message-box.js @@ -0,0 +1,49 @@ +// eslint-disable-next-line no-unused-vars +function MessageBox(target, more) { + this.target = target; + this.more = more; + this.buffer = []; + EventEmiter.subscribe('key:Space', () => this.continue()); +} + +MessageBox.prototype.write = function (message) { + if (message.length <= 64) { + this.buffer.push(message); + } else { + const words = message.split(' '); + let sentence = ''; + for (let i = 0; i < words.length; i++) { + sentence += words[i]; + sentence += ' '; + if (sentence.length > 48) { + this.buffer.push(sentence); + sentence = []; + } + } + this.buffer.push(sentence); + this.showMore(); + } + this.continue(); +}; + +MessageBox.prototype.continue = function () { + if (this.buffer.length === 0) { + this.hideMore(); + this.print(''); + return; + } + const message = this.buffer.shift(); + this.print(message); +}; + +MessageBox.prototype.print = function (message) { + this.target.innerText = message; +}; + +MessageBox.prototype.showMore = function () { + this.more.style.visibility = 'visible'; +}; + +MessageBox.prototype.hideMore = function () { + this.more.style.visibility = 'hidden'; +}; diff --git a/src/utils/event-emitter.js b/src/utils/event-emitter.js new file mode 100644 index 0000000..ee615d2 --- /dev/null +++ b/src/utils/event-emitter.js @@ -0,0 +1,19 @@ +/* eslint-disable no-unused-vars */ + +const EventEmiter = (() => { + const events = {}; + const subscribe = (event, callback) => { + if (!events[event]) { + events[event] = []; + } + events[event].push(callback); + }; + const emit = (event, ...args) => { + const callbacks = events[event]; + if (!callbacks) { + throw new Error(`cannot find event with name ${event}`); + } + callbacks.forEach(callback => callback(...args)); + }; + return { subscribe, emit }; +})(); From 9339ff9306de29d77d936f48c8c0efb5dcb95740 Mon Sep 17 00:00:00 2001 From: yehorbk Date: Sat, 5 Nov 2022 20:08:37 +0200 Subject: [PATCH 2/3] ui-rederer and hud functionality implemented --- .eslintrc.json | 5 ++++- assets/css/style.css | 13 +++++++++++++ index.html | 15 +++++++++++++-- main.js | 17 ++++++++--------- src/hud.js | 37 ++++++++++++++++++++++++++++++++++++ src/message-box.js | 10 ++++------ src/renderers/ui-renderer.js | 31 ++++++++++++++++++++++++++++++ src/utils/objects.js | 27 ++++++++++++++++++++++++++ 8 files changed, 137 insertions(+), 18 deletions(-) create mode 100644 src/hud.js create mode 100644 src/renderers/ui-renderer.js create mode 100644 src/utils/objects.js diff --git a/.eslintrc.json b/.eslintrc.json index 07911b3..127bbaa 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -17,6 +17,9 @@ "implicit-arrow-linebreak": "off", "func-names": "off", "object-curly-newline": "off", - "no-plusplus": "off" + "no-plusplus": "off", + "no-restricted-syntax": "off", + "guard-for-in": "off", + "no-continue": "off" } } diff --git a/assets/css/style.css b/assets/css/style.css index 4f4cfcb..479167b 100644 --- a/assets/css/style.css +++ b/assets/css/style.css @@ -24,6 +24,19 @@ body { color: magenta; } +#hud ul { + margin: 0; + padding: 0; +} + +#hud li { + display: inline-block; +} + +#hud li:not(:first-child) { + margin-left: 5px; +} + .center { margin-left: auto; margin-right: auto; diff --git a/index.html b/index.html index 5cdea33..264f535 100644 --- a/index.html +++ b/index.html @@ -15,15 +15,26 @@ More -
HP: 100
+
+
    +
  • Level:
  • +
  • Hits:()
  • +
  • Str:()
  • +
  • Gold:
  • +
  • Armor:
  • +
+
+ + + - + diff --git a/main.js b/main.js index 9071b98..79b91e9 100644 --- a/main.js +++ b/main.js @@ -1,17 +1,16 @@ -const Elements = { - field: document.getElementById('field'), - message: document.getElementById('message'), - moreBreak: document.getElementById('more-break'), -}; +// eslint-disable-next-line no-unused-vars +const field = document.getElementById('field'); // eslint-disable-next-line no-undef -const messageBox = new MessageBox( - Elements.message, - Elements.moreBreak, -); +const messageBox = new MessageBox(); + +// eslint-disable-next-line no-undef +const hud = new HUD(); // eslint-disable-next-line no-undef const keyboardHandler = new KeyboardHandler(); document.addEventListener('keydown', keyboardHandler); messageBox.write('Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nunc sit amet molestie nisi, quis dictum nisl. Phasellus at tellus vulputate, placerat tortor suscipit, laoreet neque. Maecenas bibendum, justo in fermentum. Lorem lorem'); +hud.print(); +hud.update({ strength: { max: 5 } }); diff --git a/src/hud.js b/src/hud.js new file mode 100644 index 0000000..7660d0e --- /dev/null +++ b/src/hud.js @@ -0,0 +1,37 @@ +// eslint-disable-next-line no-unused-vars +function HUD() { + this.indicators = { + level: 0, + hits: { + current: 0, + max: 0, + }, + strength: { + current: 0, + max: 0, + }, + gold: 0, // change to something else + armor: 0, + }; +} + +HUD.prototype.update = function (indicators) { + // eslint-disable-next-line no-undef + deepCopy(this.indicators, indicators); + this.print(); +}; + +HUD.prototype.print = function () { + // eslint-disable-next-line no-undef + UIRenderer.write(this.indicators); +}; + +HUD.prototype.hide = function () { + // eslint-disable-next-line no-undef + UIRenderer.hide('hud'); +}; + +HUD.prototype.show = function () { + // eslint-disable-next-line no-undef + UIRenderer.show('hud'); +}; diff --git a/src/message-box.js b/src/message-box.js index 6d72e8a..73bf55e 100644 --- a/src/message-box.js +++ b/src/message-box.js @@ -1,7 +1,5 @@ // eslint-disable-next-line no-unused-vars -function MessageBox(target, more) { - this.target = target; - this.more = more; +function MessageBox() { this.buffer = []; EventEmiter.subscribe('key:Space', () => this.continue()); } @@ -37,13 +35,13 @@ MessageBox.prototype.continue = function () { }; MessageBox.prototype.print = function (message) { - this.target.innerText = message; + UIRenderer.write({ message }); }; MessageBox.prototype.showMore = function () { - this.more.style.visibility = 'visible'; + UIRenderer.show('more-break'); }; MessageBox.prototype.hideMore = function () { - this.more.style.visibility = 'hidden'; + UIRenderer.hide('more-break'); }; diff --git a/src/renderers/ui-renderer.js b/src/renderers/ui-renderer.js new file mode 100644 index 0000000..b3f1bde --- /dev/null +++ b/src/renderers/ui-renderer.js @@ -0,0 +1,31 @@ +/* eslint-disable no-console */ +function UIRenderer() {} + +UIRenderer.write = data => { + // eslint-disable-next-line no-undef + const expanded = expandObject(data); + expanded.forEach(([id, value]) => { + const element = document.getElementById(id); + if (!element) { + console.error(`element with id ${id} not found`); + return; + } + element.innerText = value; + }); +}; + +UIRenderer.show = id => { + const element = document.getElementById(id); + if (!element) { + console.error(`element with id ${id} not found`); + } + element.style.visibility = 'visible'; +}; + +UIRenderer.hide = id => { + const element = document.getElementById(id); + if (!element) { + console.error(`element with id ${id} not found`); + } + element.style.visibility = 'hidden'; +}; diff --git a/src/utils/objects.js b/src/utils/objects.js new file mode 100644 index 0000000..9ce2680 --- /dev/null +++ b/src/utils/objects.js @@ -0,0 +1,27 @@ +// eslint-disable-next-line no-unused-vars +const expandObject = (object, prefix = '') => { + const result = []; + for (const key in object) { + const value = object[key]; + const path = prefix ? `${prefix}.${key}` : key; + if (typeof value === 'object') { + result.push(...expandObject(value, path)); + continue; + } + result.push([path, value]); + } + return result; +}; + +// eslint-disable-next-line no-unused-vars +const deepCopy = (target, source) => { + for (const key in source) { + if (target[key] === undefined) continue; + if (typeof target[key] === 'object') { + deepCopy(target[key], source[key]); + continue; + } + // eslint-disable-next-line no-param-reassign + target[key] = source[key]; + } +}; From 1f139e7977f2213f8c37b225d76ea37cad91707e Mon Sep 17 00:00:00 2001 From: yehorbk Date: Thu, 24 Nov 2022 17:38:57 +0200 Subject: [PATCH 3/3] director and menu added --- index.html | 3 ++ main.js | 16 +++++++---- src/director.js | 49 ++++++++++++++++++++++++++++++++ src/handlers/keyboard-handler.js | 7 +---- src/hud.js | 4 +++ src/menu.js | 33 +++++++++++++++++++++ src/message-box.js | 3 ++ 7 files changed, 103 insertions(+), 12 deletions(-) create mode 100644 src/director.js create mode 100644 src/menu.js diff --git a/index.html b/index.html index 264f535..0fc3171 100644 --- a/index.html +++ b/index.html @@ -36,6 +36,9 @@ + + + diff --git a/main.js b/main.js index 79b91e9..4666f3b 100644 --- a/main.js +++ b/main.js @@ -1,16 +1,20 @@ // eslint-disable-next-line no-unused-vars -const field = document.getElementById('field'); +const field = document.getElementById('game-field'); -// eslint-disable-next-line no-undef +// eslint-disable-next-line no-undef, no-unused-vars const messageBox = new MessageBox(); -// eslint-disable-next-line no-undef +// eslint-disable-next-line no-undef, no-unused-vars const hud = new HUD(); +// eslint-disable-next-line no-undef +const director = new Director(); + +// eslint-disable-next-line no-undef, no-unused-vars +const menu = new Menu(); + // eslint-disable-next-line no-undef const keyboardHandler = new KeyboardHandler(); document.addEventListener('keydown', keyboardHandler); -messageBox.write('Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nunc sit amet molestie nisi, quis dictum nisl. Phasellus at tellus vulputate, placerat tortor suscipit, laoreet neque. Maecenas bibendum, justo in fermentum. Lorem lorem'); -hud.print(); -hud.update({ strength: { max: 5 } }); +director.enter(); diff --git a/src/director.js b/src/director.js new file mode 100644 index 0000000..78aead2 --- /dev/null +++ b/src/director.js @@ -0,0 +1,49 @@ +function Director() { + this.stage = null; + EventEmiter.subscribe('key:F1', () => this.startGame()); + EventEmiter.subscribe('key:F2', () => this.startBot()); + EventEmiter.subscribe('key:F8', () => this.pause()); + EventEmiter.subscribe('key:F9', () => this.exit()); +} + +Director.Stages = { + MENU: 'menu', + GAME: 'game', + BOT: 'bot', + PAUSE: 'pause', +}; + +Director.prototype.enter = function () { + this.stage = Director.Stages.MENU; + this.emitStage(); +}; + +Director.prototype.startGame = function () { + if (this.stage !== Director.Stages.MENU) return; + this.stage = Director.Stages.GAME; + this.emitStage(); +}; + +Director.prototype.startBot = function () { + if (this.stage !== Director.Stages.MENU) return; + this.stage = Director.Stages.BOT; + this.emitStage(); +}; + +Director.prototype.pause = function () { + if (this.stage !== Director.Stages.GAME + && this.stage !== Director.Stages.BOT) return; + this.stage = Director.Stages.PAUSE; + this.emitStage(); +}; + +Director.prototype.exit = function () { + if (this.stage !== Director.Stages.GAME + && this.stage !== Director.Stages.BOT) return; + this.stage = Director.Stages.MENU; + this.emitStage(); +}; + +Director.prototype.emitStage = function () { + EventEmiter.emit(`stage:${this.stage}`); +}; diff --git a/src/handlers/keyboard-handler.js b/src/handlers/keyboard-handler.js index 04ec316..d7e3377 100644 --- a/src/handlers/keyboard-handler.js +++ b/src/handlers/keyboard-handler.js @@ -1,12 +1,7 @@ /* eslint-disable no-undef */ -function KeyboardHandler() { - this.keys = [ - 'Space', - ]; -} +function KeyboardHandler() {} KeyboardHandler.prototype.handleEvent = function ({ code }) { - if (!this.keys.includes(code)) return; EventEmiter.emit(`key:${code}`); }; diff --git a/src/hud.js b/src/hud.js index 7660d0e..a32a7c5 100644 --- a/src/hud.js +++ b/src/hud.js @@ -13,6 +13,10 @@ function HUD() { gold: 0, // change to something else armor: 0, }; + EventEmiter.subscribe('stage:menu', () => this.hide()); + EventEmiter.subscribe('stage:pause', () => this.hide()); + EventEmiter.subscribe('stage:game', () => this.show()); + EventEmiter.subscribe('stage:bot', () => this.show()); } HUD.prototype.update = function (indicators) { diff --git a/src/menu.js b/src/menu.js new file mode 100644 index 0000000..e9662bd --- /dev/null +++ b/src/menu.js @@ -0,0 +1,33 @@ +function Menu() { + EventEmiter.subscribe('stage:menu', () => this.showMain()); + EventEmiter.subscribe('stage:pause', () => this.showPause()); + EventEmiter.subscribe('stage:game', () => this.hide()); + EventEmiter.subscribe('stage:bot', () => this.hide()); +} + +Menu.prototype.show = function () { + this.context = field.getContext('2d'); + this.menuTheme = new Audio('./assets/sound/menu-theme.mp3'); + this.menuTheme.loop = true; + this.menuTheme.play(); + const cover = new Image(); + cover.src = './assets/images/cover.png'; + cover.onload = () => { + this.context.drawImage(cover, 0, 0); + }; +}; + +Menu.prototype.showMain = function () { + this.show(); + messageBox.write('Press F1 to play or F2 to start bot...'); +}; + +Menu.prototype.showPause = function () { + this.show(); + messageBox.write('Game paused. Press Enter to continue...'); +}; + +Menu.prototype.hide = function () { + this.context.clearRect(0, 0, 800, 600); + this.menuTheme.pause(); +}; diff --git a/src/message-box.js b/src/message-box.js index 73bf55e..dde5578 100644 --- a/src/message-box.js +++ b/src/message-box.js @@ -35,13 +35,16 @@ MessageBox.prototype.continue = function () { }; MessageBox.prototype.print = function (message) { + // eslint-disable-next-line no-undef UIRenderer.write({ message }); }; MessageBox.prototype.showMore = function () { + // eslint-disable-next-line no-undef UIRenderer.show('more-break'); }; MessageBox.prototype.hideMore = function () { + // eslint-disable-next-line no-undef UIRenderer.hide('more-break'); };