diff --git a/public/src/css/game.css b/public/src/css/game.css index c51aaa5..c5e24bf 100644 --- a/public/src/css/game.css +++ b/public/src/css/game.css @@ -15,36 +15,6 @@ width: 100%; height: 100%; } -#pause-menu{ - display: none; - width: 100%; - height: 100%; - position: absolute; - top: 0; - left: 0; - background: rgba(0, 0, 0, 0.75); - z-index: 5; -} -#pause-menu button{ - width: 90%; - height: 25%; - display: block; - margin: 0 auto; - cursor: pointer; - border:.5vmin solid #ae7a26; - background: #fff; - color: #000; - font-family: TnT, Meiryo, sans-serif; - font-size: 3.5vmin; - border-radius: 1.5vmin; - outline: none; -} -#pause-menu button:hover, -#pause-menu .window:not(:hover) button.selected{ - color:white; - background:#0c6577; - border-color:#fa5d3a; -} #cursor{ position: fixed; width: 1px; diff --git a/public/src/js/assets.js b/public/src/js/assets.js index c475f26..f70ddd6 100644 --- a/public/src/js/assets.js +++ b/public/src/js/assets.js @@ -32,10 +32,12 @@ var assets = { "bg_score_p1.png", "bg_score_p2.png", "bg_settings.png", + "bg_pause.png", "badge_auto.png", "touch_drum.png", "touch_pause.png", - "touch_fullscreen.png" + "touch_fullscreen.png", + "mimizu.png" ], "audioSfx": [ "don.wav", diff --git a/public/src/js/canvasdraw.js b/public/src/js/canvasdraw.js index f215936..3ec4680 100644 --- a/public/src/js/canvasdraw.js +++ b/public/src/js/canvasdraw.js @@ -217,35 +217,33 @@ var _y = config.y + 3.5 var _w = config.w - 7 var _h = config.h - 7 - var rect = () => { - if(config.radius){ - this.roundedRect({ - ctx: ctx, - x: _x, - y: _y, - w: _w, - h: _h, - radius: config.radius - }) - ctx.stroke() - }else{ - ctx.strokeRect(_x, _y, _w, _h) - } - } if(config.animate){ ctx.globalAlpha = this.fade((this.getMS() - config.animateMS) % 2000 / 2000) }else if(config.opacity){ ctx.globalAlpha = config.opacity } + if(config.radius){ + this.roundedRect({ + ctx: ctx, + x: _x, + y: _y, + w: _w, + h: _h, + radius: config.radius + }) + }else{ + ctx.beginPath() + ctx.rect(_x, _y, _w, _h) + } ctx.strokeStyle = "rgba(255, 249, 1, 0.45)" ctx.lineWidth = 14 - rect() + ctx.stroke() ctx.strokeStyle = "rgba(255, 249, 1, .8)" ctx.lineWidth = 8 - rect() + ctx.stroke() ctx.strokeStyle = "#fff" ctx.lineWidth = 6 - rect() + ctx.stroke() ctx.restore() } diff --git a/public/src/js/controller.js b/public/src/js/controller.js index 4dc08bd..db21ace 100644 --- a/public/src/js/controller.js +++ b/public/src/js/controller.js @@ -30,7 +30,6 @@ class Controller{ this.playedSounds = {} } run(syncWith){ - this.loadUIEvents() this.game.run() this.view.run() this.startMainLoop() @@ -47,22 +46,6 @@ class Controller{ } } } - loadUIEvents(){ - this.pauseMenu = document.getElementById("pause-menu") - this.continueBtn = document.getElementById("continue-butt") - this.restartBtn = document.getElementById("restart-butt") - this.songSelBtn = document.getElementById("song-selection-butt") - pageEvents.add(this.pauseMenu, "touchstart", event => event.preventDefault()) - pageEvents.add(this.continueBtn, ["click", "touchend"], this.togglePauseMenu.bind(this)) - pageEvents.add(this.restartBtn, ["click", "touchend"], () => { - assets.sounds["don"].play() - this.restartSong() - }) - pageEvents.add(this.songSelBtn, ["click", "touchend"], () => { - assets.sounds["don"].play() - this.songSelection() - }) - } startMainLoop(){ this.mainLoopStarted = false this.mainLoopRunning = true @@ -115,15 +98,11 @@ class Controller{ } this.game.playMainMusic() } - this.view.refresh() } + this.view.refresh() this.keyboard.checkMenuKeys() } } - togglePauseMenu(){ - this.togglePause() - this.view.togglePauseMenu() - } gameEnded(){ var score = this.getGlobalScore() var vp @@ -231,15 +210,6 @@ class Controller{ this.keyboard.clean() this.view.clean() - pageEvents.remove(this.pauseMenu, "touchstart") - delete this.pauseMenu - pageEvents.remove(this.continueBtn, ["click", "touchend"]) - delete this.continueBtn - pageEvents.remove(this.restartBtn, ["click", "touchend"]) - delete this.restartBtn - pageEvents.remove(this.songSelBtn, ["click", "touchend"]) - delete this.songSelBtn - if(!this.multiplayer){ debugObj.controller = null if(debugObj.debug){ diff --git a/public/src/js/game.js b/public/src/js/game.js index ce0aa55..d7a2fdc 100644 --- a/public/src/js/game.js +++ b/public/src/js/game.js @@ -325,6 +325,7 @@ class Game{ this.latestDate = +new Date this.mainAsset.stop() this.mainMusicPlaying = false + this.view.pauseMove(0, true) }else{ assets.sounds["cancel"].play() this.paused = false diff --git a/public/src/js/keyboard.js b/public/src/js/keyboard.js index 11cf82b..c594273 100644 --- a/public/src/js/keyboard.js +++ b/public/src/js/keyboard.js @@ -10,10 +10,16 @@ class Keyboard{ "ka_r": 75, // K "pause": 81, // Q "back": 8, // Backspace - "previous": 38, // Up - "next": 40, // Down + "previous": 37, // Left + "next": 39, // Right "confirm": 13 // Enter } + this.kbdAlias = { + "pause": [27], // Esc + "previous": [38], // Up + "next": [40], // Down + "confirm": [32] // Space + } this.keys = {} this.waitKeyupScore = {} this.waitKeyupSound = {} @@ -39,15 +45,26 @@ class Keyboard{ 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] + } + } + for(var name in this.kbd){ + this.kbdSearch[this.kbd[name]] = this.kbd[name] + } pageEvents.keyAdd(this, "all", "both", event => { if(event.keyCode === 8){ // Disable back navigation when pressing backspace event.preventDefault() } - if(!event.repeat && this.buttonEnabled(event.keyCode)){ + var key = this.kbdSearch[event.keyCode] + if(key && !event.repeat && this.buttonEnabled(key)){ var ms = this.game.getAccurateTime() - this.setKey(event.keyCode, event.type === "keydown", ms) + this.setKey(key, event.type === "keydown", ms) } }) } @@ -95,7 +112,7 @@ class Keyboard{ if(this.game.isPaused()){ if(keyCode === "cancel"){ return setTimeout(() => { - this.controller.togglePauseMenu() + this.controller.togglePause() }, 200) } } @@ -108,7 +125,7 @@ class Keyboard{ } }) this.checkKey(this.kbd["pause"], "menu", () => { - this.controller.togglePauseMenu() + this.controller.togglePause() for(var key in this.keyTime){ this.keys[key] = null this.keyTime[key] = -Infinity @@ -123,10 +140,7 @@ class Keyboard{ var moveMenuConfirm = () => { if(this.game.isPaused()){ setTimeout(() => { - var selected = document.getElementsByClassName("selected")[0] - if(selected){ - selected.click() - } + this.controller.view.pauseConfirm() }, 200) for(var key in this.keyTime){ this.keyTime[key] = null @@ -142,13 +156,7 @@ class Keyboard{ this.checkKey(this.kbd["don_r"], "menu", moveMenuConfirm) if(moveMenu && this.game.isPaused()){ assets.sounds["ka"].play() - var selected = document.getElementsByClassName("selected")[0] - selected.classList.remove("selected") - var next = selected[(moveMenu === 1 ? "next" : "previous") + "ElementSibling"] - if(!next){ - next = selected.parentNode[(moveMenu === 1 ? "first" : "last") + "ElementChild"] - } - next.classList.add("selected") + this.controller.view.pauseMove(moveMenu) } } if(this.controller.multiplayer !== 2){ diff --git a/public/src/js/view.js b/public/src/js/view.js index c148370..0a76deb 100644 --- a/public/src/js/view.js +++ b/public/src/js/view.js @@ -5,13 +5,18 @@ this.canvas = document.getElementById("canvas") this.ctx = this.canvas.getContext("2d") - this.pauseMenu = document.getElementById("pause-menu") this.cursor = document.getElementById("cursor") this.gameDiv = document.getElementById("game") this.portraitClass = false this.touchp2Class = false + this.pauseOptions = [ + "演奏をつづける", + "はじめからやりなおす", + "「曲をえらぶ」にもどる" + ] + this.currentScore = { ms: -Infinity, type: 0 @@ -20,6 +25,12 @@ small: 0, big: 3 } + this.state = { + pausePos: 0, + moveMS: 0, + moveHover: null, + hasPointer: false + } this.nextBeat = 0 this.gogoTime = 0 this.drumroll = [] @@ -32,6 +43,7 @@ this.titleCache = new CanvasCache() this.comboCache = new CanvasCache() + this.pauseCache = new CanvasCache() this.multiplayer = this.controller.multiplayer @@ -39,12 +51,6 @@ this.touch = -Infinity if(this.multiplayer !== 2){ - pageEvents.add(window, "resize", () => { - if(this.controller.game.isPaused()){ - this.refresh() - setTimeout(this.refresh.bind(this), 100) - } - }) if(this.controller.touchEnabled){ this.touchDrumDiv = document.getElementById("touch-drum") @@ -67,13 +73,16 @@ this.touchPauseBtn = document.getElementById("touch-pause-btn") pageEvents.add(this.touchPauseBtn, "touchend", () => { - this.controller.togglePauseMenu() + this.controller.togglePause() }) if(this.multiplayer){ this.touchPauseBtn.style.display = "none" } } } + if(!this.multiplayer){ + pageEvents.add(this.canvas, ["mousedown", "touchstart"], this.onmousedown.bind(this)) + } } run(){ this.setBackground() @@ -122,7 +131,12 @@ this.titleCache.resize(640, 80, ratio) } + if(!this.multiplayer){ + this.pauseCache.resize(81 * this.pauseOptions.length * 2, 464, ratio) + } this.fillComboCache() + }else if(this.controller.game.paused && !document.hasFocus()){ + return }else if(this.multiplayer !== 2){ ctx.clearRect(0, 0, winW / ratio, winH / ratio) } @@ -749,6 +763,125 @@ if(!this.touchEnabled && !this.portrait && !this.multiplayer){ this.assets.drawAssets("foreground") } + + // Pause screen + if(!this.multiplayer && this.controller.game.paused){ + ctx.fillStyle = "rgba(0, 0, 0, 0.5)" + ctx.fillRect(0, 0, winW, winH) + + if(this.portrait){ + ctx.save() + var pauseScale = 720 / 766 + ctx.scale(pauseScale, pauseScale) + ctx.translate(-257, 328) + } + + var pauseRect = (ctx, mul) => { + this.draw.roundedRect({ + ctx: ctx, + x: (frameLeft + 269) * mul, + y: (frameTop + 93) * mul, + w: 742 * mul, + h: 494 * mul, + radius: 17 * mul + }) + } + pauseRect(ctx, 1) + ctx.strokeStyle = "#fff" + ctx.lineWidth = 24 + ctx.stroke() + ctx.strokeStyle = "#000" + ctx.lineWidth = 12 + ctx.stroke() + this.draw.pattern({ + ctx: ctx, + img: assets.image["bg_pause"], + shape: pauseRect, + dx: frameLeft + 68, + dy: frameTop + 11 + }) + + ctx.drawImage(assets.image["mimizu"], + frameLeft + 313, frameTop + 247, + 136, 315 + ) + + var _y = frameTop + 108 + var _w = 80 + var _h = 464 + for(var i = 0; i < this.pauseOptions.length; i++){ + var _x = frameLeft + 520 + 110 * i + if(this.state.moveHover !== null){ + var selected = i === this.state.moveHover + }else{ + var selected = i === this.state.pausePos + } + if(selected){ + ctx.fillStyle = "#ffb447" + this.draw.roundedRect({ + ctx: ctx, + x: _x - _w / 2, + y: _y, + w: _w, + h: _h, + radius: 30 + }) + ctx.fill() + } + this.pauseCache.get({ + ctx: ctx, + x: _x - _w / 2, + y: _y, + w: _w, + h: _h, + id: this.pauseOptions[i] + (selected ? "1" : "0") + }, ctx => { + var textConfig = { + ctx: ctx, + text: this.pauseOptions[i], + x: _w / 2, + y: 18, + width: _w, + height: _h, + fontSize: 40, + fontFamily: this.font, + letterSpacing: -1 + } + if(selected){ + textConfig.fill = "#fff" + textConfig.outline = "#000" + textConfig.outlineSize = 10 + }else{ + textConfig.fill = "#000" + } + this.draw.verticalText(textConfig) + }) + + var highlight = 0 + if(this.state.moveHover === i){ + highlight = 2 + }else if(selected){ + highlight = 1 + } + if(highlight){ + this.draw.highlight({ + ctx: ctx, + x: _x - _w / 2 - 3.5, + y: _y - 3.5, + w: _w + 7, + h: _h + 7, + animate: highlight === 1, + animateMS: this.state.moveMS, + opacity: highlight === 2 ? 0.8 : 1, + radius: 30 + }) + } + } + + if(this.portrait){ + ctx.restore() + } + } } setBackground(){ var gameDiv = document.getElementById("game") @@ -1196,16 +1329,6 @@ var circleSize = 70 * this.slotPos.size / 106 / 2 return speed / (140 / circleSize) * ms } - togglePauseMenu(){ - if(this.controller.game.isPaused()){ - this.pauseMenu.style.display = "block" - this.lastMousemove = this.controller.getElapsedTime() - this.cursorHidden = false - this.mouseIdle() - }else{ - this.pauseMenu.style.display = "" - } - } drawTouch(){ if(this.touchEnabled){ var ms = this.getMS() @@ -1266,9 +1389,90 @@ keyboard.setKey(kbd[note], false) keyboard.setKey(kbd[note], true, ms) } + mod(length, index){ + return ((index % length) + length) % length + } + pauseMove(pos, absolute){ + if(absolute){ + this.state.pausePos = pos + }else{ + this.state.pausePos = this.mod(this.pauseOptions.length, this.state.pausePos + pos) + } + this.state.moveMS = +new Date - (absolute ? 0 : 500) + this.state.moveHover = null + } + pauseConfirm(pos){ + if(typeof pos === "undefined"){ + pos = this.state.pausePos + } + switch(pos){ + case 1: + return this.controller.restartSong() + case 2: + return this.controller.songSelection() + default: + return this.controller.togglePause() + } + } + onmousedown(event){ + if(this.controller.game.paused){ + if(event.type === "mousedown"){ + if(event.which !== 1){ + return + } + var mouse = this.mouseOffset(event.offsetX, event.offsetY) + }else{ + event.preventDefault() + var mouse = this.mouseOffset(event.touches[0].pageX, event.touches[0].pageY) + } + var moveTo = this.pauseMouse(mouse.x, mouse.y) + if(moveTo !== null){ + this.pauseConfirm(moveTo) + } + } + } onmousemove(event){ this.lastMousemove = this.controller.getElapsedTime() this.cursorHidden = false + + if(!this.multiplayer && this.controller.game.paused){ + var mouse = this.mouseOffset(event.offsetX, event.offsetY) + var moveTo = this.pauseMouse(mouse.x, mouse.y) + if(moveTo === null && this.state.moveHover === this.state.pausePos){ + this.state.moveMS = +new Date - 500 + } + this.state.moveHover = moveTo + this.pointer(moveTo !== null) + } + } + mouseOffset(offsetX, offsetY){ + return { + x: (offsetX * this.pixelRatio - this.winW / 2) / this.ratio + (this.portrait ? 720 : 1280) / 2, + y: (offsetY * this.pixelRatio - this.winH / 2) / this.ratio + (this.portrait ? 1280 : 720) / 2 + } + } + pointer(enabled){ + if(!this.canvas){ + return + } + if(enabled && this.state.hasPointer === false){ + this.canvas.style.cursor = "pointer" + this.state.hasPointer = true + }else if(!enabled && this.state.hasPointer === true){ + this.canvas.style.cursor = "" + this.state.hasPointer = false + } + } + pauseMouse(x, y){ + if(this.portrait){ + var pauseScale = 766 / 720 + x = x * pauseScale + 257 + y = y * pauseScale - 328 + } + if(104 <= y && y <= 575 && 465 <= x && x <= 465 + 110 * this.pauseOptions.length){ + return Math.floor((x - 465) / 110) + } + return null } mouseIdle(){ var lastMouse = pageEvents.getMouse() @@ -1299,7 +1503,6 @@ this.comboCache.clean() if(this.multiplayer !== 2){ - pageEvents.remove(window, "resize") if(this.touchEnabled){ pageEvents.remove(this.canvas, "touchstart") pageEvents.remove(this.touchFullBtn, "touchend") @@ -1312,6 +1515,9 @@ delete this.touchPauseBtn } } + if(!this.multiplayer){ + pageEvents.remove(this.canvas, ["mousedown", "touchstart"]) + } pageEvents.mouseRemove(this) delete this.pauseMenu delete this.cursor diff --git a/public/src/views/game.html b/public/src/views/game.html index 65aa851..c95aae5 100644 --- a/public/src/views/game.html +++ b/public/src/views/game.html @@ -3,13 +3,6 @@
-
-
- - - -
-