Merge pull request #41 from LoveEevee/scoresheet-countup-animation

Scoresheet: Add counting up animation
This commit is contained in:
Bui 2018-10-03 15:28:13 +01:00 committed by GitHub
commit 724c82814e
13 changed files with 307 additions and 138 deletions

View File

@ -38,29 +38,13 @@ var assets = {
"bg_genre_6.png", "bg_genre_6.png",
"bg_genre_7.png", "bg_genre_7.png",
"bg_score_p1.png", "bg_score_p1.png",
"bg_score_p2.png" "bg_score_p2.png",
"badge_auto.png"
], ],
"audioSfx": [ "audioSfx": [
"start.wav",
"don.wav", "don.wav",
"ka.wav", "ka.wav",
"start.wav",
"combo-50.wav",
"combo-100.wav",
"combo-200.wav",
"combo-300.wav",
"combo-400.wav",
"combo-500.wav",
"combo-600.wav",
"combo-700.wav",
"combo-800.wav",
"combo-900.wav",
"combo-1000.wav",
"combo-1100.wav",
"combo-1200.wav",
"combo-1300.wav",
"combo-1400.wav",
"fullcombo.wav",
"combo-50-meka.wav", "combo-50-meka.wav",
"combo-100-meka.wav", "combo-100-meka.wav",
@ -83,17 +67,42 @@ var assets = {
"title.ogg", "title.ogg",
"pause.wav", "pause.wav",
"cancel.wav", "cancel.wav",
"results.ogg", "results.ogg"
"diffsel.wav", ],
"audioSfxLR": [
"note_don.ogg",
"note_ka.ogg",
"balloon.ogg",
"renda.ogg",
"combo-50.wav",
"combo-100.wav",
"combo-200.wav",
"combo-300.wav",
"combo-400.wav",
"combo-500.wav",
"combo-600.wav",
"combo-700.wav",
"combo-800.wav",
"combo-900.wav",
"combo-1000.wav",
"combo-1100.wav",
"combo-1200.wav",
"combo-1300.wav",
"combo-1400.wav",
"fullcombo.wav",
"gamefullcombo.wav", "gamefullcombo.wav",
"gameclear.wav", "gameclear.wav",
"gamefail.wav", "gamefail.wav",
"note_don.ogg", "results_fullcombo.ogg",
"note_ka.ogg", "results_fullcombo2.ogg",
"balloon.ogg", "results_crown.ogg",
"renda.ogg" "results_countup.wav"
],
"audioSfxLoud": [
"diffsel.wav"
], ],
"audioMusic": [ "audioMusic": [
"bgm_songsel.ogg", "bgm_songsel.ogg",

View File

@ -12,7 +12,7 @@ class CanvasAsset{
if(this.animation){ if(this.animation){
var u = (a, b) => typeof a === "undefined" ? b : a var u = (a, b) => typeof a === "undefined" ? b : a
var frame = 0 var frame = 0
var ms = this.controller.getElapsedTime().ms var ms = this.controller.getElapsedTime()
if(this.animationEnd){ if(this.animationEnd){
if(ms > this.animationEnd.ms){ if(ms > this.animationEnd.ms){
this.animationEnd.callback() this.animationEnd.callback()

View File

@ -390,6 +390,8 @@
drawn.push({text: symbol, x: -2, y: 0, w: 20, scale: [0.6, 0.5]}) drawn.push({text: symbol, x: -2, y: 0, w: 20, scale: [0.6, 0.5]})
}else if(symbol === " "){ }else if(symbol === " "){
drawn.push({text: symbol, x: 0, y: 0, w: 10}) drawn.push({text: symbol, x: 0, y: 0, w: 10})
}else if(symbol === "'"){
drawn.push({text: ",", x: 0, y: -15, w: 7, scale: [1, 0.7]})
}else if(r.en.test(symbol)){ }else if(r.en.test(symbol)){
// n-width // n-width
drawn.push({text: symbol, x: 0, y: 0, w: 28, scale: [1, 0.95]}) drawn.push({text: symbol, x: 0, y: 0, w: 28, scale: [1, 0.95]})

View File

@ -4,6 +4,7 @@ class Controller{
this.songData = songData this.songData = songData
this.autoPlayEnabled = autoPlayEnabled this.autoPlayEnabled = autoPlayEnabled
this.multiplayer = multiplayer this.multiplayer = multiplayer
this.snd = this.multiplayer ? "_p" + this.multiplayer : ""
var backgroundURL = "/songs/" + this.selectedSong.folder + "/bg.png" var backgroundURL = "/songs/" + this.selectedSong.folder + "/bg.png"
var songParser = new ParseSong(songData) var songParser = new ParseSong(songData)
@ -26,15 +27,9 @@ class Controller{
this.view.run() this.view.run()
this.startMainLoop() this.startMainLoop()
if(syncWith){ if(syncWith){
syncWith.game.getElapsedTime = () => {
return this.game.elapsedTime
}
this.game.setElapsedTime =
syncWith.game.setElapsedTime = time => {
this.game.elapsedTime.ms = time
syncWith.game.elapsedTime.ms = time
}
syncWith.run() syncWith.run()
syncWith.elapsedTime = this.game.elapsedTime
syncWith.startDate = this.game.startDate
this.syncWith = syncWith this.syncWith = syncWith
} }
} }
@ -71,7 +66,7 @@ class Controller{
if(this.multiplayer !== 2){ if(this.multiplayer !== 2){
requestAnimationFrame(() => { requestAnimationFrame(() => {
if(this.syncWith){ if(this.syncWith){
this.syncWith.game.elapsedTime.ms = this.game.elapsedTime.ms this.syncWith.game.elapsedTime = this.game.elapsedTime
} }
this.mainLoop() this.mainLoop()
if(this.syncWith){ if(this.syncWith){
@ -79,7 +74,7 @@ class Controller{
} }
}) })
} }
var ms = this.game.getElapsedTime().ms var ms = this.game.elapsedTime
if(!this.game.isPaused()){ if(!this.game.isPaused()){
this.keyboard.checkGameKeys() this.keyboard.checkGameKeys()
@ -121,7 +116,7 @@ class Controller{
}else{ }else{
vp = "fail" vp = "fail"
} }
assets.sounds["game" + vp].play() this.playSound("game" + vp)
} }
displayResults(){ displayResults(){
if(this.multiplayer !== 2){ if(this.multiplayer !== 2){
@ -147,12 +142,15 @@ class Controller{
taikoGame.run() taikoGame.run()
} }
} }
playSound(id, time){
assets.sounds[id + this.snd].play(time)
}
playSoundMeka(soundID, time){ playSoundMeka(soundID, time){
var meka = "" var meka = ""
if(this.autoPlayEnabled && !this.multiplayer){ if(this.autoPlayEnabled && !this.multiplayer){
meka = "-meka" meka = "-meka"
} }
assets.sounds[soundID + meka].play(time) this.playSound(soundID + meka, time)
} }
togglePause(){ togglePause(){
if(this.syncWith){ if(this.syncWith){
@ -173,7 +171,7 @@ class Controller{
return this.game.getSongData() return this.game.getSongData()
} }
getElapsedTime(){ getElapsedTime(){
return this.game.getElapsedTime() return this.game.elapsedTime
} }
getCircles(){ getCircles(){
return this.game.getCircles() return this.game.getCircles()

View File

@ -25,11 +25,9 @@ class Game{
this.paused = false this.paused = false
this.started = false this.started = false
this.mainMusicPlaying = false this.mainMusicPlaying = false
this.elapsedTimeSincePause = 0
this.musicFadeOut = 0 this.musicFadeOut = 0
this.fadeOutStarted = false this.fadeOutStarted = false
this.currentTimingPoint = 0 this.currentTimingPoint = 0
this.offsetTime = 0
assets.songs.forEach(song => { assets.songs.forEach(song => {
if(song.id == selectedSong.folder){ if(song.id == selectedSong.folder){
@ -43,12 +41,10 @@ class Game{
} }
initTiming(){ initTiming(){
// Date when the chrono is started (before the game begins) // Date when the chrono is started (before the game begins)
this.offsetDate = new Date() var offsetTime = Math.max(0, this.timeForDistanceCircle - this.songData.circles[0].ms) |0
this.offsetTime = Math.max(0, this.timeForDistanceCircle - this.songData.circles[0].ms) |0 this.elapsedTime = -offsetTime
this.setElapsedTime(-this.offsetTime)
// The real start for the game will start when chrono will reach 0 // The real start for the game will start when chrono will reach 0
this.startDate = new Date() this.startDate = +(new Date) + offsetTime
this.startDate.setMilliseconds(this.startDate.getMilliseconds() + this.offsetTime)
} }
update(){ update(){
// Main operations // Main operations
@ -67,7 +63,7 @@ class Game{
var circles = this.songData.circles var circles = this.songData.circles
circles.forEach(circle => { circles.forEach(circle => {
if(!circle.getPlayed()){ if(!circle.getPlayed()){
var ms = this.getElapsedTime().ms var ms = this.elapsedTime
var type = circle.getType() var type = circle.getType()
var drumrollNotes = type === "balloon" || type === "drumroll" || type === "daiDrumroll" var drumrollNotes = type === "balloon" || type === "drumroll" || type === "daiDrumroll"
var endTime = circle.getEndTime() + (drumrollNotes ? 0 : this.rules.bad) var endTime = circle.getEndTime() + (drumrollNotes ? 0 : this.rules.bad)
@ -76,8 +72,8 @@ class Game{
if(drumrollNotes && !circle.rendaPlayed){ if(drumrollNotes && !circle.rendaPlayed){
circle.rendaPlayed = true circle.rendaPlayed = true
if(this.rules.difficulty === "easy"){ if(this.rules.difficulty === "easy"){
assets.sounds["renda"].stop() assets.sounds["renda" + this.controller.snd].stop()
assets.sounds["renda"].play() this.controller.playSound("renda")
} }
} }
} }
@ -153,7 +149,7 @@ class Game{
}) })
} }
checkScore(circle, check){ checkScore(circle, check){
var ms = this.getElapsedTime().ms var ms = this.elapsedTime
var type = circle.getType() var type = circle.getType()
var keysDon = check === "don" || check === "daiDon" var keysDon = check === "don" || check === "daiDon"
@ -234,7 +230,7 @@ class Game{
circle.played(score) circle.played(score)
if(this.controller.multiplayer == 1){ if(this.controller.multiplayer == 1){
p2.send("drumroll", { p2.send("drumroll", {
pace: (this.getElapsedTime().ms - circle.getMS()) / circle.timesHit pace: (this.elapsedTime - circle.getMS()) / circle.timesHit
}) })
} }
}else{ }else{
@ -256,7 +252,7 @@ class Game{
} }
var circleAnim = new Circle({ var circleAnim = new Circle({
id: 0, id: 0,
start: this.getElapsedTime().ms, start: this.elapsedTime,
type: sound, type: sound,
txt: "", txt: "",
speed: circle.speed, speed: circle.speed,
@ -271,7 +267,7 @@ class Game{
whenLastCirclePlayed(){ whenLastCirclePlayed(){
var circles = this.songData.circles var circles = this.songData.circles
var lastCircle = circles[circles.length - 1] var lastCircle = circles[circles.length - 1]
var ms = this.getElapsedTime().ms var ms = this.elapsedTime
if(!this.fadeOutStarted && ms >= lastCircle.getEndTime() + 2000){ if(!this.fadeOutStarted && ms >= lastCircle.getEndTime() + 2000){
this.fadeOutStarted = ms this.fadeOutStarted = ms
} }
@ -279,7 +275,7 @@ class Game{
whenFadeoutMusic(){ whenFadeoutMusic(){
var started = this.fadeOutStarted var started = this.fadeOutStarted
if(started){ if(started){
var ms = this.getElapsedTime().ms var ms = this.elapsedTime
if(this.musicFadeOut === 0){ if(this.musicFadeOut === 0){
if(this.controller.multiplayer === 1){ if(this.controller.multiplayer === 1){
p2.send("gameresults", this.getGlobalScore()) p2.send("gameresults", this.getGlobalScore())
@ -302,13 +298,13 @@ class Game{
} }
checkTiming(){ checkTiming(){
if(this.songData.timingPoints[this.currentTimingPoint + 1]){ if(this.songData.timingPoints[this.currentTimingPoint + 1]){
if(this.getElapsedTime().ms >= this.songData.timingPoints[this.currentTimingPoint + 1].start){ if(this.elapsedTime >= this.songData.timingPoints[this.currentTimingPoint + 1].start){
this.currentTimingPoint++ this.currentTimingPoint++
} }
} }
} }
playMainMusic(){ playMainMusic(){
var ms = this.getElapsedTime().ms var ms = this.elapsedTime
if(!this.mainMusicPlaying && (!this.fadeOutStarted || ms<this.fadeOutStarted + 1600)){ if(!this.mainMusicPlaying && (!this.fadeOutStarted || ms<this.fadeOutStarted + 1600)){
if(this.controller.multiplayer !== 2){ if(this.controller.multiplayer !== 2){
this.mainAsset.play((ms < 0 ? -ms : 0) / 1000, false, Math.max(0, ms / 1000)) this.mainAsset.play((ms < 0 ? -ms : 0) / 1000, false, Math.max(0, ms / 1000))
@ -320,48 +316,44 @@ class Game{
if(!this.paused){ if(!this.paused){
assets.sounds["pause"].play() assets.sounds["pause"].play()
this.paused = true this.paused = true
this.latestDate = new Date() this.latestDate = +new Date
this.mainAsset.stop() this.mainAsset.stop()
this.mainMusicPlaying = false this.mainMusicPlaying = false
}else{ }else{
assets.sounds["cancel"].play() assets.sounds["cancel"].play()
this.paused = false this.paused = false
var currentDate = new Date() var currentDate = +new Date
this.elapsedTimeSincePause = this.elapsedTimeSincePause + currentDate.getTime() - this.latestDate.getTime() this.startDate += currentDate - this.latestDate
this.sndTime = currentDate - snd.buffer.getTime() * 1000
} }
} }
isPaused(){ isPaused(){
return this.paused return this.paused
} }
getElapsedTime(){
// Current time in ms from the beginning of the song
return this.elapsedTime
}
setElapsedTime(time){
this.elapsedTime.ms = time
this.elapsedTime.sec = (this.elapsedTime.ms / 1000 |0) % 60
this.elapsedTime.min = (this.elapsedTime.ms / 1000 / 60 |0) % 60
this.elapsedTime.hour = (this.elapsedTime.ms / 1000 / 60 / 60 |0) % 60
}
updateTime(){ updateTime(){
// Refreshed date // Refreshed date
var currentDate = new Date() var ms = this.elapsedTime
var ms = this.getElapsedTime().ms
if(ms >= 0 && !this.started){ if(ms >= 0 && !this.started){
this.startDate = new Date() this.startDate = +new Date
this.elapsedTimeSincePause = 0 this.elapsedTime = this.getAccurateTime()
this.setElapsedTime(this.getAccurateTime())
this.started = true this.started = true
this.sndTime = this.startDate - snd.buffer.getTime() * 1000
}else if(ms < 0 || ms >= 0 && this.started){ }else if(ms < 0 || ms >= 0 && this.started){
this.setElapsedTime(this.getAccurateTime()) this.elapsedTime = this.getAccurateTime(ms >= 0)
} }
} }
getAccurateTime(){ getAccurateTime(){
if(this.isPaused()){ if(this.isPaused()){
return this.getElapsedTime().ms return this.elapsedTime
}else{ }else{
var currentDate = new Date() var currentDate = +new Date
return currentDate.getTime() - this.startDate.getTime() - this.elapsedTimeSincePause var sndTime = currentDate - snd.buffer.getTime() * 1000
var lag = sndTime - this.sndTime
if(Math.abs(lag) >= 50){
this.startDate += lag
this.sndTime = sndTime
}
return currentDate - this.startDate
} }
} }
getCircles(){ getCircles(){

View File

@ -177,9 +177,9 @@ class Keyboard{
&& circle.getType() === "balloon" && circle.getType() === "balloon"
&& circle.requiredHits - circle.timesHit <= 1 && circle.requiredHits - circle.timesHit <= 1
){ ){
assets.sounds["balloon"].play() this.controller.playSound("balloon")
}else{ }else{
assets.sounds["note_" + sound].play() this.controller.playSound("note_" + sound)
} }
this.keyTime[sound] = this.keyTime[keyCode] this.keyTime[sound] = this.keyTime[keyCode]
}) })

View File

@ -36,9 +36,16 @@ class Loader{
snd.buffer = new SoundBuffer() snd.buffer = new SoundBuffer()
snd.musicGain = snd.buffer.createGain() snd.musicGain = snd.buffer.createGain()
snd.sfxGain = snd.buffer.createGain() snd.sfxGain = snd.buffer.createGain()
snd.buffer.setCrossfade(snd.musicGain, snd.sfxGain, 0.5)
snd.previewGain = snd.buffer.createGain() snd.previewGain = snd.buffer.createGain()
snd.previewGain.setVolume(0.5) snd.sfxGainL = snd.buffer.createGain("left")
snd.sfxGainR = snd.buffer.createGain("right")
snd.sfxLoudGain = snd.buffer.createGain()
snd.buffer.setCrossfade(
[snd.musicGain, snd.previewGain],
[snd.sfxGain, snd.sfxGainL, snd.sfxGainR],
0.5
)
snd.sfxLoudGain.setVolume(1.2)
assets.audioSfx.forEach(name => { assets.audioSfx.forEach(name => {
this.promises.push(this.loadSound(name, snd.sfxGain)) this.promises.push(this.loadSound(name, snd.sfxGain))
@ -46,6 +53,16 @@ class Loader{
assets.audioMusic.forEach(name => { assets.audioMusic.forEach(name => {
this.promises.push(this.loadSound(name, snd.musicGain)) this.promises.push(this.loadSound(name, snd.musicGain))
}) })
assets.audioSfxLR.forEach(name => {
this.promises.push(this.loadSound(name, snd.sfxGain).then(sound => {
var id = this.getFilename(name)
assets.sounds[id + "_p1"] = assets.sounds[id].copy(snd.sfxGainL)
assets.sounds[id + "_p2"] = assets.sounds[id].copy(snd.sfxGainR)
}))
})
assets.audioSfxLoud.forEach(name => {
this.promises.push(this.loadSound(name, snd.sfxLoudGain))
})
p2 = new P2Connection() p2 = new P2Connection()

View File

@ -89,7 +89,7 @@ class Mekadon{
return true return true
} }
getMS(){ getMS(){
return this.controller.getElapsedTime().ms return this.controller.getElapsedTime()
} }
setKey(keyCode, ms){ setKey(keyCode, ms){
this.controller.setKey(keyCode, false) this.controller.setKey(keyCode, false)

View File

@ -100,7 +100,10 @@ class P2Connection{
this.otherConnected = false this.otherConnected = false
break break
case "gameresults": case "gameresults":
this.results = response.value this.results = {}
for(var i in response.value){
this.results[i] = response.value[i].toString()
}
break break
case "note": case "note":
this.notes.push(response.value) this.notes.push(response.value)

View File

@ -1,7 +1,10 @@
class Scoresheet{ class Scoresheet{
constructor(controller, results, multiplayer){ constructor(controller, results, multiplayer){
this.controller = controller this.controller = controller
this.results = results this.results = {}
for(var i in results){
this.results[i] = results[i].toString()
}
this.multiplayer = multiplayer this.multiplayer = multiplayer
this.canvas = document.getElementById("canvas") this.canvas = document.getElementById("canvas")
@ -14,6 +17,9 @@ class Scoresheet{
startDelay: 3300, startDelay: 3300,
hasPointer: 0 hasPointer: 0
} }
this.frame = 1000 / 60
this.numbers = "001122334455667788900112233445".split("")
this.draw = new CanvasDraw() this.draw = new CanvasDraw()
this.gamepad = new Gamepad({ this.gamepad = new Gamepad({
@ -57,17 +63,16 @@ class Scoresheet{
} }
toNext(){ toNext(){
var ms = this.getMS() var ms = this.getMS()
var elapsed = ms - this.state.screenMS - this.state.startDelay var elapsed = ms - this.state.screenMS
if(this.state.screen === "fadeIn"){ if(this.state.screen === "fadeIn" && elapsed >= this.state.startDelay){
if(elapsed >= 3400){ this.state.screen = "scoresShown"
this.state.screenMS = ms
assets.sounds["note_don"].play()
}else if(this.state.screen === "scoresShown" && elapsed >= 1000){
snd.musicGain.fadeOut(0.5) snd.musicGain.fadeOut(0.5)
this.state.screen = "fadeOut" this.state.screen = "fadeOut"
this.state.screenMS = ms this.state.screenMS = ms
assets.sounds["don"].play() assets.sounds["note_don"].play()
}else if(elapsed >= 0 && elapsed <= 2400){
this.state.screenMS = ms - 2400 - this.state.startDelay
assets.sounds["don"].play()
}
} }
} }
@ -116,7 +121,7 @@ class Scoresheet{
ctx.scale(ratio, ratio) ctx.scale(ratio, ratio)
this.canvas.style.width = (winW / this.pixelRatio) + "px" this.canvas.style.width = (winW / this.pixelRatio) + "px"
this.canvas.style.height = (winH / this.pixelRatio) + "px" this.canvas.style.height = (winH / this.pixelRatio) + "px"
}else if(!document.hasFocus() && ms - this.state.screenMS - this.state.startDelay > 2400){ }else if(!document.hasFocus() && this.state.screen === "scoresShown"){
return return
}else{ }else{
ctx.clearRect(0, 0, winW / ratio, winH / ratio) ctx.clearRect(0, 0, winW / ratio, winH / ratio)
@ -158,8 +163,12 @@ class Scoresheet{
}) })
ctx.fillStyle = "rgba(127, 28, 12, 0.5)" ctx.fillStyle = "rgba(127, 28, 12, 0.5)"
ctx.fillRect(0, winH / 2 - 12, winW, 12) ctx.fillRect(0, winH / 2 - 12, winW, 12)
ctx.fillStyle = "rgba(0, 0, 0, 0.25)"
ctx.fillRect(0, winH / 2, winW, 20)
if(bgOffset !== 0){
ctx.fillStyle = "#000" ctx.fillStyle = "#000"
ctx.fillRect(0, winH / 2 - 2, winW, 3) ctx.fillRect(0, winH / 2 - 2, winW, 2)
}
ctx.fillStyle = "#fa4529" ctx.fillStyle = "#fa4529"
ctx.fillRect(0, 0, winW, frameTop + 64) ctx.fillRect(0, 0, winW, frameTop + 64)
ctx.fillStyle = "#bf2900" ctx.fillStyle = "#bf2900"
@ -184,7 +193,11 @@ class Scoresheet{
ctx.fillStyle = this.multiplayer ? "rgba(138, 245, 247, 0.5)" : "rgba(249, 163, 149, 0.5)" ctx.fillStyle = this.multiplayer ? "rgba(138, 245, 247, 0.5)" : "rgba(249, 163, 149, 0.5)"
ctx.fillRect(0, winH / 2, winW, 12) ctx.fillRect(0, winH / 2, winW, 12)
ctx.fillStyle = "#000" ctx.fillStyle = "#000"
ctx.fillRect(0, winH / 2 - 1, winW, 3) if(bgOffset === 0){
ctx.fillRect(0, winH / 2 - 2, winW, 4)
}else{
ctx.fillRect(0, winH / 2, winW, 2)
}
ctx.fillStyle = this.multiplayer ? "#6bbec0" : "#fa4529" ctx.fillStyle = this.multiplayer ? "#6bbec0" : "#fa4529"
ctx.fillRect(0, winH - frameTop - 64, winW, frameTop + 64) ctx.fillRect(0, winH - frameTop - 64, winW, frameTop + 64)
ctx.fillStyle = this.multiplayer ? "rgba(160, 228, 229, 0.8)" : "rgba(255, 144, 116, 0.8)" ctx.fillStyle = this.multiplayer ? "rgba(160, 228, 229, 0.8)" : "rgba(255, 144, 116, 0.8)"
@ -196,8 +209,8 @@ class Scoresheet{
ctx.restore() ctx.restore()
} }
if(this.state.screen === "fadeOut"){ if(this.state.screen === "scoresShown" || this.state.screen === "fadeOut"){
var elapsed = 2400 var elapsed = Infinity
}else{ }else{
var elapsed = ms - this.state.screenMS - this.state.startDelay var elapsed = ms - this.state.screenMS - this.state.startDelay
} }
@ -257,6 +270,12 @@ class Scoresheet{
276, 150, imgScale * 176, imgScale * 120 276, 150, imgScale * 176, imgScale * 120
) )
if(this.controller.autoPlayEnabled){
ctx.drawImage(assets.image["badge_auto"],
431, 311, 34, 34
)
}
this.draw.roundedRect({ this.draw.roundedRect({
ctx: ctx, ctx: ctx,
x: 532, x: 532,
@ -331,12 +350,12 @@ class Scoresheet{
this.draw.layeredText({ this.draw.layeredText({
ctx: ctx, ctx: ctx,
text: "最大コンボ数", text: "最大コンボ数",
x: 1150, x: 1149,
y: 193, y: 193,
fontSize: 29, fontSize: 29,
fontFamily: this.font, fontFamily: this.font,
align: "right", align: "right",
width: 216, width: 215,
letterSpacing: 1 letterSpacing: 1
}, [ }, [
{outline: "#000", letterBorder: 8}, {outline: "#000", letterBorder: 8},
@ -397,7 +416,7 @@ class Scoresheet{
results = p2.results results = p2.results
} }
var crownType = null var crownType = null
if(results.bad === 0){ if(results.bad === "0"){
crownType = "gold" crownType = "gold"
}else if(results.gauge >= 50){ }else if(results.gauge >= 50){
crownType = "silver" crownType = "silver"
@ -424,6 +443,16 @@ class Scoresheet{
shine = 2 - shine shine = 2 - shine
} }
} }
if(this.state.screen === "fadeIn" && elapsed >= 1200 && !this.state["fullcomboPlayed" + p]){
this.state["fullcomboPlayed" + p] = true
if(crownType === "gold"){
this.playSound("results_fullcombo" + (p === 1 ? "2" : ""), p)
}
}
if(this.state.screen === "fadeIn" && elapsed >= 1650 && !this.state["crownPlayed" + p]){
this.state["crownPlayed" + p] = true
this.playSound("results_crown", p)
}
this.draw.crown({ this.draw.crown({
ctx: ctx, ctx: ctx,
type: crownType, type: crownType,
@ -444,6 +473,35 @@ class Scoresheet{
ctx.save() ctx.save()
ctx.translate(frameLeft, frameTop) ctx.translate(frameLeft, frameTop)
var printNumbers = ["good", "ok", "bad", "maxCombo", "drumroll"]
if(!this.state["countupTime0"]){
var times = {}
var lastTime = 0
for(var p = 0; p < players; p++){
var results = p === 0 ? this.results : p2.results
var currentTime = 3100 + results.points.length * 30 * this.frame
if(currentTime > lastTime){
lastTime = currentTime
}
}
for(var i in printNumbers){
var largestTime = 0
for(var p = 0; p < players; p++){
var results = p === 0 ? this.results : p2.results
times[printNumbers[i]] = lastTime + 500
var currentTime = lastTime + 500 + results[printNumbers[i]].length * 30 * this.frame
if(currentTime > largestTime){
largestTime = currentTime
}
}
lastTime = largestTime
}
this.state.fadeInEnd = lastTime
for(var p = 0; p < players; p++){
this.state["countupTime" + p] = times
}
}
for(var p = 0; p < players; p++){ for(var p = 0; p < players; p++){
var results = this.results var results = this.results
if(p === 1){ if(p === 1){
@ -451,9 +509,12 @@ class Scoresheet{
ctx.translate(0, p2Offset) ctx.translate(0, p2Offset)
} }
ctx.save() ctx.save()
var points = results.points.toString()
this.state.countupShown = false
var points = this.getNumber(results.points, 3100, elapsed)
var scale = 1.3 var scale = 1.3
ctx.font = "36px " + this.font ctx.font = "35px " + this.font
ctx.translate(760, 286) ctx.translate(760, 286)
ctx.scale(1 / scale, 1 * 1.1) ctx.scale(1 / scale, 1 * 1.1)
ctx.textAlign = "center" ctx.textAlign = "center"
@ -461,28 +522,56 @@ class Scoresheet{
ctx.strokeStyle = "#fff" ctx.strokeStyle = "#fff"
ctx.lineWidth = 0.5 ctx.lineWidth = 0.5
for(var i = 0; i < points.length; i++){ for(var i = 0; i < points.length; i++){
ctx.translate(-23 * scale, 0) ctx.translate(-23.3 * scale, 0)
ctx.fillText(points[points.length - i - 1], 0, 0) ctx.fillText(points[points.length - i - 1], 0, 0)
ctx.strokeText(points[points.length - i - 1], 0, 0) ctx.strokeText(points[points.length - i - 1], 0, 0)
} }
ctx.restore() ctx.restore()
var printNumbers = ["good", "ok", "bad", "maxCombo", "drumroll"] if(!this.state["countupTime" + p]){
var times = {}
var lastTime = 3100 + results.points.length * 30 * this.frame + 1000
for(var i in printNumbers){ for(var i in printNumbers){
times[printNumbers[i]] = lastTime + 500
lastTime = lastTime + 500 + results[printNumbers[i]].length * 30 * this.frame
}
this.state["countupTime" + p] = times
}
for(var i in printNumbers){
var start = this.state["countupTime" + p][printNumbers[i]]
this.draw.layeredText({ this.draw.layeredText({
ctx: ctx, ctx: ctx,
text: results[printNumbers[i]].toString(), text: this.getNumber(results[printNumbers[i]], start, elapsed),
x: 971 + 270 * Math.floor(i / 3), x: 971 + 270 * Math.floor(i / 3),
y: 194 + (40 * (i % 3)), y: 196 + (40 * (i % 3)),
fontSize: 27, fontSize: 26,
fontFamily: this.font, fontFamily: this.font,
letterSpacing: 4, letterSpacing: 1,
align: "right" align: "right"
}, [ }, [
{outline: "#000", letterBorder: 9}, {outline: "#000", letterBorder: 9},
{fill: "#fff"} {fill: "#fff"}
]) ])
} }
if(this.state.countupShown){
if(!this.state["countup" + p]){
this.state["countup" + p] = true
this.loopSound("results_countup", p, [0.1, false, 0, 0, 0.07])
}
}else if(this.state["countup" + p]){
this.state["countup" + p] = false
this.stopSound("results_countup", p)
if(this.state.screen === "fadeIn"){
this.playSound("note_don", p)
}
}
if(this.state.screen === "fadeIn" && elapsed >= this.state.fadeInEnd){
this.state.screen = "scoresShown"
this.state.screenMS = this.getMS()
}
} }
ctx.restore() ctx.restore()
} }
@ -510,6 +599,36 @@ class Scoresheet{
ctx.restore() ctx.restore()
} }
getNumber(score, start, elapsed){
var numberPos = Math.floor((elapsed - start) / this.frame)
if(numberPos < 0){
return ""
}
var output = ""
for(var i = 0; i < score.length; i++){
if(numberPos < 30 * (i + 1)){
this.state.countupShown = true
return this.numbers[numberPos % 30] + output
}else{
output = score[score.length - i - 1] + output
}
}
return output
}
getSound(id, p){
return assets.sounds[id + (this.multiplayer ? "_p" + (p + 1) : "")]
}
playSound(id, p){
this.getSound(id, p).play()
}
loopSound(id, p, args){
this.getSound(id, p).playLoop(...args)
}
stopSound(id, p){
this.getSound(id, p).stop()
}
mod(length, index){ mod(length, index){
return ((index % length) + length) % length return ((index % length) + length) % length
} }

View File

@ -16,12 +16,18 @@
return new Sound(gain || {soundBuffer: this}, buffer) return new Sound(gain || {soundBuffer: this}, buffer)
}) })
} }
createGain(){ createGain(channel){
return new SoundGain(this) return new SoundGain(this, channel)
} }
setCrossfade(gain1, gain2, median){ setCrossfade(gain1, gain2, median){
gain1.setCrossfade(1 - median) if(!Array.isArray(gain1)){
gain2.setCrossfade(median) gain1 = [gain1]
}
if(!Array.isArray(gain2)){
gain2 = [gain2]
}
gain1.forEach(gain => gain.setCrossfade(1 - median))
gain2.forEach(gain => gain.setCrossfade(median))
} }
getTime(){ getTime(){
return this.context.currentTime return this.context.currentTime
@ -41,10 +47,17 @@
} }
} }
class SoundGain{ class SoundGain{
constructor(soundBuffer){ constructor(soundBuffer, channel){
this.soundBuffer = soundBuffer this.soundBuffer = soundBuffer
this.gainNode = soundBuffer.context.createGain() this.gainNode = soundBuffer.context.createGain()
if(channel){
var index = channel === "left" ? 0 : 1
this.merger = soundBuffer.context.createChannelMerger(2)
this.merger.connect(soundBuffer.context.destination)
this.gainNode.connect(this.merger, 0, index)
}else{
this.gainNode.connect(soundBuffer.context.destination) this.gainNode.connect(soundBuffer.context.destination)
}
this.setVolume(1) this.setVolume(1)
} }
load(url){ load(url){
@ -87,6 +100,9 @@ class Sound{
this.timeouts = new Set() this.timeouts = new Set()
this.sources = new Set() this.sources = new Set()
} }
copy(gain){
return new Sound(gain, this.buffer)
}
getTime(){ getTime(){
return this.soundBuffer.getTime() return this.soundBuffer.getTime()
} }
@ -132,7 +148,7 @@ class Sound{
}, 100) }, 100)
} }
addLoop(){ addLoop(){
if(this.getTime() > this.loop.started - 1){ while(this.getTime() > this.loop.started - 1){
this.play(this.loop.started, true, this.loop.seek, this.loop.until) this.play(this.loop.started, true, this.loop.seek, this.loop.until)
this.loop.started += this.loop.until - this.loop.seek this.loop.started += this.loop.until - this.loop.seek
} }

View File

@ -59,7 +59,7 @@ class View{
gameSong.appendChild(document.createTextNode(this.songTitle)) gameSong.appendChild(document.createTextNode(this.songTitle))
gameSong.setAttribute("alt", this.songTitle) gameSong.setAttribute("alt", this.songTitle)
} }
this.lastMousemove = this.controller.getElapsedTime().ms this.lastMousemove = this.controller.getElapsedTime()
pageEvents.mouseAdd(this, this.onmousemove.bind(this)) pageEvents.mouseAdd(this, this.onmousemove.bind(this))
this.refresh() this.refresh()
@ -162,7 +162,7 @@ class View{
//this.drawTime() //this.drawTime()
} }
updateDonFaces(){ updateDonFaces(){
if(this.controller.getElapsedTime().ms >= this.nextBeat){ if(this.controller.getElapsedTime() >= this.nextBeat){
this.nextBeat += this.beatInterval this.nextBeat += this.beatInterval
if(this.controller.getCombo() >= 50){ if(this.controller.getCombo() >= 50){
this.currentBigDonFace = (this.currentBigDonFace + 1) % 2 this.currentBigDonFace = (this.currentBigDonFace + 1) % 2
@ -236,7 +236,7 @@ class View{
} }
drawMeasures(){ drawMeasures(){
var measures = this.controller.getSongData().measures var measures = this.controller.getSongData().measures
var currentTime = this.controller.getElapsedTime().ms var currentTime = this.controller.getElapsedTime()
measures.forEach((measure, index)=>{ measures.forEach((measure, index)=>{
var timeForDistance = this.posToMs(this.distanceForCircle, measure.speed) var timeForDistance = this.posToMs(this.distanceForCircle, measure.speed)
@ -251,7 +251,7 @@ class View{
} }
drawMeasure(measure){ drawMeasure(measure){
var z = this.canvas.scale var z = this.canvas.scale
var currentTime = this.controller.getElapsedTime().ms var currentTime = this.controller.getElapsedTime()
var measureX = this.slotX + this.msToPos(measure.ms - currentTime, measure.speed) var measureX = this.slotX + this.msToPos(measure.ms - currentTime, measure.speed)
this.ctx.strokeStyle = "#bab8b8" this.ctx.strokeStyle = "#bab8b8"
this.ctx.lineWidth = 2 this.ctx.lineWidth = 2
@ -348,7 +348,7 @@ class View{
} }
} }
drawPressedKeys(){ drawPressedKeys(){
var ms = this.controller.getElapsedTime().ms var ms = this.controller.getElapsedTime()
var keyTime = this.controller.getKeyTime() var keyTime = this.controller.getKeyTime()
var kbd = this.controller.getBindings() var kbd = this.controller.getBindings()
@ -432,7 +432,7 @@ class View{
drawCircles(circles){ drawCircles(circles){
for(var i = circles.length; i--;){ for(var i = circles.length; i--;){
var circle = circles[i] var circle = circles[i]
var ms = this.controller.getElapsedTime().ms var ms = this.controller.getElapsedTime()
var speed = circle.getSpeed() var speed = circle.getSpeed()
var timeForDistance = this.posToMs(this.distanceForCircle + this.bigCircleSize / 2, speed) var timeForDistance = this.posToMs(this.distanceForCircle + this.bigCircleSize / 2, speed)
@ -499,7 +499,7 @@ class View{
var z = this.canvas.scale var z = this.canvas.scale
var fill, size, faceID var fill, size, faceID
var type = circle.getType() var type = circle.getType()
var ms = this.controller.getElapsedTime().ms var ms = this.controller.getElapsedTime()
var circleMs = circle.getMS() var circleMs = circle.getMS()
var endTime = circle.getEndTime() var endTime = circle.getEndTime()
var animated = circle.isAnimated() var animated = circle.isAnimated()
@ -607,7 +607,7 @@ class View{
togglePauseMenu(){ togglePauseMenu(){
if(this.controller.game.isPaused()){ if(this.controller.game.isPaused()){
this.pauseMenu.style.display = "block" this.pauseMenu.style.display = "block"
this.lastMousemove = this.controller.getElapsedTime().ms this.lastMousemove = this.controller.getElapsedTime()
this.cursorHidden = false this.cursorHidden = false
this.mouseIdle() this.mouseIdle()
}else{ }else{
@ -619,6 +619,12 @@ class View{
this.diffX, this.diffY, this.diffX, this.diffY,
this.diffW, this.diffH this.diffW, this.diffH
) )
if(this.controller.autoPlayEnabled){
this.ctx.drawImage(assets.image["badge_auto"],
this.diffX + this.diffW * 0.71, this.diffY + this.diffH * 0.01,
this.diffH * 0.3, this.diffH * 0.3
)
}
this.ctx.drawImage(assets.image.taiko, this.ctx.drawImage(assets.image.taiko,
this.taikoX, this.taikoY, this.taikoX, this.taikoY,
this.taikoW, this.taikoH this.taikoW, this.taikoH
@ -626,7 +632,14 @@ class View{
} }
drawTime(){ drawTime(){
var z = this.canvas.scale var z = this.canvas.scale
var time = this.controller.getElapsedTime() var ms = this.controller.getElapsedTime()
var sign = Math.sign(ms) < 0 ? "-" : ""
ms = Math.abs(ms) + (sign === "-" ? 1000 : 0)
var time = {
sec: Math.floor(ms / 1000) % 60,
min: Math.floor(ms / 1000 / 60) % 60,
hour: Math.floor(ms / 1000 / 60 / 60) % 60
}
this.ctx.globalAlpha = 0.7 this.ctx.globalAlpha = 0.7
this.ctx.fillStyle = "#000" this.ctx.fillStyle = "#000"
@ -641,10 +654,10 @@ class View{
this.ctx.font = "normal " + (this.barH / 12) + "px Kozuka" this.ctx.font = "normal " + (this.barH / 12) + "px Kozuka"
this.ctx.textAlign = "right" this.ctx.textAlign = "right"
this.ctx.fillText(formatedH + ":" + formatedM + ":" + formatedS, this.ctx.fillText(sign + formatedH + ":" + formatedM + ":" + formatedS,
this.winW - 10 * z, this.winH - 30 * z this.winW - 10 * z, this.winH - 30 * z
) )
this.ctx.fillText(time.ms, this.winW - 10 * z, this.winH - 10 * z) this.ctx.fillText(sign + Math.floor(ms), this.winW - 10 * z, this.winH - 10 * z)
} }
drawBar(){ drawBar(){
this.ctx.strokeStyle = "#000" this.ctx.strokeStyle = "#000"
@ -655,7 +668,7 @@ class View{
this.ctx.closePath() this.ctx.closePath()
this.ctx.fill() this.ctx.fill()
var ms = this.controller.getElapsedTime().ms var ms = this.controller.getElapsedTime()
var keyTime = this.controller.getKeyTime() var keyTime = this.controller.getKeyTime()
var sound = keyTime["don"] > keyTime["ka"] ? "don" : "ka" var sound = keyTime["don"] > keyTime["ka"] ? "don" : "ka"
if(this.gogoTime || ms <= this.gogoTimeStarted + 100){ if(this.gogoTime || ms <= this.gogoTimeStarted + 100){
@ -666,7 +679,7 @@ class View{
grd.addColorStop(1, "#2c2a2c") grd.addColorStop(1, "#2c2a2c")
this.ctx.fillStyle = grd this.ctx.fillStyle = grd
this.ctx.rect(0, this.barY, this.winW, this.barH) this.ctx.rect(0, this.barY, this.winW, this.barH)
var alpha = Math.min(100, this.controller.getElapsedTime().ms - this.gogoTimeStarted) / 100 var alpha = Math.min(100, this.controller.getElapsedTime() - this.gogoTimeStarted) / 100
if(!this.gogoTime){ if(!this.gogoTime){
alpha = 1 - alpha alpha = 1 - alpha
} }
@ -755,7 +768,7 @@ class View{
} }
} }
drawGogoTime(){ drawGogoTime(){
var ms = this.controller.getElapsedTime().ms var ms = this.controller.getElapsedTime()
if(this.gogoTime){ if(this.gogoTime){
var circles = this.controller.parsedSongData.circles var circles = this.controller.parsedSongData.circles
@ -788,7 +801,7 @@ class View{
&& animation !== "gogo" && animation !== "gogo"
){ ){
don.setAnimation("10combo") don.setAnimation("10combo")
var ms = this.controller.getElapsedTime().ms var ms = this.controller.getElapsedTime()
don.setAnimationStart(ms) don.setAnimationStart(ms)
var length = don.getAnimationLength("normal") var length = don.getAnimationLength("normal")
don.setUpdateSpeed(this.beatInterval / (length / 4)) don.setUpdateSpeed(this.beatInterval / (length / 4))
@ -797,13 +810,13 @@ class View{
} }
} }
onmousemove(event){ onmousemove(event){
this.lastMousemove = this.controller.getElapsedTime().ms this.lastMousemove = this.controller.getElapsedTime()
this.cursorHidden = false this.cursorHidden = false
} }
mouseIdle(){ mouseIdle(){
var lastMouse = pageEvents.getMouse() var lastMouse = pageEvents.getMouse()
if(lastMouse && !this.cursorHidden){ if(lastMouse && !this.cursorHidden){
if(this.controller.getElapsedTime().ms >= this.lastMousemove + 2000){ if(this.controller.getElapsedTime() >= this.lastMousemove + 2000){
this.cursor.style.top = lastMouse.clientY + "px" this.cursor.style.top = lastMouse.clientY + "px"
this.cursor.style.left = lastMouse.clientX + "px" this.cursor.style.left = lastMouse.clientX + "px"
this.cursor.style.pointerEvents = "auto" this.cursor.style.pointerEvents = "auto"

View File

@ -60,7 +60,7 @@ class ViewAssets{
var imgw = 360 var imgw = 360
var imgh = 370 var imgh = 370
var scale = 175 var scale = 175
var ms = this.controller.getElapsedTime().ms var ms = this.controller.getElapsedTime()
var elapsed = ms - this.view.gogoTimeStarted var elapsed = ms - this.view.gogoTimeStarted
if(this.view.gogoTime){ if(this.view.gogoTime){
var grow = 3 - Math.min(200, elapsed) / 100 var grow = 3 - Math.min(200, elapsed) / 100