diff --git a/.github/ISSUE_TEMPLATE.md b/.github/ISSUE_TEMPLATE.md new file mode 100644 index 0000000..95fd27a --- /dev/null +++ b/.github/ISSUE_TEMPLATE.md @@ -0,0 +1,2 @@ +###### Describe the problem you are having below. Please include a screenshot and the diagnostic information. + diff --git a/public/src/css/main.css b/public/src/css/main.css index b91867a..b814f6a 100644 --- a/public/src/css/main.css +++ b/public/src/css/main.css @@ -12,6 +12,7 @@ body{ width: 100%; height: 100%; background: #fe7839; + position: relative; user-select: none; touch-action: none; } @@ -135,30 +136,34 @@ body{ #tutorial{ background: rgb(246, 234, 212); color: black; - border: 5px black solid; - border-radius: 10px; - height: 65%; - max-width: 800px; - padding: 20px; - margin: 8px; - font-size: 16pt; + 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: -25px; - font-size: 26pt; + top: -0.7em; + font-size: 1.65em; } #tutorial-content{ - padding: 15px 30px; + 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: 13px; + 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; @@ -169,26 +174,61 @@ kbd{ white-space: nowrap; } .taibtn{ - bottom: 15px; - margin: 0 auto; - position: absolute; - right: 15px; - padding: 10px 40px; - border-radius: 15px; - border: 3px rgba(218, 205, 178, 1) solid; + display: inline-block; + padding: 0.4em 0.4em; + border-radius: 0.5em; + border: 0.1em rgba(218, 205, 178, 1) solid; cursor: pointer; -} -.taibtn:hover{ - z-index: 1; - color: white; - background: rgb(255, 181, 71); - border-color: white; -} -.taibtn::before{ - padding: 0 40px; + font-size: 1.4em; + box-sizing: border-box; + color: #555; + text-align: center; } #tutorial-end-button{ - font-size: 22pt; + float: right; + padding: 0.4em 1.5em; + font-weight: bold; + border-color: #000; + color: #000; +} +.taibtn:hover, +#tutorial-end-button:hover{ + 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{ + width: 100%; + height: 5em; + font-size: inherit; + resize: none; + word-break: break-all; + margin-bottom: 1em; + background: #fff; + border: 1px solid #a9a9a9; +} +.text-warn{ + color: #d00; +} +.link-btn a{ + color: inherit; + text-decoration: none; + pointer-events: none; +} +.nowrap{ + white-space: nowrap; } @keyframes bgscroll{ from{ diff --git a/public/src/js/about.js b/public/src/js/about.js new file mode 100644 index 0000000..29eeb1b --- /dev/null +++ b/public/src/js/about.js @@ -0,0 +1,122 @@ +class About{ + constructor(touchEnabled){ + this.touchEnabled = touchEnabled + loader.changePage("about") + cancelTouch = false + + this.endButton = document.getElementById("tutorial-end-button") + this.diagTxt = document.getElementById("diag-txt") + this.version = document.getElementById("version-link").href + this.tutorialOuter = document.getElementById("tutorial-outer") + if(touchEnabled){ + this.tutorialOuter.classList.add("touch-enabled") + } + this.linkGithub = document.getElementById("link-github") + this.linkEmail = document.getElementById("link-email") + + pageEvents.add(this.linkGithub, ["click", "touchend"], this.linkButton) + pageEvents.add(this.linkEmail, ["click", "touchend"], this.linkButton) + pageEvents.once(this.endButton, ["mousedown", "touchstart"]).then(this.onEnd.bind(this)) + pageEvents.keyOnce(this, 13, "down").then(this.onEnd.bind(this)) + + this.gamepad = new Gamepad({ + "confirm": ["start", "b", "ls", "rs"] + }, this.onEnd.bind(this)) + + this.addDiag() + } + 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("about", false, touched) + }, 500) + } + addDiag(){ + var diag = [] + + diag.push("```") + diag.push("Taiko-Web version: " + this.version) + diag.push("User agent: " + navigator.userAgent) + diag.push("Screen size: " + innerWidth + "x" + innerHeight + ", outer: " + outerWidth + "x" + outerHeight + ", ratio: " + (window.devicePixelRatio || 1).toFixed(2)) + if(this.touchEnabled){ + diag.push("Touch enabled: true") + } + if(!fullScreenSupported){ + diag.push("Full screen supported: false") + } + if("getGamepads" in navigator){ + var gamepads = navigator.getGamepads() + for(var i = 0; i < gamepads.length; i++){ + if(gamepads[i]){ + var gamepadDiag = [] + gamepadDiag.push(gamepads[i].id) + gamepadDiag.push("buttons: " + gamepads[i].buttons.length) + gamepadDiag.push("axes: " + gamepads[i].axes.length) + diag.push("Gamepad #" + (i + 1) + ": " + gamepadDiag.join(", ")) + } + } + } + var errorObj = {} + if(localStorage["lastError"]){ + try{ + errorObj = JSON.parse(localStorage["lastError"]) + }catch(e){} + } + if(errorObj.timestamp && errorObj.stack){ + if(errorObj.timestamp + 1000 * 60 * 60 * 24 > (+new Date)){ + diag.push("Last error: " + errorObj.stack) + diag.push("Error date: " + new Date(errorObj.timestamp).toGMTString()) + }else{ + localStorage.removeItem("lastError") + } + } + diag.push("```") + + var body = this.diagTxt.contentWindow.document.body + body.innerText = diag.join("\n") + + body.setAttribute("style", ` + font-family: monospace; + margin: 2px 0 0 2px; + white-space: pre-wrap; + word-break: break-all; + cursor: text; + `) + body.setAttribute("onblur", ` + getSelection().removeAllRanges() + `) + if(!this.touchEnabled){ + body.setAttribute("onfocus", ` + var selection = getSelection() + selection.removeAllRanges() + var range = document.createRange() + range.selectNodeContents(document.body) + selection.addRange(range) + `) + } + } + linkButton(event){ + event.currentTarget.getElementsByTagName("a")[0].click() + } + clean(){ + cancelTouch = true + this.gamepad.clean() + pageEvents.remove(this.linkGithub, ["click", "touchend"]) + pageEvents.remove(this.linkEmail, ["click", "touchend"]) + pageEvents.remove(this.endButton, ["mousedown", "touchstart"]) + pageEvents.keyRemove(this, 13) + delete this.endButton + delete this.diagTxt + delete this.version + delete this.tutorialOuter + delete this.linkGithub + delete this.linkEmail + } +} diff --git a/public/src/js/assets.js b/public/src/js/assets.js index e289e16..fde1bec 100644 --- a/public/src/js/assets.js +++ b/public/src/js/assets.js @@ -123,7 +123,8 @@ var assets = { "loadsong.html", "songselect.html", "titlescreen.html", - "tutorial.html" + "tutorial.html", + "about.html" ], "songs": [], diff --git a/public/src/js/loader.js b/public/src/js/loader.js index e8bda9d..9d1f188 100644 --- a/public/src/js/loader.js +++ b/public/src/js/loader.js @@ -6,15 +6,6 @@ class Loader{ this.canvasTest = new CanvasTest() p2 = new P2Connection() this.ajax("src/views/loader.html").then(this.run.bind(this)) - - pageEvents.add(root, ["touchstart", "touchmove", "touchend"], event => { - event.preventDefault() - }) - var versionDiv = document.getElementById("version") - var versionLink = document.getElementById("version-link") - pageEvents.add(versionDiv, ["click", "touchend"], () => { - versionLink.click() - }) } run(page){ this.promises = [] diff --git a/public/src/js/main.js b/public/src/js/main.js index 98f6121..a22b310 100644 --- a/public/src/js/main.js +++ b/public/src/js/main.js @@ -1,3 +1,16 @@ +addEventListener("error", err => { + var stack + if("error" in err){ + stack = err.error.stack + }else{ + stack = err.message + "\n at " + err.filename + ":" + err.lineno + ":" + err.colno + } + localStorage["lastError"] = JSON.stringify({ + timestamp: +new Date, + stack: stack + }) +}) + function toggleFullscreen(){ if("requestFullscreen" in root){ if(document.fullscreenElement){ @@ -19,6 +32,14 @@ function toggleFullscreen(){ } } } + +function resizeRoot(){ + if(lastHeight !== innerHeight){ + lastHeight = innerHeight + root.style.height = innerHeight + "px" + } +} + var root = document.documentElement var fullScreenSupported = "requestFullscreen" in root || "webkitRequestFullscreen" in root || "mozRequestFullScreen" in root @@ -26,6 +47,22 @@ var pageEvents = new PageEvents() var snd = {} var p2 var disableBlur = false +var cancelTouch = true +var lastHeight + +pageEvents.add(root, ["touchstart", "touchmove", "touchend"], event => { + if(event.cancelable && cancelTouch){ + event.preventDefault() + } +}) +var versionDiv = document.getElementById("version") +var versionLink = document.getElementById("version-link") +pageEvents.add(versionDiv, ["click", "touchend"], () => { + versionLink.click() +}) +resizeRoot() +pageEvents.add(window, "resize", resizeRoot) + var loader = new Loader(() => { new Titlescreen() }) diff --git a/public/src/js/songselect.js b/public/src/js/songselect.js index 53248e9..aee12cb 100644 --- a/public/src/js/songselect.js +++ b/public/src/js/songselect.js @@ -29,6 +29,12 @@ class SongSelect{ border: ["#d6ffff", "#6bae9c"], outline: "#31ae94" }, + "about": { + sort: 7, + background: "#91cfff", + border: ["#dff0ff", "#6890b2"], + outline: "#217abb" + }, "J-POP": { sort: 0, background: "#219fbb", @@ -114,7 +120,9 @@ class SongSelect{ category: "ランダム" }) if(touchEnabled){ - fromTutorial = false + if(fromTutorial === "tutorial"){ + fromTutorial = false + } }else{ this.songs.push({ title: "あそびかた説明", @@ -123,6 +131,12 @@ class SongSelect{ category: "ランダム" }) } + this.songs.push({ + title: "について", + skin: this.songSkin.about, + action: "about", + category: "ランダム" + }) this.songs.push({ title: "もどる", skin: this.songSkin.back, @@ -155,16 +169,20 @@ class SongSelect{ this.selectedDiff = 0 assets.sounds["bgm_songsel"].playLoop(0.1, false, 0, 1.442, 3.506) - if(touchEnabled || !fromTutorial && "selectedSong" in localStorage){ + if(!touchEnabled && !fromTutorial && !("selectedSong" in localStorage)){ + fromTutorial = "tutorial" + } + + if(fromTutorial){ + this.selectedSong = this.songs.findIndex(song => song.action === fromTutorial) + this.playBgm(true) + }else{ 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) @@ -454,6 +472,8 @@ class SongSelect{ }, 200) }else if(currentSong.action === "tutorial"){ this.toTutorial() + }else if(currentSong.action === "about"){ + this.toAbout() } this.pointer(false) } @@ -505,6 +525,13 @@ class SongSelect{ new Tutorial(true) }, 500) } + toAbout(){ + assets.sounds["don"].play() + this.clean() + setTimeout(() => { + new About(this.touchEnabled) + }, 500) + } redraw(){ if(!this.redrawRunning){ diff --git a/public/src/js/tutorial.js b/public/src/js/tutorial.js index 3f9e1e3..b340d2c 100644 --- a/public/src/js/tutorial.js +++ b/public/src/js/tutorial.js @@ -22,7 +22,7 @@ class Tutorial{ assets.sounds["don"].play() localStorage.setItem("tutorial", "true") setTimeout(() => { - new SongSelect(this.fromSongSel, false, touched) + new SongSelect(this.fromSongSel ? "tutorial" : false, false, touched) }, 500) } clean(){ diff --git a/public/src/js/view.js b/public/src/js/view.js index 99d37ae..a9f5dcf 100644 --- a/public/src/js/view.js +++ b/public/src/js/view.js @@ -949,8 +949,10 @@ class View{ } clean(){ pageEvents.mouseRemove(this) - if(this.controller.multiplayer === 2 && this.canvas){ - this.canvas.canvas.parentNode.removeChild(this.canvas.canvas) + if(this.controller.multiplayer === 2){ + if(this.canvas){ + this.canvas.canvas.parentNode.removeChild(this.canvas.canvas) + } }else{ this.cursor.parentNode.removeChild(this.cursor) } diff --git a/public/src/views/about.html b/public/src/views/about.html new file mode 100644 index 0000000..f2581b2 --- /dev/null +++ b/public/src/views/about.html @@ -0,0 +1,27 @@ +
+
+
について / About
+
+ このシミュレータは現在開発中です。
+ バグが発生した場合は、報告してください。
+ GitHubかメールでバグを報告してください。
+ 以下の診断情報を含めてください!
+
+ This simulator is still in development.
+ Please report any bugs you find.
+ You can report bugs either via GitHub or email.
+ Be sure to include the following diagnostic data! + +
+ + +
OK
+
+
diff --git a/templates/index.html b/templates/index.html index d813baf..d4b8f13 100644 --- a/templates/index.html +++ b/templates/index.html @@ -15,7 +15,6 @@ 太鼓の達人ウェブ - Taiko no Tatsujin Web - @@ -52,6 +51,7 @@ +