diff --git a/public/src/js/about.js b/public/src/js/about.js index 235a8de..1c3586d 100644 --- a/public/src/js/about.js +++ b/public/src/js/about.js @@ -41,7 +41,7 @@ "confirm": ["start", "b", "ls", "rs"] }, this.onEnd.bind(this)) - this.addDiag() + pageEvents.send("about", this.addDiag()) } onEnd(event){ var touched = false @@ -145,12 +145,17 @@ var issueBody = strings.issueTemplate + "\n\n\n\n" + diag this.getLink(this.linkEmail).href += "?body=" + encodeURIComponent(issueBody.replace(/\n/g, "
\r\n")) + + return diag } getLink(target){ return target.getElementsByTagName("a")[0] } linkButton(event){ - this.getLink(event.currentTarget).click() + if(event.target === event.currentTarget){ + this.getLink(event.currentTarget).click() + pageEvents.send("about-link", event) + } } clean(){ cancelTouch = true diff --git a/public/src/js/controller.js b/public/src/js/controller.js index ef7dca3..d161d83 100644 --- a/public/src/js/controller.js +++ b/public/src/js/controller.js @@ -58,6 +58,12 @@ class Controller{ this.viewLoop() if(this.multiplayer !== 2){ this.gameInterval = setInterval(this.gameLoop.bind(this), 1000 / 60) + pageEvents.send("game-start", { + selectedSong: this.selectedSong, + autoPlayEnabled: this.autoPlayEnabled, + multiplayer: this.multiplayer, + touchEnabled: this.touchEnabled + }) } } stopMainLoop(){ diff --git a/public/src/js/debug.js b/public/src/js/debug.js index ca2cf51..6b03534 100644 --- a/public/src/js/debug.js +++ b/public/src/js/debug.js @@ -37,6 +37,7 @@ class Debug{ this.moveTo(100, 100) this.restore() this.updateStatus() + pageEvents.send("debug") } startMove(event){ if(event.which === 1){ diff --git a/public/src/js/game.js b/public/src/js/game.js index 2df56d0..76f7006 100644 --- a/public/src/js/game.js +++ b/public/src/js/game.js @@ -362,6 +362,7 @@ class Game{ this.view.gameDiv.classList.add("game-paused") this.view.lastMousemove = this.view.getMS() this.view.cursorHidden = false + pageEvents.send("pause") }else{ assets.sounds["se_cancel"].play() this.paused = false @@ -370,6 +371,7 @@ class Game{ this.sndTime = currentDate - snd.buffer.getTime() * 1000 this.view.gameDiv.classList.remove("game-paused") this.view.pointer() + pageEvents.send("unpause", currentDate - this.latestDate) } } isPaused(){ @@ -391,6 +393,7 @@ class Game{ if(Math.abs(lag) >= 50){ this.startDate += lag this.sndTime = sndTime + pageEvents.send("game-lag", lag) } } this.elapsedTime = currentDate - this.startDate diff --git a/public/src/js/gamepad.js b/public/src/js/gamepad.js index b6255c0..2956c1a 100644 --- a/public/src/js/gamepad.js +++ b/public/src/js/gamepad.js @@ -25,6 +25,7 @@ class Gamepad{ "lsl": "lsl" } this.btn = {} + this.gamepadEvents = 0 if(callback){ this.interval = setInterval(() => { this.play(callback) @@ -123,6 +124,7 @@ class Gamepad{ if(pressed){ callback(true, keyCode) + this.gamepadEvents++ }else if(!button){ if(released){ this.toRelease[keyCode + "released"] = true diff --git a/public/src/js/importsongs.js b/public/src/js/importsongs.js index bf669ea..400f443 100644 --- a/public/src/js/importsongs.js +++ b/public/src/js/importsongs.js @@ -386,6 +386,7 @@ document.head.appendChild(style) } if(this.songs.length){ + var length = this.songs.length assets.songs = this.songs assets.customSongs = true assets.customSelected = 0 @@ -395,6 +396,7 @@ loader.screen.removeChild(this.loaderDiv) this.clean() new SongSelect("browse", false, this.songSelect.touchEnabled) + pageEvents.send("import-songs", length) }, 500) }else{ loader.screen.removeChild(this.loaderDiv) diff --git a/public/src/js/keyboard.js b/public/src/js/keyboard.js index 6d938ac..186c651 100644 --- a/public/src/js/keyboard.js +++ b/public/src/js/keyboard.js @@ -28,6 +28,7 @@ class Keyboard{ "don": -Infinity, "ka": -Infinity } + this.keyboardEvents = 0 var gameBtn = {} gameBtn[this.kbd["don_l"]] = ["u", "d", "l", "r", "ls"] @@ -66,8 +67,19 @@ class Keyboard{ if(key && !event.repeat && this.buttonEnabled(key)){ var ms = this.game.getAccurateTime() this.setKey(key, event.type === "keydown", ms) + if(event.type === "keydown"){ + this.keyboardEvents++ + } } }) + + if(controller.multiplayer === 1){ + pageEvents.add(window, "beforeunload", event => { + if(p2.otherConnected){ + pageEvents.send("p2-abandoned", event) + } + }) + } } getBindings(){ return this.kbd @@ -165,8 +177,9 @@ class Keyboard{ } if(this.controller.multiplayer !== 2){ this.checkKey(this.kbd["back"], "menu", () => { - if(this.controller.multiplayer === 1){ + if(this.controller.multiplayer === 1 && p2.otherConnected){ p2.send("gameend") + pageEvents.send("p2-abandoned") } this.controller.togglePause() this.controller.songSelection() @@ -243,5 +256,8 @@ class Keyboard{ clean(){ pageEvents.keyRemove(this, "all") clearInterval(this.gamepadInterval) + if(this.controller.multiplayer === 1){ + pageEvents.remove(window, "beforeunload") + } } } diff --git a/public/src/js/loader.js b/public/src/js/loader.js index a2ce20d..a171642 100644 --- a/public/src/js/loader.js +++ b/public/src/js/loader.js @@ -25,6 +25,12 @@ class Loader{ var queryString = gameConfig._version.commit_short ? "?" + gameConfig._version.commit_short : "" + if(gameConfig.custom_js){ + var script = document.createElement("script") + this.addPromise(pageEvents.load(script)) + script.src = gameConfig.custom_js + queryString + document.head.appendChild(script) + } assets.js.forEach(name => { var script = document.createElement("script") this.addPromise(pageEvents.load(script)) @@ -147,17 +153,29 @@ class Loader{ } })) + var readyEvent = "normal" + var songId + var hashLower = location.hash.toLowerCase() p2 = new P2Connection() - if(location.hash.length === 6){ + if(hashLower.startsWith("#song=")){ + var number = parseInt(location.hash.slice(6)) + if(number > 0){ + songId = number + readyEvent = "song-id" + } + }else if(location.hash.length === 6){ p2.hashLock = true this.addPromise(new Promise(resolve => { p2.open() pageEvents.add(p2, "message", response => { if(response.type === "session"){ + pageEvents.send("session-start", "invited") + readyEvent = "session-start" resolve() }else if(response.type === "gameend"){ p2.hash("") p2.hashLock = false + readyEvent = "session-expired" resolve() } }) @@ -182,7 +200,8 @@ class Loader{ perf.load = Date.now() - this.startTime this.canvasTest.clean() this.clean() - this.callback() + this.callback(songId) + pageEvents.send("ready", readyEvent) }) }, this.errorMsg.bind(this)) @@ -205,6 +224,7 @@ class Loader{ } errorMsg(error){ console.error(error) + pageEvents.send("loader-error", error) this.error = true this.loaderPercentage.appendChild(document.createElement("br")) this.loaderPercentage.appendChild(document.createTextNode("An error occurred, please refresh")) diff --git a/public/src/js/loadsong.js b/public/src/js/loadsong.js index 8bf1da4..6629afc 100644 --- a/public/src/js/loadsong.js +++ b/public/src/js/loadsong.js @@ -15,6 +15,12 @@ class LoadSong{ cancel.setAttribute("alt", strings.cancel) } this.run() + pageEvents.send("load-song", { + selectedSong: selectedSong, + autoPlayEnabled: autoPlayEnabled, + multiplayer: multiplayer, + touchEnabled: touchEnabled + }) } run(){ var song = this.selectedSong @@ -117,6 +123,7 @@ class LoadSong{ if(Array.isArray(error) && error[1] instanceof HTMLElement){ error = error[0] + ": " + error[1].outerHTML } + pageEvents.send("load-song-error", error) errorMessage(new Error(error).stack) alert("An error occurred, please refresh") }) @@ -243,6 +250,7 @@ class LoadSong{ var taikoGame1 = new Controller(song, this.songData, false, 1, this.touchEnabled) var taikoGame2 = new Controller(this.selectedSong2, this.song2Data, true, 2, this.touchEnabled) taikoGame1.run(taikoGame2) + pageEvents.send("load-song-player2", this.selectedSong2) }else if(event.type === "left" || event.type === "gameend"){ this.clean() new SongSelect(false, false, this.touchEnabled) @@ -264,6 +272,7 @@ class LoadSong{ }else{ if(!repeat){ assets.sounds["v_sanka"].play() + pageEvents.send("load-song-unfocused") } setTimeout(() => { this.startMultiplayer(true) @@ -281,6 +290,7 @@ class LoadSong{ p2.send("leave") assets.sounds["se_don"].play() this.cancelButton.style.pointerEvents = "none" + pageEvents.send("load-song-cancel") } clean(){ pageEvents.remove(p2, "message") diff --git a/public/src/js/logo.js b/public/src/js/logo.js index 44f98d7..e77f992 100644 --- a/public/src/js/logo.js +++ b/public/src/js/logo.js @@ -2,7 +2,7 @@ constructor(){ this.canvas = document.getElementById("logo") this.ctx = this.canvas.getContext("2d") - this.pathSvg = failedTests.indexOf("Path2D SVG") === -1 + this.pathSvg = failedTests.indexOf("Path2D SVG") === -1 && vectors.logo1 this.symbolFont = "TnT, Meiryo, sans-serif" this.symbols = [{ x: 315, y: 18, xAlt: 15, scale: true, text: "ブ", diff --git a/public/src/js/main.js b/public/src/js/main.js index 1ba7a91..a63691e 100644 --- a/public/src/js/main.js +++ b/public/src/js/main.js @@ -90,8 +90,11 @@ pageEvents.add(root, ["touchstart", "touchmove", "touchend"], event => { }) var versionDiv = document.getElementById("version") var versionLink = document.getElementById("version-link") -pageEvents.add(versionDiv, ["click", "touchend"], () => { - versionLink.click() +pageEvents.add(versionDiv, ["click", "touchend"], event => { + if(event.target === versionDiv){ + versionLink.click() + pageEvents.send("version-link") + } }) resizeRoot() setInterval(resizeRoot, 100) @@ -112,7 +115,7 @@ pageEvents.keyAdd(debugObj, "all", "down", event => { } }) -var loader = new Loader(() => { - new Titlescreen() +var loader = new Loader(songId => { + new Titlescreen(songId) }) diff --git a/public/src/js/p2.js b/public/src/js/p2.js index b635cb1..1f6f97e 100644 --- a/public/src/js/p2.js +++ b/public/src/js/p2.js @@ -58,6 +58,7 @@ class P2Connection{ this.open() } }, 500) + pageEvents.send("p2-disconnected") } var addedType = this.allEvents.get("close") if(addedType){ @@ -111,6 +112,11 @@ class P2Connection{ break case "gameend": this.otherConnected = false + if(this.session){ + pageEvents.send("session-end") + }else if(!this.results){ + pageEvents.send("p2-game-end") + } this.session = false if(this.hashLock){ this.hash("") diff --git a/public/src/js/pageevents.js b/public/src/js/pageevents.js index 789275e..7ba8d68 100644 --- a/public/src/js/pageevents.js +++ b/public/src/js/pageevents.js @@ -143,4 +143,7 @@ class PageEvents{ getMouse(){ return this.lastMouse } + send(name, detail){ + dispatchEvent(new CustomEvent(name, {detail: detail})) + } } diff --git a/public/src/js/scoresheet.js b/public/src/js/scoresheet.js index 35f93c1..1402b86 100644 --- a/public/src/js/scoresheet.js +++ b/public/src/js/scoresheet.js @@ -60,6 +60,17 @@ class Scoresheet{ } }) } + pageEvents.send("scoresheet", { + selectedSong: controller.selectedSong, + autoPlayEnabled: controller.autoPlayEnabled, + multiplayer: multiplayer, + touchEnabled: touchEnabled, + results: this.results, + p2results: multiplayer ? p2.results : null, + keyboardEvents: controller.keyboard.keyboardEvents, + gamepadEvents: controller.keyboard.gamepad.gamepadEvents, + touchEvents: controller.view.touchEvents + }) } keyDown(event, code){ if(!code){ diff --git a/public/src/js/session.js b/public/src/js/session.js index fb967c9..8dfe8e6 100644 --- a/public/src/js/session.js +++ b/public/src/js/session.js @@ -30,9 +30,11 @@ class Session{ }else if(response.type === "songsel"){ p2.clearMessage("users") this.onEnd(false, true) + pageEvents.send("session-start", "host") } }) p2.send("invite") + pageEvents.send("session") } mouseDown(event){ if(event.target === this.sessionInvite){ @@ -50,6 +52,7 @@ class Session{ p2.send("leave") p2.hash("") p2.hashLock = false + pageEvents.send("session-cancel") }else if(!fromP2){ return p2.send("songsel") } diff --git a/public/src/js/songselect.js b/public/src/js/songselect.js index f8462be..6dbe579 100644 --- a/public/src/js/songselect.js +++ b/public/src/js/songselect.js @@ -1,5 +1,5 @@ class SongSelect{ - constructor(fromTutorial, fadeIn, touchEnabled){ + constructor(fromTutorial, fadeIn, touchEnabled, songId){ this.touchEnabled = touchEnabled loader.changePage("songselect", false) @@ -213,23 +213,32 @@ class SongSelect{ this.selectedDiff = 0 assets.sounds["bgm_songsel"].playLoop(0.1, false, 0, 1.442, 3.506) - if(!assets.customSongs && !fromTutorial && !("selectedSong" in localStorage)){ + if(!assets.customSongs && !fromTutorial && !("selectedSong" in localStorage) && !songId){ fromTutorial = touchEnabled ? "about" : "tutorial" } if(p2.session){ fromTutorial = false } + var songIdIndex = -1 if(fromTutorial){ this.selectedSong = this.songs.findIndex(song => song.action === fromTutorial) this.playBgm(true) }else{ - if(assets.customSongs){ + if(songId){ + songIdIndex = this.songs.findIndex(song => song.id === songId) + if(songIdIndex === -1){ + this.clearHash() + } + } + if(songIdIndex !== -1){ + this.selectedSong = songIdIndex + }else if(assets.customSongs){ this.selectedSong = assets.customSelected }else if((!p2.session || fadeIn) && "selectedSong" in localStorage){ this.selectedSong = Math.min(Math.max(0, localStorage["selectedSong"] |0), this.songs.length - 1) } - assets.sounds["v_songsel"].play() + assets.sounds[songIdIndex !== -1 ? "v_diffsel" : "v_songsel"].play() snd.musicGain.fadeOut() this.playBgm(false) } @@ -247,7 +256,7 @@ class SongSelect{ var skipStart = fromTutorial || p2.session this.state = { - screen: fadeIn ? "titleFadeIn" : (skipStart ? "song" : "title"), + screen: songIdIndex !== -1 ? "difficulty" : (fadeIn ? "titleFadeIn" : (skipStart ? "song" : "title")), screenMS: this.getMS(), move: 0, moveMS: 0, @@ -302,6 +311,11 @@ class SongSelect{ this.redrawRunning = true this.redrawBind = this.redraw.bind(this) this.redraw() + pageEvents.send("song-select") + pageEvents.send("song-select-move", this.songs[this.selectedSong]) + if(songIdIndex !== -1){ + pageEvents.send("song-select-difficulty", this.songs[this.selectedSong]) + } } keyDown(event, code){ @@ -590,6 +604,7 @@ class SongSelect{ assets.sounds["se_don"].play() assets.sounds["v_songsel"].stop() assets.sounds["v_diffsel"].play(0.3) + pageEvents.send("song-select-difficulty", currentSong) }else if(currentSong.action === "back"){ this.clean() this.toTitleScreen() @@ -603,6 +618,7 @@ class SongSelect{ setTimeout(() => { this.moveToSong(moveBy) }, 200) + pageEvents.send("song-select-random") }else if(currentSong.action === "tutorial"){ this.toTutorial() }else if(currentSong.action === "about"){ @@ -630,6 +646,8 @@ class SongSelect{ assets.sounds["v_diffsel"].stop() assets.sounds["se_cancel"].play() } + this.clearHash() + pageEvents.send("song-select-back") } toLoadSong(difficulty, shift, ctrl, touch){ this.clean() @@ -728,6 +746,7 @@ class SongSelect{ setTimeout(() => { new SongSelect("browse", false, this.touchEnabled) }, 500) + pageEvents.send("import-songs-default") }else{ this.browse.click() } @@ -952,7 +971,11 @@ class SongSelect{ var elapsed = ms - this.state.moveMS if(this.state.move && ms > this.state.moveMS + resize2 - scrollDelay){ assets.sounds["se_ka"].play() + var previousSelectedSong = this.selectedSong this.selectedSong = this.mod(this.songs.length, this.selectedSong + this.state.move) + if(previousSelectedSong !== this.selectedSong){ + pageEvents.send("song-select-move", this.songs[this.selectedSong]) + } this.state.move = 0 this.state.locked = 2 @@ -1687,16 +1710,11 @@ class SongSelect{ if("id" in currentSong){ var startLoad = this.getMS() if(loadOnly){ - var resolveLoading - this.previewLoading = currentSong.id + var currentId = null }else{ + var currentId = this.previewId this.previewing = this.selectedSong - if(this.previewLoading === currentSong.id){ - this.previewLoading = null - return - } } - var currentId = this.previewId var songObj = this.previewList.find(song => song && song.id === id) if(songObj){ @@ -1728,14 +1746,9 @@ class SongSelect{ }).then(sound => { if(currentId === this.previewId){ songObj.preview_sound = sound - if(!loadOnly || !this.previewLoading){ - this.previewing = this.selectedSong - this.preview = sound - this.previewLoaded(startLoad, songObj.preview_time) - } - if(loadOnly){ - this.previewLoading = null - } + this.preview = sound + this.previewLoaded(startLoad, songObj.preview_time) + var oldPreview = this.previewList.shift() if(oldPreview){ oldPreview.preview_sound.clean() @@ -1880,11 +1893,18 @@ class SongSelect{ return title } + clearHash(){ + if(location.hash.toLowerCase().startsWith("#song=")){ + p2.hash("") + } + } + getMS(){ return Date.now() } clean(){ + this.clearHash() this.draw.clean() this.songTitleCache.clean() this.selectTextCache.clean() diff --git a/public/src/js/strings.js b/public/src/js/strings.js index 510a36c..967d0a1 100644 --- a/public/src/js/strings.js +++ b/public/src/js/strings.js @@ -65,16 +65,16 @@ this.tutorial = { basics: [ - "Hit the drum when the notes reach the taiko!", - "For red notes, hit the face of the drum (%s or %s)...", - "...and for blue notes, hit the rim! (%s or %s)", - "USB controllers are also supported!" + "流れてくる音符がワクに重なったらバチで太鼓をたたこう!", + "赤い音符は面をたたこう(%sまたは%s)", + "青い音符はフチをたたこう(%sまたは%s)", + "USBコントローラがサポートされています!" ], - otherControls: "Other controls", + otherControls: "他のコントロール", otherTutorial: [ - "%s \u2014 pause game", - "%s while selecting difficulty \u2014 enable autoplay mode", - "%s while selecting difficulty \u2014 enable 2P mode" + "%sはゲームを一時停止します", + "むずかしさをえらぶしながら%sキーを押しながらオートモードを有効", + "むずかしさをえらぶしながら%sキーを押しながらネットプレイモードを有効" ], ok: "OK" } @@ -166,8 +166,8 @@ function StringsEn(){ this.tutorial = { basics: [ - "Hit the drum when the notes reach the taiko!", - "For red notes, hit the face of the drum (%s or %s)...", + "When a note overlaps the frame, that is your cue to hit the drum!", + "For red notes, hit the surface of the drum (%s or %s)...", "...and for blue notes, hit the rim! (%s or %s)", "USB controllers are also supported!" ], @@ -267,16 +267,16 @@ function StringsCn(){ this.tutorial = { basics: [ - "Hit the drum when the notes reach the taiko!", - "For red notes, hit the face of the drum (%s or %s)...", - "...and for blue notes, hit the rim! (%s or %s)", - "USB controllers are also supported!" + "当流动的音符将与框框重叠时就用鼓棒敲打太鼓吧", + "遇到红色音符要敲打鼓面(%s或%s)", + "遇到蓝色音符则敲打鼓边(%s或%s)", + "USB控制器也支持!" ], - otherControls: "Other controls", + otherControls: "其他控制", otherTutorial: [ - "%s \u2014 pause game", - "%s while selecting difficulty \u2014 enable autoplay mode", - "%s while selecting difficulty \u2014 enable 2P mode" + "%s暂停游戏", + "选择难度时按住%s以启用自动模式", + "选择难度时按住%s以启用网络对战模式" ], ok: "确定" } @@ -368,16 +368,16 @@ function StringsTw(){ this.tutorial = { basics: [ - "Hit the drum when the notes reach the taiko!", - "For red notes, hit the face of the drum (%s or %s)...", - "...and for blue notes, hit the rim! (%s or %s)", - "USB controllers are also supported!" + "當流動的音符將與框框重疊時就用鼓棒敲打太鼓吧", + "遇到紅色音符要敲打鼓面(%s或%s)", + "遇到藍色音符則敲打鼓邊(%s或%s)", + "USB控制器也支持!" ], - otherControls: "Other controls", + otherControls: "其他控制", otherTutorial: [ - "%s \u2014 pause game", - "%s while selecting difficulty \u2014 enable autoplay mode", - "%s while selecting difficulty \u2014 enable 2P mode" + "%s暫停遊戲", + "選擇難度時按住%s以啟用自動模式", + "選擇難度時按住%s以啟用網上對打模式" ], ok: "確定" } @@ -469,16 +469,16 @@ function StringsKo(){ this.tutorial = { basics: [ - "Hit the drum when the notes reach the taiko!", - "For red notes, hit the face of the drum (%s or %s)...", - "...and for blue notes, hit the rim! (%s or %s)", - "USB controllers are also supported!" + "이동하는 음표가 테두리와 겹쳐졌을 때 북채로 태고를 두드리자!", + "빨간 음표는 면을 두드리자 (%s 또는 %s)", + "파란 음표는 테를 두드리자 (%s 또는 %s)", + "USB 컨트롤러도 지원됩니다!" ], - otherControls: "Other controls", + otherControls: "기타 컨트롤", otherTutorial: [ - "%s \u2014 pause game", - "%s while selecting difficulty \u2014 enable autoplay mode", - "%s while selecting difficulty \u2014 enable 2P mode" + "%s \u2014 게임을 일시 중지합니다", + "난이도 선택 동안 %s 홀드 \u2014 오토 모드 활성화", + "난이도 선택 동안 %s 홀드 \u2014 넷 플레이 모드 활성화" ], ok: "확인" } diff --git a/public/src/js/titlescreen.js b/public/src/js/titlescreen.js index 9f7c4b5..642aab9 100644 --- a/public/src/js/titlescreen.js +++ b/public/src/js/titlescreen.js @@ -1,38 +1,47 @@ class Titlescreen{ - constructor(){ - loader.changePage("titlescreen", false) + constructor(songId){ + this.songId = songId - this.titleScreen = document.getElementById("title-screen") - this.proceed = document.getElementById("title-proceed") - this.langDropdown = document.getElementById("lang-dropdown") - this.langId = document.getElementById("lang-id") - this.disclaimerText = document.getElementById("title-disclaimer-text") - this.disclaimerCopyright = document.getElementById("title-disclaimer-copyright") - document.getElementById("globe-path").setAttribute("d", vectors.globe) - - this.logo = new Logo() + if(!songId){ + loader.changePage("titlescreen", false) + + this.titleScreen = document.getElementById("title-screen") + this.proceed = document.getElementById("title-proceed") + this.langDropdown = document.getElementById("lang-dropdown") + this.langId = document.getElementById("lang-id") + this.disclaimerText = document.getElementById("title-disclaimer-text") + this.disclaimerCopyright = document.getElementById("title-disclaimer-copyright") + document.getElementById("globe-path").setAttribute("d", vectors.globe) + this.logo = new Logo() + } this.lang = this.getLang() - this.setLang(allStrings[this.lang]) - this.addLangs() + this.setLang(allStrings[this.lang], true) - pageEvents.keyAdd(this, "all", "down", this.keyDown.bind(this)) - pageEvents.add(this.titleScreen, ["mousedown", "touchstart"], this.onPressed.bind(this)) - pageEvents.add(this.langDropdown, "change", this.langChange.bind(this)) - - assets.sounds["v_title"].play() - this.gamepad = new Gamepad({ - "13": ["a", "b", "x", "y", "start", "ls", "rs"] - }, pressed => { - if(pressed){ - this.onPressed() - } - }) - if(p2.session){ - pageEvents.add(p2, "message", response => { - if(response.type === "songsel"){ - this.goNext(true) + if(songId){ + this.goNext() + }else{ + this.addLangs() + + pageEvents.keyAdd(this, "all", "down", this.keyDown.bind(this)) + pageEvents.add(this.titleScreen, ["mousedown", "touchstart"], this.onPressed.bind(this)) + pageEvents.add(this.langDropdown, "change", this.langChange.bind(this)) + + assets.sounds["v_title"].play() + this.gamepad = new Gamepad({ + "13": ["a", "b", "x", "y", "start", "ls", "rs"] + }, pressed => { + if(pressed){ + this.onPressed() } }) + if(p2.session){ + pageEvents.add(p2, "message", response => { + if(response.type === "songsel"){ + this.goNext(true) + } + }) + } + pageEvents.send("title-screen") } } @@ -66,13 +75,16 @@ class Titlescreen{ if(p2.session && !fromP2){ p2.send("songsel") }else if(fromP2 || this.touched || localStorage.getItem("tutorial") === "true"){ + if(this.touched){ + localStorage.setItem("tutorial", "true") + } pageEvents.remove(p2, "message") setTimeout(() => { - new SongSelect(false, false, this.touched) + new SongSelect(false, false, this.touched, this.songId) }, 500) }else{ setTimeout(() => { - new Tutorial() + new Tutorial(false, this.songId) }, 500) } } @@ -94,8 +106,18 @@ class Titlescreen{ } return "ja" } - setLang(lang){ + setLang(lang, initial){ strings = lang + + loader.screen.style.fontFamily = strings.font + loader.screen.style.fontWeight = strings.font === "Microsoft YaHei, sans-serif" ? "bold" : "" + + if(failedTests.length !== 0){ + showUnsupported(strings) + } + if(this.songId){ + return + } this.proceed.innerText = strings.titleProceed this.proceed.setAttribute("alt", strings.titleProceed) this.langId.innerText = strings.id.toUpperCase() @@ -106,12 +128,10 @@ class Titlescreen{ this.disclaimerCopyright.innerText = strings.titleCopyright this.disclaimerCopyright.setAttribute("alt", strings.titleCopyright) - loader.screen.style.fontFamily = strings.font - loader.screen.style.fontWeight = strings.font === "Microsoft YaHei, sans-serif" ? "bold" : "" - if(failedTests.length !== 0){ - showUnsupported(strings) - } this.logo.updateSubtitle() + if(!initial){ + pageEvents.send("language-change", lang.id) + } } addLangs(){ for(var i in allStrings){ diff --git a/public/src/js/tutorial.js b/public/src/js/tutorial.js index 7de7e31..d2999cd 100644 --- a/public/src/js/tutorial.js +++ b/public/src/js/tutorial.js @@ -1,6 +1,7 @@ class Tutorial{ - constructor(fromSongSel){ + constructor(fromSongSel, songId){ this.fromSongSel = fromSongSel + this.songId = songId loader.changePage("tutorial", true) assets.sounds["bgm_setsume"].playLoop(0.1, false, 0, 1.054, 16.054) this.endButton = document.getElementById("tutorial-end-button") @@ -47,6 +48,7 @@ class Tutorial{ this.gamepad = new Gamepad({ "confirm": ["start", "b", "ls", "rs"] }, this.onEnd.bind(this)) + pageEvents.send("tutorial") } insertText(text, parent){ parent.appendChild(document.createTextNode(text)) @@ -66,7 +68,7 @@ class Tutorial{ assets.sounds["se_don"].play() localStorage.setItem("tutorial", "true") setTimeout(() => { - new SongSelect(this.fromSongSel ? "tutorial" : false, false, touched) + new SongSelect(this.fromSongSel ? "tutorial" : false, false, touched, this.songId) }, 500) } clean(){ diff --git a/public/src/js/view.js b/public/src/js/view.js index 61513d0..fa0c534 100644 --- a/public/src/js/view.js +++ b/public/src/js/view.js @@ -74,6 +74,7 @@ this.nextBeat = 0 this.gogoTime = 0 this.drumroll = [] + this.touchEvents = 0 this.beatInterval = this.controller.parsedSongData.beatInfo.beatInterval this.font = strings.font @@ -750,7 +751,7 @@ comboScale = this.draw.fade(scoreMS / 100) } var glyphW = 51 - var glyphH = 64 + var glyphH = 65 var letterSpacing = (comboText.length >= 4 ? 38 : 42) * mul var orange = comboCount >= 100 ? "1" : "0" @@ -1374,8 +1375,8 @@ fillComboCache(){ var fontSize = 58 var letterSpacing = fontSize * 0.67 - var glyphW = 50 - var glyphH = 64 + var glyphW = 51 + var glyphH = 65 var textX = 5 var textY = 5 var letterBorder = fontSize * 0.15 @@ -1601,6 +1602,7 @@ this.touchNote("ka_r") } } + this.touchEvents++ } } } @@ -1631,12 +1633,17 @@ switch(pos){ case 1: assets.sounds["se_don"].play() - return this.controller.restartSong() + this.controller.restartSong() + pageEvents.send("pause-restart") + break case 2: assets.sounds["se_don"].play() - return this.controller.songSelection() + this.controller.songSelection() + pageEvents.send("pause-song-select") + break default: - return this.controller.togglePause() + this.controller.togglePause() + break } } onmousedown(event){ diff --git a/server.py b/server.py index 19ddd03..b4b65ca 100644 --- a/server.py +++ b/server.py @@ -210,6 +210,7 @@ async def connection(ws, path): user["other_user"]["ws"].send(sent_msg1), user["other_user"]["ws"].send(sent_msg2) ]) + del user["other_user"]["other_user"] del user["other_user"] else: # Other user disconnected @@ -304,6 +305,7 @@ async def connection(ws, path): user["other_user"]["ws"].send(sent_msg1), user["other_user"]["ws"].send(sent_msg2) ]) + del user["other_user"]["other_user"] del user["other_user"] else: # Other user disconnected @@ -324,6 +326,7 @@ async def connection(ws, path): user["other_user"]["ws"].send(msgobj("gameend")), user["other_user"]["ws"].send(status_event()) ]) + del user["other_user"]["other_user"] if user["action"] == "waiting": del server_status["waiting"][user["gameid"]] await notify_status()