From f05b2518f35e2b6ffd37b28c9a72b6a5ce8f90f8 Mon Sep 17 00:00:00 2001 From: LoveEevee Date: Tue, 16 Apr 2019 21:06:41 +0300 Subject: [PATCH] Split language and tutorial, add gamepad settings --- public/assets/img/img.css | 4 + public/assets/img/settings_gamepad.png | Bin 0 -> 490 bytes public/src/css/main.css | 183 -------------- public/src/css/view.css | 235 ++++++++++++++++++ public/src/js/about.js | 38 +-- public/src/js/assets.js | 7 +- public/src/js/controller.js | 9 +- public/src/js/debug.js | 9 +- public/src/js/game.js | 21 +- public/src/js/gameinput.js | 247 +++++++++++++++++++ public/src/js/gamepad.js | 11 +- public/src/js/keyboard.js | 327 +++++++------------------ public/src/js/mekadon.js | 18 +- public/src/js/pageevents.js | 24 +- public/src/js/scoresheet.js | 37 +-- public/src/js/session.js | 32 ++- public/src/js/settings.js | 314 +++++++++++++++--------- public/src/js/songselect.js | 89 +++---- public/src/js/strings.js | 54 +++- public/src/js/titlescreen.js | 64 ++--- public/src/js/tutorial.js | 86 +++---- public/src/js/view.js | 8 +- public/src/views/about.html | 12 +- public/src/views/session.html | 10 +- public/src/views/settings.html | 22 +- public/src/views/tutorial.html | 10 +- 26 files changed, 1036 insertions(+), 835 deletions(-) create mode 100644 public/assets/img/settings_gamepad.png create mode 100644 public/src/css/view.css create mode 100644 public/src/js/gameinput.js diff --git a/public/assets/img/img.css b/public/assets/img/img.css index 7d339c6..2a79238 100644 --- a/public/assets/img/img.css +++ b/public/assets/img/img.css @@ -19,3 +19,7 @@ .settings-outer{ background-image: url("bg_settings.png"); } +#gamepad-bg, +#gamepad-buttons{ + background-image: url("settings_gamepad.png"); +} diff --git a/public/assets/img/settings_gamepad.png b/public/assets/img/settings_gamepad.png new file mode 100644 index 0000000000000000000000000000000000000000..c287f06cc505d9858d2bc4bfb04d759bd9a92330 GIT binary patch literal 490 zcmeAS@N?(olHy`uVBq!ia0y~yU{V9(lN`)Ik?l+p%0P-az$e5NNH4Fly#=HgOM?7@ z862M7NCUE`db&7{F_6 M)78&qol`;+0G}!ymjD0& literal 0 HcmV?d00001 diff --git a/public/src/css/main.css b/public/src/css/main.css index 11e4c64..6927ff1 100644 --- a/public/src/css/main.css +++ b/public/src/css/main.css @@ -23,117 +23,6 @@ left: 0; z-index: -1; } -#tutorial-outer{ - display: flex; - justify-content: center; - align-items: center; - overflow: hidden; - position: absolute; - width: 100%; - height: 100%; -} -#tutorial{ - background: rgb(246, 234, 212); - color: black; - border: 0.25em black solid; - border-radius: 0.5em; - width: 800px; - padding: 1em; - margin: 1em; - font-size: 21px; - position: relative; -} -.touch-enabled #tutorial{ - font-size: 3vmin; -} -#tutorial-title{ - z-index: 1; - position: absolute; - color: white; - top: -0.7em; - font-size: 1.65em; -} -#tutorial-content{ - margin: 0.7em 0; - overflow-y: auto; - max-height: calc(100vh - 14em); -} -kbd{ - font-family: inherit; - padding: 0.1em 0.6em; - border: 1px solid #ccc; - font-size: 0.6em; - background-color: #f7f7f7; - color: #333; - box-shadow: 0 1px 0px rgba(0, 0, 0, 0.2), 0 0 0 2px #ffffff inset; - border-radius: 3px; - display: inline-block; - text-shadow: 0 1px 0 #fff; - line-height: 1.4; - white-space: nowrap; -} -.taibtn{ - display: inline-block; - background: #f6ead4; - padding: 0.4em 0.4em; - border-radius: 0.5em; - border: 0.1em rgba(218, 205, 178, 1) solid; - cursor: pointer; - font-size: 1.4em; - box-sizing: border-box; - color: #555; - text-align: center; -} -#tutorial-end-button{ - float: right; - padding: 0.4em 1.5em; - font-weight: bold; - border-color: #000; - color: #000; -} -.taibtn:hover, -.taibtn.selected, -#tutorial-end-button:hover, -#tutorial-end-button.selected{ - position: relative; - z-index: 1; - color: #fff; - background: #ffb547; - border-color: #fff; -} -.taibtn::before{ - padding-left: inherit; -} -#about-link-btns{ - float: left; - display: flex; -} -#about-link-btns .taibtn{ - margin-right: 0.4em; -} -#diag-txt textarea, -#diag-txt iframe{ - width: 100%; - height: 5em; - font-size: inherit; - resize: none; - word-break: break-all; - margin-bottom: 1em; - background: #fff; - border: 1px solid #a9a9a9; - user-select: all; -} -.text-warn{ - color: #d00; -} -.link-btn a{ - color: inherit; - text-decoration: none; - pointer-events: none; -} -.nowrap{ - white-space: nowrap; -} #session-invite{ width: 100%; height: 1.9em; @@ -149,78 +38,6 @@ kbd{ cursor: text; overflow: hidden; } -@keyframes border-pulse{ - 0%{border-color: #ff0} - 50%{border-color: rgba(255, 255, 0, 0)} - 100%{border-color: #ff0} -} -@keyframes border-pulse2{ - 0%{border-color: #e29e06} - 50%{border-color: rgba(226, 158, 6, 0)} - 100%{border-color: #e29e06} -} -.settings-outer{ - background-size: 50vh; -} -.setting-box{ - display: flex; - height: 2em; - margin-top: 1.2em; - border: 0.25em solid #000; - border-radius: 0.5em; - padding: 0.3em; - outline: none; - color: #000; - cursor: pointer; -} -.setting-box:first-child{ - margin-top: 0; -} -.settings-outer #tutorial-content:not(:hover) .setting-box.selected, -#tutorial-outer:not(.settings-outer) .setting-box.selected, -.setting-box:hover{ - background: #ffb547; - animation: 2s linear border-pulse infinite; -} -.bold-fonts .setting-box{ - line-height: 1em; -} -.setting-name{ - position: relative; - width: 50%; - padding: 0.3em; - font-size: 1.3em; - box-sizing: border-box; -} -#tutorial-content:not(:hover) .setting-box.selected .setting-name, -#tutorial-outer:not(.settings-outer) .setting-box.selected .setting-name, -.setting-box:hover .setting-name{ - color: #fff; - z-index: 0; -} -.setting-name::before{ - padding-left: 0.3em; -} -.setting-value{ - display: flex; - background: #fff; - width: 50%; - border-radius: 0.2em; - padding: 0.5em; - box-sizing: border-box; -} -.setting-value.selected{ - width: calc(50% + 0.2em); - margin: -0.1em; - border: 0.2em solid #e29e06; - padding: 0.4em; - animation: 2s linear border-pulse2 infinite; -} -.setting-value>div{ - padding: 0 0.4em; - overflow: hidden; - text-overflow: ellipsis; -} @keyframes bgscroll{ from{ background-position: 0 top; diff --git a/public/src/css/view.css b/public/src/css/view.css new file mode 100644 index 0000000..3b80242 --- /dev/null +++ b/public/src/css/view.css @@ -0,0 +1,235 @@ +.view-outer{ + display: flex; + justify-content: center; + align-items: center; + overflow: hidden; + position: absolute; + width: 100%; + height: 100%; +} +.view{ + background: rgb(246, 234, 212); + color: black; + border: 0.25em black solid; + border-radius: 0.5em; + width: 800px; + padding: 1em; + margin: 1em; + font-size: 21px; + position: relative; +} +.touch-enabled .view{ + font-size: 3vmin; +} +.view-title{ + z-index: 1; + position: absolute; + color: white; + top: -0.7em; + font-size: 1.65em; +} +.view-content{ + margin: 0.7em 0; + overflow-y: auto; + max-height: calc(100vh - 14em); +} +kbd{ + font-family: inherit; + padding: 0.1em 0.6em; + border: 1px solid #ccc; + font-size: 0.6em; + background-color: #f7f7f7; + color: #333; + box-shadow: 0 1px 0px rgba(0, 0, 0, 0.2), 0 0 0 2px #ffffff inset; + border-radius: 3px; + display: inline-block; + text-shadow: 0 1px 0 #fff; + line-height: 1.4; + white-space: nowrap; +} +.taibtn{ + display: inline-block; + background: #f6ead4; + padding: 0.4em 0.4em; + border-radius: 0.5em; + border: 0.1em rgba(218, 205, 178, 1) solid; + cursor: pointer; + font-size: 1.4em; + box-sizing: border-box; + color: #555; + text-align: center; +} +.view-end-button{ + float: right; + padding: 0.4em 1.5em; + font-weight: bold; + border-color: #000; + color: #000; + z-index: 1; +} +.taibtn:hover, +.taibtn.selected, +.view-end-button:hover, +.view-end-button.selected{ + position: relative; + color: #fff; + background: #ffb547; + border-color: #fff; +} +.taibtn::before, +.view-end-button::before{ + display: none; +} +.taibtn:hover::before, +.taibtn.selected::before, +.view-end-button:hover::before, +.view-end-button.selected::before{ + display: block +} +.taibtn::before{ + padding-left: inherit; +} +.left-buttons{ + float: left; + display: flex; +} +.left-buttons .taibtn{ + margin-right: 0.4em; +} +#diag-txt textarea, +#diag-txt iframe{ + width: 100%; + height: 5em; + font-size: inherit; + resize: none; + word-break: break-all; + margin-bottom: 1em; + background: #fff; + border: 1px solid #a9a9a9; + user-select: all; +} +.text-warn{ + color: #d00; +} +.link-btn a{ + color: inherit; + text-decoration: none; + pointer-events: none; +} +.nowrap{ + white-space: nowrap; +} +@keyframes border-pulse{ + 0%{border-color: #ff0} + 50%{border-color: rgba(255, 255, 0, 0)} + 100%{border-color: #ff0} +} +@keyframes border-pulse2{ + 0%{border-color: #e29e06} + 50%{border-color: rgba(226, 158, 6, 0)} + 100%{border-color: #e29e06} +} +.settings-outer{ + background-size: 50vh; +} +.setting-box{ + display: flex; + height: 2em; + margin-top: 1.2em; + border: 0.25em solid #000; + border-radius: 0.5em; + padding: 0.3em; + outline: none; + color: #000; + cursor: pointer; +} +.setting-box:first-child{ + margin-top: 0; +} +.settings-outer .view-content:not(:hover) .setting-box.selected, +.view-outer:not(.settings-outer) .setting-box.selected, +.setting-box:hover{ + background: #ffb547; + animation: 2s linear border-pulse infinite; +} +.bold-fonts .setting-box{ + line-height: 1em; +} +.setting-name{ + position: relative; + width: 50%; + padding: 0.3em; + font-size: 1.3em; + box-sizing: border-box; +} +.view-content:not(:hover) .setting-box.selected .setting-name, +.view-outer:not(.settings-outer) .setting-box.selected .setting-name, +.setting-box:hover .setting-name{ + color: #fff; + z-index: 0; +} +.setting-name::before{ + padding-left: 0.3em; +} +.setting-value{ + display: flex; + background: #fff; + width: 50%; + border-radius: 0.2em; + padding: 0.5em; + box-sizing: border-box; +} +.setting-value.selected{ + width: calc(50% + 0.2em); + margin: -0.1em; + border: 0.2em solid #e29e06; + padding: 0.4em; + animation: 2s linear border-pulse2 infinite; +} +.setting-value>div{ + padding: 0 0.4em; + overflow: hidden; + text-overflow: ellipsis; +} +.shadow-outer{ + position: fixed; + top: 0; + right: 0; + bottom: 0; + left: 0; + background: rgba(0, 0, 0, 0.5); + z-index: 1; +} +#settings-gamepad{ + display: none; +} +#settings-gamepad .view{ + position: absolute; + margin: auto; + top: 0; + right: 0; + bottom: 0; + left: 0; + width: 550px; + height: 417px; +} +#gamepad-bg{ + position: relative; + width: 550px; + height: 317px; + max-height: none; + background-repeat: none; + text-align: center; + font-size: 1.4em; + cursor: pointer; +} +#gamepad-buttons{ + position: absolute; + left: 141px; + top: 120px; + width: 282px; + height: 131px; + background-position: 0 -318px; + background-repeat: none; + pointer-events: none; +} diff --git a/public/src/js/about.js b/public/src/js/about.js index 95575b7..104d8a1 100644 --- a/public/src/js/about.js +++ b/public/src/js/about.js @@ -4,20 +4,20 @@ loader.changePage("about", true) cancelTouch = false - this.endButton = document.getElementById("tutorial-end-button") + this.endButton = this.getElement("view-end-button") this.diagTxt = document.getElementById("diag-txt") this.version = document.getElementById("version-link").href - this.tutorialOuter = document.getElementById("tutorial-outer") + this.tutorialOuter = this.getElement("view-outer") if(touchEnabled){ this.tutorialOuter.classList.add("touch-enabled") } this.linkIssues = document.getElementById("link-issues") this.linkEmail = document.getElementById("link-email") - var tutorialTitle = document.getElementById("tutorial-title") + var tutorialTitle = this.getElement("view-title") tutorialTitle.innerText = strings.aboutSimulator tutorialTitle.setAttribute("alt", strings.aboutSimulator) - var tutorialContent = document.getElementById("tutorial-content") + var tutorialContent = this.getElement("view-content") strings.about.bugReporting.forEach(string => { tutorialContent.appendChild(document.createTextNode(string)) tutorialContent.appendChild(document.createElement("br")) @@ -32,20 +32,18 @@ var versionUrl = gameConfig._version.url this.getLink(this.linkIssues).href = versionUrl + "issues" - var kbdSettings = settings.getItem("keyboardSettings") - this.kbd = { - confirm: ["enter", " ", kbdSettings.don_l[0], kbdSettings.don_r[0]], - previous: ["arrowleft", "arrowup", kbdSettings.ka_l[0]], - next: ["arrowright", "arrowdown", kbdSettings.ka_r[0]], - back: ["backspace", "escape"] - } pageEvents.add(this.linkIssues, ["click", "touchend"], this.linkButton.bind(this)) pageEvents.add(this.linkEmail, ["click", "touchend"], this.linkButton.bind(this)) pageEvents.add(this.endButton, ["mousedown", "touchstart"], this.onEnd.bind(this)) - pageEvents.keyAdd(this, "all", "down", this.keyEvent.bind(this)) this.items = [this.linkIssues, this.linkEmail, this.endButton] this.selected = 2 + this.keyboard = new Keyboard({ + confirm: ["enter", "space", "don_l", "don_r"], + previous: ["left", "up", "ka_l"], + next: ["right", "down", "ka_r"], + back: ["escape"] + }, this.keyPressed.bind(this)) this.gamepad = new Gamepad({ "confirm": ["b", "ls", "rs"], "previous": ["u", "l", "lb", "lt", "lsu", "lsl"], @@ -55,19 +53,8 @@ pageEvents.send("about", this.addDiag()) } - keyEvent(event){ - if(event.keyCode === 27 || event.keyCode === 8 || event.keyCode === 9){ - // Escape, Backspace, Tab - event.preventDefault() - } - if(!event.repeat){ - for(var i in this.kbd){ - if(this.kbd[i].indexOf(event.key.toLowerCase()) !== -1){ - this.keyPressed(true, i) - break - } - } - } + getElement(name){ + return loader.screen.getElementsByClassName(name)[0] } keyPressed(pressed, name){ if(!pressed){ @@ -215,6 +202,7 @@ } clean(){ cancelTouch = true + this.keyboard.clean() this.gamepad.clean() pageEvents.remove(this.linkIssues, ["click", "touchend"]) pageEvents.remove(this.linkEmail, ["click", "touchend"]) diff --git a/public/src/js/assets.js b/public/src/js/assets.js index 80b46f3..e363842 100644 --- a/public/src/js/assets.js +++ b/public/src/js/assets.js @@ -7,6 +7,7 @@ var assets = { "scoresheet.js", "songselect.js", "keyboard.js", + "gameinput.js", "game.js", "controller.js", "circle.js", @@ -36,7 +37,8 @@ var assets = { "loadsong.css", "game.css", "debug.css", - "songbg.css" + "songbg.css", + "view.css" ], "assetsCss": [ "fonts/fonts.css", @@ -79,7 +81,8 @@ var assets = { "results_flowers.png", "results_mikoshi.png", "results_tetsuohana.png", - "results_tetsuohana2.png" + "results_tetsuohana2.png", + "settings_gamepad.png" ], "audioSfx": [ "se_cancel.wav", diff --git a/public/src/js/controller.js b/public/src/js/controller.js index 6e2baae..cf253b4 100644 --- a/public/src/js/controller.js +++ b/public/src/js/controller.js @@ -28,7 +28,7 @@ class Controller{ this.game = new Game(this, this.selectedSong, this.parsedSongData) this.view = new View(this) this.mekadon = new Mekadon(this, this.game) - this.keyboard = new Keyboard(this) + this.keyboard = new GameInput(this) this.playedSounds = {} } @@ -210,11 +210,8 @@ class Controller{ getKeys(){ return this.keyboard.getKeys() } - setKey(keyCode, down, ms){ - return this.keyboard.setKey(keyCode, down, ms) - } - getBindings(){ - return this.keyboard.getBindings() + setKey(pressed, name, ms){ + return this.keyboard.setKey(pressed, name, ms) } getElapsedTime(){ return this.game.elapsedTime diff --git a/public/src/js/debug.js b/public/src/js/debug.js index 844e8d1..a6fa9a7 100644 --- a/public/src/js/debug.js +++ b/public/src/js/debug.js @@ -202,11 +202,10 @@ class Debug{ this.controller.autoPlayEnabled = this.autoplayCheckbox.checked if(!this.controller.autoPlayEnabled){ var keyboard = debugObj.controller.keyboard - var kbd = keyboard.getBindings() - keyboard.setKey(kbd.don_l, false) - keyboard.setKey(kbd.don_r, false) - keyboard.setKey(kbd.ka_l, false) - keyboard.setKey(kbd.ka_r, false) + keyboard.setKey(false, "don_l") + keyboard.setKey(false, "don_r") + keyboard.setKey(false, "ka_l") + keyboard.setKey(false, "ka_r") } } } diff --git a/public/src/js/game.js b/public/src/js/game.js index 3417209..63a92b7 100644 --- a/public/src/js/game.js +++ b/public/src/js/game.js @@ -254,29 +254,28 @@ class Game{ return } var keys = this.controller.getKeys() - var kbd = this.controller.getBindings() - var don_l = keys[kbd["don_l"]] && !this.controller.isWaiting(kbd["don_l"], "score") - var don_r = keys[kbd["don_r"]] && !this.controller.isWaiting(kbd["don_r"], "score") - var ka_l = keys[kbd["ka_l"]] && !this.controller.isWaiting(kbd["ka_l"], "score") - var ka_r = keys[kbd["ka_r"]] && !this.controller.isWaiting(kbd["ka_r"], "score") + var don_l = keys["don_l"] && !this.controller.isWaiting("don_l", "score") + var don_r = keys["don_r"] && !this.controller.isWaiting("don_r", "score") + var ka_l = keys["ka_l"] && !this.controller.isWaiting("ka_l", "score") + var ka_r = keys["ka_r"] && !this.controller.isWaiting("ka_r", "score") var checkDon = () => { if(don_l && don_r){ - this.checkKey([kbd["don_l"], kbd["don_r"]], circle, "daiDon") + this.checkKey(["don_l", "don_r"], circle, "daiDon") }else if(don_l){ - this.checkKey([kbd["don_l"]], circle, "don") + this.checkKey(["don_l"], circle, "don") }else if(don_r){ - this.checkKey([kbd["don_r"]], circle, "don") + this.checkKey(["don_r"], circle, "don") } } var checkKa = () => { if(ka_l && ka_r){ - this.checkKey([kbd["ka_l"], kbd["ka_r"]], circle, "daiKa") + this.checkKey(["ka_l", "ka_r"], circle, "daiKa") }else if(ka_l){ - this.checkKey([kbd["ka_l"]], circle, "ka") + this.checkKey(["ka_l"], circle, "ka") }else if(ka_r){ - this.checkKey([kbd["ka_r"]], circle, "ka") + this.checkKey(["ka_r"], circle, "ka") } } var keyTime = this.controller.getKeyTime() diff --git a/public/src/js/gameinput.js b/public/src/js/gameinput.js new file mode 100644 index 0000000..4707652 --- /dev/null +++ b/public/src/js/gameinput.js @@ -0,0 +1,247 @@ +class GameInput{ + constructor(controller){ + this.controller = controller + this.game = this.controller.game + + this.keyboard = new Keyboard({ + ka_l: ["ka_l"], + don_l: ["don_l"], + don_r: ["don_r"], + ka_r: ["ka_r"], + pause: ["q", "esc"], + back: ["backspace"], + previous: ["left", "up"], + next: ["right", "down"], + confirm: ["enter", "space"] + }, this.keyPress.bind(this)) + this.keys = {} + this.waitKeyupScore = {} + this.waitKeyupSound = {} + this.waitKeyupMenu = {} + this.keyTime = { + "don": -Infinity, + "ka": -Infinity + } + this.keyboardEvents = 0 + + var layout = settings.getItem("gamepadLayout") + if(layout === "b"){ + var gameBtn = { + don_l: ["d", "r", "ls"], + don_r: ["a", "x", "rs"], + ka_l: ["u", "l", "lb", "lt"], + ka_r: ["b", "y", "rb", "rt"] + } + }else if(layout === "c"){ + var gameBtn = { + don_l: ["d", "l", "ls"], + don_r: ["a", "b", "rs"], + ka_l: ["u", "r", "lb", "lt"], + ka_r: ["x", "y", "rb", "rt"] + } + }else{ + var gameBtn = { + don_l: ["u", "d", "l", "r", "ls"], + don_r: ["a", "b", "x", "y", "rs"], + ka_l: ["lb", "lt"], + ka_r: ["rb", "rt"] + } + } + this.gamepad = new Gamepad(gameBtn) + this.gamepadInterval = setInterval(this.gamepadKeys.bind(this), 1000 / 60 / 2) + + this.gamepadMenu = new Gamepad({ + cancel: ["a"], + confirm: ["b", "ls", "rs"], + previous: ["u", "l", "lb", "lt", "lsu", "lsl"], + next: ["d", "r", "rb", "rt", "lsd", "lsr"], + pause: ["start"] + }) + + if(controller.multiplayer === 1){ + pageEvents.add(window, "beforeunload", event => { + if(p2.otherConnected){ + pageEvents.send("p2-abandoned", event) + } + }) + } + } + keyPress(pressed, name){ + if(!this.controller.autoPlayEnabled || this.game.isPaused() || name !== "don_l" && name !== "don_r" && name !== "ka_l" && name !== "ka_r"){ + this.setKey(pressed, name, this.game.getAccurateTime()) + } + } + checkGameKeys(){ + if(this.controller.autoPlayEnabled){ + this.checkKeySound("don_l", "don") + this.checkKeySound("don_r", "don") + this.checkKeySound("ka_l", "ka") + this.checkKeySound("ka_r", "ka") + } + } + gamepadKeys(){ + if(!this.game.isPaused() && !this.controller.autoPlayEnabled){ + this.gamepad.play((pressed, name) => { + if(pressed){ + if(this.keys[name]){ + this.setKey(false, name) + } + this.setKey(true, name, this.game.getAccurateTime()) + }else{ + this.setKey(false, name) + } + }) + } + } + checkMenuKeys(){ + if(!this.controller.multiplayer && !this.locked){ + var moveMenu = 0 + var ms = this.game.getAccurateTime() + this.gamepadMenu.play((pressed, name) => { + if(pressed){ + if(this.game.isPaused()){ + if(name === "cancel"){ + this.locked = true + return setTimeout(() => { + this.controller.togglePause() + this.locked = false + }, 200) + } + } + if(this.keys[name]){ + this.setKey(false, name) + } + this.setKey(true, name, ms) + }else{ + this.setKey(false, name) + } + }) + this.checkKey("pause", "menu", () => { + this.controller.togglePause() + for(var key in this.keyTime){ + this.keys[key] = null + this.keyTime[key] = -Infinity + } + }) + var moveMenuMinus = () => { + moveMenu = -1 + } + var moveMenuPlus = () => { + moveMenu = 1 + } + var moveMenuConfirm = () => { + if(this.game.isPaused()){ + this.locked = true + setTimeout(() => { + this.controller.view.pauseConfirm() + this.locked = false + }, 200) + } + } + this.checkKey("previous", "menu", moveMenuMinus) + this.checkKey("ka_l", "menu", moveMenuMinus) + this.checkKey("next", "menu", moveMenuPlus) + this.checkKey("ka_r", "menu", moveMenuPlus) + this.checkKey("confirm", "menu", moveMenuConfirm) + this.checkKey("don_l", "menu", moveMenuConfirm) + this.checkKey("don_r", "menu", moveMenuConfirm) + if(moveMenu && this.game.isPaused()){ + assets.sounds["se_ka"].play() + this.controller.view.pauseMove(moveMenu) + } + } + if(this.controller.multiplayer !== 2){ + this.checkKey("back", "menu", () => { + if(this.controller.multiplayer === 1 && p2.otherConnected){ + p2.send("gameend") + pageEvents.send("p2-abandoned") + } + this.controller.togglePause() + this.controller.songSelection() + }) + } + } + checkKey(name, type, callback){ + if(this.keys[name] && !this.isWaiting(name, type)){ + this.waitForKeyup(name, type) + callback() + } + } + checkKeySound(name, sound){ + this.checkKey(name, "sound", () => { + var circles = this.controller.getCircles() + var circle = circles[this.controller.getCurrentCircle()] + var currentTime = this.keyTime[name] + this.keyTime[sound] = currentTime + if(circle && !circle.isPlayed){ + if(circle.type === "balloon"){ + if(sound === "don" && circle.requiredHits - circle.timesHit <= 1){ + this.controller.playSound("se_balloon") + return + } + } + } + this.controller.playSound("neiro_1_" + sound) + }) + } + getKeys(){ + return this.keys + } + setKey(pressed, name, ms){ + if(pressed){ + this.keys[name] = true + this.waitKeyupScore[name] = false + this.waitKeyupSound[name] = false + this.waitKeyupMenu[name] = false + if(this.game.isPaused()){ + return + } + this.keyTime[name] = ms + if(name == "don_l" || name == "don_r"){ + this.checkKeySound(name, "don") + this.keyboardEvents++ + }else if(name == "ka_l" || name == "ka_r"){ + this.checkKeySound(name, "ka") + this.keyboardEvents++ + } + }else{ + this.keys[name] = false + this.waitKeyupScore[name] = false + this.waitKeyupSound[name] = false + this.waitKeyupMenu[name] = false + } + } + isWaiting(name, type){ + if(type === "score"){ + return this.waitKeyupScore[name] + }else if(type === "sound"){ + return this.waitKeyupSound[name] + }else if(type === "menu"){ + return this.waitKeyupMenu[name] + } + } + waitForKeyup(name, type){ + if(!this.keys[name]){ + return + } + if(type === "score"){ + this.waitKeyupScore[name] = true + }else if(type === "sound"){ + this.waitKeyupSound[name] = true + }else if(type === "menu"){ + this.waitKeyupMenu[name] = true + } + } + getKeyTime(){ + return this.keyTime + } + clean(){ + this.keyboard.clean() + this.gamepad.clean() + this.gamepadMenu.clean() + clearInterval(this.gamepadInterval) + if(this.controller.multiplayer === 1){ + pageEvents.remove(window, "beforeunload") + } + } +} diff --git a/public/src/js/gamepad.js b/public/src/js/gamepad.js index 2956c1a..a4b3327 100644 --- a/public/src/js/gamepad.js +++ b/public/src/js/gamepad.js @@ -1,6 +1,7 @@ class Gamepad{ constructor(bindings, callback){ this.bindings = bindings + this.callback = !!callback this.b = { "a": 0, "b": 1, @@ -87,6 +88,9 @@ class Gamepad{ for(var name in bindings[bind]){ var bindName = bindings[bind][name] this.checkButton(gamepads, this.b[bindName], bind, callback, force[bindName]) + if(!this.b){ + return + } } } break @@ -136,6 +140,11 @@ class Gamepad{ } } clean(){ - clearInterval(this.interval) + if(this.callback){ + clearInterval(this.interval) + } + delete this.bindings + delete this.b + delete this.btn } } diff --git a/public/src/js/keyboard.js b/public/src/js/keyboard.js index f038a44..949673b 100644 --- a/public/src/js/keyboard.js +++ b/public/src/js/keyboard.js @@ -1,266 +1,105 @@ class Keyboard{ - constructor(controller){ - this.controller = controller - this.game = this.controller.game - + constructor(bindings, callback){ + this.bindings = bindings + this.callback = callback + this.wildcard = false + this.substitute = { + "up": "arrowup", + "right": "arrowright", + "down": "arrowdown", + "left": "arrowleft", + "space": " ", + "esc": "escape", + "ctrl": "control", + "altgr": "altgraph" + } + this.btn = {} + this.update() + pageEvents.keyAdd(this, "all", "both", this.keyEvent.bind(this)) + pageEvents.blurAdd(this, this.blurEvent.bind(this)) + } + update(){ var kbdSettings = settings.getItem("keyboardSettings") - this.kbd = { - "ka_l": kbdSettings.ka_l[0], - "don_l": kbdSettings.don_l[0], - "don_r": kbdSettings.don_r[0], - "ka_r": kbdSettings.ka_r[0], - "pause": "q", - "back": "backspace", - "previous": "arrowleft", - "next": "arrowright", - "confirm": "enter" - } - this.kbdAlias = { - "pause": ["escape"], - "previous": ["arrowup"], - "next": ["arrowdown"], - "confirm": [" "] - } - this.keys = {} - this.waitKeyupScore = {} - this.waitKeyupSound = {} - this.waitKeyupMenu = {} - this.keyTime = { - "don": -Infinity, - "ka": -Infinity - } - this.keyboardEvents = 0 - - var gameBtn = {} - gameBtn[this.kbd["don_l"]] = ["u", "d", "l", "r", "ls"] - gameBtn[this.kbd["don_r"]] = ["a", "b", "x", "y", "rs"] - gameBtn[this.kbd["ka_l"]] = ["lb", "lt"] - gameBtn[this.kbd["ka_r"]] = ["rb", "rt"] - this.gamepad = new Gamepad(gameBtn) - this.gamepadInterval = setInterval(this.gamepadKeys.bind(this), 1000 / 60 / 2) - - var menuBtn = { - "cancel": ["a"], - } - menuBtn[this.kbd["confirm"]] = ["b", "ls", "rs"] - menuBtn[this.kbd["previous"]] = ["u", "l", "lb", "lt", "lsu", "lsl"], - menuBtn[this.kbd["next"]] = ["d", "r", "rb", "rt", "lsd", "lsr"] - menuBtn[this.kbd["pause"]] = ["start"] - this.gamepadMenu = new Gamepad(menuBtn) - - this.kbdSearch = {} - for(var name in this.kbdAlias){ - var list = this.kbdAlias[name] - for(var i in list){ - this.kbdSearch[list[i]] = this.kbd[name] + var drumKeys = {} + for(var name in kbdSettings){ + var keys = kbdSettings[name] + for(var i in keys){ + drumKeys[keys[i]] = name } } - for(var name in this.kbd){ - this.kbdSearch[this.kbd[name]] = this.kbd[name] - } - - pageEvents.keyAdd(this, "all", "both", event => { - if(event.keyCode === 27 || event.keyCode === 8 || event.keyCode === 9){ - // Escape, Backspace, Tab - event.preventDefault() - } - var key = this.kbdSearch[event.key.toLowerCase()] - if(key && !event.repeat && this.buttonEnabled(key)){ - var ms = this.game.getAccurateTime() - this.setKey(key, event.type === "keydown", ms) - if(event.type === "keydown"){ - this.keyboardEvents++ + this.kbd = {} + for(var name in this.bindings){ + var keys = this.bindings[name] + for(var i in keys){ + var key = keys[i] + if(key in drumKeys){ + continue } - } - }) - - if(controller.multiplayer === 1){ - pageEvents.add(window, "beforeunload", event => { - if(p2.otherConnected){ - pageEvents.send("p2-abandoned", event) - } - }) - } - } - getBindings(){ - return this.kbd - } - buttonEnabled(keyCode){ - if(this.controller.autoPlayEnabled){ - switch(keyCode){ - case this.kbd["don_l"]: - case this.kbd["don_r"]: - case this.kbd["ka_l"]: - case this.kbd["ka_r"]: - return false - } - } - return true - } - checkGameKeys(){ - if(this.controller.autoPlayEnabled){ - this.checkKeySound(this.kbd["don_l"], "don") - this.checkKeySound(this.kbd["don_r"], "don") - this.checkKeySound(this.kbd["ka_l"], "ka") - this.checkKeySound(this.kbd["ka_r"], "ka") - } - } - gamepadKeys(){ - if(!this.game.isPaused() && !this.controller.autoPlayEnabled){ - this.gamepad.play((pressed, keyCode) => { - if(pressed){ - if(this.keys[keyCode]){ - this.setKey(keyCode, false) - } - this.setKey(keyCode, true, this.game.getAccurateTime()) - }else{ - this.setKey(keyCode, false) - } - }) - } - } - checkMenuKeys(){ - if(!this.controller.multiplayer && !this.locked){ - var moveMenu = 0 - var ms = this.game.getAccurateTime() - this.gamepadMenu.play((pressed, keyCode) => { - if(pressed){ - if(this.game.isPaused()){ - if(keyCode === "cancel"){ - this.locked = true - return setTimeout(() => { - this.controller.togglePause() - this.locked = false - }, 200) + if(key in kbdSettings){ + var keyArray = kbdSettings[key] + for(var j in keyArray){ + key = keyArray[j] + if(!(key in this.kbd)){ + this.kbd[key] = name } } - if(this.keys[keyCode]){ - this.setKey(keyCode, false) - } - this.setKey(keyCode, true, ms) }else{ - this.setKey(keyCode, false) - } - }) - this.checkKey(this.kbd["pause"], "menu", () => { - this.controller.togglePause() - for(var key in this.keyTime){ - this.keys[key] = null - this.keyTime[key] = -Infinity - } - }) - var moveMenuMinus = () => { - moveMenu = -1 - } - var moveMenuPlus = () => { - moveMenu = 1 - } - var moveMenuConfirm = () => { - if(this.game.isPaused()){ - this.locked = true - setTimeout(() => { - this.controller.view.pauseConfirm() - this.locked = false - }, 200) - } - } - this.checkKey(this.kbd["previous"], "menu", moveMenuMinus) - this.checkKey(this.kbd["ka_l"], "menu", moveMenuMinus) - this.checkKey(this.kbd["next"], "menu", moveMenuPlus) - this.checkKey(this.kbd["ka_r"], "menu", moveMenuPlus) - this.checkKey(this.kbd["confirm"], "menu", moveMenuConfirm) - this.checkKey(this.kbd["don_l"], "menu", moveMenuConfirm) - this.checkKey(this.kbd["don_r"], "menu", moveMenuConfirm) - if(moveMenu && this.game.isPaused()){ - assets.sounds["se_ka"].play() - this.controller.view.pauseMove(moveMenu) - } - } - if(this.controller.multiplayer !== 2){ - this.checkKey(this.kbd["back"], "menu", () => { - if(this.controller.multiplayer === 1 && p2.otherConnected){ - p2.send("gameend") - pageEvents.send("p2-abandoned") - } - this.controller.togglePause() - this.controller.songSelection() - }) - } - } - checkKey(keyCode, type, callback){ - if(this.keys[keyCode] && !this.isWaiting(keyCode, type)){ - this.waitForKeyup(keyCode, type) - callback() - } - } - checkKeySound(keyCode, sound){ - this.checkKey(keyCode, "sound", () => { - var circles = this.controller.getCircles() - var circle = circles[this.controller.getCurrentCircle()] - var currentTime = this.keyTime[keyCode] - this.keyTime[sound] = currentTime - if(circle && !circle.isPlayed){ - if(circle.type === "balloon"){ - if(sound === "don" && circle.requiredHits - circle.timesHit <= 1){ - this.controller.playSound("se_balloon") - return + if(key in this.substitute){ + key = this.substitute[key] + } + if(!(key in this.kbd)){ + if(key === "wildcard"){ + this.wildcard = true + } + this.kbd[key] = name } } } - this.controller.playSound("neiro_1_" + sound) - }) + } } - getKeys(){ - return this.keys - } - setKey(keyCode, down, ms){ - if(down){ - this.keys[keyCode] = true - if(this.game.isPaused()){ - return + keyEvent(event){ + var key = event.key.toLowerCase() + if(key === "escape" || key === "backspace" || key === "tab"){ + event.preventDefault() + } + if(!event.repeat){ + var pressed = event.type === "keydown" + if(pressed){ + this.btn[key] = true + }else{ + delete this.btn[key] + if(key in this.kbd){ + for(var i in this.btn){ + if(this.kbd[i] === this.kbd[key]){ + return + } + } + } } - this.keyTime[keyCode] = ms - if(keyCode == this.kbd.don_l || keyCode == this.kbd.don_r){ - this.checkKeySound(keyCode, "don") - }else if(keyCode == this.kbd.ka_l || keyCode == this.kbd.ka_r){ - this.checkKeySound(keyCode, "ka") + if(key in this.kbd){ + this.callback(pressed, this.kbd[key], event) + }else if(this.wildcard){ + this.callback(pressed, this.kbd["wildcard"], event) } - }else{ - this.keys[keyCode] = false - this.waitKeyupScore[keyCode] = false - this.waitKeyupSound[keyCode] = false - this.waitKeyupMenu[keyCode] = false } } - isWaiting(keyCode, type){ - if(type === "score"){ - return this.waitKeyupScore[keyCode] - }else if(type === "sound"){ - return this.waitKeyupSound[keyCode] - }else if(type === "menu"){ - return this.waitKeyupMenu[keyCode] + blurEvent(){ + for(var key in this.btn){ + if(this.btn[key]){ + delete this.btn[key] + var name = this.kbd[key] || (this.wildcard ? "wildcard" : false) + if(name){ + this.callback(false, name) + } + } } } - waitForKeyup(keyCode, type){ - if(!this.keys[keyCode]){ - return - } - if(type === "score"){ - this.waitKeyupScore[keyCode] = true - }else if(type === "sound"){ - this.waitKeyupSound[keyCode] = true - }else if(type === "menu"){ - this.waitKeyupMenu[keyCode] = true - } - } - getKeyTime(){ - return this.keyTime - } clean(){ pageEvents.keyRemove(this, "all") - clearInterval(this.gamepadInterval) - if(this.controller.multiplayer === 1){ - pageEvents.remove(window, "beforeunload") - } + pageEvents.blurRemove(this) + delete this.bindings + delete this.callback + delete this.kbd + delete this.btn } } diff --git a/public/src/js/mekadon.js b/public/src/js/mekadon.js index eff1537..a58247e 100644 --- a/public/src/js/mekadon.js +++ b/public/src/js/mekadon.js @@ -50,7 +50,6 @@ class Mekadon{ } } playNow(circle, score, dai, reverse){ - var kbd = this.controller.getBindings() var type = circle.type var keyDai = false var playDai = !dai || dai === 2 @@ -70,20 +69,20 @@ class Mekadon{ } } if(type === "daiDon" && playDai){ - this.setKey(kbd["don_l"], ms) - this.setKey(kbd["don_r"], ms) + this.setKey("don_l", ms) + this.setKey("don_r", ms) this.lr = false keyDai = true }else if(type === "don" || type === "daiDon" || drumrollNotes && score !== 2){ - this.setKey(this.lr ? kbd["don_l"] : kbd["don_r"], ms) + this.setKey(this.lr ? "don_l" : "don_r", ms) this.lr = !this.lr }else if(type === "daiKa" && playDai){ - this.setKey(kbd["ka_l"], ms) - this.setKey(kbd["ka_r"], ms) + this.setKey("ka_l", ms) + this.setKey("ka_r", ms) this.lr = false keyDai = true }else if(type === "ka" || type === "daiKa" || drumrollNotes){ - this.setKey(this.lr ? kbd["ka_l"] : kbd["ka_r"], ms) + this.setKey(this.lr ? "ka_l" : "ka_r", ms) this.lr = !this.lr } if(type === "balloon"){ @@ -110,8 +109,7 @@ class Mekadon{ getMS(){ return this.controller.getElapsedTime() } - setKey(keyCode, ms){ - this.controller.setKey(keyCode, false) - this.controller.setKey(keyCode, true, ms) + setKey(name, ms){ + this.controller.setKey(true, name, ms) } } diff --git a/public/src/js/pageevents.js b/public/src/js/pageevents.js index c180802..c8c0af7 100644 --- a/public/src/js/pageevents.js +++ b/public/src/js/pageevents.js @@ -3,10 +3,12 @@ class PageEvents{ this.allEvents = new Map() this.keyListeners = new Map() this.mouseListeners = new Map() + this.blurListeners = new Map() this.lastKeyEvent = -Infinity this.add(window, "keydown", this.keyEvent.bind(this)) this.add(window, "keyup", this.keyEvent.bind(this)) this.add(window, "mousemove", this.mouseEvent.bind(this)) + this.add(window, "blur", this.blurEvent.bind(this)) this.kbd = [] } add(target, type, callback){ @@ -142,6 +144,15 @@ class PageEvents{ mouseRemove(target){ this.mouseListeners.delete(target) } + blurEvent(event){ + this.blurListeners.forEach(callback => callback(event)) + } + blurAdd(target, callback){ + this.blurListeners.set(target, callback) + } + blurRemove(target){ + this.blurListeners.delete(target) + } getMouse(){ return this.lastMouse } @@ -149,12 +160,13 @@ class PageEvents{ dispatchEvent(new CustomEvent(name, {detail: detail})) } setKbd(){ + this.kbd = [] var kbdSettings = settings.getItem("keyboardSettings") - this.kbd = [ - kbdSettings.ka_l[0], - kbdSettings.don_l[0], - kbdSettings.don_r[0], - kbdSettings.ka_r[0] - ] + for(var name in kbdSettings){ + var keys = kbdSettings[name] + for(var i in keys){ + this.kbd.push(keys[i]) + } + } } } diff --git a/public/src/js/scoresheet.js b/public/src/js/scoresheet.js index 4d0360c..24fde5d 100644 --- a/public/src/js/scoresheet.js +++ b/public/src/js/scoresheet.js @@ -31,13 +31,12 @@ class Scoresheet{ this.draw = new CanvasDraw() this.canvasCache = new CanvasCache() - var kbdSettings = settings.getItem("keyboardSettings") - this.kbd = { - confirm: ["enter", " ", "escape", "backspace", kbdSettings.don_l[0], kbdSettings.don_r[0]] - } + this.keyboard = new Keyboard({ + confirm: ["enter", "space", "esc", "don_l", "don_r"] + }, this.keyDown.bind(this)) this.gamepad = new Gamepad({ confirm: ["a", "b", "start", "ls", "rs"] - }) + }, this.keyDown.bind(this)) this.difficulty = { "easy": 0, @@ -76,22 +75,8 @@ class Scoresheet{ touchEvents: controller.view.touchEvents }) } - keyDown(event, key){ - if(!key){ - if(event.repeat){ - return - } - for(var i in this.kbd){ - if(this.kbd[i].indexOf(event.key.toLowerCase()) !== -1){ - key = i - break - } - } - } - if(event && event.keyCode === 27 || event.keyCode === 8 || event.keyCode === 9){ - event.preventDefault() - } - if(key === "confirm"){ + keyDown(pressed){ + if(pressed && this.redrawing){ this.toNext() } } @@ -140,7 +125,6 @@ class Scoresheet{ this.winW = null this.winH = null - pageEvents.keyAdd(this, "all", "down", this.keyDown.bind(this)) pageEvents.add(this.canvas, ["mousedown", "touchstart"], this.mouseDown.bind(this)) if(!this.multiplayer){ @@ -180,12 +164,6 @@ class Scoresheet{ } var ms = this.getMS() - this.gamepad.play((pressed, keyCode) => { - if(pressed){ - this.keyDown(false, keyCode) - } - }) - if(!this.redrawRunning){ return } @@ -864,12 +842,13 @@ class Scoresheet{ } clean(){ + this.keyboard.clean() + this.gamepad.clean() this.draw.clean() this.canvasCache.clean() assets.sounds["bgm_result"].stop() snd.buffer.loadSettings() this.redrawRunning = false - pageEvents.keyRemove(this, "all") pageEvents.remove(this.canvas, ["mousedown", "touchstart"]) if(this.multiplayer !== 2 && this.touchEnabled){ pageEvents.remove(document.getElementById("touch-full-btn"), "touchend") diff --git a/public/src/js/session.js b/public/src/js/session.js index 43efa9e..0f08c67 100644 --- a/public/src/js/session.js +++ b/public/src/js/session.js @@ -2,13 +2,13 @@ class Session{ constructor(touchEnabled){ this.touchEnabled = touchEnabled loader.changePage("session", true) - this.endButton = document.getElementById("tutorial-end-button") + this.endButton = this.getElement("view-end-button") if(touchEnabled){ - document.getElementById("tutorial-outer").classList.add("touch-enabled") + this.getElement("view-outer").classList.add("touch-enabled") } this.sessionInvite = document.getElementById("session-invite") - var tutorialTitle = document.getElementById("tutorial-title") + var tutorialTitle = this.getElement("view-title") tutorialTitle.innerText = strings.session.multiplayerSession tutorialTitle.setAttribute("alt", strings.session.multiplayerSession) this.sessionInvite.parentNode.insertBefore(document.createTextNode(strings.session.linkTutorial), this.sessionInvite) @@ -16,11 +16,12 @@ class Session{ this.endButton.setAttribute("alt", strings.session.cancel) pageEvents.add(window, ["mousedown", "touchstart"], this.mouseDown.bind(this)) - pageEvents.keyOnce(this, 27, "down").then(this.onEnd.bind(this)) - + this.keyboard = new Keyboard({ + confirm: ["esc"] + }, this.keyPress.bind(this)) this.gamepad = new Gamepad({ - "confirm": ["start", "b", "ls", "rs"] - }, this.onEnd.bind(this)) + confirm: ["start", "b", "ls", "rs"] + }, this.keyPress.bind(this)) p2.hashLock = true pageEvents.add(p2, "message", response => { @@ -29,13 +30,16 @@ class Session{ p2.hash(response.value) }else if(response.type === "songsel"){ p2.clearMessage("users") - this.onEnd(false, true) + this.onEnd(true) pageEvents.send("session-start", "host") } }) p2.send("invite") pageEvents.send("session") } + getElement(name){ + return loader.screen.getElementsByClassName(name)[0] + } mouseDown(event){ if(event.type === "mousedown" && event.which !== 1){ return @@ -50,7 +54,12 @@ class Session{ this.onEnd() } } - onEnd(event, fromP2){ + keyPress(pressed){ + if(pressed){ + this.onEnd() + } + } + onEnd(fromP2){ if(!p2.session){ p2.send("leave") p2.hash("") @@ -59,9 +68,6 @@ class Session{ }else if(!fromP2){ return p2.send("songsel") } - if(event && event.type === "keydown"){ - event.preventDefault() - } this.clean() assets.sounds["se_don"].play() setTimeout(() => { @@ -69,9 +75,9 @@ class Session{ }, 500) } clean(){ + this.keyboard.clean() this.gamepad.clean() pageEvents.remove(window, ["mousedown", "touchstart"]) - pageEvents.keyRemove(this, 27) pageEvents.remove(p2, "message") delete this.endButton delete this.sessionInvite diff --git a/public/src/js/settings.js b/public/src/js/settings.js index d17c92b..572d1ae 100644 --- a/public/src/js/settings.js +++ b/public/src/js/settings.js @@ -28,6 +28,12 @@ class Settings{ ka_r: ["k"] }, touch: false + }, + gamepadLayout: { + type: "gamepad", + options: ["a", "b", "c"], + default: "a", + gamepad: true } } @@ -42,7 +48,7 @@ class Settings{ this.storage[i] = null } }else if(i in storage){ - if(current.type === "select" && current.options.indexOf(storage[i]) === -1){ + if((current.type === "select" || current.type === "gamepad") && current.options.indexOf(storage[i]) === -1){ this.storage[i] = null }else if(current.type === "keyboard"){ var obj = {} @@ -116,29 +122,50 @@ class Settings{ } class SettingsView{ - constructor(touchEnabled, tutorial){ + constructor(touchEnabled, tutorial, songId){ this.touchEnabled = touchEnabled this.tutorial = tutorial - if(!tutorial){ - loader.changePage("settings", tutorial) - assets.sounds["bgm_settings"].playLoop(0.1, false, 0, 1.392, 26.992) - this.defaultButton = document.getElementById("settings-default") - }else if(touchEnabled){ - document.getElementById("tutorial-outer").classList.add("settings-outer") - } + this.songId = songId + + loader.changePage("settings", tutorial) + assets.sounds["bgm_settings"].playLoop(0.1, false, 0, 1.392, 26.992) + this.defaultButton = document.getElementById("settings-default") if(touchEnabled){ - document.getElementById("tutorial-outer").classList.add("touch-enabled") + this.getElement("view-outer").classList.add("touch-enabled") + } + var gamepadEnabled = false + if("getGamepads" in navigator){ + var gamepads = navigator.getGamepads() + for(var i = 0; i < gamepads.length; i++){ + if(gamepads[i]){ + gamepadEnabled = true + break + } + } } this.mode = "settings" - this.tutorialTitle = document.getElementById("tutorial-title") - this.endButton = document.getElementById("tutorial-end-button") - if(!tutorial){ - this.setStrings() - } + this.keyboard = new Keyboard({ + "confirm": ["enter", "space", "don_l", "don_r"], + "up": ["up"], + "previous": ["left", "ka_l"], + "next": ["right", "down", "ka_r"], + "back": ["esc"], + "other": ["wildcard"] + }, this.keyPressed.bind(this)) + this.gamepad = new Gamepad({ + "confirm": ["b", "ls", "rs"], + "up": ["u", "lsu"], + "previous": ["l", "lb", "lt", "lsl"], + "next": ["d", "r", "rb", "rt", "lsd", "lsr"], + "back": ["start", "a"] + }, this.keyPressed.bind(this)) + + this.viewTitle = this.getElement("view-title") + this.endButton = this.getElement("view-end-button") this.resolution = settings.getItem("resolution") - var content = document.getElementById("tutorial-content") + var content = this.getElement("view-content") this.items = [] this.selected = tutorial ? 1 : 0 for(let i in settings.items){ @@ -146,6 +173,7 @@ class SettingsView{ if( !touchEnabled && current.touch === true || touchEnabled && current.touch === false || + !gamepadEnabled && current.gamepad === true || tutorial && current.type !== "language" ){ continue @@ -166,12 +194,7 @@ class SettingsView{ if(this.items.length === this.selected){ settingBox.classList.add("selected") } - pageEvents.add(settingBox, ["mousedown", "touchstart"], event => { - if(event.type !== "mousedown" || event.which === 1){ - event.preventDefault() - this.setValue(i) - } - }) + this.addTouch(settingBox, event => this.setValue(i)) this.items.push({ id: i, settingBox: settingBox, @@ -179,58 +202,82 @@ class SettingsView{ valueDiv: valueDiv }) } - if(!tutorial){ + if(tutorial){ + this.defaultButton.style.display = "none" + this.endButton.classList.add("selected") + }else{ this.items.push({ id: "default", settingBox: this.defaultButton }) - pageEvents.add(this.defaultButton, ["mousedown", "touchstart"], this.defaultSettings.bind(this)) + this.addTouch(this.defaultButton, this.defaultSettings.bind(this)) } this.items.push({ id: "back", settingBox: this.endButton }) + this.addTouch(this.endButton, this.onEnd.bind(this)) - this.setKbd() - pageEvents.add(this.endButton, ["mousedown", "touchstart"], this.onEnd.bind(this)) - pageEvents.keyAdd(this, "all", "down", this.keyEvent.bind(this)) - this.gamepad = new Gamepad({ - "confirm": ["b", "ls", "rs"], - "up": ["u", "lsu"], - "previous": ["l", "lb", "lt", "lsl"], - "next": ["d", "r", "rb", "rt", "lsd", "lsr"], - "back": ["start", "a"] - }, this.keyPressed.bind(this)) - if(!tutorial){ - pageEvents.send("settings") - } + this.gamepadSettings = document.getElementById("settings-gamepad") + this.addTouch(this.gamepadSettings, event => { + if(event.target === event.currentTarget){ + this.gamepadBack() + } + }) + this.gamepadTitle = this.gamepadSettings.getElementsByClassName("view-title")[0] + this.gamepadEndButton = this.gamepadSettings.getElementsByClassName("view-end-button")[0] + this.addTouch(this.gamepadEndButton, event => this.gamepadBack(true)) + this.gamepadBg = document.getElementById("gamepad-bg") + this.addTouch(this.gamepadBg, event => this.gamepadSet(1)) + this.gamepadButtons = document.getElementById("gamepad-buttons") + this.gamepadValue = document.getElementById("gamepad-value") + + this.setStrings() + + pageEvents.send("settings") } - setKbd(){ - var kbdSettings = settings.getItem("keyboardSettings") - this.kbd = { - "confirm": ["enter", " ", kbdSettings.don_l[0], kbdSettings.don_r[0]], - "up": ["arrowup"], - "previous": ["arrowleft", kbdSettings.ka_l[0]], - "next": ["arrowright", "arrowdown", kbdSettings.ka_r[0]], - "back": ["backspace", "escape"] - } + getElement(name){ + return loader.screen.getElementsByClassName(name)[0] + } + addTouch(element, callback){ + pageEvents.add(element, ["mousedown", "touchstart"], event => { + if(event.type === "touchstart"){ + event.preventDefault() + this.touched = true + }else if(event.which !== 1){ + return + }else{ + this.touched = false + } + callback(event) + }) + } + removeTouch(element){ + pageEvents.remove(element, ["mousedown", "touchstart"]) } getValue(name, valueDiv){ var current = settings.items[name] var value = settings.getItem(name) if(current.type === "language"){ value = allStrings[value].name + " (" + value + ")" - }else if(current.type === "select"){ + }else if(current.type === "select" || current.type === "gamepad"){ value = strings.settings[name][value] }else if(current.type === "toggle"){ value = value ? strings.settings.on : strings.settings.off }else if(current.type === "keyboard"){ valueDiv.innerHTML = "" for(var i in value){ - var key = document.createElement("div") - key.style.color = i === "ka_l" || i === "ka_r" ? "#009aa5" : "#ef2c10" - key.innerText = value[i][0].toUpperCase() - valueDiv.appendChild(key) + var keyDiv = document.createElement("div") + keyDiv.style.color = i === "ka_l" || i === "ka_r" ? "#009aa5" : "#ef2c10" + var key = value[i][0] + for(var j in this.keyboard.substitute){ + if(this.keyboard.substitute[j] === key){ + key = j + break + } + } + keyDiv.innerText = key.toUpperCase() + valueDiv.appendChild(keyDiv) } return } @@ -264,6 +311,12 @@ class SettingsView{ this.keyboardSet() assets.sounds["se_don"].play() return + }else if(current.type === "gamepad"){ + this.mode = "gamepad" + this.gamepadSelected = current.options.indexOf(value) + this.gamepadSet() + assets.sounds["se_don"].play() + return } settings.setItem(name, value) this.getValue(name, this.items[this.selected].valueDiv) @@ -272,37 +325,11 @@ class SettingsView{ this.setLang(allStrings[value]) } } - keyEvent(event){ - if(event.keyCode === 27 || event.keyCode === 8 || event.keyCode === 9){ - // Escape, Backspace, Tab - event.preventDefault() - } - if(!event.repeat){ - for(var i in this.kbd){ - if(this.kbd[i].indexOf(event.key.toLowerCase()) !== -1){ - if(this.mode !== "keyboard" || i === "back"){ - this.keyPressed(true, i) - return - } - } - } - if(this.mode === "keyboard"){ - event.preventDefault() - var currentKey = event.key.toLowerCase() - for(var i in this.keyboardKeys){ - if(this.keyboardKeys[i][0] === currentKey || !currentKey){ - return - } - } - this.keyboardKeys[this.keyboardCurrent] = [currentKey] - this.keyboardSet() - } - } - } - keyPressed(pressed, name){ + keyPressed(pressed, name, event){ if(!pressed){ return } + this.touched = false var selected = this.items[this.selected] if(this.mode === "settings"){ if(name === "confirm"){ @@ -325,9 +352,30 @@ class SettingsView{ }else if(name === "back"){ this.onEnd() } + }else if(this.mode === "gamepad"){ + if(name === "confirm"){ + this.gamepadBack(true) + }else if(name === "up" || name === "previous" || name === "next"){ + this.gamepadSet(name === "next" ? 1 : -1) + }else if(name === "back"){ + this.gamepadBack() + } }else if(this.mode === "keyboard"){ if(name === "back"){ this.keyboardBack(selected) + assets.sounds["se_cancel"].play() + }else{ + event.preventDefault() + var currentKey = event.key.toLowerCase() + for(var i in this.keyboardKeys){ + if(this.keyboardKeys[i][0] === currentKey || !currentKey){ + return + } + } + var current = this.keyboardCurrent + assets.sounds[current === "ka_l" || current === "ka_r" ? "se_ka" : "se_don"].play() + this.keyboardKeys[current] = [currentKey] + this.keyboardSet() } } } @@ -336,21 +384,28 @@ class SettingsView{ var current = settings.items[selected.id] selected.valueDiv.innerHTML = "" for(var i in current.default){ - var key = document.createElement("div") - key.style.color = i === "ka_l" || i === "ka_r" ? "#009aa5" : "#ef2c10" + var keyDiv = document.createElement("div") + keyDiv.style.color = i === "ka_l" || i === "ka_r" ? "#009aa5" : "#ef2c10" if(this.keyboardKeys[i]){ - key.innerText = this.keyboardKeys[i][0].toUpperCase() - selected.valueDiv.appendChild(key) + var key = this.keyboardKeys[i][0] + for(var j in this.keyboard.substitute){ + if(this.keyboard.substitute[j] === key){ + key = j + break + } + } + keyDiv.innerText = key.toUpperCase() + selected.valueDiv.appendChild(keyDiv) }else{ - key.innerText = "[" + strings.settings[selected.id][i] + "]" - selected.valueDiv.appendChild(key) + keyDiv.innerText = "[" + strings.settings[selected.id][i] + "]" + selected.valueDiv.appendChild(keyDiv) this.keyboardCurrent = i return } } settings.setItem(selected.id, this.keyboardKeys) this.keyboardBack(selected) - this.setKbd() + this.keyboard.update() pageEvents.setKbd() } keyboardBack(selected){ @@ -359,10 +414,38 @@ class SettingsView{ selected.valueDiv.classList.remove("selected") this.getValue(selected.id, selected.valueDiv) } - defaultSettings(event){ - if(event && event.type === "touchstart"){ - event.preventDefault() + gamepadSet(diff){ + if(this.mode !== "gamepad"){ + return } + var selected = this.items[this.selected] + var current = settings.items[selected.id] + if(diff){ + this.gamepadSelected = this.mod(current.options.length, this.gamepadSelected + diff) + assets.sounds["se_ka"].play() + } + var opt = current.options[this.gamepadSelected] + this.gamepadValue.innerText = strings.settings[selected.id][opt] + this.gamepadButtons.style.backgroundPosition = "0 " + (-318 - 132 * this.gamepadSelected) + "px" + this.gamepadSettings.style.display = "block" + } + gamepadBack(save){ + if(this.mode !== "gamepad"){ + return + } + if(save){ + var selected = this.items[this.selected] + var current = settings.items[selected.id] + settings.setItem(selected.id, current.options[this.gamepadSelected]) + this.getValue(selected.id, selected.valueDiv) + assets.sounds["se_don"].play() + }else{ + assets.sounds["se_cancel"].play() + } + this.gamepadSettings.style.display = "" + this.mode = "settings" + } + defaultSettings(){ if(this.mode === "keyboard"){ this.keyboardBack(this.items[this.selected]) } @@ -370,27 +453,19 @@ class SettingsView{ settings.setItem(i, null) } this.setLang(allStrings[settings.getItem("language")]) - this.setKbd() + this.keyboard.update() + pageEvents.setKbd() assets.sounds["se_don"].play() } - onEnd(event){ - if(this.tutorial){ - this.clean() - return this.tutorial.onEnd(event) - } - var touched = false - if(event){ - if(event.type === "touchstart"){ - event.preventDefault() - touched = true - }else if(event.which !== 1){ - return - } - } + onEnd(){ this.clean() assets.sounds["se_don"].play() setTimeout(() => { - new SongSelect("settings", false, touched) + if(this.tutorial && !this.touched){ + new Tutorial(false, this.songId) + }else{ + new SongSelect(this.tutorial ? false : "settings", false, this.touched, this.songId) + } }, 500) } setLang(lang){ @@ -410,33 +485,44 @@ class SettingsView{ this.setStrings() } setStrings(){ - if(this.tutorial){ - this.tutorial.setStrings() - }else{ - this.tutorialTitle.innerText = strings.gameSettings - this.tutorialTitle.setAttribute("alt", strings.gameSettings) + this.viewTitle.innerText = strings.gameSettings + this.viewTitle.setAttribute("alt", strings.gameSettings) + this.endButton.innerText = strings.settings.ok + this.endButton.setAttribute("alt", strings.settings.ok) + this.gamepadTitle.innerText = strings.settings.gamepadLayout.name + this.gamepadTitle.setAttribute("alt", strings.settings.gamepadLayout.name) + this.gamepadEndButton.innerText = strings.settings.ok + this.gamepadEndButton.setAttribute("alt", strings.settings.ok) + if(!this.tutorial){ this.defaultButton.innerText = strings.settings.default this.defaultButton.setAttribute("alt", strings.settings.default) - this.endButton.innerText = strings.settings.ok - this.endButton.setAttribute("alt", strings.settings.ok) } } mod(length, index){ return ((index % length) + length) % length } clean(){ + this.keyboard.clean() this.gamepad.clean() assets.sounds["bgm_settings"].stop() - pageEvents.keyRemove(this, "all") for(var i in this.items){ - pageEvents.remove(this.items[i].settingBox, ["mousedown", "touchstart"]) + this.removeTouch(this.items[i].settingBox) } if(this.defaultButton){ delete this.defaultButton } + this.removeTouch(this.gamepadSettings) + this.removeTouch(this.gamepadEndButton) + this.removeTouch(this.gamepadBg) delete this.tutorialTitle delete this.endButton delete this.items + delete this.gamepadSettings + delete this.gamepadTitle + delete this.gamepadEndButton + delete this.gamepadBg + delete this.gamepadButtons + delete this.gamepadValue if(this.resolution !== settings.getItem("resolution")){ for(var i in assets.image){ if(i === "touch_drum" || i.startsWith("bg_song_") || i.startsWith("bg_stage_") || i.startsWith("bg_don_")){ diff --git a/public/src/js/songselect.js b/public/src/js/songselect.js index ea7ba1b..f50dbc1 100644 --- a/public/src/js/songselect.js +++ b/public/src/js/songselect.js @@ -289,16 +289,17 @@ class SongSelect{ this.startPreview(true) this.pressedKeys = {} - var kbdSettings = settings.getItem("keyboardSettings") - this.kbd = { - confirm: ["enter", " ", kbdSettings.don_l[0], kbdSettings.don_r[0]], + this.keyboard = new Keyboard({ + confirm: ["enter", "space", "don_l", "don_r"], back: ["escape"], - left: ["arrowleft", kbdSettings.ka_l[0]], - right: ["arrowright", kbdSettings.ka_r[0]], - up: ["arrowup"], - down: ["arrowdown"], - session: ["backspace"] - } + left: ["left", "ka_l"], + right: ["right", "ka_r"], + up: ["up"], + down: ["down"], + session: ["backspace"], + ctrl: ["ctrl"], + shift: ["shift"] + }, this.keyPress.bind(this)) this.gamepad = new Gamepad({ confirm: ["b", "start", "ls", "rs"], back: ["a"], @@ -309,13 +310,12 @@ class SongSelect{ session: ["back"], ctrl: ["y"], shift: ["x"] - }) + }, this.keyPress.bind(this)) if(!assets.customSongs){ this.startP2() } - pageEvents.keyAdd(this, "all", "down", this.keyDown.bind(this)) pageEvents.add(loader.screen, "mousemove", this.mouseMove.bind(this)) pageEvents.add(loader.screen, "mouseleave", () => { this.state.moveHover = null @@ -341,61 +341,47 @@ class SongSelect{ } } - keyDown(event, key){ - if(key){ - var modifiers = { - shift: this.pressedKeys["shift"], - ctrl: this.pressedKeys["ctrl"] + keyPress(pressed, name, event){ + if(pressed){ + if(!this.pressedKeys[name]){ + this.pressedKeys[name] = this.getMS() + 300 } }else{ - var modifiers = { - shift: event.shiftKey, - ctrl: event.ctrlKey - } - for(var i in this.kbd){ - if(this.kbd[i].indexOf(event.key.toLowerCase()) !== -1){ - key = i - break - } - } - } - if(key === "ctrl" || key === "shift" || !this.redrawRunning){ + this.pressedKeys[name] = 0 return } - - if(event && (event.keyCode === 27 || event.keyCode === 8 || event.keyCode === 9)){ - // Escape, Backspace, Tab - event.preventDefault() + if(name === "ctrl" || name === "shift" || !this.redrawRunning){ + return } if(this.state.screen === "song"){ - if(key === "confirm"){ + if(name === "confirm"){ this.toSelectDifficulty() - }else if(key === "back"){ + }else if(name === "back"){ this.toTitleScreen() - }else if(key === "session"){ + }else if(name === "session"){ this.toSession() - }else if(key === "left"){ + }else if(name === "left"){ this.moveToSong(-1) - }else if(key === "right"){ + }else if(name === "right"){ this.moveToSong(1) } }else if(this.state.screen === "difficulty"){ - if(key === "confirm"){ + if(name === "confirm"){ if(this.selectedDiff === 0){ this.toSongSelect() }else if(this.selectedDiff === 1){ this.toOptions(1) }else{ - this.toLoadSong(this.selectedDiff - this.diffOptions.length, modifiers.shift, modifiers.ctrl) + this.toLoadSong(this.selectedDiff - this.diffOptions.length, this.pressedKeys["shift"], this.pressedKeys["ctrl"]) } - }else if(key === "back" || key === "session"){ + }else if(name === "back" || name === "session"){ this.toSongSelect() - }else if(key === "left"){ + }else if(name === "left"){ this.moveToDiff(-1) - }else if(key === "right"){ + }else if(name === "right"){ this.moveToDiff(1) - }else if(this.selectedDiff === 1 && (key === "up" || key === "down")){ - this.toOptions(key === "up" ? -1 : 1) + }else if(this.selectedDiff === 1 && (name === "up" || name === "down")){ + this.toOptions(name === "up" ? -1 : 1) } } } @@ -781,20 +767,10 @@ class SongSelect{ requestAnimationFrame(this.redrawBind) var ms = this.getMS() - this.gamepad.play((pressed, keyCode) => { - if(pressed){ - if(!this.pressedKeys[keyCode]){ - this.pressedKeys[keyCode] = ms + 300 - this.keyDown(false, keyCode) - } - }else{ - this.pressedKeys[keyCode] = 0 - } - }) for(var key in this.pressedKeys){ if(this.pressedKeys[key]){ if(ms >= this.pressedKeys[key] + 50){ - this.keyDown(false, key) + this.keyPress(true, key) this.pressedKeys[key] = ms } } @@ -1957,6 +1933,8 @@ class SongSelect{ } clean(){ + this.keyboard.clean() + this.gamepad.clean() this.clearHash() this.draw.clean() this.songTitleCache.clean() @@ -1979,7 +1957,6 @@ class SongSelect{ song.preview_sound.clean() } }) - pageEvents.keyRemove(this, "all") pageEvents.remove(loader.screen, ["mousemove", "mouseleave", "mousedown", "touchstart"]) pageEvents.remove(this.canvas, "touchend") pageEvents.remove(p2, "message") diff --git a/public/src/js/strings.js b/public/src/js/strings.js index 57134ef..eb77015 100644 --- a/public/src/js/strings.js +++ b/public/src/js/strings.js @@ -120,6 +120,12 @@ don_r: "面(右)", ka_r: "ふち(右)" }, + gamepadLayout: { + name: "そうさタイプ設定", + a: "タイプA", + b: "タイプB", + c: "タイプC" + }, on: "オン", off: "オフ", default: "既定値にリセット", @@ -254,6 +260,12 @@ function StringsEn(){ don_r: "Right Surface", ka_r: "Right Rim" }, + gamepadLayout: { + name: "Gamepad Layout", + a: "Type A", + b: "Type B", + c: "Type C" + }, on: "On", off: "Off", default: "Reset to Defaults", @@ -383,10 +395,16 @@ function StringsCn(){ }, keyboardSettings: { name: "键盘设置", - ka_l: "Left Rim", - don_l: "Left Surface", - don_r: "Right Surface", - ka_r: "Right Rim" + ka_l: "边缘(左)", + don_l: "表面(左)", + don_r: "表面(右)", + ka_r: "边缘(右)" + }, + gamepadLayout: { + name: "操作类型设定", + a: "类型A", + b: "类型B", + c: "类型C" }, on: "开", off: "关", @@ -517,10 +535,16 @@ function StringsTw(){ }, keyboardSettings: { name: "鍵盤設置", - ka_l: "Left Rim", - don_l: "Left Surface", - don_r: "Right Surface", - ka_r: "Right Rim" + ka_l: "邊緣(左)", + don_l: "表面(左)", + don_r: "表面(右)", + ka_r: "邊緣(右)" + }, + gamepadLayout: { + name: "操作類型設定", + a: "類型A", + b: "類型B", + c: "類型C" }, on: "開", off: "關", @@ -651,10 +675,16 @@ function StringsKo(){ }, keyboardSettings: { name: "키보드 설정", - ka_l: "Left Rim", - don_l: "Left Surface", - don_r: "Right Surface", - ka_r: "Right Rim" + ka_l: "가장자리 (왼쪽)", + don_l: "표면 (왼쪽)", + don_r: "표면 (오른쪽)", + ka_r: "가장자리 (오른쪽)" + }, + gamepadLayout: { + name: "조작 타입 설정", + a: "타입 A", + b: "타입 B", + c: "타입 C" }, on: "온", off: "오프", diff --git a/public/src/js/titlescreen.js b/public/src/js/titlescreen.js index a5ba7b6..6068a93 100644 --- a/public/src/js/titlescreen.js +++ b/public/src/js/titlescreen.js @@ -17,24 +17,26 @@ class Titlescreen{ if(localStorage.getItem("tutorial") === "true"){ new SongSelect(false, false, this.touched, this.songId) }else{ - new Tutorial(false, this.songId) + new SettingsView(false, true, this.songId) } }else{ - pageEvents.keyAdd(this, "all", "down", this.keyDown.bind(this)) - pageEvents.add(this.titleScreen, ["mousedown", "touchstart"], this.onPressed.bind(this)) + pageEvents.add(this.titleScreen, ["mousedown", "touchstart"], event => { + if(event.type === "touchstart"){ + event.preventDefault() + this.touched = true + }else if(event.type === "mousedown" && event.which !== 1){ + return + } + this.onPressed(true) + }) assets.sounds["v_title"].play() - var kbdSettings = settings.getItem("keyboardSettings") - this.kbd = { - confirm: ["enter", " ", kbdSettings.don_l[0], kbdSettings.don_r[0]] - } + this.keyboard = new Keyboard({ + confirm: ["enter", "space", "don_l", "don_r"] + }, this.onPressed.bind(this)) this.gamepad = new Gamepad({ confirm: ["a", "b", "x", "y", "start", "ls", "rs"] - }, pressed => { - if(pressed){ - this.onPressed() - } - }) + }, this.onPressed.bind(this)) if(p2.session){ pageEvents.add(p2, "message", response => { if(response.type === "songsel"){ @@ -46,35 +48,13 @@ class Titlescreen{ } } - keyDown(event, key){ - if(!key){ - if(event.repeat || event.target === this.langDropdown){ - return - } - for(var i in this.kbd){ - if(this.kbd[i].indexOf(event.key.toLowerCase()) !== -1){ - key = i - break - } - } + onPressed(pressed, name){ + if(pressed){ + this.titleScreen.style.cursor = "auto" + this.clean() + assets.sounds["se_don"].play() + this.goNext() } - if(key === "confirm"){ - this.onPressed() - } - } - onPressed(event){ - if(event){ - if(event.type === "touchstart"){ - event.preventDefault() - this.touched = true - }else if(event.type === "mousedown" && event.which !== 1){ - return - } - } - this.titleScreen.style.cursor = "auto" - this.clean() - assets.sounds["se_don"].play() - this.goNext() } goNext(fromP2){ if(p2.session && !fromP2){ @@ -89,7 +69,7 @@ class Titlescreen{ }, 500) }else{ setTimeout(() => { - new Tutorial(false, this.songId, this.touched) + new SettingsView(this.touched, true, this.songId) }, 500) } } @@ -109,10 +89,10 @@ class Titlescreen{ this.logo.updateSubtitle() } clean(){ + this.keyboard.clean() this.gamepad.clean() this.logo.clean() assets.sounds["v_title"].stop() - pageEvents.keyRemove(this, "all") pageEvents.remove(this.titleScreen, ["mousedown", "touchstart"]) delete this.titleScreen delete this.proceed diff --git a/public/src/js/tutorial.js b/public/src/js/tutorial.js index 01a30a7..711265c 100644 --- a/public/src/js/tutorial.js +++ b/public/src/js/tutorial.js @@ -1,34 +1,37 @@ class Tutorial{ - constructor(fromSongSel, songId, touchEnabled){ + constructor(fromSongSel, songId){ this.fromSongSel = fromSongSel this.songId = songId - this.touchEnabled = touchEnabled - loader.changePage("tutorial", fromSongSel || !touchEnabled) + loader.changePage("tutorial", true) assets.sounds["bgm_setsume"].playLoop(0.1, false, 0, 1.054, 16.054) - this.endButton = document.getElementById("tutorial-end-button") + this.endButton = this.getElement("view-end-button") - this.tutorialTitle = document.getElementById("tutorial-title") + this.tutorialTitle = this.getElement("view-title") this.tutorialDiv = document.createElement("div") - document.getElementById("tutorial-content").appendChild(this.tutorialDiv) + this.getElement("view-content").appendChild(this.tutorialDiv) this.setStrings() - if(fromSongSel){ - pageEvents.add(this.endButton, ["mousedown", "touchstart"], this.onEnd.bind(this)) - pageEvents.keyAdd(this, "all", "down", event => { - if(event.keyCode === 13 || event.keyCode === 27 || event.keyCode === 8){ - // Enter, Esc, Backspace - this.onEnd.bind(this) - } - }) - - this.gamepad = new Gamepad({ - "confirm": ["start", "b", "ls", "rs"] - }, this.onEnd.bind(this)) - }else{ - new SettingsView(touchEnabled, this) - } + pageEvents.add(this.endButton, ["mousedown", "touchstart"], event => { + if(event.type === "touchstart"){ + event.preventDefault() + this.touched = true + }else if(event.type === "mousedown" && event.which !== 1){ + return + } + this.onEnd(true) + }) + this.keyboard = new Keyboard({ + confirm: ["enter", "space", "esc", "don_l", "don_r"] + }, this.onEnd.bind(this)) + this.gamepad = new Gamepad({ + confirm: ["start", "b", "ls", "rs"] + }, this.onEnd.bind(this)) + pageEvents.send("tutorial") } + getElement(name){ + return loader.screen.getElementsByClassName(name)[0] + } insertText(text, parent){ parent.appendChild(document.createTextNode(text)) } @@ -37,43 +40,30 @@ class Tutorial{ kbd.innerText = key parent.appendChild(kbd) } - onEnd(event){ - var touched = false - if(event){ - if(event.type === "touchstart"){ - event.preventDefault() - touched = true - }else if(event.which !== 1){ - return - } + onEnd(pressed, name){ + if(pressed){ + this.clean() + assets.sounds["se_don"].play() + localStorage.setItem("tutorial", "true") + setTimeout(() => { + new SongSelect(this.fromSongSel ? "tutorial" : false, false, this.touched, this.songId) + }, 500) } - this.clean() - assets.sounds["se_don"].play() - localStorage.setItem("tutorial", "true") - setTimeout(() => { - new SongSelect(this.fromSongSel ? "tutorial" : false, false, touched, this.songId) - }, 500) } setStrings(){ - if(!this.fromSongSel && this.touchEnabled){ - this.tutorialTitle.innerText = strings.gameSettings - this.tutorialTitle.setAttribute("alt", strings.gameSettings) - this.endButton.innerText = strings.settings.ok - this.endButton.setAttribute("alt", strings.settings.ok) - return - } this.tutorialTitle.innerText = strings.howToPlay this.tutorialTitle.setAttribute("alt", strings.howToPlay) this.endButton.innerText = strings.tutorial.ok this.endButton.setAttribute("alt", strings.tutorial.ok) this.tutorialDiv.innerHTML = "" var kbdSettings = settings.getItem("keyboardSettings") + var pauseKey = pageEvents.kbd.indexOf("q") === -1 ? "Q" : "ESC" var keys = [ kbdSettings.don_l[0].toUpperCase(), kbdSettings.don_r[0].toUpperCase(), kbdSettings.ka_l[0].toUpperCase(), kbdSettings.ka_r[0].toUpperCase(), - "Q", "SHIFT", "CTRL" + pauseKey, "SHIFT", "CTRL" ] var keyIndex = 0 strings.tutorial.basics.forEach(string => { @@ -105,11 +95,9 @@ class Tutorial{ this.tutorialDiv.appendChild(par) } clean(){ - if(this.fromSongSel){ - this.gamepad.clean() - pageEvents.remove(this.endButton, ["mousedown", "touchstart"]) - pageEvents.keyRemove(this, "all") - } + this.keyboard.clean() + this.gamepad.clean() + pageEvents.remove(this.endButton, ["mousedown", "touchstart"]) assets.sounds["bgm_setsume"].stop() delete this.tutorialTitle delete this.endButton diff --git a/public/src/js/view.js b/public/src/js/view.js index f045b09..06c30c7 100644 --- a/public/src/js/view.js +++ b/public/src/js/view.js @@ -830,11 +830,10 @@ ) // Taiko pressed keys - var kbd = this.controller.getBindings() var keys = ["ka_l", "ka_r", "don_l", "don_r"] for(var i = 0; i < keys.length; i++){ - var keyMS = ms - keyTime[kbd[keys[i]]] + var keyMS = ms - keyTime[keys[i]] if(keyMS < 130){ if(keyMS > 70 && !this.touchEnabled){ ctx.globalAlpha = this.draw.easeOut(1 - (keyMS - 70) / 60) @@ -1769,11 +1768,10 @@ } touchNote(note){ var keyboard = this.controller.keyboard - var kbd = keyboard.getBindings() var ms = this.controller.game.getAccurateTime() this.touch = ms - keyboard.setKey(kbd[note], false) - keyboard.setKey(kbd[note], true, ms) + keyboard.setKey(false, note) + keyboard.setKey(true, note, ms) } mod(length, index){ return ((index % length) + length) % length diff --git a/public/src/views/about.html b/public/src/views/about.html index f6165c7..3506eb3 100644 --- a/public/src/views/about.html +++ b/public/src/views/about.html @@ -1,9 +1,9 @@ -
-
-
-
+
+
+
+
- -
+
diff --git a/public/src/views/session.html b/public/src/views/session.html index 5e57005..f47ce54 100644 --- a/public/src/views/session.html +++ b/public/src/views/session.html @@ -1,9 +1,9 @@ -
-
-
-
+
+
+
+
-
+
diff --git a/public/src/views/settings.html b/public/src/views/settings.html index 2333ff5..6a35a91 100644 --- a/public/src/views/settings.html +++ b/public/src/views/settings.html @@ -1,10 +1,20 @@ -
-
-
-
-