japanese-drum-game/public/src/js/settings.js
LoveEevee e81bf9b480 More bug fixes
- BPM and go go time change even when there are no notes after the change, seen in Ego Ego Atakushi and UFO Swingin'
- Maker URL can be added to a local tja
  - Example: `MAKER: Creator name <https://example.com/path>`
- Long list of settings scrolls more naturally with arrow keys
- When media engagement is low, gamepad users will not be able to proceed on the title screen until a mouse click or a key press unpauses the audio context
- Fix "Bad" note gauge judgement on easy difficulty
- In debug, use hash to tell apart songs
2020-03-12 07:59:28 +03:00

974 lines
29 KiB
JavaScript

class Settings{
constructor(){
var ios = /iPhone|iPad/.test(navigator.userAgent)
var phone = /Android|iPhone|iPad/.test(navigator.userAgent)
this.allLanguages = []
for(var i in allStrings){
this.allLanguages.push(i)
}
this.items = {
language: {
type: "language",
options: this.allLanguages,
default: this.getLang()
},
resolution: {
type: "select",
options: ["high", "medium", "low", "lowest"],
default: phone ? "medium" : "high"
},
touchAnimation: {
type: "toggle",
default: !ios,
touch: true
},
keyboardSettings: {
type: "keyboard",
default: {
ka_l: ["d"],
don_l: ["f"],
don_r: ["j"],
ka_r: ["k"]
},
touch: false
},
gamepadLayout: {
type: "gamepad",
options: ["a", "b", "c"],
default: "a",
gamepad: true
},
latency: {
type: "latency",
default: {
"audio": 0,
"video": 0,
"drumSounds": true
}
},
easierBigNotes: {
type: "toggle",
default: false
}
}
this.storage = {}
try{
var storage = JSON.parse(localStorage.getItem("settings") || "{}")
for(var i in this.items){
var current = this.items[i]
if(current.type === "language"){
this.storage[i] = localStorage.getItem("lang")
if(current.options.indexOf(this.storage[i]) === -1){
this.storage[i] = null
}
}else if(i in storage){
if((current.type === "select" || current.type === "gamepad") && current.options.indexOf(storage[i]) === -1){
this.storage[i] = null
}else if(current.type === "keyboard"){
var obj = {}
for(var j in current.default){
if(storage[i] && storage[i][j] && storage[i][j][0]){
obj[j] = storage[i][j]
}else{
obj = null
break
}
}
this.storage[i] = obj
}else if(current.type === "latency"){
var obj = {}
for(var j in current.default){
if(storage[i] && j in storage[i]){
if(j === "drumSounds"){
obj[j] = !!storage[i][j]
continue
}else if(!isNaN(storage[i][j])){
obj[j] = Math.round(parseFloat(storage[i][j]) || 0)
continue
}
}
obj = null
break
}
this.storage[i] = obj
}else{
this.storage[i] = storage[i]
}
}else{
this.storage[i] = null
}
}
}catch(e){
for(var i in this.items){
this.storage[i] = null
}
}
}
getItem(name){
var value = this.storage[name]
return value === null ? this.items[name].default : value
}
setItem(name, value){
this.storage[name] = value
try{
if(name === "language"){
if(value){
localStorage.setItem("lang", value)
}else{
localStorage.removeItem("lang")
}
}else{
var language = this.storage.language
delete this.storage.language
localStorage.setItem("settings", JSON.stringify(this.storage))
this.storage.language = language
}
}catch(e){}
}
getLang(){
if("languages" in navigator){
var userLang = navigator.languages.slice()
userLang.unshift(navigator.language)
for(var i in userLang){
for(var j in allStrings){
if(allStrings[j].regex.test(userLang[i])){
return j
}
}
}
}
return this.allLanguages[0]
}
setLang(lang, noEvent){
strings = lang
var boldFonts = strings.font === "Microsoft YaHei, sans-serif"
loader.screen.style.fontFamily = strings.font
loader.screen.style.fontWeight = boldFonts ? "bold" : ""
loader.screen.classList[boldFonts ? "add" : "remove"]("bold-fonts")
if(!noEvent){
pageEvents.send("language-change", lang.id)
}
}
}
class SettingsView{
constructor(touchEnabled, tutorial, songId, toSetting){
this.touchEnabled = touchEnabled
this.tutorial = tutorial
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")
this.viewOuter = this.getElement("view-outer")
if(touchEnabled){
this.viewOuter.classList.add("touch-enabled")
}
this.touchEnd = []
this.windowSymbol = Symbol()
this.touchMove = {
active: false,
x: 0,
y: 0
}
pageEvents.add(window, ["mouseup", "touchstart", "touchmove", "touchend", "blur"], event => {
var move = this.touchMove
if(event.type === "touchstart"){
var cursor = event.changedTouches[0]
move.active = false
move.x = cursor.pageX
move.y = cursor.pageY
}else if(event.type === "touchmove"){
var cursor = event.changedTouches[0]
if (Math.abs(move.x - cursor.pageX) > 10 || Math.abs(move.y - cursor.pageY) > 10){
move.active = true
}
}else{
this.touchEnd.forEach(func => func(event))
move.active = false
}
}, this.windowSymbol)
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.pressedKeys = {}
this.keyboard = new Keyboard({
"confirm": ["enter", "space", "don_l", "don_r"],
"up": ["up"],
"right": ["right", "ka_r"],
"down": ["down"],
"left": ["left", "ka_l"],
"back": ["esc"],
"other": ["wildcard"]
}, this.keyPressed.bind(this))
this.gamepad = new Gamepad({
"confirm": ["b", "ls", "rs"],
"up": ["u", "lsu"],
"right": ["r", "rb", "rt", "lsr"],
"down": ["d", "lsd"],
"left": ["l", "lb", "lt", "lsl"],
"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 = this.getElement("view-content")
this.items = []
this.selected = 0
for(let i in settings.items){
var current = settings.items[i]
if(
!touchEnabled && current.touch === true ||
touchEnabled && current.touch === false ||
!gamepadEnabled && current.gamepad === true
){
continue
}
var settingBox = document.createElement("div")
settingBox.classList.add("setting-box")
var nameDiv = document.createElement("div")
nameDiv.classList.add("setting-name", "stroke-sub")
var name = strings.settings[i].name
this.setAltText(nameDiv, name)
settingBox.appendChild(nameDiv)
var valueDiv = document.createElement("div")
valueDiv.classList.add("setting-value")
this.getValue(i, valueDiv)
settingBox.appendChild(valueDiv)
content.appendChild(settingBox)
if(!toSetting && this.items.length === this.selected || toSetting === i){
this.selected = this.items.length
settingBox.classList.add("selected")
}
this.addTouchEnd(settingBox, event => this.setValue(i))
this.items.push({
id: i,
settingBox: settingBox,
nameDiv: nameDiv,
valueDiv: valueDiv
})
}
this.items.push({
id: "default",
settingBox: this.defaultButton
})
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.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.gamepadBox = this.gamepadSettings.getElementsByClassName("setting-box")[0]
this.addTouch(this.gamepadBox, event => this.gamepadSet(1))
this.gamepadButtons = document.getElementById("gamepad-buttons")
this.gamepadValue = document.getElementById("gamepad-value")
this.latencySettings = document.getElementById("settings-latency")
this.addTouch(this.latencySettings, event => {
if(event.target === event.currentTarget){
this.latencyBack()
}
})
this.latencyTitle = this.latencySettings.getElementsByClassName("view-title")[0]
this.latencyItems = []
this.latencySelected = 0
var latencyContent = this.latencySettings.getElementsByClassName("view-content")[0]
var latencyWindow = ["calibration", "audio", "video", "drumSounds"]
for(let i in latencyWindow){
let current = latencyWindow[i]
var settingBox = document.createElement("div")
settingBox.classList.add("setting-box")
var nameDiv = document.createElement("div")
nameDiv.classList.add("setting-name", "stroke-sub")
var name = strings.settings.latency[current]
this.setAltText(nameDiv, name)
settingBox.appendChild(nameDiv)
let outputObject = {
id: current,
settingBox: settingBox,
nameDiv: nameDiv
}
if(current === "calibration"){
nameDiv.style.width = "100%"
}else{
var valueDiv = document.createElement("div")
valueDiv.classList.add("setting-value")
settingBox.appendChild(valueDiv)
var valueText = document.createTextNode("")
valueDiv.appendChild(valueText)
this.latencyGetValue(current, valueText)
if(current !== "drumSounds"){
var buttons = document.createElement("div")
buttons.classList.add("latency-buttons")
var buttonMinus = document.createElement("span")
buttonMinus.innerText = "-"
buttons.appendChild(buttonMinus)
this.addTouchRepeat(buttonMinus, event => {
this.latencySetAdjust(outputObject, -1)
})
var buttonPlus = document.createElement("span")
buttonPlus.innerText = "+"
buttons.appendChild(buttonPlus)
this.addTouchRepeat(buttonPlus, event => {
this.latencySetAdjust(outputObject, 1)
})
valueDiv.appendChild(buttons)
}
}
latencyContent.appendChild(settingBox)
if(this.latencyItems.length === this.latencySelected){
settingBox.classList.add("selected")
}
this.addTouch(settingBox, event => {
if(event.target.tagName !== "SPAN"){
this.latencySetValue(current, event.type === "touchstart")
}
})
if(current !== "calibration"){
outputObject.valueDiv = valueDiv
outputObject.valueText = valueText
outputObject.buttonMinus = buttonMinus
outputObject.buttonPlus = buttonPlus
}
this.latencyItems.push(outputObject)
}
this.latencyDefaultButton = document.getElementById("latency-default")
this.latencyItems.push({
id: "default",
settingBox: this.latencyDefaultButton
})
this.addTouch(this.latencyDefaultButton, event => this.latencyDefault())
this.latencyEndButton = this.latencySettings.getElementsByClassName("view-end-button")[0]
this.latencyItems.push({
id: "back",
settingBox: this.latencyEndButton
})
this.addTouch(this.latencyEndButton, event => this.latencyBack(true))
this.setStrings()
this.drumSounds = settings.getItem("latency").drumSounds
this.playedSounds = {}
this.redrawRunning = true
this.redrawBind = this.redraw.bind(this)
this.redraw()
if(toSetting === "latency"){
this.mode = "latency"
this.latencySet()
}
pageEvents.send("settings")
}
getElement(name){
return loader.screen.getElementsByClassName(name)[0]
}
addTouch(element, callback, end){
var touchEvent = end ? "touchend" : "touchstart"
pageEvents.add(element, ["mousedown", touchEvent], event => {
if(event.type === touchEvent){
event.preventDefault()
this.touched = true
}else if(event.which !== 1){
return
}else{
this.touched = false
}
if(event.type !== "touchend" || !this.touchMove.active){
callback(event)
}
})
}
addTouchEnd(element, callback){
this.addTouch(element, callback, true)
}
addTouchRepeat(element, callback){
this.addTouch(element, event => {
var active = true
var func = () => {
active = false
this.touchEnd.splice(this.touchEnd.indexOf(func), 1)
}
this.touchEnd.push(func)
var repeat = delay => {
if(active){
callback()
setTimeout(() => repeat(50), delay)
}
}
repeat(400)
})
}
removeTouch(element){
pageEvents.remove(element, ["mousedown", "touchstart"])
}
removeTouchEnd(element){
pageEvents.remove(element, ["mousedown", "touchend"])
}
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" || 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 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
}else if(current.type === "latency"){
var audioVideo = [Math.round(value.audio), Math.round(value.video)]
var latencyValue = strings.settings[name].value.split("%s")
var latencyIndex = 0
value = ""
latencyValue.forEach((string, i) => {
if(i !== 0){
value += this.addMs(audioVideo[latencyIndex++])
}
value += string
})
}
valueDiv.innerText = value
}
setValue(name){
var current = settings.items[name]
var value = settings.getItem(name)
var selectedIndex = this.items.findIndex(item => item.id === name)
var selected = this.items[selectedIndex]
if(this.mode !== "settings"){
if(this.selected === selectedIndex){
this.keyboardBack(selected)
this.playSound("se_don")
}
return
}
if(this.selected !== selectedIndex){
this.items[this.selected].settingBox.classList.remove("selected")
this.selected = selectedIndex
selected.settingBox.classList.add("selected")
}
if(current.type === "language" || current.type === "select"){
value = current.options[this.mod(current.options.length, current.options.indexOf(value) + 1)]
}else if(current.type === "toggle"){
value = !value
}else if(current.type === "keyboard"){
this.mode = "keyboard"
selected.settingBox.style.animation = "none"
selected.valueDiv.classList.add("selected")
this.keyboardKeys = {}
this.keyboardSet()
this.playSound("se_don")
return
}else if(current.type === "gamepad"){
this.mode = "gamepad"
this.gamepadSelected = current.options.indexOf(value)
this.gamepadSet()
this.playSound("se_don")
return
}else if(current.type === "latency"){
this.mode = "latency"
this.latencySet()
this.playSound("se_don")
return
}
settings.setItem(name, value)
this.getValue(name, this.items[this.selected].valueDiv)
this.playSound("se_ka")
if(current.type === "language"){
this.setLang(allStrings[value])
}
}
keyPressed(pressed, name, event, repeat){
if(pressed){
if(!this.pressedKeys[name]){
this.pressedKeys[name] = this.getMS() + 300
}
}else{
this.pressedKeys[name] = 0
return
}
if(repeat && name !== "up" && name !== "right" && name !== "down" && name !== "left"){
return
}
this.touched = false
var selected = this.items[this.selected]
if(this.mode === "settings"){
if(name === "confirm"){
if(selected.id === "back"){
this.onEnd()
}else if(selected.id === "default"){
this.defaultSettings()
}else{
this.setValue(selected.id)
}
}else if(name === "up" || name === "right" || name === "down" || name === "left"){
selected.settingBox.classList.remove("selected")
do{
this.selected = this.mod(this.items.length, this.selected + ((name === "right" || name === "down") ? 1 : -1))
}while(this.items[this.selected].id === "default" && name !== "left")
selected = this.items[this.selected]
selected.settingBox.classList.add("selected")
this.scrollTo(selected.settingBox)
this.playSound("se_ka")
}else if(name === "back"){
this.onEnd()
}
}else if(this.mode === "gamepad"){
if(name === "confirm"){
this.gamepadBack(true)
}else if(name === "up" || name === "right" || name === "down" || name === "left"){
this.gamepadSet((name === "right" || name === "down") ? 1 : -1)
}else if(name === "back"){
this.gamepadBack()
}
}else if(this.mode === "keyboard"){
if(name === "back"){
this.keyboardBack(selected)
this.playSound("se_cancel")
}else if(event){
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
this.playSound(current === "ka_l" || current === "ka_r" ? "se_ka" : "se_don")
this.keyboardKeys[current] = [currentKey]
this.keyboardSet()
}
}else if(this.mode === "latency"){
var latencySelected = this.latencyItems[this.latencySelected]
if(name === "confirm"){
if(latencySelected.id === "back"){
this.latencyBack(true)
}else if(latencySelected.id === "default"){
this.latencyDefault()
}else{
this.latencySetValue(latencySelected.id)
}
}else if(name === "up" || name === "right" || name === "down" || name === "left"){
latencySelected.settingBox.classList.remove("selected")
do{
this.latencySelected = this.mod(this.latencyItems.length, this.latencySelected + ((name === "right" || name === "down") ? 1 : -1))
}while(this.latencyItems[this.latencySelected].id === "default" && name !== "left")
latencySelected = this.latencyItems[this.latencySelected]
latencySelected.settingBox.classList.add("selected")
latencySelected.settingBox.scrollIntoView()
this.playSound("se_ka")
}else if(name === "back"){
this.latencyBack()
}
}else if(this.mode === "latencySet"){
var latencySelected = this.latencyItems[this.latencySelected]
if(name === "confirm" || name === "back"){
this.latencySetBack(latencySelected)
this.playSound(name === "confirm" ? "se_don" : "se_cancel")
}else if(name === "up" || name === "right" || name === "down" || name === "left"){
this.latencySetAdjust(latencySelected, (name === "up" || name === "right") ? 1 : -1)
}
}
}
scrollTo(element){
var parentNode = element.parentNode
var selected = element.getBoundingClientRect()
var parent = parentNode.getBoundingClientRect()
var scrollY = parentNode.scrollTop
var selectedPosTop = selected.top - selected.height / 2
if(Math.floor(selectedPosTop) < Math.floor(parent.top)){
parentNode.scrollTop += selectedPosTop - parent.top
}else{
var selectedPosBottom = selected.top + selected.height * 1.5 - parent.top
if(Math.floor(selectedPosBottom) > Math.floor(parent.height)){
parentNode.scrollTop += selectedPosBottom - parent.height
}
}
}
keyboardSet(){
var selected = this.items[this.selected]
var current = settings.items[selected.id]
selected.valueDiv.innerHTML = ""
for(var i in current.default){
var keyDiv = document.createElement("div")
keyDiv.style.color = i === "ka_l" || i === "ka_r" ? "#009aa5" : "#ef2c10"
if(this.keyboardKeys[i]){
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{
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.keyboard.update()
pageEvents.setKbd()
}
keyboardBack(selected){
this.mode = "settings"
selected.settingBox.style.animation = ""
selected.valueDiv.classList.remove("selected")
this.getValue(selected.id, selected.valueDiv)
}
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)
this.playSound("se_ka")
}
var opt = current.options[this.gamepadSelected]
var value = strings.settings[selected.id][opt]
this.setAltText(this.gamepadValue, value)
this.gamepadButtons.style.backgroundPosition = "0 " + (-11.87 - 4.93 * this.gamepadSelected) + "em"
this.gamepadSettings.style.display = "flex"
}
gamepadBack(confirm){
if(this.mode !== "gamepad"){
return
}
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)
this.playSound(confirm ? "se_don" : "se_cancel")
this.gamepadSettings.style.display = ""
this.mode = "settings"
}
latencySet(){
if(this.mode !== "latency"){
return
}
var selected = this.items[this.selected]
var current = settings.items[selected.id]
this.latencySettings.style.display = "flex"
}
latencyGetValue(name, valueText){
var currentLatency = settings.getItem("latency")
if(name === "drumSounds"){
valueText.data = currentLatency[name] ? strings.settings.on : strings.settings.off
}else{
valueText.data = this.addMs(currentLatency[name] || 0)
}
}
latencySetValue(name, touched){
var selectedIndex = this.latencyItems.findIndex(item => item.id === name)
var selected = this.latencyItems[selectedIndex]
if(this.mode === "latencySet"){
this.latencySetBack(this.latencyItems[this.latencySelected])
if(this.latencySelected === selectedIndex){
this.playSound("se_don")
return
}
}else if(this.mode !== "latency"){
return
}
if(name === "calibration"){
this.playSound("se_don")
this.clean()
new LoadSong({
"title": strings.calibration.title,
"folder": "calibration",
"type": "tja",
"songSkin": {}
}, false, false, touched)
}else if(name === "drumSounds"){
this.drumSounds = !settings.getItem("latency")[name]
this.latencySave(name, this.drumSounds)
this.latencyGetValue(name, selected.valueText)
this.playSound("se_don")
}else{
var value = Math.round(settings.getItem("latency")[name] || 0)
if(this.latencySelected !== selectedIndex){
this.latencyItems[this.latencySelected].settingBox.classList.remove("selected")
this.latencySelected = selectedIndex
selected.settingBox.classList.add("selected")
}
this.mode = "latencySet"
selected.settingBox.style.animation = "none"
selected.valueDiv.classList.add("selected")
selected.value = value
this.playSound("se_don")
}
}
latencySetAdjust(selected, add){
selected.value += add
if(selected.value > 500){
selected.value = 500
}else if(selected.value < -200){
selected.value = -200
}else{
this.playSound("se_ka")
}
selected.valueText.data = this.addMs(selected.value)
}
latencySetBack(selected){
this.mode = "latency"
selected.settingBox.style.animation = ""
selected.valueDiv.classList.remove("selected")
this.latencySave(selected.id, selected.value)
this.latencyGetValue(selected.id, selected.valueText)
}
latencySave(id, value){
var input = settings.getItem("latency")
var output = {}
for(var i in input){
if(i === id){
output[i] = value
}else{
output[i] = input[i]
}
}
settings.setItem("latency", output)
}
latencyDefault(){
if(this.mode === "latencySet"){
this.latencySetBack(this.latencyItems[this.latencySelected])
}else if(this.mode !== "latency"){
return
}
settings.setItem("latency", null)
this.latencyItems.forEach(item => {
if(item.id === "audio" || item.id === "video" || item.id === "drumSounds"){
this.latencyGetValue(item.id, item.valueText)
}
})
this.drumSounds = settings.getItem("latency").drumSounds
this.playSound("se_don")
}
latencyBack(confirm){
if(this.mode === "latencySet"){
this.latencySetBack(this.latencyItems[this.latencySelected])
if(!confirm){
this.playSound("se_don")
return
}
}
if(this.mode !== "latency"){
return
}
var selected = this.items[this.selected]
var current = settings.items[selected.id]
this.getValue(selected.id, selected.valueDiv)
this.playSound(confirm ? "se_don" : "se_cancel")
this.latencySettings.style.display = ""
this.mode = "settings"
}
addMs(input){
var split = strings.calibration.ms.split("%s")
var index = 0
var output = ""
var inputStrings = [(input > 0 ? "+" : "") + input.toString()]
split.forEach((string, i) => {
if(i !== 0){
output += inputStrings[index++]
}
output += string
})
return output
}
defaultSettings(){
if(this.mode === "keyboard"){
this.keyboardBack(this.items[this.selected])
}
for(var i in settings.items){
settings.setItem(i, null)
}
this.setLang(allStrings[settings.getItem("language")])
this.keyboard.update()
pageEvents.setKbd()
this.latencyItems.forEach(item => {
if(item.id === "audio" || item.id === "video" || item.id === "drumSounds"){
this.latencyGetValue(item.id, item.valueText)
}
})
this.drumSounds = settings.getItem("latency").drumSounds
this.playSound("se_don")
}
onEnd(){
this.clean()
this.playSound("se_don")
setTimeout(() => {
if(this.tutorial && !this.touched){
new Tutorial(false, this.songId)
}else{
try{
localStorage.setItem("tutorial", "true")
}catch(e){}
new SongSelect(this.tutorial ? false : "settings", false, this.touched, this.songId)
}
}, 500)
}
setLang(lang){
settings.setLang(lang)
if(failedTests.length !== 0){
showUnsupported(strings)
}
for(var i in this.items){
var item = this.items[i]
if(item.valueDiv){
var name = strings.settings[item.id].name
this.setAltText(item.nameDiv, name)
this.getValue(item.id, item.valueDiv)
}
}
for(var i in this.latencyItems){
var current = this.latencyItems[i]
if(current.nameDiv){
this.setAltText(current.nameDiv, strings.settings.latency[current.id])
}
if(current.valueText){
this.latencyGetValue(current.id, current.valueText)
}
}
this.setStrings()
}
setStrings(){
this.setAltText(this.viewTitle, strings.gameSettings)
this.setAltText(this.endButton, strings.settings.ok)
this.setAltText(this.gamepadTitle, strings.settings.gamepadLayout.name)
this.setAltText(this.gamepadEndButton, strings.settings.ok)
this.setAltText(this.latencyTitle, strings.settings.latency.name)
this.setAltText(this.latencyDefaultButton, strings.settings.default)
this.setAltText(this.latencyEndButton, strings.settings.ok)
this.setAltText(this.defaultButton, strings.settings.default)
}
setAltText(element, text){
element.innerText = text
element.setAttribute("alt", text)
}
mod(length, index){
return ((index % length) + length) % length
}
playSound(id, time){
if(!this.drumSounds && (id === "se_don" || id === "se_ka" || id === "se_cancel")){
return
}
var ms = Date.now() + (time || 0) * 1000
if(!(id in this.playedSounds) || ms > this.playedSounds[id] + 30){
assets.sounds[id].play(time)
this.playedSounds[id] = ms
}
}
redraw(){
if(!this.redrawRunning){
return
}
requestAnimationFrame(this.redrawBind)
var ms = this.getMS()
for(var key in this.pressedKeys){
if(this.pressedKeys[key]){
if(ms >= this.pressedKeys[key] + 50){
this.keyPressed(true, key, null, true)
this.pressedKeys[key] = ms
}
}
}
}
getMS(){
return Date.now()
}
clean(){
this.redrawRunning = false
this.keyboard.clean()
this.gamepad.clean()
assets.sounds["bgm_settings"].stop()
pageEvents.remove(window, ["mouseup", "touchstart", "touchmove", "touchend", "blur"], this.windowSymbol)
for(var i in this.items){
this.removeTouchEnd(this.items[i].settingBox)
}
for(var i in this.latencyItems){
this.removeTouch(this.latencyItems[i].settingBox)
if(this.latencyItems[i].buttonMinus){
this.removeTouch(this.latencyItems[i].buttonMinus)
this.removeTouch(this.latencyItems[i].buttonPlus)
}
}
if(this.defaultButton){
delete this.defaultButton
}
this.removeTouch(this.gamepadSettings)
this.removeTouch(this.gamepadEndButton)
this.removeTouch(this.gamepadBox)
this.removeTouch(this.latencySettings)
this.removeTouch(this.latencyDefaultButton)
this.removeTouch(this.latencyEndButton)
delete this.windowSymbol
delete this.touchMove
delete this.viewOuter
delete this.touchEnd
delete this.tutorialTitle
delete this.endButton
delete this.items
delete this.gamepadSettings
delete this.gamepadTitle
delete this.gamepadEndButton
delete this.gamepadBox
delete this.gamepadButtons
delete this.gamepadValue
delete this.latencyItems
delete this.latencySettings
delete this.latencyTitle
delete this.latencyDefaultButton
delete this.latencyEndButton
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_")){
URL.revokeObjectURL(assets.image[i].src)
delete assets.image[i]
}
}
}
}
}