Custom scripting, #song=, translations

- A song can be linked directly by adding "#song=<id>" to the url, replace `<id>` with the id in the database, after loading it jumps immediately jumps to the difficulty selection
- Added tutorial translations
- Fixed song preview not playing
- Use text fallback for the logo when there are no vectors
- Increased combo cache by 1 pixel
- A custom javascript file can be loaded from config.json by defining "custom_js" value
- Added lots of events to help writing custom js files: `version-link, title-screen, language-change, song-select, song-select-move, song-select-difficulty, song-select-back, about, about-link, tutorial, import-songs, import-songs-default, session, session-start, session-end, debug, load-song, load-song-player2, load-song-unfocused, load-song-cancel, load-song-error, game-start, key-events, p2-game-end, p2-disconnected, p2-abandoned, pause, unpause, pause-restart, pause-song-select, game-lag, scoresheet, scoresheet-player2`
- Event syntax example:
```js
addEventListener("game-start", event => {
	console.log("game-start", event.detail)
})
```
This commit is contained in:
LoveEevee 2019-02-14 12:32:45 +03:00
parent ca85bc1b2d
commit adc45cb652
20 changed files with 224 additions and 104 deletions

View File

@ -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,15 @@
var issueBody = strings.issueTemplate + "\n\n\n\n" + diag
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){
this.getLink(event.currentTarget).click()
pageEvents.send("about-link", event)
}
clean(){
cancelTouch = true

View File

@ -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(){

View File

@ -37,6 +37,7 @@ class Debug{
this.moveTo(100, 100)
this.restore()
this.updateStatus()
pageEvents.send("debug")
}
startMove(event){
if(event.which === 1){

View File

@ -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

View File

@ -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

View File

@ -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)

View File

@ -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,14 @@ class Keyboard{
clean(){
pageEvents.keyRemove(this, "all")
clearInterval(this.gamepadInterval)
if(this.controller.multiplayer === 1){
pageEvents.remove(window, "beforeunload")
}
if(this.controller.multiplayer !== 2){
pageEvents.send("key-events", {
keyboard: this.keyboardEvents,
gamepad: this.gamepad.gamepadEvents
})
}
}
}

View File

@ -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,8 +153,15 @@ class Loader{
}
}))
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
}
}else if(location.hash.length === 6){
p2.hashLock = true
this.addPromise(new Promise(resolve => {
p2.open()
@ -182,7 +195,7 @@ class Loader{
perf.load = Date.now() - this.startTime
this.canvasTest.clean()
this.clean()
this.callback()
this.callback(songId)
})
}, this.errorMsg.bind(this))

View File

@ -15,6 +15,11 @@ class LoadSong{
cancel.setAttribute("alt", strings.cancel)
}
this.run()
pageEvents.send("load-song", {
selectedSong: selectedSong,
autoPlayEnabled: autoPlayEnabled,
multiplayer: multiplayer
})
}
run(){
var song = this.selectedSong
@ -117,6 +122,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 +249,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 +271,7 @@ class LoadSong{
}else{
if(!repeat){
assets.sounds["v_sanka"].play()
pageEvents.send("load-song-unfocused")
}
setTimeout(() => {
this.startMultiplayer(true)
@ -281,6 +289,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")

View File

@ -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: "ブ",

View File

@ -92,6 +92,7 @@ var versionDiv = document.getElementById("version")
var versionLink = document.getElementById("version-link")
pageEvents.add(versionDiv, ["click", "touchend"], () => {
versionLink.click()
pageEvents.send("version-link")
})
resizeRoot()
setInterval(resizeRoot, 100)
@ -112,7 +113,7 @@ pageEvents.keyAdd(debugObj, "all", "down", event => {
}
})
var loader = new Loader(() => {
new Titlescreen()
var loader = new Loader(songId => {
new Titlescreen(songId)
})

View File

@ -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("")
@ -122,6 +128,7 @@ class P2Connection{
for(var i in response.value){
this.results[i] = response.value[i].toString()
}
pageEvents.send("scoresheet-player2", this.results)
break
case "note":
this.notes.push(response.value)

View File

@ -143,4 +143,7 @@ class PageEvents{
getMouse(){
return this.lastMouse
}
send(name, detail){
dispatchEvent(new CustomEvent(name, {detail: detail}))
}
}

View File

@ -60,6 +60,10 @@ class Scoresheet{
}
})
}
pageEvents.send("scoresheet", {
results: this.results,
multiplayer: multiplayer
})
}
keyDown(event, code){
if(!code){

View File

@ -30,9 +30,11 @@ class Session{
}else if(response.type === "songsel"){
p2.clearMessage("users")
this.onEnd(false, true)
pageEvents.send("session-start")
}
})
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")
}

View File

@ -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,8 @@ 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])
}
keyDown(event, code){
@ -590,6 +601,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()
@ -630,6 +642,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 +742,7 @@ class SongSelect{
setTimeout(() => {
new SongSelect("browse", false, this.touchEnabled)
}, 500)
pageEvents.send("import-songs-default")
}else{
this.browse.click()
}
@ -952,7 +967,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 +1706,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 +1742,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 +1889,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()

View File

@ -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: "확인"
}

View File

@ -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()
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)
}
}
@ -96,6 +108,16 @@ class Titlescreen{
}
setLang(lang){
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,8 @@ 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()
pageEvents.send("language-change", lang.id)
}
addLangs(){
for(var i in allStrings){

View File

@ -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(){

View File

@ -750,7 +750,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 +1374,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
@ -1631,12 +1631,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){