Add Go-Go Time

This commit is contained in:
LoveEevee 2018-09-20 02:20:26 +03:00
parent bba6ad525b
commit e3af27f23c
9 changed files with 293 additions and 88 deletions

View File

@ -45,6 +45,7 @@
<script src="/src/js/p2.js"></script> <script src="/src/js/p2.js"></script>
<script src="/src/js/canvasasset.js"></script> <script src="/src/js/canvasasset.js"></script>
<script src="/src/js/pageevents.js"></script> <script src="/src/js/pageevents.js"></script>
<script src="/src/js/viewassets.js"></script>
</head> </head>
<body> <body>

View File

@ -7,6 +7,7 @@ var assets = {
"don-1.png", "don-1.png",
"big-don-0.png", "big-don-0.png",
"big-don-1.png", "big-don-1.png",
"balloon.png",
"taiko.png", "taiko.png",
"taiko-key-blue.png", "taiko-key-blue.png",
"taiko-key-red.png", "taiko-key-red.png",
@ -28,7 +29,10 @@ var assets = {
"muzu_oni.png", "muzu_oni.png",
"don_anim_normal.png", "don_anim_normal.png",
"don_anim_10combo.png", "don_anim_10combo.png",
"balloon.png" "don_anim_gogo.png",
"don_anim_gogostart.png",
"fire_anim.png",
"fireworks_anim.png"
], ],
"audioSfx": [ "audioSfx": [
"start.wav", "start.wav",

View File

@ -1,19 +1,17 @@
class CanvasAsset{ class CanvasAsset{
constructor(view, position, image){ constructor(view, layer, position){
this.ctx = view.ctx this.ctx = view.ctx
this.controller = view.controller this.controller = view.controller
if(image){
this.image = assets.image[image]
}
this.position = position this.position = position
this.animationFrames = {} this.animationFrames = {}
this.speed = 1000 / 60 this.speed = 1000 / 60
this.animationStart = 0 this.animationStart = 0
this.layer = layer
} }
draw(){ draw(){
var u = (a, b) => typeof a === "undefined" ? b : a
var frame = 0
if(this.animation){ if(this.animation){
var u = (a, b) => typeof a === "undefined" ? b : a
var frame = 0
var ms = this.controller.getElapsedTime().ms var ms = this.controller.getElapsedTime().ms
if(this.animationEnd){ if(this.animationEnd){
if(ms > this.animationEnd.ms){ if(ms > this.animationEnd.ms){
@ -28,14 +26,17 @@ class CanvasAsset{
}else{ }else{
frame = this.mod(this.animation, index) frame = this.mod(this.animation, index)
} }
} var pos = this.position(frame)
var pos = this.position(frame) if(this.image){
if(this.image){ this.ctx.drawImage(this.image,
this.ctx.drawImage(this.image, u(pos.sx, pos.x), u(pos.sy, pos.y),
u(pos.sx, pos.x), u(pos.sy, pos.y), u(pos.sw, pos.w), u(pos.sh, pos.h),
u(pos.sw, pos.w), u(pos.sh, pos.h), pos.x, pos.y, pos.w, pos.h
pos.x, pos.y, pos.w, pos.h )
) }
if(pos.callback){
pos.callback()
}
} }
} }
mod(length, index){ mod(length, index){
@ -52,17 +53,21 @@ class CanvasAsset{
} }
setAnimation(name){ setAnimation(name){
var framesObj = this.animationFrames[name] var framesObj = this.animationFrames[name]
this.animation = framesObj.frames
this.animationName = name this.animationName = name
if(framesObj.image){ if(framesObj){
this.image = framesObj.image this.animation = framesObj.frames
if(framesObj.image){
this.image = framesObj.image
}
}else{
this.animation = false
} }
} }
getAnimation(){ getAnimation(){
return this.animationName return this.animationName
} }
getAnimationLength(){ getAnimationLength(name){
var frames = this.animationFrames["10combo"].frames var frames = this.animationFrames[name].frames
if(Array.isArray(frames)){ if(Array.isArray(frames)){
return frames.length return frames.length
}else{ }else{

View File

@ -1,21 +1,24 @@
class Circle{ class Circle{
constructor(id, ms, type, text, speed, endTime, requiredHits){ constructor(config){
this.id = id // id, ms, type, text, speed, endTime, requiredHits
this.ms = ms this.id = config.id
this.type = type this.ms = config.start
this.text = text this.type = config.type
this.speed = speed this.text = config.txt
this.endTime = endTime ? endTime : ms + 150 this.speed = config.speed
this.endTime = config.endTime || this.ms + 150
this.isPlayed = 0 this.isPlayed = 0
this.animating = false this.animating = false
this.animT = 0 this.animT = 0
this.score = 0 this.score = 0
this.lastFrame = ms + 100 this.lastFrame = this.ms + 100
this.animationEnded = false this.animationEnded = false
this.status = -1 this.status = -1
this.timesHit = 0 this.timesHit = 0
this.requiredHits = requiredHits ? requiredHits : 0 this.requiredHits = config.requiredHits || 0
this.rendaPlayed = false this.rendaPlayed = false
this.gogoTime = config.gogoTime
this.gogoChecked = false
} }
getMS(){ getMS(){
return this.ms return this.ms

View File

@ -41,7 +41,7 @@ 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() this.offsetDate = new Date()
this.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.setElapsedTime(-this.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()
@ -192,9 +192,9 @@ class Game{
this.controller.displayScore(score, true) this.controller.displayScore(score, true)
} }
this.updateCombo(score) this.updateCombo(score)
this.updateGlobalScore(score, typeDai && keyDai ? 2 : 1) this.updateGlobalScore(score, typeDai && keyDai ? 2 : 1, circle.gogoTime)
this.updateCurrentCircle() this.updateCurrentCircle()
circle.played(score, keyDai) circle.played(score, score === 0 ? typeDai : keyDai)
if(this.controller.multiplayer == 1){ if(this.controller.multiplayer == 1){
p2.send("note", { p2.send("note", {
score: score, score: score,
@ -243,7 +243,14 @@ class Game{
}else{ }else{
var sound = keyTime["don"] > keyTime["ka"] ? "daiDon" : "daiKa" var sound = keyTime["don"] > keyTime["ka"] ? "daiDon" : "daiKa"
} }
var circleAnim = new Circle(0, this.getElapsedTime().ms, sound, "", circle.speed) var circleAnim = new Circle({
id: 0,
start: this.getElapsedTime().ms,
type: sound,
txt: "",
speed: circle.speed,
gogoTime: circle.gogoTime
})
circleAnim.played(score, dai) circleAnim.played(score, dai)
circleAnim.animate() circleAnim.animate()
this.controller.view.drumroll.push(circleAnim) this.controller.view.drumroll.push(circleAnim)
@ -252,7 +259,7 @@ class Game{
} }
whenLastCirclePlayed(){ whenLastCirclePlayed(){
var circles = this.songData.circles var circles = this.songData.circles
var lastCircle = circles[this.songData.circles.length - 1] var lastCircle = circles[circles.length - 1]
var ms = this.getElapsedTime().ms var ms = this.getElapsedTime().ms
if(!this.fadeOutStarted && ms >= lastCircle.getEndTime() + 1900){ if(!this.fadeOutStarted && ms >= lastCircle.getEndTime() + 1900){
this.fadeOutStarted = ms this.fadeOutStarted = ms
@ -365,7 +372,7 @@ class Game{
getGlobalScore(){ getGlobalScore(){
return this.globalScore return this.globalScore
} }
updateGlobalScore(score, multiplier){ updateGlobalScore(score, multiplier, gogoTime){
// Circle score // Circle score
switch(score){ switch(score){
case 450: case 450:
@ -389,6 +396,9 @@ class Game{
// Points update // Points update
score += Math.max(0, Math.floor((Math.min(this.combo, 100) - 1) / 10) * 100) score += Math.max(0, Math.floor((Math.min(this.combo, 100) - 1) / 10) * 100)
this.globalScore.points += score * multiplier if(gogoTime){
multiplier *= 1.2
}
this.globalScore.points += Math.floor(score * multiplier / 10) * 10
} }
} }

View File

@ -33,7 +33,7 @@ class Mekadon{
this.controller.displayScore(0, true) this.controller.displayScore(0, true)
this.game.updateCurrentCircle() this.game.updateCurrentCircle()
this.game.updateCombo(0) this.game.updateCombo(0)
this.game.updateGlobalScore(0, 1) this.game.updateGlobalScore(0, 1, circle.gogoTime)
return true return true
} }
} }
@ -72,7 +72,7 @@ class Mekadon{
}else{ }else{
this.controller.displayScore(score) this.controller.displayScore(score)
this.game.updateCombo(score) this.game.updateCombo(score)
this.game.updateGlobalScore(score, keyDai ? 2 : 1) this.game.updateGlobalScore(score, keyDai ? 2 : 1, circle.gogoTime)
this.game.updateCurrentCircle() this.game.updateCurrentCircle()
} }
circle.updateStatus(score) circle.updateStatus(score)

View File

@ -121,7 +121,8 @@ class ParseSong{
timingPoints.push({ timingPoints.push({
start: start, start: start,
sliderMultiplier: sliderMultiplier, sliderMultiplier: sliderMultiplier,
measure: parseInt(values[this.osu.METER]) measure: parseInt(values[this.osu.METER]),
gogoTime: parseInt(values[this.osu.KIAIMODE])
}) })
} }
return timingPoints return timingPoints
@ -142,7 +143,7 @@ class ParseSong{
speed: this.timingPoints[i].sliderMultiplier speed: this.timingPoints[i].sliderMultiplier
}) })
measureNumber++ measureNumber++
if(measureNumber == this.timingPoints[i].measure + 1){ if(measureNumber === this.timingPoints[i].measure + 1){
measureNumber = 0 measureNumber = 0
} }
} }
@ -229,6 +230,7 @@ class ParseSong{
var emptyValue = false var emptyValue = false
var start = parseInt(values[this.osu.TIME]) var start = parseInt(values[this.osu.TIME])
var speed = this.difficulty.originalMultiplier var speed = this.difficulty.originalMultiplier
var gogoTime = false
var osuType = parseInt(values[this.osu.TYPE]) var osuType = parseInt(values[this.osu.TYPE])
var hitSound = parseInt(values[this.osu.HITSOUND]) var hitSound = parseInt(values[this.osu.HITSOUND])
@ -237,6 +239,7 @@ class ParseSong{
break break
} }
speed = this.timingPoints[j].sliderMultiplier speed = this.timingPoints[j].sliderMultiplier
gogoTime = this.timingPoints[j].gogoTime
} }
if(osuType & this.osu.SPINNER){ if(osuType & this.osu.SPINNER){
@ -244,7 +247,16 @@ class ParseSong{
var endTime = parseInt(values[this.osu.ENDTIME]) var endTime = parseInt(values[this.osu.ENDTIME])
var hitMultiplier = this.difficultyRange(this.difficulty.overallDifficulty, 3, 5, 7.5) * 1.65 var hitMultiplier = this.difficultyRange(this.difficulty.overallDifficulty, 3, 5, 7.5) * 1.65
var requiredHits = Math.floor(Math.max(1, (endTime - start) / 1000 * hitMultiplier)) var requiredHits = Math.floor(Math.max(1, (endTime - start) / 1000 * hitMultiplier))
circles.push(new Circle(circleID, start, "balloon", "ふうせん", speed, endTime, requiredHits)) circles.push(new Circle({
id: circleID,
start: start,
type: "balloon",
txt: "ふうせん",
speed: speed,
endTime: endTime,
requiredHits: requiredHits,
gogoTime: gogoTime
}))
}else if(osuType & this.osu.SLIDER){ }else if(osuType & this.osu.SLIDER){
@ -258,7 +270,15 @@ class ParseSong{
type = "drumroll" type = "drumroll"
txt = "連打ーっ!!" txt = "連打ーっ!!"
} }
circles.push(new Circle(circleID, start, type, txt, speed, endTime)) circles.push(new Circle({
id: circleID,
start: start,
type: type,
txt: txt,
speed: speed,
endTime: endTime,
gogoTime: gogoTime
}))
}else if(osuType & this.osu.CIRCLE){ }else if(osuType & this.osu.CIRCLE){
var type var type
@ -284,7 +304,14 @@ class ParseSong{
emptyValue = true emptyValue = true
} }
if(!emptyValue){ if(!emptyValue){
circles.push(new Circle(circleID, start, type, txt, speed)) circles.push(new Circle({
id: circleID,
start: start,
type: type,
txt: txt,
speed: speed,
gogoTime: gogoTime
}))
} }
}else{ }else{
emptyValue = true emptyValue = true

View File

@ -42,37 +42,13 @@ class View{
this.currentDonFace = 0 this.currentDonFace = 0
this.currentBigDonFace = 1 this.currentBigDonFace = 1
this.nextBeat = 0 this.nextBeat = 0
this.gogoTime = 0
this.gogoTimeStarted = -Infinity
this.drumroll = [] this.drumroll = []
this.beatInterval = this.controller.getSongData().beatInfo.beatInterval this.beatInterval = this.controller.getSongData().beatInfo.beatInterval
this.assets = [] this.assets = new ViewAssets(this)
this.don = this.createAsset(frame => {
var imgw = 360
var imgh = 184
var scale = 165
var w = (this.barH * imgw) / scale
var h = (this.barH * imgh) / scale
return {
sx: 0,
sy: frame * imgh,
sw: imgw,
sh: imgh,
x: this.taikoSquareW - w + this.barH * 0.2,
y: this.barY - h,
w: w,
h: h
}
})
this.don.addFrames("normal", [
0 ,0 ,0 ,0 ,1 ,2 ,3 ,4 ,5 ,6 ,6 ,5 ,4 ,3 ,2 ,1 ,
0 ,0 ,0 ,0 ,1 ,2 ,3 ,4 ,5 ,6 ,6 ,5 ,4 ,3 ,2 ,1 ,
0 ,0 ,0 ,0 ,1 ,2 ,3 ,4 ,5 ,6 ,6 ,5 ,7 ,8 ,9 ,10,
11,11,11,11,10,9 ,8 ,7 ,13,12,12,13,14,15,16,17
], "don_anim_normal")
this.don.addFrames("10combo", 22, "don_anim_10combo")
this.don.setAnimation("normal")
this.don.setUpdateSpeed(this.beatInterval / 16)
} }
run(){ run(){
this.ctx.font = "normal 14pt TnT" this.ctx.font = "normal 14pt TnT"
@ -146,11 +122,12 @@ class View{
this.ctx.clearRect(0, 0, this.canvas.scaledWidth, this.canvas.scaledHeight) this.ctx.clearRect(0, 0, this.canvas.scaledWidth, this.canvas.scaledHeight)
// Draw // Draw
this.drawAssets() this.assets.drawAssets("background")
this.drawBar() this.drawBar()
this.drawSlot() this.drawSlot()
this.drawMeasures()
this.drawHPBar() this.drawHPBar()
this.assets.drawAssets("bar")
this.drawMeasures()
this.drawScore() this.drawScore()
this.drawCircles(this.controller.getCircles()) this.drawCircles(this.controller.getCircles())
this.drawCircles(this.drumroll) this.drawCircles(this.drumroll)
@ -160,7 +137,9 @@ class View{
this.drawCombo() this.drawCombo()
this.drawGlobalScore() this.drawGlobalScore()
this.updateDonFaces() this.updateDonFaces()
this.drawGogoTime()
this.mouseIdle() this.mouseIdle()
this.assets.drawAssets("foreground")
//this.drawTime() //this.drawTime()
} }
updateDonFaces(){ updateDonFaces(){
@ -449,6 +428,12 @@ class View{
// Start animation to HP bar // Start animation to HP bar
circle.animate() circle.animate()
} }
if(ms >= circle.ms && !circle.gogoChecked){
if(this.gogoTime != circle.gogoTime){
this.toggleGogoTime(circle)
}
circle.gogoChecked = true
}
if(circle.isAnimated()){ if(circle.isAnimated()){
var animationDuration = 470 var animationDuration = 470
if(ms <= finishTime + animationDuration){ if(ms <= finishTime + animationDuration){
@ -654,6 +639,22 @@ class View{
var ms = this.controller.getElapsedTime().ms var ms = this.controller.getElapsedTime().ms
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){
var grd = this.ctx.createLinearGradient(0, this.barY, this.winW, this.barH)
grd.addColorStop(0, "#512a2c")
grd.addColorStop(0.46, "#6f2a2d")
grd.addColorStop(0.76, "#8a4763")
grd.addColorStop(1, "#2c2a2c")
this.ctx.fillStyle = grd
this.ctx.rect(0, this.barY, this.winW, this.barH)
var alpha = Math.min(100, this.controller.getElapsedTime().ms - this.gogoTimeStarted) / 100
if(!this.gogoTime){
alpha = 1 - alpha
}
this.ctx.globalAlpha = alpha
this.ctx.fill()
this.ctx.globalAlpha = 1
}
if(keyTime[sound] > ms - 200){ if(keyTime[sound] > ms - 200){
var gradients = { var gradients = {
"don": ["#f54c25", "#232323"], "don": ["#f54c25", "#232323"],
@ -710,27 +711,78 @@ class View{
this.ctx.closePath() this.ctx.closePath()
this.ctx.stroke() this.ctx.stroke()
} }
createAsset(image, position){ toggleGogoTime(circle){
var asset = new CanvasAsset(this, image, position) this.gogoTime = circle.gogoTime
this.assets.push(asset) this.gogoTimeStarted = circle.ms
return asset if(this.gogoTime){
} this.assets.fireworks.forEach(fireworksAsset => {
drawAssets(){ fireworksAsset.setAnimation("normal")
if(this.controller.multiplayer !== 2){ fireworksAsset.setAnimationStart(circle.ms)
this.assets.forEach(asset => { var length = fireworksAsset.getAnimationLength("normal")
asset.draw() fireworksAsset.setAnimationEnd(circle.ms + length * fireworksAsset.speed, () => {
fireworksAsset.setAnimation(false)
})
})
this.assets.fire.setAnimation("normal")
var don = this.assets.don
don.setAnimation("gogostart")
don.setAnimationStart(circle.ms)
var length = don.getAnimationLength("gogostart")
don.setAnimationEnd(circle.ms + length * don.speed, () => {
don.setAnimationStart(0)
if(this.gogoTime){
don.setAnimation("gogo")
}else{
don.setAnimation("normal")
}
}) })
} }
} }
drawGogoTime(){
var ms = this.controller.getElapsedTime().ms
if(this.gogoTime){
if(this.gogoTimeStarted){
}
var circles = this.controller.parsedSongData.circles
var lastCircle = circles[circles.length - 1]
var endTime = lastCircle.getEndTime() + 3000
if(ms >= endTime){
this.toggleGogoTime({
gogoTime: 0,
ms: endTime
})
}
}else{
if(this.assets.don.getAnimation() === "gogo"){
this.assets.don.setAnimation("normal")
}
if(ms >= this.gogoTimeStarted + 100){
this.assets.fire.setAnimation(false)
}
}
}
updateCombo(combo){ updateCombo(combo){
if(combo > 0 && combo % 10 === 0 && this.don.getAnimation() != "10combo"){ var don = this.assets.don
this.don.setAnimation("10combo") var animation = don.getAnimation()
if(
combo > 0
&& combo % 10 === 0
&& animation !== "10combo"
&& animation !== "gogostart"
&& animation !== "gogo"
){
don.setAnimation("10combo")
var ms = this.controller.getElapsedTime().ms var ms = this.controller.getElapsedTime().ms
this.don.setAnimationStart(ms) don.setAnimationStart(ms)
var length = this.don.getAnimationLength("10combo") var length = don.getAnimationLength("10combo")
this.don.setAnimationEnd(ms + length * this.don.speed, () => { don.setAnimationEnd(ms + length * don.speed, () => {
this.don.setAnimationStart(0) don.setAnimationStart(0)
this.don.setAnimation("normal") if(this.gogoTime){
don.setAnimation("gogo")
}else{
don.setAnimation("normal")
}
}) })
} }
} }

103
public/src/js/viewassets.js Normal file
View File

@ -0,0 +1,103 @@
class ViewAssets{
constructor(view){
this.view = view
this.controller = this.view.controller
this.allAssets = []
this.beatInterval = this.view.beatInterval
this.ctx = this.view.ctx
this.don = this.createAsset("background", frame => {
var imgw = 360
var imgh = 184
var scale = 165
var w = (this.view.barH * imgw) / scale
var h = (this.view.barH * imgh) / scale
return {
sx: Math.floor(frame / 10) * imgw,
sy: (frame % 10) * imgh,
sw: imgw,
sh: imgh,
x: this.view.taikoSquareW - w + this.view.barH * 0.2,
y: this.view.barY - h,
w: w,
h: h
}
})
this.don.addFrames("normal", [
0 ,0 ,0 ,0 ,1 ,2 ,3 ,4 ,5 ,6 ,6 ,5 ,4 ,3 ,2 ,1 ,
0 ,0 ,0 ,0 ,1 ,2 ,3 ,4 ,5 ,6 ,6 ,5 ,4 ,3 ,2 ,1 ,
0 ,0 ,0 ,0 ,1 ,2 ,3 ,4 ,5 ,6 ,6 ,5 ,7 ,8 ,9 ,10,
11,11,11,11,10,9 ,8 ,7 ,13,12,12,13,14,15,16,17
], "don_anim_normal")
this.don.addFrames("10combo", 22, "don_anim_10combo")
this.don.addFrames("gogo", 56, "don_anim_gogo")
this.don.addFrames("gogostart", 27, "don_anim_gogostart")
this.don.setAnimation("normal")
this.don.setUpdateSpeed(this.beatInterval / 16)
this.fire = this.createAsset("bar", frame => {
var imgw = 360
var imgh = 370
var scale = 175
var ms = this.controller.getElapsedTime().ms
var grow = Math.min(100, ms - this.view.gogoTimeStarted) / 100
if(!this.view.gogoTime){
grow = 1 - grow
}
var w = (this.view.barH * imgw) / scale * grow
var h = (this.view.barH * imgh) / scale * grow
this.ctx.globalCompositeOperation = "lighter"
return {
sx: frame * imgw,
sy: 0,
sw: imgw,
sh: imgh,
x: this.view.slotX - w / 2,
y: this.view.circleY - h / 2,
w: w,
h: h,
callback: () => {
this.ctx.globalCompositeOperation = "source-over"
}
}
})
this.fire.addFrames("normal", 7, "fire_anim")
this.fire.setUpdateSpeed(this.beatInterval / 8)
this.fireworks = []
for(let i = 0; i < 5 ; i++){
var fireworksAsset = this.createAsset("foreground", frame => {
var imgw = 230
var imgh = 460
var scale = 165
var w = (this.view.barH * imgw) / scale
var h = (this.view.barH * imgh) / scale
return {
sx: Math.floor(frame / 4) * imgw,
sy: (frame % 4) * imgh,
sw: imgw,
sh: imgh,
x: this.view.winW / 4 * i - w / 2 * (i / 2),
y: this.view.winH - h,
w: w,
h: h
}
})
fireworksAsset.addFrames("normal", 30, "fireworks_anim")
fireworksAsset.setUpdateSpeed(this.beatInterval / 16)
this.fireworks.push(fireworksAsset)
}
}
createAsset(layer, position){
var asset = new CanvasAsset(this.view, layer, position)
this.allAssets.push(asset)
return asset
}
drawAssets(layer){
if(this.controller.multiplayer !== 2){
this.allAssets.forEach(asset => {
if(layer === asset.layer){
asset.draw()
}
})
}
}
}