From c8acfc3188df462263c5647cb1fcea05e699653f Mon Sep 17 00:00:00 2001 From: LoveEevee Date: Fri, 5 Oct 2018 20:03:59 +0300 Subject: [PATCH 1/6] View: Add touch controls --- public/index.html | 2 +- public/src/css/game.css | 59 +++++++++ public/src/js/assets.js | 7 +- public/src/js/controller.js | 6 +- public/src/js/game.js | 2 +- public/src/js/keyboard.js | 16 ++- public/src/js/loadsong.js | 9 +- public/src/js/scoresheet.js | 17 ++- public/src/js/songselect.js | 32 +++-- public/src/js/titlescreen.js | 9 +- public/src/js/view.js | 227 ++++++++++++++++++++++++++++++++++- public/src/views/game.html | 9 ++ 12 files changed, 362 insertions(+), 33 deletions(-) diff --git a/public/index.html b/public/index.html index 742ea9a..dc78b49 100644 --- a/public/index.html +++ b/public/index.html @@ -14,7 +14,7 @@ 太鼓の達人ウェブ - Taiko no Tatsujin Web - + diff --git a/public/src/css/game.css b/public/src/css/game.css index 8416bbe..7853dc4 100644 --- a/public/src/css/game.css +++ b/public/src/css/game.css @@ -51,3 +51,62 @@ pointer-events: none; z-index: 1; } +#touch-bg{ + display: none; + position: absolute; + right: 0; + bottom: 0; + left: 0; + height: 50%; + background: url(/assets/img/touch_bg.png) center bottom; + background-size: cover; + overflow: hidden; +} +#touch-bg-blue{ + position: absolute; + top: 0; + right: 0; + bottom: 0; + left: 0; + background: url(/assets/img/touch_bg_blue.png) center bottom; + background-size: cover; + opacity: 0; +} +#touch-drum{ + position: absolute; + right: 0; + bottom: 0; + left: 0; + text-align: center; + margin: auto; +} +#touch-drum img{ + width: 100%; +} +#touch-buttons{ + display: none; + position: absolute; + top: 7vh; + right: 2vh; + opacity: 0.5; + z-index: 5; +} +#touch-buttons img{ + width: 12vh; +} +.touch-visible #touch-bg, +.touch-visible #touch-buttons{ + display: block; +} +.touch-visible .window{ + width: 80vmin; + height: 53vmin; +} +.touch-visible #pause-menu .window button{ + font-size: 5vmin; +} +.touch-visible #pause-menu .window button.selected{ + color: #000; + background: #fff; + border-color: #ae7a26; +} diff --git a/public/src/js/assets.js b/public/src/js/assets.js index 6f1c873..2ec1a5d 100644 --- a/public/src/js/assets.js +++ b/public/src/js/assets.js @@ -39,7 +39,12 @@ var assets = { "bg_genre_7.png", "bg_score_p1.png", "bg_score_p2.png", - "badge_auto.png" + "badge_auto.png", + "touch_bg.png", + "touch_bg_blue.png", + "touch_drum.png", + "touch_pause.png", + "touch_fullscreen.png" ], "audioSfx": [ "don.wav", diff --git a/public/src/js/controller.js b/public/src/js/controller.js index da8ec3c..4e013db 100644 --- a/public/src/js/controller.js +++ b/public/src/js/controller.js @@ -1,9 +1,10 @@ class Controller{ - constructor(selectedSong, songData, autoPlayEnabled, multiplayer){ + constructor(selectedSong, songData, autoPlayEnabled, multiplayer, touchEnabled){ this.selectedSong = selectedSong this.songData = songData this.autoPlayEnabled = autoPlayEnabled this.multiplayer = multiplayer + this.touchEnabled = touchEnabled this.snd = this.multiplayer ? "_p" + this.multiplayer : "" var backgroundURL = "/songs/" + this.selectedSong.folder + "/bg.png" @@ -202,6 +203,9 @@ class Controller{ } } clean(){ + if(this.syncWith){ + this.syncWith.clean() + } this.stopMainLoop() this.keyboard.clean() this.view.clean() diff --git a/public/src/js/game.js b/public/src/js/game.js index 5498ac9..1b0d657 100644 --- a/public/src/js/game.js +++ b/public/src/js/game.js @@ -289,10 +289,10 @@ class Game{ this.controller.displayResults() this.musicFadeOut++ }else if(this.musicFadeOut === 3 && (ms >= started + 9600 && ms >= this.controller.mainAsset.duration * 1000 + 1250)){ + this.controller.clean() if(this.controller.scoresheet){ this.controller.scoresheet.startRedraw() } - this.controller.clean() } } } diff --git a/public/src/js/keyboard.js b/public/src/js/keyboard.js index 67f6494..30871d1 100644 --- a/public/src/js/keyboard.js +++ b/public/src/js/keyboard.js @@ -79,11 +79,12 @@ class Keyboard{ this.setKey(keyCode, false) } }) + }else{ + 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") } - 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") } checkMenuKeys(){ if(!this.controller.multiplayer){ @@ -171,7 +172,7 @@ class Keyboard{ var circles = this.controller.getCircles() var circle = circles[this.controller.getCurrentCircle()] if( - (keyCode === this.kbd["don_l"] || keyCode === this.kbd["don_r"]) + sound === "don" && circle && !circle.getPlayed() && circle.getType() === "balloon" @@ -191,6 +192,11 @@ class Keyboard{ if(down){ this.keys[keyCode] = true 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") + } }else{ this.keys[keyCode] = false this.waitKeyupScore[keyCode] = false diff --git a/public/src/js/loadsong.js b/public/src/js/loadsong.js index 0d58857..3ae4ebf 100644 --- a/public/src/js/loadsong.js +++ b/public/src/js/loadsong.js @@ -1,8 +1,9 @@ class loadSong{ - constructor(selectedSong, autoPlayEnabled, multiplayer){ + constructor(selectedSong, autoPlayEnabled, multiplayer, touchEnabled){ this.selectedSong = selectedSong - this.multiplayer = multiplayer this.autoPlayEnabled = autoPlayEnabled + this.multiplayer = multiplayer + this.touchEnabled = touchEnabled loader.changePage("loadsong") this.run() } @@ -81,7 +82,7 @@ class loadSong{ }else if(event.type === "gamestart"){ this.clean() loader.changePage("game") - var taikoGame1 = new Controller(this.selectedSong, this.songData, false, 1) + var taikoGame1 = new Controller(this.selectedSong, this.songData, false, 1, this.touchEnabled) var taikoGame2 = new Controller(this.selectedSong2, this.song2Data, true, 2) taikoGame1.run(taikoGame2) } @@ -93,7 +94,7 @@ class loadSong{ }else{ this.clean() loader.changePage("game") - var taikoGame = new Controller(this.selectedSong, this.songData, this.autoPlayEnabled) + var taikoGame = new Controller(this.selectedSong, this.songData, this.autoPlayEnabled, false, this.touchEnabled) taikoGame.run() } } diff --git a/public/src/js/scoresheet.js b/public/src/js/scoresheet.js index 8acd94c..5c2c7e4 100644 --- a/public/src/js/scoresheet.js +++ b/public/src/js/scoresheet.js @@ -29,8 +29,6 @@ class Scoresheet{ this.redrawRunning = true this.redrawBind = this.redraw.bind(this) this.redraw() - pageEvents.keyAdd(this, "all", "down", this.keyDown.bind(this)) - pageEvents.add(this.canvas, "mousedown", this.mouseDown.bind(this)) assets.sounds["results"].play() assets.sounds["bgm_result"].playLoop(3, false, 0, 0.847, 17.689) @@ -56,7 +54,11 @@ class Scoresheet{ } } mouseDown(event){ - if(event.which !== 1){ + if(event.type === "touchstart"){ + event.preventDefault() + this.canvas.style.cursor = "" + this.state.pointerLocked = true + }else if(event.which !== 1){ return } this.toNext() @@ -81,6 +83,10 @@ class Scoresheet{ requestAnimationFrame(this.redrawBind) this.winW = null this.winH = null + + pageEvents.keyAdd(this, "all", "down", this.keyDown.bind(this)) + pageEvents.add(this.canvas, "mousedown", this.mouseDown.bind(this)) + pageEvents.add(this.canvas, "touchstart", this.mouseDown.bind(this)) } redraw(){ @@ -218,7 +224,9 @@ class Scoresheet{ if(elapsed >= 0){ if(this.state.hasPointer === 0){ this.state.hasPointer = 1 - this.canvas.style.cursor = "pointer" + if(!this.state.pointerLocked){ + this.canvas.style.cursor = "pointer" + } } ctx.save() ctx.setTransform(1, 0, 0, 1, 0, 0) @@ -643,6 +651,7 @@ class Scoresheet{ this.redrawRunning = false pageEvents.keyRemove(this, "all") pageEvents.remove(this.canvas, "mousedown") + pageEvents.remove(this.canvas, "touchstart") delete this.ctx delete this.canvas } diff --git a/public/src/js/songselect.js b/public/src/js/songselect.js index 75dbfe1..33a0f83 100644 --- a/public/src/js/songselect.js +++ b/public/src/js/songselect.js @@ -197,6 +197,7 @@ class SongSelect{ pageEvents.keyAdd(this, "all", "down", this.keyDown.bind(this)) pageEvents.add(this.canvas, "mousemove", this.mouseMove.bind(this)) pageEvents.add(this.canvas, "mousedown", this.mouseDown.bind(this)) + pageEvents.add(this.canvas, "touchstart", this.mouseDown.bind(this)) } keyDown(event, code){ @@ -256,10 +257,21 @@ class SongSelect{ } mouseDown(event){ - if(event.which !== 1){ - return + if(event.type === "mousedown"){ + if(event.which !== 1){ + return + } + var mouse = this.mouseOffset(event.offsetX, event.offsetY) + var shift = event.shiftKey + var ctrl = event.ctrlKey + var touch = false + }else{ + event.preventDefault() + var mouse = this.mouseOffset(event.touches[0].pageX, event.touches[0].pageY) + var shift = false + var ctrl = false + var touch = true } - var mouse = this.mouseOffset(event) if(this.state.screen === "song"){ var moveBy = this.songSelMouse(mouse.x, mouse.y) if(moveBy === 0){ @@ -276,12 +288,12 @@ class SongSelect{ ){ this.toSongSelect() }else if(moveBy !== null){ - this.toLoadSong(moveBy - 1, event.shiftKey, event.ctrlKey) + this.toLoadSong(moveBy - 1, shift, ctrl, touch) } } } mouseMove(event){ - var mouse = this.mouseOffset(event) + var mouse = this.mouseOffset(event.offsetX, event.offsetY) var moveTo = null if(this.state.screen === "song"){ var moveTo = this.songSelMouse(mouse.x, mouse.y) @@ -298,10 +310,10 @@ class SongSelect{ } this.pointer(moveTo !== null) } - mouseOffset(event){ + mouseOffset(offsetX, offsetY){ return { - x: (event.offsetX * this.pixelRatio - this.winW / 2) / this.ratio + 1024 / 2, - y: (event.offsetY * this.pixelRatio - this.winH / 2) / this.ratio + 720 / 2 + x: (offsetX * this.pixelRatio - this.winW / 2) / this.ratio + 1024 / 2, + y: (offsetY * this.pixelRatio - this.winH / 2) / this.ratio + 720 / 2 } } pointer(enabled){ @@ -425,7 +437,7 @@ class SongSelect{ assets.sounds["cancel"].play() } } - toLoadSong(difficulty, shift, ctrl){ + toLoadSong(difficulty, shift, ctrl, touch){ this.clean() var selectedSong = this.songs[this.selectedSong] assets.sounds["diffsel"].stop() @@ -439,7 +451,7 @@ class SongSelect{ "folder": selectedSong.id, "difficulty": this.difficultyId[difficulty], "category": selectedSong.category - }, shift, ctrl) + }, shift, ctrl, touch) } toTitleScreen(){ assets.sounds["cancel"].play() diff --git a/public/src/js/titlescreen.js b/public/src/js/titlescreen.js index 905d8d4..d5cdfa9 100644 --- a/public/src/js/titlescreen.js +++ b/public/src/js/titlescreen.js @@ -3,7 +3,8 @@ class Titlescreen{ loader.changePage("titlescreen") this.titleScreen = document.getElementById("title-screen") pageEvents.keyOnce(this, 13, "down").then(this.onPressed.bind(this)) - pageEvents.once(this.titleScreen, "click").then(this.onPressed.bind(this)) + pageEvents.once(this.titleScreen, "mousedown").then(this.onPressed.bind(this)) + pageEvents.once(this.titleScreen, "touchstart").then(this.onPressed.bind(this)) assets.sounds["title"].play() this.gamepad = new Gamepad({ "start": ["b", "x", "y", "start"], @@ -15,6 +16,7 @@ class Titlescreen{ }) } onPressed(){ + this.titleScreen.style.cursor = "auto" this.clean() assets.sounds["don"].play() setTimeout(this.goNext.bind(this), 500) @@ -22,7 +24,7 @@ class Titlescreen{ goNext(){ if(localStorage.getItem("tutorial") !== "true"){ new Tutorial() - } else { + }else{ new SongSelect() } } @@ -30,7 +32,8 @@ class Titlescreen{ this.gamepad.clean() assets.sounds["title"].stop() pageEvents.keyRemove(this, 13) - pageEvents.remove(this.titleScreen, "click") + pageEvents.remove(this.titleScreen, "mousedown") + pageEvents.remove(this.titleScreen, "touchstart") delete this.titleScreen } } diff --git a/public/src/js/view.js b/public/src/js/view.js index cdba97b..22e5aec 100644 --- a/public/src/js/view.js +++ b/public/src/js/view.js @@ -7,6 +7,7 @@ class View{ this.pauseMenu = document.getElementById("pause-menu") this.cursor = document.getElementById("cursor") + this.gameDiv = document.getElementById("game") var docW = document.body.offsetWidth var docH = document.body.offsetHeight @@ -14,7 +15,7 @@ class View{ this.canvas = new ScalableCanvas("canvas-p2", docW, docH / 3 * 2) this.canvas.canvas.style.position = "absolute" this.canvas.canvas.style.top = "33%" - document.getElementById("game").appendChild(this.canvas.canvas) + this.gameDiv.appendChild(this.canvas.canvas) }else{ this.canvas = new ScalableCanvas("canvas", docW, docH) } @@ -49,6 +50,39 @@ class View{ this.beatInterval = this.controller.getSongData().beatInfo.beatInterval this.assets = new ViewAssets(this) + + this.touch = { + don_l: -Infinity, + don_r: -Infinity, + don_c: -Infinity, + ka_l: -Infinity, + ka_r: -Infinity, + ka_c: -Infinity, + cursor: { + ms: -Infinity, + x: 0, + y: 0 + } + } + + if(this.controller.touchEnabled){ + this.touchEnabled = true + + this.touchBgDiv = document.getElementById("touch-bg") + this.touchBgBlueDiv = document.getElementById("touch-bg-blue") + this.touchDrumDiv = document.getElementById("touch-drum") + this.gameDiv.classList.add("touch-visible") + + pageEvents.add(this.canvas.canvas, "touchstart", this.ontouch.bind(this)) + + this.touchFullBtn = document.getElementById("touch-full-btn") + pageEvents.add(this.touchFullBtn, "click", this.toggleFullscreen) + + this.touchPauseBtn = document.getElementById("touch-pause-btn") + pageEvents.add(this.touchPauseBtn, "click", () => { + this.controller.togglePauseMenu() + }) + } } run(){ this.ctx.font = "normal 14pt TnT" @@ -133,6 +167,37 @@ class View{ this.diffW = this.diffH * diffRatio this.diffX = this.taikoX * 0.10 this.diffY = this.taikoY * 1.05 + this.taikoH * 0.19 + this.touchDrum = (() => { + var sw = 842 + var sh = 340 + var x = 0 + var y = this.barY + this.barH + 5 + var paddingTop = this.barH * 0.1 + var w = this.winW + var maxH = this.winH - (this.barY + this.barH + 5) + var h = maxH - paddingTop + if(w / h >= sw / sh){ + w = h / sh * sw + x = (this.winW - w) / 2 + y += paddingTop + }else{ + h = w / sw * sh + y = y + (maxH - h) + } + return { + x: x, y: y, w: w, h: h + } + })() + this.touchCircle = (() => { + var padTop = this.touchDrum.h * 0.062 + var padLeft = this.touchDrum.h * 0.05 + return { + x: this.winW / 2, + y: this.winH + padTop, + rx: this.touchDrum.w / 2 - padLeft * 2, + ry: this.touchDrum.h + } + })() } refresh(){ this.positionning() @@ -158,7 +223,10 @@ class View{ this.updateDonFaces() this.drawGogoTime() this.mouseIdle() - this.assets.drawAssets("foreground") + if(!this.touchEnabled){ + this.assets.drawAssets("foreground") + } + this.drawTouch() //this.drawTime() } updateDonFaces(){ @@ -809,6 +877,147 @@ class View{ don.setAnimationEnd(ms + length * don.speed, don.normalAnimation) } } + drawTouch(){ + if(this.touchEnabled){ + var ms = this.controller.getElapsedTime() + this.ctx.save() + + var bgHeight = (this.winH - (this.barY + this.barH + 5)) / this.canvas.scale + if(bgHeight !== this.touchBgHeight){ + this.touchBgHeight = bgHeight + this.touchBgDiv.style.height = bgHeight + "px" + } + var drumWidth = this.touchDrum.w / this.canvas.scale + var drumHeight = this.touchDrum.h / this.canvas.scale + if(drumHeight !== this.touchDrumHeight || drumWidth !== this.touchDrumWidth){ + this.touchDrumWidth = drumWidth + this.touchDrumHeight = drumHeight + this.touchDrumDiv.style.width = drumWidth + "px" + this.touchDrumDiv.style.height = drumHeight + "px" + } + + var lastKa = this.touch.ka_l > this.touch.ka_r ? this.touch.ka_l : this.touch.ka_r + if(ms < lastKa + 150){ + if(!this.blueBgShown){ + this.blueBgShown = true + this.touchBgBlueDiv.style.opacity = 0.5 + } + }else if(this.blueBgShown){ + this.blueBgShown = false + this.touchBgBlueDiv.style.opacity = 0 + } + + var c = this.touchCircle + var pi = Math.PI + var lastDon = this.touch.don_l > this.touch.don_r ? this.touch.don_l : this.touch.don_r + if(lastDon > ms - 150){ + this.ctx.fillStyle = "rgba(239, 86, 51, 0.5)" + this.ctx.beginPath() + this.ctx.ellipse(c.x, c.y, c.rx * 0.9, c.ry * 0.9, 0, pi, 0) + this.ctx.fill() + } + if(this.touch.don_c > ms - 150){ + this.ctx.beginPath() + this.ctx.ellipse(c.x, c.y, c.rx * 0.6, c.ry * 0.6, 0, pi, 0) + this.ctx.fill() + } + if(this.touch.ka_c > ms - 150){ + this.ctx.fillStyle = "rgba(33, 191, 211, 0.5)" + this.ctx.beginPath() + this.ctx.ellipse(c.x, c.y, c.rx * 1.3, c.ry * 1.3, 0, pi, 0) + this.ctx.ellipse(c.x, c.y, c.rx * 0.9, c.ry * 0.9, 0, 0, pi, true) + this.ctx.fill() + } + + this.ctx.restore() + } + } + ontouch(event){ + for(let touch of event.touches){ + event.preventDefault() + var scale = this.canvas.scale + var pageX = touch.pageX * scale + var pageY = touch.pageY * scale + + this.touch.cursor = { + ms: this.controller.getElapsedTime(), + x: pageX, + y: pageY + } + + var c = this.touchCircle + var pi = Math.PI + var inPath = () => this.ctx.isPointInPath(pageX, pageY) + + this.ctx.beginPath() + this.ctx.ellipse(c.x, c.y, c.rx * 0.6, c.ry * 0.6, 0, pi, 0) + + if(inPath()){ + this.touchNote("don_c") + }else{ + this.ctx.beginPath() + this.ctx.ellipse(c.x, c.y, c.rx * 0.9, c.ry * 0.9, 0, pi, 0) + + if(inPath()){ + if(pageX < this.winW / 2){ + this.touchNote("don_l") + }else{ + this.touchNote("don_r") + } + }else{ + + this.ctx.beginPath() + this.ctx.ellipse(c.x, c.y, c.rx * 1.3, c.ry * 1.3, 0, pi, 0) + + if(inPath()){ + this.touchNote("ka_c") + }else if(pageX < this.winW / 2){ + this.touchNote("ka_l") + }else{ + this.touchNote("ka_r") + } + } + } + } + } + touchNote(note){ + var keyboard = this.controller.keyboard + var kbd = keyboard.getBindings() + var ms = this.controller.game.getAccurateTime() + this.touch[note] = ms + if(note === "don_c"){ + this.touchNote("don_l") + this.touchNote("don_r") + }else if(note === "ka_c"){ + this.touchNote("ka_l") + this.touchNote("ka_r") + }else{ + keyboard.setKey(kbd[note], false) + keyboard.setKey(kbd[note], true, ms) + } + } + toggleFullscreen(){ + var root = document.documentElement + if("requestFullscreen" in root){ + if(document.fullscreenElement){ + document.exitFullscreen() + }else{ + root.requestFullscreen() + } + }else if("webkitRequestFullscreen" in root){ + if(document.webkitFullscreenElement){ + document.webkitExitFullscreen() + }else{ + root.webkitRequestFullscreen() + } + }else if("mozRequestFullScreen" in root){ + if(document.mozFullScreenElement){ + document.mozCancelFullScreen() + }else{ + root.mozRequestFullScreen() + } + } + } onmousemove(event){ this.lastMousemove = this.controller.getElapsedTime() this.cursorHidden = false @@ -832,10 +1041,22 @@ class View{ pageEvents.mouseRemove(this) if(this.controller.multiplayer === 2){ this.canvas.canvas.parentNode.removeChild(this.canvas.canvas) + }else{ + this.cursor.parentNode.removeChild(this.cursor) + } + if(this.touchEnabled){ + pageEvents.remove(this.canvas.canvas, "touchstart") + pageEvents.remove(this.touchFullBtn, "click") + pageEvents.remove(this.touchPauseBtn, "click") + this.gameDiv.classList.remove("touch-visible") + delete this.touchBgDiv + delete this.touchFullBtn + delete this.touchPauseBtn + delete this.touchBgBlueDiv } - this.cursor.parentNode.removeChild(this.cursor) delete this.pauseMenu delete this.cursor + delete this.gameDiv delete this.canvas delete this.ctx } diff --git a/public/src/views/game.html b/public/src/views/game.html index fe5ef6f..c6e44e8 100644 --- a/public/src/views/game.html +++ b/public/src/views/game.html @@ -1,5 +1,11 @@

+
+
+
+ +
+
@@ -8,5 +14,8 @@
+
+ +
From c999dca204015aa6ec49ba7f3e54c87be842fde7 Mon Sep 17 00:00:00 2001 From: LoveEevee Date: Fri, 5 Oct 2018 21:12:50 +0300 Subject: [PATCH 2/6] Fix song restarting and multiple touches --- public/src/js/controller.js | 4 ++-- public/src/js/view.js | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/public/src/js/controller.js b/public/src/js/controller.js index 4e013db..2b1ea13 100644 --- a/public/src/js/controller.js +++ b/public/src/js/controller.js @@ -136,10 +136,10 @@ class Controller{ restartSong(){ this.clean() if(this.multiplayer){ - new loadSong(this.selectedSong, false, true) + new loadSong(this.selectedSong, false, true, this.touchEnabled) }else{ loader.changePage("game") - var taikoGame = new Controller(this.selectedSong, this.songData, this.autoPlayEnabled) + var taikoGame = new Controller(this.selectedSong, this.songData, this.autoPlayEnabled, false, this.touchEnabled) taikoGame.run() } } diff --git a/public/src/js/view.js b/public/src/js/view.js index 22e5aec..35ea3b5 100644 --- a/public/src/js/view.js +++ b/public/src/js/view.js @@ -933,7 +933,7 @@ class View{ } } ontouch(event){ - for(let touch of event.touches){ + for(let touch of event.changedTouches){ event.preventDefault() var scale = this.canvas.scale var pageX = touch.pageX * scale From 57632a83e5b1fcca5a71643e82fde7e80cbf52f3 Mon Sep 17 00:00:00 2001 From: LoveEevee Date: Sat, 6 Oct 2018 10:23:36 +0300 Subject: [PATCH 3/6] Disable checking sound timer on touch devices --- public/src/js/game.js | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/public/src/js/game.js b/public/src/js/game.js index 1b0d657..b06ddd5 100644 --- a/public/src/js/game.js +++ b/public/src/js/game.js @@ -339,21 +339,23 @@ class Game{ this.started = true this.sndTime = this.startDate - snd.buffer.getTime() * 1000 }else if(ms < 0 || ms >= 0 && this.started){ - this.elapsedTime = this.getAccurateTime(ms >= 0) + var currentDate = +new Date + if(!this.controller.touchEnabled){ + var sndTime = currentDate - snd.buffer.getTime() * 1000 + var lag = sndTime - this.sndTime + if(Math.abs(lag) >= 50){ + this.startDate += lag + this.sndTime = sndTime + } + } + this.elapsedTime = currentDate - this.startDate } } getAccurateTime(){ if(this.isPaused()){ return this.elapsedTime }else{ - var currentDate = +new Date - var sndTime = currentDate - snd.buffer.getTime() * 1000 - var lag = sndTime - this.sndTime - if(Math.abs(lag) >= 50){ - this.startDate += lag - this.sndTime = sndTime - } - return currentDate - this.startDate + return (+new Date) - this.startDate } } getCircles(){ From e1b8b45d881154f2a180fce5b1d5f2c89063aa24 Mon Sep 17 00:00:00 2001 From: LoveEevee Date: Sat, 6 Oct 2018 16:24:23 +0300 Subject: [PATCH 4/6] Change drum to match Switch, add fullscreen to songsel, fix tutorial --- public/index.html | 5 +- public/src/css/game.css | 31 ++----- public/src/css/main.css | 12 ++- public/src/js/assets.js | 2 - public/src/js/controller.js | 2 +- public/src/js/loader.js | 10 +- public/src/js/main.js | 29 ++++++ public/src/js/scoresheet.js | 9 +- public/src/js/songselect.js | 14 ++- public/src/js/titlescreen.js | 8 +- public/src/js/tutorial.js | 14 ++- public/src/js/view.js | 152 ++++++------------------------- public/src/views/game.html | 7 +- public/src/views/songselect.html | 1 + 14 files changed, 121 insertions(+), 175 deletions(-) create mode 100644 public/src/js/main.js diff --git a/public/index.html b/public/index.html index dc78b49..da43ec0 100644 --- a/public/index.html +++ b/public/index.html @@ -47,11 +47,12 @@ +
- + - \ No newline at end of file + diff --git a/public/src/css/game.css b/public/src/css/game.css index 7853dc4..776983a 100644 --- a/public/src/css/game.css +++ b/public/src/css/game.css @@ -51,50 +51,33 @@ pointer-events: none; z-index: 1; } -#touch-bg{ +#touch-drum{ display: none; position: absolute; right: 0; bottom: 0; left: 0; + width: 50%; height: 50%; - background: url(/assets/img/touch_bg.png) center bottom; - background-size: cover; - overflow: hidden; -} -#touch-bg-blue{ - position: absolute; - top: 0; - right: 0; - bottom: 0; - left: 0; - background: url(/assets/img/touch_bg_blue.png) center bottom; - background-size: cover; - opacity: 0; -} -#touch-drum{ - position: absolute; - right: 0; - bottom: 0; - left: 0; text-align: center; margin: auto; } -#touch-drum img{ +#touch-drum-img{ width: 100%; } #touch-buttons{ display: none; position: absolute; - top: 7vh; + top: 6.5vh; right: 2vh; opacity: 0.5; z-index: 5; } #touch-buttons img{ - width: 12vh; + width: 12.5vmin; + height: 12.5vmin; } -.touch-visible #touch-bg, +.touch-visible #touch-drum, .touch-visible #touch-buttons{ display: block; } diff --git a/public/src/css/main.css b/public/src/css/main.css index 3ee4261..faeaba9 100644 --- a/public/src/css/main.css +++ b/public/src/css/main.css @@ -137,8 +137,9 @@ body{ border: 5px black solid; border-radius: 10px; height: 65%; - width: 50%; + max-width: 800px; padding: 20px; + margin: 8px; font-size: 16pt; position: relative; } @@ -214,3 +215,12 @@ kbd{ left: 0; margin: auto; } +#song-select #touch-full-btn{ + display: none; + position: absolute; + top: 0; + right: 0; + width: 12.5vmin; + height: 12.5vmin; + opacity: 0.5; +} diff --git a/public/src/js/assets.js b/public/src/js/assets.js index 2ec1a5d..1b8e7e4 100644 --- a/public/src/js/assets.js +++ b/public/src/js/assets.js @@ -40,8 +40,6 @@ var assets = { "bg_score_p1.png", "bg_score_p2.png", "badge_auto.png", - "touch_bg.png", - "touch_bg_blue.png", "touch_drum.png", "touch_pause.png", "touch_fullscreen.png" diff --git a/public/src/js/controller.js b/public/src/js/controller.js index 2b1ea13..ae49f8d 100644 --- a/public/src/js/controller.js +++ b/public/src/js/controller.js @@ -131,7 +131,7 @@ class Controller{ if(!fadeIn){ this.clean() } - new SongSelect(false, fadeIn) + new SongSelect(false, fadeIn, this.touchEnabled) } restartSong(){ this.clean() diff --git a/public/src/js/loader.js b/public/src/js/loader.js index ce99d0e..3da5613 100644 --- a/public/src/js/loader.js +++ b/public/src/js/loader.js @@ -1,5 +1,6 @@ class Loader{ - constructor(){ + constructor(callback){ + this.callback = callback this.loadedAssets = 0 this.assetsDiv = document.getElementById("assets") this.ajax("src/views/loader.html").then(this.run.bind(this)) @@ -83,7 +84,7 @@ class Loader{ Promise.all(this.promises).then(() => { this.clean() - new Titlescreen() + this.callback() }, this.errorMsg.bind(this)) } loadSound(name, gain){ @@ -132,8 +133,3 @@ class Loader{ delete this.promises } } - -var pageEvents = new PageEvents() -var loader = new Loader() -var snd = {} -var p2 diff --git a/public/src/js/main.js b/public/src/js/main.js new file mode 100644 index 0000000..19254a9 --- /dev/null +++ b/public/src/js/main.js @@ -0,0 +1,29 @@ +function toggleFullscreen(){ + var root = document.documentElement + if("requestFullscreen" in root){ + if(document.fullscreenElement){ + document.exitFullscreen() + }else{ + root.requestFullscreen() + } + }else if("webkitRequestFullscreen" in root){ + if(document.webkitFullscreenElement){ + document.webkitExitFullscreen() + }else{ + root.webkitRequestFullscreen() + } + }else if("mozRequestFullScreen" in root){ + if(document.mozFullScreenElement){ + document.mozCancelFullScreen() + }else{ + root.mozRequestFullScreen() + } + } +} + +var pageEvents = new PageEvents() +var snd = {} +var p2 +var loader = new Loader(() => { + new Titlescreen() +}) diff --git a/public/src/js/scoresheet.js b/public/src/js/scoresheet.js index 5c2c7e4..df73a02 100644 --- a/public/src/js/scoresheet.js +++ b/public/src/js/scoresheet.js @@ -58,8 +58,11 @@ class Scoresheet{ event.preventDefault() this.canvas.style.cursor = "" this.state.pointerLocked = true - }else if(event.which !== 1){ - return + }else{ + this.state.pointerLocked = false + if(event.which !== 1){ + return + } } this.toNext() } @@ -600,7 +603,7 @@ class Scoresheet{ if(elapsed >= 1000){ this.clean() - this.controller.songSelection(true) + this.controller.songSelection(true, false, this.state.pointerLocked) } } diff --git a/public/src/js/songselect.js b/public/src/js/songselect.js index 33a0f83..9719648 100644 --- a/public/src/js/songselect.js +++ b/public/src/js/songselect.js @@ -1,5 +1,7 @@ class SongSelect{ - constructor(fromTutorial, fadeIn){ + constructor(fromTutorial, fadeIn, touchEnabled){ + this.touchEnabled = touchEnabled + loader.changePage("songselect") this.canvas = document.getElementById("song-sel-canvas") this.ctx = this.canvas.getContext("2d") @@ -198,6 +200,11 @@ class SongSelect{ pageEvents.add(this.canvas, "mousemove", this.mouseMove.bind(this)) pageEvents.add(this.canvas, "mousedown", this.mouseDown.bind(this)) pageEvents.add(this.canvas, "touchstart", this.mouseDown.bind(this)) + if(touchEnabled){ + this.touchFullBtn = document.getElementById("touch-full-btn") + this.touchFullBtn.style.display = "block" + pageEvents.add(this.touchFullBtn, "click", toggleFullscreen) + } } keyDown(event, code){ @@ -1135,6 +1142,11 @@ class SongSelect{ pageEvents.keyRemove(this, "all") pageEvents.remove(this.canvas, "mousemove") pageEvents.remove(this.canvas, "mousedown") + pageEvents.remove(this.canvas, "touchstart") + if(this.touchEnabled){ + pageEvents.remove(this.touchFullBtn, "click") + delete this.touchFullBtn + } delete this.ctx delete this.canvas } diff --git a/public/src/js/titlescreen.js b/public/src/js/titlescreen.js index d5cdfa9..6bddd09 100644 --- a/public/src/js/titlescreen.js +++ b/public/src/js/titlescreen.js @@ -15,7 +15,11 @@ class Titlescreen{ } }) } - onPressed(){ + onPressed(event){ + if(event && event.type === "touchstart"){ + event.preventDefault() + this.touched = true + } this.titleScreen.style.cursor = "auto" this.clean() assets.sounds["don"].play() @@ -25,7 +29,7 @@ class Titlescreen{ if(localStorage.getItem("tutorial") !== "true"){ new Tutorial() }else{ - new SongSelect() + new SongSelect(false, false, this.touched) } } clean(){ diff --git a/public/src/js/tutorial.js b/public/src/js/tutorial.js index 5589c81..ba37a0e 100644 --- a/public/src/js/tutorial.js +++ b/public/src/js/tutorial.js @@ -4,18 +4,26 @@ class Tutorial{ loader.changePage("tutorial") assets.sounds["bgm_setsume"].playLoop(0.1, false, 0, 1.054, 16.054) this.endButton = document.getElementById("tutorial-end-button") - pageEvents.once(this.endButton, "click").then(this.onEnd.bind(this)) + + pageEvents.once(this.endButton, "mousedown").then(this.onEnd.bind(this)) + pageEvents.once(this.endButton, "touchstart").then(this.onEnd.bind(this)) pageEvents.keyOnce(this, 13, "down").then(this.onEnd.bind(this)) + this.gamepad = new Gamepad({ "confirm": ["start", "b"] }, this.onEnd.bind(this)) } - onEnd(){ + onEnd(event){ + var touched = false + if(event && event.type === "touchstart"){ + event.preventDefault() + touched = true + } this.clean() assets.sounds["don"].play() localStorage.setItem("tutorial", "true") setTimeout(() => { - new SongSelect(this.fromSongSel) + new SongSelect(this.fromSongSel, false, touched) }, 500) } clean(){ diff --git a/public/src/js/view.js b/public/src/js/view.js index 35ea3b5..8555a0c 100644 --- a/public/src/js/view.js +++ b/public/src/js/view.js @@ -51,32 +51,19 @@ class View{ this.beatInterval = this.controller.getSongData().beatInfo.beatInterval this.assets = new ViewAssets(this) - this.touch = { - don_l: -Infinity, - don_r: -Infinity, - don_c: -Infinity, - ka_l: -Infinity, - ka_r: -Infinity, - ka_c: -Infinity, - cursor: { - ms: -Infinity, - x: 0, - y: 0 - } - } + this.touch = -Infinity if(this.controller.touchEnabled){ this.touchEnabled = true - this.touchBgDiv = document.getElementById("touch-bg") - this.touchBgBlueDiv = document.getElementById("touch-bg-blue") this.touchDrumDiv = document.getElementById("touch-drum") + this.touchDrumImg = document.getElementById("touch-drum-img") this.gameDiv.classList.add("touch-visible") pageEvents.add(this.canvas.canvas, "touchstart", this.ontouch.bind(this)) this.touchFullBtn = document.getElementById("touch-full-btn") - pageEvents.add(this.touchFullBtn, "click", this.toggleFullscreen) + pageEvents.add(this.touchFullBtn, "click", toggleFullscreen) this.touchPauseBtn = document.getElementById("touch-pause-btn") pageEvents.add(this.touchPauseBtn, "click", () => { @@ -189,13 +176,11 @@ class View{ } })() this.touchCircle = (() => { - var padTop = this.touchDrum.h * 0.062 - var padLeft = this.touchDrum.h * 0.05 return { x: this.winW / 2, - y: this.winH + padTop, - rx: this.touchDrum.w / 2 - padLeft * 2, - ry: this.touchDrum.h + y: this.winH + this.touchDrum.h * 0.1, + rx: this.touchDrum.w / 2 - this.touchDrum.h * 0.03, + ry: this.touchDrum.h * 1.07 } })() } @@ -880,13 +865,7 @@ class View{ drawTouch(){ if(this.touchEnabled){ var ms = this.controller.getElapsedTime() - this.ctx.save() - var bgHeight = (this.winH - (this.barY + this.barH + 5)) / this.canvas.scale - if(bgHeight !== this.touchBgHeight){ - this.touchBgHeight = bgHeight - this.touchBgDiv.style.height = bgHeight + "px" - } var drumWidth = this.touchDrum.w / this.canvas.scale var drumHeight = this.touchDrum.h / this.canvas.scale if(drumHeight !== this.touchDrumHeight || drumWidth !== this.touchDrumWidth){ @@ -895,41 +874,15 @@ class View{ this.touchDrumDiv.style.width = drumWidth + "px" this.touchDrumDiv.style.height = drumHeight + "px" } - - var lastKa = this.touch.ka_l > this.touch.ka_r ? this.touch.ka_l : this.touch.ka_r - if(ms < lastKa + 150){ - if(!this.blueBgShown){ - this.blueBgShown = true - this.touchBgBlueDiv.style.opacity = 0.5 + if(this.touch > ms - 150){ + if(!this.drumPadding){ + this.drumPadding = true + this.touchDrumImg.style.paddingTop = "1%" } - }else if(this.blueBgShown){ - this.blueBgShown = false - this.touchBgBlueDiv.style.opacity = 0 + }else if(this.drumPadding){ + this.drumPadding = false + this.touchDrumImg.style.paddingTop = "" } - - var c = this.touchCircle - var pi = Math.PI - var lastDon = this.touch.don_l > this.touch.don_r ? this.touch.don_l : this.touch.don_r - if(lastDon > ms - 150){ - this.ctx.fillStyle = "rgba(239, 86, 51, 0.5)" - this.ctx.beginPath() - this.ctx.ellipse(c.x, c.y, c.rx * 0.9, c.ry * 0.9, 0, pi, 0) - this.ctx.fill() - } - if(this.touch.don_c > ms - 150){ - this.ctx.beginPath() - this.ctx.ellipse(c.x, c.y, c.rx * 0.6, c.ry * 0.6, 0, pi, 0) - this.ctx.fill() - } - if(this.touch.ka_c > ms - 150){ - this.ctx.fillStyle = "rgba(33, 191, 211, 0.5)" - this.ctx.beginPath() - this.ctx.ellipse(c.x, c.y, c.rx * 1.3, c.ry * 1.3, 0, pi, 0) - this.ctx.ellipse(c.x, c.y, c.rx * 0.9, c.ry * 0.9, 0, 0, pi, true) - this.ctx.fill() - } - - this.ctx.restore() } } ontouch(event){ @@ -939,43 +892,24 @@ class View{ var pageX = touch.pageX * scale var pageY = touch.pageY * scale - this.touch.cursor = { - ms: this.controller.getElapsedTime(), - x: pageX, - y: pageY - } - var c = this.touchCircle var pi = Math.PI var inPath = () => this.ctx.isPointInPath(pageX, pageY) this.ctx.beginPath() - this.ctx.ellipse(c.x, c.y, c.rx * 0.6, c.ry * 0.6, 0, pi, 0) + this.ctx.ellipse(c.x, c.y, c.rx, c.ry, 0, pi, 0) if(inPath()){ - this.touchNote("don_c") - }else{ - this.ctx.beginPath() - this.ctx.ellipse(c.x, c.y, c.rx * 0.9, c.ry * 0.9, 0, pi, 0) - - if(inPath()){ - if(pageX < this.winW / 2){ - this.touchNote("don_l") - }else{ - this.touchNote("don_r") - } + if(pageX < this.winW / 2){ + this.touchNote("don_l") }else{ - - this.ctx.beginPath() - this.ctx.ellipse(c.x, c.y, c.rx * 1.3, c.ry * 1.3, 0, pi, 0) - - if(inPath()){ - this.touchNote("ka_c") - }else if(pageX < this.winW / 2){ - this.touchNote("ka_l") - }else{ - this.touchNote("ka_r") - } + this.touchNote("don_r") + } + }else{ + if(pageX < this.winW / 2){ + this.touchNote("ka_l") + }else{ + this.touchNote("ka_r") } } } @@ -984,39 +918,9 @@ class View{ var keyboard = this.controller.keyboard var kbd = keyboard.getBindings() var ms = this.controller.game.getAccurateTime() - this.touch[note] = ms - if(note === "don_c"){ - this.touchNote("don_l") - this.touchNote("don_r") - }else if(note === "ka_c"){ - this.touchNote("ka_l") - this.touchNote("ka_r") - }else{ - keyboard.setKey(kbd[note], false) - keyboard.setKey(kbd[note], true, ms) - } - } - toggleFullscreen(){ - var root = document.documentElement - if("requestFullscreen" in root){ - if(document.fullscreenElement){ - document.exitFullscreen() - }else{ - root.requestFullscreen() - } - }else if("webkitRequestFullscreen" in root){ - if(document.webkitFullscreenElement){ - document.webkitExitFullscreen() - }else{ - root.webkitRequestFullscreen() - } - }else if("mozRequestFullScreen" in root){ - if(document.mozFullScreenElement){ - document.mozCancelFullScreen() - }else{ - root.mozRequestFullScreen() - } - } + this.touch = ms + keyboard.setKey(kbd[note], false) + keyboard.setKey(kbd[note], true, ms) } onmousemove(event){ this.lastMousemove = this.controller.getElapsedTime() @@ -1049,10 +953,10 @@ class View{ pageEvents.remove(this.touchFullBtn, "click") pageEvents.remove(this.touchPauseBtn, "click") this.gameDiv.classList.remove("touch-visible") - delete this.touchBgDiv + delete this.touchDrumDiv + delete this.touchDrumImg delete this.touchFullBtn delete this.touchPauseBtn - delete this.touchBgBlueDiv } delete this.pauseMenu delete this.cursor diff --git a/public/src/views/game.html b/public/src/views/game.html index c6e44e8..2763175 100644 --- a/public/src/views/game.html +++ b/public/src/views/game.html @@ -1,10 +1,7 @@

-
-
-
- -
+
+
diff --git a/public/src/views/songselect.html b/public/src/views/songselect.html index ed1e45e..4eec0d9 100644 --- a/public/src/views/songselect.html +++ b/public/src/views/songselect.html @@ -1,3 +1,4 @@
+
From 386b8905ac3abae2e6a1df20a172f04729e853bd Mon Sep 17 00:00:00 2001 From: LoveEevee Date: Sat, 6 Oct 2018 17:53:39 +0300 Subject: [PATCH 5/6] Shorten drum hit duration --- public/src/js/view.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/public/src/js/view.js b/public/src/js/view.js index 8555a0c..1a60f6f 100644 --- a/public/src/js/view.js +++ b/public/src/js/view.js @@ -874,7 +874,7 @@ class View{ this.touchDrumDiv.style.width = drumWidth + "px" this.touchDrumDiv.style.height = drumHeight + "px" } - if(this.touch > ms - 150){ + if(this.touch > ms - 100){ if(!this.drumPadding){ this.drumPadding = true this.touchDrumImg.style.paddingTop = "1%" From d36d0135511e51b93d1c343898fa675e20b57f6f Mon Sep 17 00:00:00 2001 From: LoveEevee Date: Sat, 6 Oct 2018 18:09:57 +0300 Subject: [PATCH 6/6] Hide keyboard tutorial from mobile users --- public/src/js/songselect.js | 27 +++++++++++++++++---------- public/src/js/titlescreen.js | 6 +++--- 2 files changed, 20 insertions(+), 13 deletions(-) diff --git a/public/src/js/songselect.js b/public/src/js/songselect.js index 9719648..e113b28 100644 --- a/public/src/js/songselect.js +++ b/public/src/js/songselect.js @@ -111,12 +111,16 @@ class SongSelect{ action: "random", category: "ランダム" }) - this.songs.push({ - title: "あそびかた説明", - skin: this.songSkin.tutorial, - action: "tutorial", - category: "ランダム" - }) + if(touchEnabled){ + fromTutorial = false + }else{ + this.songs.push({ + title: "あそびかた説明", + skin: this.songSkin.tutorial, + action: "tutorial", + category: "ランダム" + }) + } this.songs.push({ title: "もどる", skin: this.songSkin.back, @@ -143,16 +147,16 @@ class SongSelect{ this.selectedDiff = 0 assets.sounds["bgm_songsel"].playLoop(0.1, false, 0, 1.442, 3.506) - if(fromTutorial || !("selectedSong" in localStorage)){ - this.selectedSong = this.songs.findIndex(song => song.action === "tutorial") - this.playBgm(true) - }else{ + if(touchEnabled || !fromTutorial && "selectedSong" in localStorage){ if("selectedSong" in localStorage){ this.selectedSong = Math.min(Math.max(0, localStorage["selectedSong"] |0), this.songs.length) } assets.sounds["song-select"].play() snd.musicGain.fadeOut() this.playBgm(false) + }else{ + this.selectedSong = this.songs.findIndex(song => song.action === "tutorial") + this.playBgm(true) } if("selectedDiff" in localStorage){ this.selectedDiff = Math.min(Math.max(0, localStorage["selectedDiff"] |0), 4) @@ -324,6 +328,9 @@ class SongSelect{ } } pointer(enabled){ + if(!this.canvas){ + return + } if(enabled && this.state.hasPointer === false){ this.canvas.style.cursor = "pointer" this.state.hasPointer = true diff --git a/public/src/js/titlescreen.js b/public/src/js/titlescreen.js index 6bddd09..63cdd89 100644 --- a/public/src/js/titlescreen.js +++ b/public/src/js/titlescreen.js @@ -26,10 +26,10 @@ class Titlescreen{ setTimeout(this.goNext.bind(this), 500) } goNext(){ - if(localStorage.getItem("tutorial") !== "true"){ - new Tutorial() - }else{ + if(this.touched || localStorage.getItem("tutorial") === "true"){ new SongSelect(false, false, this.touched) + }else{ + new Tutorial() } } clean(){