From a49cc6a3c45a861e09187792ab36cc598ca24431 Mon Sep 17 00:00:00 2001 From: LoveEevee Date: Tue, 18 Sep 2018 20:33:18 +0300 Subject: [PATCH] Add renda sound, dai notes scoring, fix music timing --- public/src/js/assets.js | 3 +- public/src/js/circle.js | 7 +- public/src/js/controller.js | 4 +- public/src/js/game.js | 144 +++++++++++++++++++++--------------- public/src/js/keyboard.js | 4 +- public/src/js/loadsong.js | 15 ++-- public/src/js/mekadon.js | 30 ++++---- public/src/js/p2.js | 10 ++- public/src/js/songselect.js | 2 +- public/src/js/view.js | 107 +++++++++++++-------------- 10 files changed, 181 insertions(+), 145 deletions(-) diff --git a/public/src/js/assets.js b/public/src/js/assets.js index cb91c81..9006cc1 100644 --- a/public/src/js/assets.js +++ b/public/src/js/assets.js @@ -82,7 +82,8 @@ var assets = { "note_don.ogg", "note_ka.ogg", - "balloon.ogg" + "balloon.ogg", + "renda.ogg" ], "audioMusic": [ "bgm_songsel.ogg", diff --git a/public/src/js/circle.js b/public/src/js/circle.js index 579755c..c80a7ea 100644 --- a/public/src/js/circle.js +++ b/public/src/js/circle.js @@ -6,7 +6,7 @@ class Circle{ this.text = text this.speed = speed this.endTime = endTime ? endTime : ms + 150 - this.isPlayed = false + this.isPlayed = 0 this.animating = false this.animT = 0 this.score = 0 @@ -15,6 +15,7 @@ class Circle{ this.status = -1 this.timesHit = 0 this.requiredHits = requiredHits ? requiredHits : 0 + this.rendaPlayed = false } getMS(){ return this.ms @@ -58,9 +59,9 @@ class Circle{ endAnimation(){ this.animationEnded = true } - played(score){ + played(score, big){ this.score = score - this.isPlayed = true + this.isPlayed = big ? 2 : 1 } hit(){ this.timesHit++ diff --git a/public/src/js/controller.js b/public/src/js/controller.js index 0f221ef..43cb03a 100644 --- a/public/src/js/controller.js +++ b/public/src/js/controller.js @@ -174,8 +174,8 @@ class Controller{ getCurrentCircle(){ return this.game.getCurrentCircle() } - isWaitingForKeyup(key, type){ - return this.keyboard.isWaitingForKeyup(key, type) + isWaiting(key, type){ + return this.keyboard.isWaiting(key, type) } waitForKeyup(key, type){ this.keyboard.waitForKeyup(key, type) diff --git a/public/src/js/game.js b/public/src/js/game.js index d879ce2..02f68f1 100644 --- a/public/src/js/game.js +++ b/public/src/js/game.js @@ -41,7 +41,7 @@ class Game{ initTiming(){ // Date when the chrono is started (before the game begins) this.offsetDate = new Date() - this.offsetTime = this.timeForDistanceCircle |0 + this.offsetTime = Math.max(0, this.timeForDistanceCircle - this.songData.circles[0].ms) |0 this.setElapsedTime(-this.offsetTime) // The real start for the game will start when chrono will reach 0 this.startDate = new Date() @@ -70,20 +70,26 @@ class Game{ var hitTime = circle.getMS() var endTime = circle.getEndTime() var type = circle.getType() - var normalNotes = type == "don" || type == "daiDon" || type == "ka" || type == "daiKa" + var drumrollNotes = type === "balloon" || type === "drumroll" || type === "daiDrumroll" if(currentTime >= startingTime && currentTime <= endTime){ if(currentTime>= hitTime - 50 && currentTime < hitTime - 30){ circle.updateStatus(0) - }else if(currentTime>= hitTime - 30 && currentTime < hitTime){ + }else if(currentTime >= hitTime - 30 && currentTime < hitTime){ circle.updateStatus(230) }else if(currentTime >= hitTime && currentTime < endTime){ circle.updateStatus(450) + if(drumrollNotes && !circle.rendaPlayed){ + circle.rendaPlayed = true + if(this.controller.selectedSong.difficulty === "easy"){ + assets.sounds["renda"].stop() + assets.sounds["renda"].play() + } + } } - - }else if(currentTime>endTime){ - if(type == "balloon" || type == "drumroll" || type == "daiDrumroll"){ + }else if(currentTime > endTime){ + if(drumrollNotes){ circle.updateStatus(-1) circle.played(0) this.updateCurrentCircle() @@ -100,9 +106,9 @@ class Game{ this.controller.displayScore(currentScore, true) this.updateCurrentCircle() this.updateCombo(currentScore) - this.updateGlobalScore(currentScore) + this.updateGlobalScore(currentScore, 1) } - if(this.controller.multiplayer == 1){ + if(this.controller.multiplayer === 1){ p2.send("note", { score: -1 }) @@ -124,42 +130,61 @@ class Game{ } var keys = this.controller.getKeys() var kbd = this.controller.getBindings() - if(keys[kbd["don_l"]]){ - this.checkKey(kbd["don_l"], circle) - } - if(keys[kbd["don_r"]]){ - this.checkKey(kbd["don_r"], circle) - } - if(keys[kbd["ka_l"]]){ - this.checkKey(kbd["ka_l"], circle) - } - if(keys[kbd["ka_r"]]){ - this.checkKey(kbd["ka_r"], circle) - } - } - checkKey(keyCode, circle){ - if(!this.controller.isWaitingForKeyup(keyCode, "score")){ - if(circle && !circle.getPlayed() && circle.getStatus() != -1){ - this.checkScore(circle) - } - this.controller.waitForKeyup(keyCode, "score") - } - } - checkScore(circle){ - var keys = this.controller.getKeys() - var kbd = this.controller.getBindings() - var keysDon = keys[kbd["don_l"]] || keys[kbd["don_r"]] - var keysKa = keys[kbd["ka_l"]] || keys[kbd["ka_r"]] + var don_l = keys[kbd["don_l"]] && !this.controller.isWaiting(kbd["don_l"], "score") + var don_r = keys[kbd["don_r"]] && !this.controller.isWaiting(kbd["don_r"], "score") + var ka_l = keys[kbd["ka_l"]] && !this.controller.isWaiting(kbd["ka_l"], "score") + var ka_r = keys[kbd["ka_r"]] && !this.controller.isWaiting(kbd["ka_r"], "score") + + if(don_l && don_r){ + this.checkKey([kbd["don_l"], kbd["don_r"]], circle, "daiDon") + }else if(don_l){ + this.checkKey([kbd["don_l"]], circle, "don") + }else if(don_r){ + this.checkKey([kbd["don_r"]], circle, "don") + } + if(ka_l && ka_r){ + this.checkKey([kbd["ka_l"], kbd["ka_r"]], circle, "daiKa") + }else if(ka_l){ + this.checkKey([kbd["ka_l"]], circle, "ka") + }else if(ka_r){ + this.checkKey([kbd["ka_r"]], circle, "ka") + } + } + checkKey(keyCodes, circle, check){ + if(circle && !circle.getPlayed() && circle.getStatus() != -1){ + if(!this.checkScore(circle, check)){ + return + } + } + keyCodes.forEach(keyCode => { + this.controller.waitForKeyup(keyCode, "score") + }) + } + checkScore(circle, check){ + var ms = this.getElapsedTime().ms var type = circle.getType() - var typeDon = type == "don" || type == "daiDon" - var typeKa = type == "ka" || type == "daiKa" + + var keysDon = check === "don" || check === "daiDon" + var keysKa = check === "ka" || check === "daiKa" + var keyDai = check === "daiDon" || check === "daiKa" + var typeDon = type === "don" || type === "daiDon" + var typeKa = type === "ka" || type === "daiKa" + var typeDai = type === "daiDon" || type === "daiKa" if(typeDon || typeKa){ var score = 0 if(keysDon && typeDon || keysKa && typeKa){ + if(typeDai && !keyDai){ + if(!circle.daiFailed){ + circle.daiFailed = ms + return false + }else if(ms < circle.daiFailed + 2000 / 60){ + return false + } + } var circleStatus = circle.getStatus() - if(circleStatus == 230 || circleStatus == 450){ + if(circleStatus === 230 || circleStatus === 450){ score = circleStatus } this.controller.displayScore(score) @@ -167,20 +192,28 @@ class Game{ this.controller.displayScore(score, true) } this.updateCombo(score) - this.updateGlobalScore(score) + this.updateGlobalScore(score, typeDai && keyDai ? 2 : 1) this.updateCurrentCircle() - circle.played(score) + circle.played(score, keyDai) if(this.controller.multiplayer == 1){ p2.send("note", { score: score, - ms: circle.getMS() - this.getElapsedTime().ms + ms: circle.getMS() - ms, + dai: typeDai ? keyDai ? 2 : 1 : 0 }) } }else if(keysDon && type == "balloon"){ this.checkBalloon(circle) - }else if((keysDon || keysKa) && (type == "drumroll" || type == "daiDrumroll")){ + if(check === "daiDon" && !circle.getPlayed()){ + this.checkBalloon(circle) + } + }else if((keysDon || keysKa) && (type === "drumroll" || type === "daiDrumroll")){ this.checkDrumroll(circle) + if(keyDai){ + this.checkDrumroll(circle) + } } + return true } checkBalloon(circle){ if(circle.timesHit >= circle.requiredHits - 1){ @@ -201,20 +234,21 @@ class Game{ this.globalScore.points += score } checkDrumroll(circle){ + var dai = circle.getType() === "daiDrumroll" var score = 100 circle.hit() var keyTime = this.controller.getKeyTime() - if(circle.getType() == "drumroll"){ + if(circle.getType() === "drumroll"){ var sound = keyTime["don"] > keyTime["ka"] ? "don" : "ka" }else{ var sound = keyTime["don"] > keyTime["ka"] ? "daiDon" : "daiKa" } var circleAnim = new Circle(0, this.getElapsedTime().ms, sound, "", circle.speed) - circleAnim.played(score) + circleAnim.played(score, dai) circleAnim.animate() this.controller.view.drumroll.push(circleAnim) - this.globalScore.drumroll ++ - this.globalScore.points += score + this.globalScore.drumroll++ + this.globalScore.points += score * (dai ? 2 : 1) } whenLastCirclePlayed(){ var circles = this.songData.circles @@ -229,21 +263,15 @@ class Game{ if(started){ var ms = this.getElapsedTime().ms if(this.musicFadeOut === 0){ - snd.musicGain.fadeOut(1.6) if(this.controller.multiplayer === 1){ p2.send("gameresults", this.controller.getGlobalScore()) } this.musicFadeOut++ }else if(this.musicFadeOut === 1 && ms >= started + 1600){ this.controller.gameEnded() - this.mainAsset.stop() p2.send("gameend") this.musicFadeOut++ - }else if(this.musicFadeOut === 2 && ms >= started + 2600){ - snd.musicGain.fadeIn() - snd.musicGain.unmute() - this.musicFadeOut++ - }else if(this.musicFadeOut === 3 && ms >= started + 8600){ + }else if(this.musicFadeOut === 2 && (ms >= started + 8600 && ms >= this.controller.mainAsset.duration * 1000 + 250)){ this.controller.displayResults() this.musicFadeOut++ } @@ -259,7 +287,7 @@ class Game{ playMainMusic(){ var ms = this.getElapsedTime().ms if(!this.mainMusicPlaying && (!this.fadeOutStarted || ms this.globalScore.maxCombo){ this.globalScore.maxCombo = this.combo } - if(this.combo == 50 || this.combo > 0 && this.combo % 100 == 0 && this.combo <= 1400){ + if(this.combo === 50 || this.combo > 0 && this.combo % 100 === 0 && this.combo <= 1400){ this.controller.playSoundMeka("combo-" + this.combo) } this.controller.view.updateCombo(this.combo) @@ -337,7 +365,7 @@ class Game{ getGlobalScore(){ return this.globalScore } - updateGlobalScore(score){ + updateGlobalScore(score, multiplier){ // Circle score switch(score){ case 450: @@ -351,7 +379,7 @@ class Game{ break } // HP Update - if(score != 0){ + if(score !== 0){ this.globalScore.hp += this.HPGain }else if(this.globalScore.hp - this.HPGain > 0){ this.globalScore.hp -= this.HPGain @@ -361,6 +389,6 @@ class Game{ // Points update score += Math.max(0, Math.floor((Math.min(this.combo, 100) - 1) / 10) * 100) - this.globalScore.points+=score + this.globalScore.points += score * multiplier } } diff --git a/public/src/js/keyboard.js b/public/src/js/keyboard.js index 2a757cc..dc50d65 100644 --- a/public/src/js/keyboard.js +++ b/public/src/js/keyboard.js @@ -70,7 +70,7 @@ class Keyboard{ } } checkKey(keyCode, keyup, callback){ - if(this.keys[keyCode] && !this.isWaitingForKeyup(keyCode, keyup)){ + if(this.keys[keyCode] && !this.isWaiting(keyCode, keyup)){ this.waitForKeyup(keyCode, keyup) callback() } @@ -109,7 +109,7 @@ class Keyboard{ delete this.waitKeyupMenu[keyCode] } } - isWaitingForKeyup(key, type){ + isWaiting(key, type){ if(type === "score"){ return this.waitKeyupScore[key] }else if(type === "sound"){ diff --git a/public/src/js/loadsong.js b/public/src/js/loadsong.js index 8a6f925..c198e0e 100644 --- a/public/src/js/loadsong.js +++ b/public/src/js/loadsong.js @@ -3,8 +3,6 @@ class loadSong{ this.selectedSong = selectedSong this.multiplayer = multiplayer this.autoPlayEnabled = autoPlayEnabled - this.diff = this.selectedSong.difficulty.slice(0, -4) - this.songFilePath = "/songs/" + this.selectedSong.folder + "/" + this.selectedSong.difficulty loader.changePage("loadsong") this.run() } @@ -36,7 +34,7 @@ class loadSong{ }, reject) } })) - promises.push(loader.ajax(this.songFilePath).then(data => { + promises.push(loader.ajax(this.getOsuPath(this.selectedSong)).then(data => { this.songData = data.replace(/\0/g, "").split("\n") })) Promise.all(promises).then(() => { @@ -46,6 +44,9 @@ class loadSong{ alert("An error occurred, please refresh") }) } + getOsuPath(selectedSong){ + return "/songs/" + selectedSong.folder + "/" + selectedSong.difficulty + ".osu" + } setupMultiplayer(){ if(this.multiplayer){ var loadingText = document.getElementsByClassName("loading-text")[0] @@ -57,15 +58,15 @@ class loadSong{ this.selectedSong2 = this.selectedSong pageEvents.add(p2, "message", event => { if(event.type === "gameload"){ - if(event.value === this.diff){ + if(event.value === this.selectedSong.difficulty){ p2.send("gamestart") }else{ this.selectedSong2 = { title: this.selectedSong.title, folder: this.selectedSong.folder, - difficulty: event.value + ".osu" + difficulty: event.value } - loader.ajax("/songs/" + this.selectedSong2.folder + "/" + this.selectedSong2.difficulty).then(data => { + loader.ajax(this.getOsuPath(this.selectedSong2)).then(data => { this.song2Data = data.replace(/\0/g, "").split("\n") p2.send("gamestart") }, () => { @@ -82,7 +83,7 @@ class loadSong{ }) p2.send("join", { id: this.selectedSong.folder, - diff: this.diff + diff: this.selectedSong.difficulty }) }else{ this.clean() diff --git a/public/src/js/mekadon.js b/public/src/js/mekadon.js index c7b2ae5..4972705 100644 --- a/public/src/js/mekadon.js +++ b/public/src/js/mekadon.js @@ -16,10 +16,10 @@ class Mekadon{ this.playAt(circle, 0, 450) } } - playAt(circle, ms, score){ + playAt(circle, ms, score, dai){ var currentMs = circle.getMS() - this.getMS() if(ms > currentMs - 10){ - return this.playNow(circle, score) + return this.playNow(circle, score, dai) } } playDrumrollAt(circle, ms, pace){ @@ -33,27 +33,31 @@ class Mekadon{ this.controller.displayScore(0, true) this.game.updateCurrentCircle() this.game.updateCombo(0) - this.game.updateGlobalScore(0) + this.game.updateGlobalScore(0, 1) return true } } - playNow(circle, score){ + playNow(circle, score, dai){ var kbd = this.controller.getBindings() var type = circle.getType() - if(type == "don" || type == "balloon" || type == "drumroll" || type == "daiDrumroll"){ - this.setKey(this.lr ? kbd["don_l"] : kbd["don_r"]) - this.lr = !this.lr - }else if(type == "daiDon"){ + var keyDai = false + var playDai = !dai || dai === 2 + if(type == "daiDon" && playDai){ this.setKey(kbd["don_l"]) this.setKey(kbd["don_r"]) this.lr = false - }else if(type == "ka"){ - this.setKey(this.lr ? kbd["ka_l"] : kbd["ka_r"]) + keyDai = true + }else if(type == "don" || type == "daiDon" || type == "balloon" || type == "drumroll" || type == "daiDrumroll"){ + this.setKey(this.lr ? kbd["don_l"] : kbd["don_r"]) this.lr = !this.lr - }else if(type == "daiKa"){ + }else if(type == "daiKa" && playDai){ this.setKey(kbd["ka_l"]) this.setKey(kbd["ka_r"]) this.lr = false + keyDai = true + }else if(type == "ka" || type == "daiKa"){ + this.setKey(this.lr ? kbd["ka_l"] : kbd["ka_r"]) + this.lr = !this.lr } if(type == "balloon"){ if(circle.requiredHits == 1){ @@ -68,11 +72,11 @@ class Mekadon{ }else{ this.controller.displayScore(score) this.game.updateCombo(score) - this.game.updateGlobalScore(score) + this.game.updateGlobalScore(score, keyDai ? 2 : 1) this.game.updateCurrentCircle() } circle.updateStatus(score) - circle.played(score) + circle.played(score, keyDai) } this.lastHit = this.getMS() return true diff --git a/public/src/js/p2.js b/public/src/js/p2.js index 9160510..03a3925 100644 --- a/public/src/js/p2.js +++ b/public/src/js/p2.js @@ -93,6 +93,7 @@ class P2Connection{ this.otherConnected = true this.notes = [] this.drumrollPace = 45 + this.dai = 2 this.results = false break case "gameend": @@ -103,6 +104,9 @@ class P2Connection{ break case "note": this.notes.push(response.value) + if(response.value.dai){ + this.dai = response.value.dai + } break case "drumroll": this.drumrollPace = response.value.pace @@ -119,7 +123,11 @@ class P2Connection{ }else{ var note = this.notes[0] if(note.score >= 0){ - if(mekadon.playAt(circle, note.ms, note.score)){ + var dai = 1 + if(circle.getType() === "daiDon" || circle.getType() === "daiKa"){ + dai = this.dai + } + if(mekadon.playAt(circle, note.ms, note.score, dai)){ this.notes.shift() } }else{ diff --git a/public/src/js/songselect.js b/public/src/js/songselect.js index 9c87356..4b37b67 100644 --- a/public/src/js/songselect.js +++ b/public/src/js/songselect.js @@ -77,7 +77,7 @@ class SongSelect{ var song = target.parentNode.parentNode assets.sounds["don"].play() - this.selectedSong.difficulty = target.classList[1] + ".osu" + this.selectedSong.difficulty = target.classList[1] this.selectedSong.title = song.dataset.title this.selectedSong.folder = song.dataset.songId diff --git a/public/src/js/view.js b/public/src/js/view.js index cf11e37..f95d5af 100644 --- a/public/src/js/view.js +++ b/public/src/js/view.js @@ -1,8 +1,9 @@ class View{ - constructor(controller, bg, title, diff){ + constructor(controller, bg, songTitle, songDifficulty){ this.controller = controller this.bg = bg - this.diff = diff + this.songTitle = songTitle + this.songDifficulty = songDifficulty this.pauseMenu = document.getElementById("pause-menu") this.cursor = document.getElementById("cursor") @@ -42,9 +43,6 @@ class View{ this.currentBigDonFace = 1 this.nextBeat = 0 - this.songTitle = title - this.songDifficulty = this.diff.split(".").slice(0, -1).join(".") - this.drumroll = [] this.beatInterval = this.controller.getSongData().beatInfo.beatInterval @@ -79,10 +77,12 @@ class View{ run(){ this.ctx.font = "normal 14pt TnT" this.setBackground() - var gameSong = document.getElementsByClassName("game-song")[0] - gameSong.appendChild(document.createTextNode(this.songTitle)) - gameSong.setAttribute("alt", this.songTitle) + if(this.controller.multiplayer !== 2){ + var gameSong = document.getElementsByClassName("game-song")[0] + gameSong.appendChild(document.createTextNode(this.songTitle)) + gameSong.setAttribute("alt", this.songTitle) + } this.lastMousemove = this.controller.getElapsedTime().ms pageEvents.mouseAdd(this, this.onmousemove.bind(this)) @@ -500,6 +500,7 @@ class View{ var endTime = circle.getEndTime() var animated = circle.isAnimated() var speed = circle.getSpeed() + var played = circle.getPlayed() if(!circlePos){ circlePos = { @@ -514,34 +515,28 @@ class View{ var currentDonFace = this.currentDonFace var currentBigDonFace = this.currentBigDonFace } - switch(type){ - case "don": + if(type === "don" || type === "daiDon" && played === 1){ + fill = "#f34728" + size = this.circleSize + faceID = "don-" + currentDonFace + }else if(type === "ka" || type === "daiKa" && played === 1){ + fill = "#65bdbb" + size = this.circleSize + faceID = "don-" + currentDonFace + }else if(type === "daiDon"){ + fill = "#f34728" + size = this.bigCircleSize + faceID = "big-don-" + currentBigDonFace + }else if(type === "daiKa"){ + fill = "#65bdbb" + size = this.bigCircleSize + faceID = "big-don-" + currentBigDonFace + }else if(type === "balloon"){ + if(animated){ fill = "#f34728" - size = this.circleSize - faceID = "don-" + currentDonFace - break - case "ka": - fill = "#65bdbb" - size = this.circleSize - faceID = "don-" + currentDonFace - break - case "daiDon": - fill = "#f34728" - size = this.bigCircleSize + size = this.bigCircleSize * 0.8 faceID = "big-don-" + currentBigDonFace - break - case "daiKa": - fill = "#65bdbb" - size = this.bigCircleSize - faceID = "big-don-" + currentBigDonFace - break - case "balloon": - if(animated){ - fill = "#f34728" - size = this.bigCircleSize * 0.8 - faceID = "big-don-" + currentBigDonFace - break - } + }else{ fill = "#f87700" size = this.circleSize faceID = "don-" + currentDonFace @@ -557,29 +552,27 @@ class View{ h / 61 * 115, h ) - break - case "drumroll": - case "daiDrumroll": - fill = "#f3b500" - if(type == "drumroll"){ - size = this.circleSize - faceID = "don-" + currentDonFace - }else{ - size = this.bigCircleSize - faceID = "big-don-" + currentBigDonFace - } - var endX = this.msToPos(endTime - circleMs, speed) - this.ctx.fillStyle = fill - this.ctx.strokeStyle = "#1f1a17" - this.ctx.lineWidth = this.lyricsSize / 10 - this.ctx.beginPath() - this.ctx.moveTo(circlePos.x, circlePos.y - size) - this.ctx.lineTo(circlePos.x + endX, circlePos.y - size) - this.ctx.arc(circlePos.x + endX, circlePos.y, size, -Math.PI / 2, Math.PI / 2) - this.ctx.lineTo(circlePos.x, circlePos.y + size) - this.ctx.fill() - this.ctx.stroke() - break + } + }else if(type === "drumroll" || type === "daiDrumroll"){ + fill = "#f3b500" + if(type == "drumroll"){ + size = this.circleSize + faceID = "don-" + currentDonFace + }else{ + size = this.bigCircleSize + faceID = "big-don-" + currentBigDonFace + } + var endX = this.msToPos(endTime - circleMs, speed) + this.ctx.fillStyle = fill + this.ctx.strokeStyle = "#1f1a17" + this.ctx.lineWidth = this.lyricsSize / 10 + this.ctx.beginPath() + this.ctx.moveTo(circlePos.x, circlePos.y - size) + this.ctx.lineTo(circlePos.x + endX, circlePos.y - size) + this.ctx.arc(circlePos.x + endX, circlePos.y, size, -Math.PI / 2, Math.PI / 2) + this.ctx.lineTo(circlePos.x, circlePos.y + size) + this.ctx.fill() + this.ctx.stroke() } // Main circle this.ctx.fillStyle = fill