Files
taiko-web2/public/src/js/about.js
LoveEevee ff09cb83bd Add global offset
Adds new settings for controlling the note offset while playing. It can be either an actual offset (it is called "Audio Latency" in the settings) or just the visual offset ("Video Latency").
With higher audio latency it means you have to press the button sooner than what you hear, similarly with higher video latency it is sooner than what you see. By offsetting these events the game would play better, however, the sound effect of you hitting the drum would still play at the wrong time, the code cannot anticipate you to hit the drum in the future so to work around this issue a new option that disables drum sounds is also included.
These settings could be set through trial and error but it would be better to get the correct values through the automated latency calibration, where you can hit the drum as you hear sounds or see a blinking animation. I tried making one by measuring latency from user input, adding all the latency up, and dividing, but that gives unreliable results. I hope someone suggests to me what I should be doing during the calibration to get better results, as I cannot figure what to do on my own.
2019-11-28 09:04:40 +03:00

245 lines
7.6 KiB
JavaScript

class About{
constructor(touchEnabled){
this.touchEnabled = touchEnabled
loader.changePage("about", true)
cancelTouch = false
this.endButton = this.getElement("view-end-button")
this.diagTxt = document.getElementById("diag-txt")
this.version = document.getElementById("version-link").href
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 = this.getElement("view-title")
tutorialTitle.innerText = strings.aboutSimulator
tutorialTitle.setAttribute("alt", strings.aboutSimulator)
var tutorialContent = this.getElement("view-content")
strings.about.bugReporting.forEach(string => {
tutorialContent.appendChild(document.createTextNode(string))
tutorialContent.appendChild(document.createElement("br"))
})
var span = document.createElement("span")
span.classList.add("text-warn")
span.innerText = strings.about.diagnosticWarning
tutorialContent.appendChild(span)
this.endButton.innerText = strings.tutorial.ok
this.endButton.setAttribute("alt", strings.tutorial.ok)
this.items = []
var versionUrl = gameConfig._version.url
this.getLink(this.linkIssues).href = versionUrl + "issues"
this.items.push(this.linkIssues)
var contactEmail = gameConfig.email
this.hasEmail = typeof contactEmail === "string"
if(this.hasEmail){
this.linkEmail.setAttribute("alt", contactEmail)
this.getLink(this.linkEmail).href = "mailto:" + contactEmail
this.getLink(this.linkEmail).innerText = contactEmail
this.items.push(this.linkEmail)
}else{
this.linkEmail.parentNode.removeChild(this.linkEmail)
}
pageEvents.add(this.linkIssues, ["click", "touchend"], this.linkButton.bind(this))
if(this.hasEmail){
pageEvents.add(this.linkEmail, ["click", "touchend"], this.linkButton.bind(this))
}
pageEvents.add(this.endButton, ["mousedown", "touchstart"], this.onEnd.bind(this))
this.items.push(this.endButton)
this.selected = this.items.length - 1
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"],
"next": ["d", "r", "rb", "rt", "lsd", "lsr"],
"back": ["start", "a"]
}, this.keyPressed.bind(this))
pageEvents.send("about", this.addDiag())
}
getElement(name){
return loader.screen.getElementsByClassName(name)[0]
}
keyPressed(pressed, name){
if(!pressed){
return
}
var selected = this.items[this.selected]
if(name === "confirm"){
if(selected === this.endButton){
this.onEnd()
}else{
this.getLink(selected).click()
pageEvents.send("about-link", selected)
assets.sounds["se_don"].play()
}
}else if(name === "previous" || name === "next"){
selected.classList.remove("selected")
this.selected = this.mod(this.items.length, this.selected + (name === "next" ? 1 : -1))
this.items[this.selected].classList.add("selected")
assets.sounds["se_ka"].play()
}else if(name === "back"){
this.onEnd()
}
}
mod(length, index){
return ((index % length) + length) % length
}
onEnd(event){
var touched = false
if(event){
if(event.type === "touchstart"){
event.preventDefault()
touched = true
}else if(event.which !== 1){
return
}
}
this.clean()
assets.sounds["se_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("URL: " + location.href)
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")
}
diag.push("Blur performance: " + perf.blur + "ms, all images: " + perf.allImg + "ms")
diag.push("Page load: " + (perf.load / 1000).toFixed(1) + "s")
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 userLangStr = " (none)"
if("languages" in navigator){
var userLang = navigator.languages.slice()
if(userLang[0] !== navigator.language){
userLang.unshift(navigator.language)
}
if(userLang.length !== 0){
userLangStr = " (" + userLang.join(", ") + ")"
}
}
diag.push("Language: " + strings.id + userLangStr)
var latency = settings.getItem("latency")
diag.push("Audio Latency: " + (latency.audio > 0 ? "+" : "") + latency.audio.toString() + "ms, Video Latency: " + (latency.video > 0 ? "+" : "") + latency.video.toString() + "ms")
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 > Date.now()){
diag.push("Last error: " + errorObj.stack)
diag.push("Error date: " + new Date(errorObj.timestamp).toGMTString())
}else{
localStorage.removeItem("lastError")
}
}
diag.push("```")
var diag = diag.join("\n")
if(navigator.userAgent.indexOf("Android") >= 0){
var iframe = document.createElement("iframe")
this.diagTxt.appendChild(iframe)
var body = iframe.contentWindow.document.body
body.innerText = diag
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()
`)
}else{
this.textarea = document.createElement("textarea")
this.textarea.readOnly = true
this.textarea.value = diag
this.diagTxt.appendChild(this.textarea)
if(!this.touchEnabled){
pageEvents.add(this.textarea, "focus", () => {
this.textarea.select()
})
pageEvents.add(this.textarea, "blur", () => {
getSelection().removeAllRanges()
})
}
}
var issueBody = strings.about.issueTemplate + "\n\n\n\n" + diag
if(this.hasEmail){
this.getLink(this.linkEmail).href += "?body=" + encodeURIComponent(issueBody.replace(/\n/g, "<br>\r\n"))
}
return diag
}
getLink(target){
return target.getElementsByTagName("a")[0]
}
linkButton(event){
if(event.target === event.currentTarget){
this.getLink(event.currentTarget).click()
pageEvents.send("about-link", event.currentTarget)
assets.sounds["se_don"].play()
}
}
clean(){
cancelTouch = true
this.keyboard.clean()
this.gamepad.clean()
pageEvents.remove(this.linkIssues, ["click", "touchend"])
if(this.hasEmail){
pageEvents.remove(this.linkEmail, ["click", "touchend"])
}
pageEvents.remove(this.endButton, ["mousedown", "touchstart"])
if(this.textarea){
pageEvents.remove(this.textarea, ["focus", "blur"])
}
pageEvents.keyRemove(this, "all")
delete this.endButton
delete this.diagTxt
delete this.version
delete this.tutorialOuter
delete this.linkIssues
delete this.linkEmail
delete this.textarea
}
}