From f72f2084a81285d8ddff7756b5316f94bc1a70b5 Mon Sep 17 00:00:00 2001 From: Tissevert Date: Fri, 30 Nov 2018 14:51:42 +0100 Subject: [PATCH] Implement settings menu --- src/automaton.js | 33 ++++++++++++++++++++++++-- src/buttons.js | 10 ++++++++ src/main.js | 2 +- src/screen.css | 11 +++++++-- src/screen.js | 16 ++++++++++--- src/session.js | 30 ++++++++++++++++++++++- src/ui.js | 62 +++++++++++++++++++++++++++++++++++++++++++++--- 7 files changed, 152 insertions(+), 12 deletions(-) diff --git a/src/automaton.js b/src/automaton.js index 44ec57b..35b6ca9 100644 --- a/src/automaton.js +++ b/src/automaton.js @@ -3,10 +3,20 @@ function Automaton(async, dom, messaging, screen, session, ui) { start: { entries: [ {label: 'New Game', action: newGame}, - {label: 'Settings', action: function() { console.log("Not implemented yet"); }} + {label: 'Settings', action: settings} ], cancel: intro, name: 'start' + }, + settings: { + entries: [ + {label: 'Buttons', action: ui.setLayout}, + {label: 'Text speed', action: function() { + ui.setTextSpeed(choices.textSpeed); + }} + ], + cancel: startMenu, + name: 'settings' } }; var choices = { @@ -20,6 +30,15 @@ function Automaton(async, dom, messaging, screen, session, ui) { name: 'name' }, skin: { + }, + textSpeed: { + entries: [ + {label: 'Slow', value: 'slow'}, + {label: 'Medium', value: 'medium'}, + {label: 'Fast', value: 'fast'} + ], + cancel: function() {}, + name: 'textSpeed' } }; var game = session.getGame(); @@ -52,11 +71,21 @@ function Automaton(async, dom, messaging, screen, session, ui) { {action: function() { screen.show(subtitle); }, delay: null} ], { B: function() { intro(); }, - Start: function() { ui.frame('StartMenu'); ui.menu(menus.start); } + Start: startMenu }) ); } + function startMenu() { + ui.frame('Start'); + ui.menu(menus.start); + } + + function settings() { + screen.clear(); + ui.menu(menus.settings); + } + function newGame() { ui.frame('GameInit'); async.run( diff --git a/src/buttons.js b/src/buttons.js index 9d23f03..4762d39 100644 --- a/src/buttons.js +++ b/src/buttons.js @@ -11,11 +11,21 @@ function Buttons(session) { }); return { + findKey: findKey, map: map, pop: pop, push: push }; + function findKey(button) { + var layout = session.getOptions().layout; + for(var key in layout) { + if(layout[key] == button) { + return key; + } + } + } + function map(newMapping) { mapping = newMapping; } diff --git a/src/main.js b/src/main.js index 9c8e7a2..b2d20fa 100644 --- a/src/main.js +++ b/src/main.js @@ -5,7 +5,7 @@ window.addEventListener('load', function() { screen = Screen(dom); session = Session(); buttons = Buttons(session); - ui = UI(async, buttons, screen, session); + ui = UI(async, buttons, dom, screen, session); automaton = Automaton(async, dom, messaging, screen, session, ui); messaging.start(); diff --git a/src/screen.css b/src/screen.css index 34051f8..fd78c87 100644 --- a/src/screen.css +++ b/src/screen.css @@ -19,6 +19,7 @@ body, input { } #screen .framed { + background: #fff; border: 3px double #000; border-radius: 0.5em; margin: 0.2em; @@ -57,15 +58,21 @@ ul.menu .selected:before { float: left; } -input.framed { +.center { position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); - font-size: 1em; +} + +div.framed, input.framed { padding: 0.2em; } +input.framed { + font-size: 1em; +} + #screen.frameIntro * { position: absolute; } diff --git a/src/screen.js b/src/screen.js index 4a735d5..7a33f66 100644 --- a/src/screen.js +++ b/src/screen.js @@ -1,9 +1,11 @@ function Screen(dom) { var root = document.getElementById('screen'); + var menus = []; return { appendText: appendText, clear: clear, + currentMenu: currentMenu, frame: frame, input: input, markAsRead: markAsRead, @@ -24,12 +26,19 @@ function Screen(dom) { root.removeChild(textElem); } } else if(elem != undefined) { + if(currentMenu() == elem) { + menus.pop(); + } root.removeChild(elem); } else { dom.clear(root); } } + function currentMenu() { + return menus[menus.length - 1]; + } + function frame(n) { root.className = "frame" + n; } @@ -52,7 +61,7 @@ function Screen(dom) { function input(size) { var elem = dom.make('input', { type: 'text', - class: 'framed', + class: ['framed', 'center'], maxlength: size, size: size }); @@ -71,17 +80,18 @@ function Screen(dom) { var domEntries = []; for(var i = 0; i < entries.length; i++) { domEntries.push(dom.make('li', { - class: [entries].concat(i == 0 ? ['selected'] : []), + class: i == 0 ? 'selected' : [], textContent: entries[i].label }, [])); } var ul = dom.make('ul', {class: ['menu', 'framed'], id: name}, domEntries); root.appendChild(ul); + menus.push(ul); return ul; } function select(cursor) { - var ul = root.getElementsByClassName('menu')[0]; + var ul = currentMenu(); ul.getElementsByClassName('selected')[0].className = ''; ul.children[cursor].className = 'selected'; } diff --git a/src/session.js b/src/session.js index fa3a533..6b3ae24 100644 --- a/src/session.js +++ b/src/session.js @@ -5,7 +5,8 @@ function Session() { return { getOptions: getOptions, getGame: getGame, - save : save + save: save, + setOptions: setOptions }; function getGame() { @@ -20,6 +21,33 @@ function Session() { localStorage.setItem('game', JSON.stringify(game)); } + function merge(a, b) { + for(var key in b) { + var value = b[key]; + if(typeof value == "object") { + if(Array.isArray(value)) { + a[key] = []; + for(var i = 0; i < value.length; i++) { + a[key][i] = value[i]; + } + } else { + merge(a[key], value); + } + } else { + if(value !== undefined) { + a[key] = value; + } else { + delete a[key]; + } + } + } + } + + function setOptions(newOptions) { + merge(options, newOptions); + localStorage.setItem('options', JSON.stringify(options)); + } + function defaultOptions() { var o = { layout: { diff --git a/src/ui.js b/src/ui.js index 50ed967..fd49412 100644 --- a/src/ui.js +++ b/src/ui.js @@ -1,4 +1,4 @@ -function UI(async, buttons, screen, session) { +function UI(async, buttons, dom, screen, session) { var lineWidth = 36; var textSpeeds = { slow: 100, @@ -13,7 +13,9 @@ function UI(async, buttons, screen, session) { cinematic: cinematic, frame: frame, menu: menu, - text: text + text: text, + setLayout: setLayout, + setTextSpeed: setTextSpeed }; function animation(frames) { @@ -95,7 +97,11 @@ function UI(async, buttons, screen, session) { } function ask(config) { - var menuConfig = {entries: [], name: config.name}; + var menuConfig = { + cancel: config.cancel, + entries: [], + name: config.name + }; var apply = function(f, val) { return function() { return f(val); }; }; return function(f) { for(var i = 0; i < config.entries.length; i++) { @@ -190,4 +196,54 @@ function UI(async, buttons, screen, session) { screens.map(function(s) { return textScreen(s); }) ); } + + function keyPromptLabel(key, button) { + return button + " : " + (key != undefined ? "[" + key + "]" : "???"); + } + + function setLayout() { + var layout = session.getOptions().layout + var buttons = { + cancel: function() {}, + entries: [], + name: "layout" + }; + for(var key in layout) { + buttons.entries.push({ + label: keyPromptLabel(key, layout[key]), + action: setKey(layout[key]) + }); + } + menu(buttons); + } + + function setKey(button) { + return function() { + buttons.push({}); + var elem = dom.make('div', { + class: ['framed', 'center'], + textContent: "Press the key you wanna map to " + button + }); + screen.currentMenu().getElementsByClassName('selected')[0].textContent = keyPromptLabel(null, button); + var promptKey = function(event) { + var layout = {}; + layout[event.key] = button; + layout[buttons.findKey(button)] = undefined; + session.setOptions({layout: layout}); + screen.clear(elem); + screen.currentMenu().getElementsByClassName('selected')[0].textContent = keyPromptLabel(event.key, button); + document.removeEventListener('keydown', promptKey); + buttons.pop(); + }; + screen.show(elem); + document.addEventListener('keydown', promptKey); + } + } + + function setTextSpeed(choices) { + ask(choices)(function(value) { + session.setOptions({textSpeed: value}); + textDelay = textSpeeds[value]; + }); + } }