mirror of
https://github.com/yuukiwww/taiko-web.git
synced 2024-09-30 21:29:31 +02:00
View: Rewrite
This commit is contained in:
parent
ab2e3d2417
commit
f90f6fe6e1
@ -1,9 +1,10 @@
|
||||
#game{
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
position: asbolute;
|
||||
position: absolute;
|
||||
overflow: hidden;
|
||||
background-size: cover;
|
||||
background-position: center;
|
||||
}
|
||||
#game.default-bg{
|
||||
background-size: calc(100vh / 720 * 512);
|
||||
@ -70,7 +71,7 @@
|
||||
#touch-buttons{
|
||||
display: none;
|
||||
position: absolute;
|
||||
top: 6.5vh;
|
||||
top: 8vh;
|
||||
right: 2vh;
|
||||
opacity: 0.5;
|
||||
z-index: 5;
|
||||
@ -79,6 +80,12 @@
|
||||
width: 12.5vmin;
|
||||
height: 12.5vmin;
|
||||
}
|
||||
.portrait #touch-buttons{
|
||||
top: 11vh;
|
||||
}
|
||||
.touchp2 #touch-buttons{
|
||||
top: -1.9vh;
|
||||
}
|
||||
.touch-visible #touch-drum,
|
||||
.touch-visible #touch-buttons{
|
||||
display: block;
|
||||
|
@ -2,20 +2,11 @@ var assets = {
|
||||
"img": [
|
||||
"title-screen.png",
|
||||
"logo-big.png",
|
||||
"don-0.png",
|
||||
"don-1.png",
|
||||
"big-don-0.png",
|
||||
"big-don-1.png",
|
||||
"notes.png",
|
||||
"notes_drumroll.png",
|
||||
"notes_hit.png",
|
||||
"balloon.png",
|
||||
"taiko.png",
|
||||
"taiko-key-blue.png",
|
||||
"taiko-key-red.png",
|
||||
"hp-bar-bg.png",
|
||||
"hp-bar-colour.png",
|
||||
"score-0.png",
|
||||
"score-0-b.png",
|
||||
"score-230.png",
|
||||
"score-450.png",
|
||||
"dancing-don.gif",
|
||||
"bg-pattern-1.png",
|
||||
"muzu_easy.png",
|
||||
|
@ -27,6 +27,7 @@ class CanvasAsset{
|
||||
}else{
|
||||
frame = this.mod(this.animation, index)
|
||||
}
|
||||
this.ctx.save()
|
||||
var pos = this.position(frame)
|
||||
if(this.image){
|
||||
this.ctx.drawImage(this.image,
|
||||
@ -35,9 +36,7 @@ class CanvasAsset{
|
||||
pos.x, pos.y, pos.w, pos.h
|
||||
)
|
||||
}
|
||||
if(pos.callback){
|
||||
pos.callback()
|
||||
}
|
||||
this.ctx.restore()
|
||||
}
|
||||
}
|
||||
mod(length, index){
|
||||
|
@ -1,14 +1,17 @@
|
||||
class CanvasCache{
|
||||
constructor(w, h, scale){
|
||||
this.canvas = document.createElement("canvas")
|
||||
this.ctx = this.canvas.getContext("2d")
|
||||
this.map = new Map()
|
||||
if(w){
|
||||
this.resize(w, h, scale)
|
||||
}
|
||||
}
|
||||
resize(w, h, scale){
|
||||
this.map.clear()
|
||||
if(this.canvas){
|
||||
this.map.clear()
|
||||
}else{
|
||||
this.map = new Map()
|
||||
this.canvas = document.createElement("canvas")
|
||||
this.ctx = this.canvas.getContext("2d")
|
||||
}
|
||||
this.scale = scale
|
||||
this.x = 0
|
||||
this.y = 0
|
||||
@ -20,8 +23,11 @@ class CanvasCache{
|
||||
this.canvas.height = this.h * this.scale
|
||||
this.ctx.scale(this.scale, this.scale)
|
||||
}
|
||||
get(config, callback){
|
||||
get(config, callback, setOnly){
|
||||
var img = this.map.get(config.id)
|
||||
if(img && setOnly || !img && !callback){
|
||||
return
|
||||
}
|
||||
var saved = false
|
||||
if(!img){
|
||||
var w = config.w
|
||||
@ -50,6 +56,10 @@ class CanvasCache{
|
||||
|
||||
callback(this.ctx)
|
||||
}
|
||||
if(setOnly){
|
||||
this.ctx.restore()
|
||||
return
|
||||
}
|
||||
var z = this.scale
|
||||
config.ctx.drawImage(this.canvas,
|
||||
img.x * z |0, img.y * z |0, img.w * z |0, img.h * z |0,
|
||||
@ -59,6 +69,9 @@ class CanvasCache{
|
||||
this.ctx.restore()
|
||||
}
|
||||
}
|
||||
set(config, callback){
|
||||
return this.get(config, callback, true)
|
||||
}
|
||||
clean(){
|
||||
delete this.map
|
||||
delete this.ctx
|
||||
|
@ -39,6 +39,13 @@
|
||||
|
||||
this.crownPath = new Path2D("m82 21c0-4 3-6 5.5-6 2.5 0 5.5 2 5.5 6 0 4-3 6-5.5 6C85 27 82 25 82 21ZM41.5 6c0-4 3-6 5.5-6 2.5 0 5.5 2 5.5 6 0 4-3 6-5.5 6-2.5 0-5.5-2-5.5-6zM1 21C1 17 4 15 6.5 15 9 15 12 17 12 21 12 25 9 27 6.5 27 4 27 1 25 1 21Zm12 46h68l2 11H11ZM13 62 5 18 29 34 47 6 65 34 89 18 81 62Z")
|
||||
|
||||
this.soulPath = new Path2D("m37 29c1-4 7 2 7 4 0 1-2 2-4 2-1 0-1-4-3-6zm-4-7c3 1 5 3 4 5-1 2-3 3-3 4 3-2 5-2 5-2 0 0-1 3-5 5-4 3-5-1-3-4 2-3 3-6 0-7zm-3 8c1 3-5 10 8 7 6-1 2-4 2-4 5 1 7 3 7 5 0 3-8 4-12 4-4 0-9-2-9-5 0 0 0-6-1-8 0-3 3-3 5 1zM20 23h8C27 27 20 44 9 42 18 36 23 28 21 26 19 24 20 23 20 23Zm0-6c4-2 9-4 14-2v2c-5 0-9 1-14 2zm8-7v12h-4c2-1 1-9-1-10zm-6 12c3 0 10-2 10-2 0 0 1-10 0-10-5 1-8 3-12 3 0 0 2 5 2 9zm0-12c0 0 6-1 9-3 3-2 9 3 8 6-1 3-2 6-4 9-2 2-15 2-15 2-1 0-3-7-2-11zM21 0c8 0 10 3 8 5 0 0-6 7-15 10C22 8 23 3 23 3 23 1 21 0 21 0ZM5 9c-1 3 2 6 4 6 5-1 13-6 4-7-3 0-5 5-8 1zm7 17c2-1 4-1 6 1 2 2 1 6-2 6-1 0-2-2-2-2-1-2-3-4-2-5zm2 4c-3 2-4 5-5 6-1 1-4 2-6-2-1-2 0-3 2-5l4-4c0-1-1 0-4 1-2 1-5-2-4-4 2-5 1 0 3-1 6-4 9-5 11-3 2 2 0 3-2 5-1 1-3 4-4 6 0 1 3-1 4-2")
|
||||
|
||||
this.optionsPath = {
|
||||
shadow: new Path2D("M4-1V8H9V0l1-1 3 6v4l-4 5v10l4 5v4l-2 4-2 1V30H4L5 37 3 38 0 33V29L4 24V14L0 9V5L3 0Z"),
|
||||
main: new Path2D("M4 0V8H9V0h1l3 5v4l-4 5v10l4 5v4l-3 5H9V30H4v8H3L0 33V29L4 24V14L0 9V5L3 0Z")
|
||||
}
|
||||
|
||||
this.regex = {
|
||||
comma: /[,.]/,
|
||||
ideographicComma: /[、。]/,
|
||||
@ -76,11 +83,25 @@
|
||||
var h = config.h
|
||||
var r = config.radius
|
||||
ctx.beginPath()
|
||||
ctx.arc(x + r, y + r, r, Math.PI, Math.PI * 1.5)
|
||||
ctx.arc(x + w - r, y + r, r, Math.PI * 1.5, 0)
|
||||
ctx.arc(x + w - r, y + h - r, r, 0, Math.PI / 2)
|
||||
ctx.arc(x + r, y + h - r, r, Math.PI / 2, Math.PI)
|
||||
ctx.lineTo(x, y + r)
|
||||
this.roundedCorner(ctx, x, y, r, 0)
|
||||
this.roundedCorner(ctx, x + w, y, r, 1)
|
||||
this.roundedCorner(ctx, x + w, y + h, r, 2)
|
||||
this.roundedCorner(ctx, x, y + h, r, 3)
|
||||
ctx.closePath()
|
||||
}
|
||||
|
||||
roundedCorner(ctx, x, y, r, rotation){
|
||||
var pi = Math.PI
|
||||
switch(rotation){
|
||||
case 0:
|
||||
return ctx.arc(x + r, y + r, r, pi, pi / -2)
|
||||
case 1:
|
||||
return ctx.arc(x - r, y + r, r, pi / -2, 0)
|
||||
case 2:
|
||||
return ctx.arc(x - r, y - r, r, 0, pi / 2)
|
||||
case 3:
|
||||
return ctx.arc(x + r, y - r, r, pi / 2, pi)
|
||||
}
|
||||
}
|
||||
|
||||
songFrame(config){
|
||||
@ -428,6 +449,9 @@
|
||||
}
|
||||
|
||||
ctx.translate(config.x, config.y)
|
||||
if(config.scale){
|
||||
ctx.scale(config.scale[0], config.scale[1])
|
||||
}
|
||||
var scale = 1
|
||||
if(config.width && drawnWidth > config.width){
|
||||
scale = config.width / drawnWidth
|
||||
@ -438,7 +462,13 @@
|
||||
ctx.textAlign = "center"
|
||||
|
||||
for(let layer of layers){
|
||||
var savedLayer = false
|
||||
var action = "strokeText"
|
||||
if(layer.scale){
|
||||
savedLayer = true
|
||||
ctx.save()
|
||||
ctx.scale(layer.scale[0], layer.scale[1])
|
||||
}
|
||||
if(layer.outline){
|
||||
ctx.strokeStyle = layer.outline
|
||||
ctx.lineJoin = "round"
|
||||
@ -452,7 +482,10 @@
|
||||
action = "fillText"
|
||||
}
|
||||
if(layer.shadow){
|
||||
ctx.save()
|
||||
if(!savedLayer){
|
||||
savedLayer = true
|
||||
ctx.save()
|
||||
}
|
||||
this.shadow({
|
||||
ctx: ctx,
|
||||
fill: "rgba(0, 0, 0, " + (1 / (layer.shadow[3] || 2)) + ")",
|
||||
@ -501,7 +534,7 @@
|
||||
}
|
||||
offsetX += symbol.w * mul
|
||||
}
|
||||
if(layer.shadow){
|
||||
if(savedLayer){
|
||||
ctx.restore()
|
||||
}
|
||||
}
|
||||
@ -538,42 +571,59 @@
|
||||
diffOptionsIcon(config){
|
||||
var ctx = config.ctx
|
||||
ctx.save()
|
||||
ctx.translate(config.x - 21, config.y - 21)
|
||||
|
||||
var drawLine = y => {
|
||||
ctx.beginPath()
|
||||
ctx.moveTo(12, y)
|
||||
ctx.arc(20.5, 25, 8.5, Math.PI, Math.PI * 2, true)
|
||||
ctx.lineTo(29, 18)
|
||||
ctx.stroke()
|
||||
}
|
||||
var drawTriangle = noFill => {
|
||||
ctx.beginPath()
|
||||
ctx.moveTo(29, 5)
|
||||
ctx.lineTo(21, 19)
|
||||
ctx.lineTo(37, 19)
|
||||
ctx.closePath()
|
||||
if(!noFill){
|
||||
ctx.fill()
|
||||
if(config.iconName === "back"){
|
||||
ctx.translate(config.x - 21, config.y - 21)
|
||||
|
||||
var drawLine = y => {
|
||||
ctx.beginPath()
|
||||
ctx.moveTo(12, y)
|
||||
ctx.arc(20.5, 25, 8.5, Math.PI, Math.PI * 2, true)
|
||||
ctx.lineTo(29, 18)
|
||||
ctx.stroke()
|
||||
}
|
||||
var drawTriangle = noFill => {
|
||||
ctx.beginPath()
|
||||
ctx.moveTo(29, 5)
|
||||
ctx.lineTo(21, 19)
|
||||
ctx.lineTo(37, 19)
|
||||
ctx.closePath()
|
||||
if(!noFill){
|
||||
ctx.fill()
|
||||
}
|
||||
}
|
||||
ctx.strokeStyle = "#000"
|
||||
ctx.lineWidth = 12
|
||||
drawLine(9)
|
||||
ctx.lineWidth = 5
|
||||
drawTriangle(true)
|
||||
ctx.stroke()
|
||||
ctx.lineWidth = 7
|
||||
ctx.fillStyle = "#fff"
|
||||
ctx.strokeStyle = "#fff"
|
||||
drawLine(11)
|
||||
drawTriangle()
|
||||
ctx.translate(-1.5, -0.5)
|
||||
ctx.fillStyle = "#23a6e1"
|
||||
ctx.strokeStyle = "#23a6e1"
|
||||
ctx.globalCompositeOperation = "darken"
|
||||
drawLine(11)
|
||||
drawTriangle()
|
||||
}else if(config.iconName === "options"){
|
||||
ctx.translate(config.x, config.y)
|
||||
ctx.rotate(-55 * Math.PI / 180)
|
||||
ctx.translate(-6, -20)
|
||||
ctx.strokeStyle = "#000"
|
||||
ctx.lineWidth = 6
|
||||
ctx.stroke(this.optionsPath.main)
|
||||
ctx.translate(-2, 2)
|
||||
ctx.stroke(this.optionsPath.main)
|
||||
ctx.fillStyle = "#7e7c76"
|
||||
ctx.fill(this.optionsPath.shadow)
|
||||
ctx.translate(2, -2)
|
||||
ctx.fillStyle = "#d9d6ce"
|
||||
ctx.fill(this.optionsPath.main)
|
||||
}
|
||||
ctx.strokeStyle = "#000"
|
||||
ctx.lineWidth = 12
|
||||
drawLine(9)
|
||||
ctx.lineWidth = 5
|
||||
drawTriangle(true)
|
||||
ctx.stroke()
|
||||
ctx.lineWidth = 7
|
||||
ctx.fillStyle = "#fff"
|
||||
ctx.strokeStyle = "#fff"
|
||||
drawLine(11)
|
||||
drawTriangle()
|
||||
ctx.translate(-1.5, -0.5)
|
||||
ctx.fillStyle = "#23a6e1"
|
||||
ctx.strokeStyle = "#23a6e1"
|
||||
ctx.globalCompositeOperation = "darken"
|
||||
drawLine(11)
|
||||
drawTriangle()
|
||||
|
||||
ctx.restore()
|
||||
}
|
||||
@ -676,9 +726,13 @@
|
||||
ctx.scale(1 / mul, 1 / mul)
|
||||
}
|
||||
ctx.fillStyle = ctx.createPattern(config.img, "repeat")
|
||||
ctx.beginPath()
|
||||
ctx.rect(config.x * mul, config.y * mul, config.w * mul, config.h * mul)
|
||||
ctx.translate(config.dx, config.dy)
|
||||
if(config.shape){
|
||||
config.shape(ctx, mul)
|
||||
}else{
|
||||
ctx.beginPath()
|
||||
ctx.rect(config.x * mul, config.y * mul, config.w * mul, config.h * mul)
|
||||
}
|
||||
ctx.translate(config.dx * mul, config.dy * mul)
|
||||
ctx.fill()
|
||||
|
||||
ctx.restore()
|
||||
@ -692,6 +746,9 @@
|
||||
if(config.scale){
|
||||
ctx.scale(config.scale, config.scale)
|
||||
}
|
||||
if(config.align === "center"){
|
||||
ctx.translate(config.score === "bad" ? -49 / 2 : -23 / 2, 0)
|
||||
}
|
||||
ctx.strokeStyle = "#000"
|
||||
ctx.lineWidth = 7
|
||||
if(config.score === "good"){
|
||||
@ -790,6 +847,160 @@
|
||||
ctx.restore()
|
||||
}
|
||||
|
||||
gauge(config){
|
||||
var ctx = config.ctx
|
||||
ctx.save()
|
||||
|
||||
ctx.translate(config.x, config.y)
|
||||
if(config.scale){
|
||||
ctx.scale(config.scale, config.scale)
|
||||
}
|
||||
ctx.translate(-788, 0)
|
||||
|
||||
var firstTop = config.multiplayer ? 0 : 30
|
||||
var secondTop = config.multiplayer ? 0 : 8
|
||||
|
||||
var cleared = config.percentage - 1 / 50 >= config.clear
|
||||
|
||||
var gaugeW = 14 * 50
|
||||
var gaugeClear = gaugeW * config.clear
|
||||
var gaugeFilled = gaugeW * config.percentage
|
||||
|
||||
ctx.fillStyle = "#000"
|
||||
ctx.beginPath()
|
||||
if(config.scoresheet){
|
||||
ctx.moveTo(-4, 26)
|
||||
ctx.lineTo(gaugeClear - 4, 26)
|
||||
this.roundedCorner(ctx, gaugeClear - 4, 4, 13, 0)
|
||||
this.roundedCorner(ctx, 760, 4, 13, 1)
|
||||
ctx.lineTo(760, 56)
|
||||
ctx.lineTo(-4, 56)
|
||||
}else if(config.multiplayer){
|
||||
ctx.moveTo(gaugeClear - 7, 27)
|
||||
ctx.lineTo(788, 27)
|
||||
ctx.lineTo(788, 52)
|
||||
this.roundedCorner(ctx, gaugeClear - 7, 52, 18, 3)
|
||||
}else{
|
||||
ctx.moveTo(gaugeClear - 7, 24)
|
||||
this.roundedCorner(ctx, gaugeClear - 7, 0, 18, 0)
|
||||
ctx.lineTo(788, 0)
|
||||
ctx.lineTo(788, 24)
|
||||
}
|
||||
ctx.fill()
|
||||
|
||||
if(gaugeFilled <= gaugeClear){
|
||||
ctx.fillStyle = "#680000"
|
||||
var x = Math.max(0, gaugeFilled - 5)
|
||||
ctx.fillRect(x, firstTop, gaugeClear - x + 2, 22)
|
||||
}
|
||||
if(gaugeFilled > 0){
|
||||
var w = Math.min(gaugeClear + 1, gaugeFilled - 4)
|
||||
ctx.fillStyle = "#ff3508"
|
||||
ctx.fillRect(0, firstTop + 2, w, 20)
|
||||
ctx.fillStyle = "#ff9e94"
|
||||
ctx.fillRect(0, firstTop, w, 3)
|
||||
}
|
||||
if(gaugeFilled < gaugeW - 4){
|
||||
ctx.fillStyle = "#684c00"
|
||||
var x = Math.max(gaugeClear + 9, gaugeFilled - gaugeClear + 9)
|
||||
ctx.fillRect(x, secondTop, gaugeW - 4 - x, 44)
|
||||
}
|
||||
if(gaugeFilled > gaugeClear + 14){
|
||||
var w = Math.min(gaugeW - 4, gaugeFilled - gaugeClear - 14)
|
||||
ctx.fillStyle = "#ff0"
|
||||
ctx.fillRect(gaugeClear + 9, secondTop + 2, w, 42)
|
||||
ctx.fillStyle = "#fff"
|
||||
ctx.fillRect(gaugeClear + 9, secondTop, w, 3)
|
||||
}
|
||||
ctx.fillStyle = cleared ? "#ff0" : "#684c00"
|
||||
ctx.beginPath()
|
||||
if(config.multiplayer){
|
||||
this.roundedCorner(ctx, gaugeClear, secondTop + 44, 10, 3)
|
||||
ctx.lineTo(gaugeClear, secondTop)
|
||||
ctx.lineTo(gaugeClear + 10, secondTop)
|
||||
}else{
|
||||
ctx.moveTo(gaugeClear, secondTop + 44)
|
||||
this.roundedCorner(ctx, gaugeClear, secondTop, 10, 0)
|
||||
ctx.lineTo(gaugeClear + 10, secondTop + 44)
|
||||
}
|
||||
ctx.fill()
|
||||
if(cleared){
|
||||
ctx.save()
|
||||
ctx.clip()
|
||||
ctx.fillStyle = "#fff"
|
||||
ctx.fillRect(gaugeClear, secondTop, 10, 3)
|
||||
ctx.restore()
|
||||
}
|
||||
|
||||
ctx.strokeStyle = "rgba(0, 0, 0, 0.16)"
|
||||
ctx.beginPath()
|
||||
ctx.lineWidth = 5
|
||||
for(var i = 0; i < 49; i++){
|
||||
var x = 14 + i * 14 - ctx.lineWidth / 2
|
||||
if(i === 26){
|
||||
ctx.stroke()
|
||||
ctx.beginPath()
|
||||
ctx.lineWidth = 4
|
||||
}
|
||||
ctx.moveTo(x, x < gaugeClear ? firstTop : secondTop)
|
||||
ctx.lineTo(x, x < gaugeClear ? firstTop + 22 : secondTop + 44)
|
||||
}
|
||||
ctx.stroke()
|
||||
this.layeredText({
|
||||
ctx: ctx,
|
||||
text: "クリア",
|
||||
fontSize: 18,
|
||||
fontFamily: config.font,
|
||||
x: gaugeClear - 6,
|
||||
y: config.multiplayer ? 22 : 11,
|
||||
letterSpacing: -2
|
||||
}, [
|
||||
{scale: [1.1, 1.01], outline: "#000", letterBorder: 6},
|
||||
{scale: [1.11, 1], fill: cleared ? "#fff" : "#737373"}
|
||||
])
|
||||
|
||||
ctx.restore()
|
||||
}
|
||||
|
||||
soul(config){
|
||||
var ctx = config.ctx
|
||||
ctx.save()
|
||||
|
||||
ctx.translate(config.x, config.y)
|
||||
if(config.scale){
|
||||
ctx.scale(config.scale, config.scale)
|
||||
}
|
||||
ctx.translate(-23, -21)
|
||||
|
||||
ctx.fillStyle = config.cleared ? "#fff" : "#737373"
|
||||
ctx.fill(this.soulPath)
|
||||
|
||||
ctx.restore()
|
||||
}
|
||||
|
||||
slot(ctx, x, y, size){
|
||||
var mul = size / 106
|
||||
|
||||
ctx.save()
|
||||
ctx.globalAlpha = 0.7
|
||||
ctx.globalCompositeOperation = "screen"
|
||||
ctx.fillStyle = "#444544"
|
||||
ctx.beginPath()
|
||||
ctx.arc(x, y, 26 * mul, 0, Math.PI * 2)
|
||||
ctx.fill()
|
||||
ctx.lineWidth = 3
|
||||
ctx.strokeStyle = "#9c9e9c"
|
||||
ctx.beginPath()
|
||||
ctx.arc(x, y, 33.5 * mul, 0, Math.PI * 2)
|
||||
ctx.stroke()
|
||||
ctx.lineWidth = 3.5
|
||||
ctx.strokeStyle = "#5d5e5d"
|
||||
ctx.beginPath()
|
||||
ctx.arc(x, y, 51.5 * mul, 0, Math.PI * 2)
|
||||
ctx.stroke()
|
||||
ctx.restore()
|
||||
}
|
||||
|
||||
alpha(amount, ctx, callback){
|
||||
if(amount >= 1){
|
||||
return callback(ctx)
|
||||
|
@ -81,6 +81,17 @@ class Controller{
|
||||
if(this.syncWith){
|
||||
this.syncWith.mainLoop()
|
||||
}
|
||||
|
||||
if(this.scoresheet){
|
||||
if(this.view.ctx){
|
||||
this.view.ctx.save()
|
||||
this.view.ctx.setTransform(1, 0, 0, 1, 0, 0)
|
||||
}
|
||||
this.scoresheet.redraw()
|
||||
if(this.view.ctx){
|
||||
this.view.ctx.restore()
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
var ms = this.game.elapsedTime
|
||||
@ -104,10 +115,6 @@ class Controller{
|
||||
this.view.refresh()
|
||||
}
|
||||
this.keyboard.checkMenuKeys()
|
||||
|
||||
if(this.scoresheet){
|
||||
this.scoresheet.redraw()
|
||||
}
|
||||
}
|
||||
}
|
||||
togglePauseMenu(){
|
||||
@ -117,11 +124,13 @@ class Controller{
|
||||
gameEnded(){
|
||||
var score = this.getGlobalScore()
|
||||
var vp
|
||||
if(score.bad === 0){
|
||||
vp = "fullcombo"
|
||||
this.playSoundMeka("fullcombo", 1.350)
|
||||
}else if(score.gauge >= 50){
|
||||
vp = "clear"
|
||||
if(Math.round(score.gauge / 2) - 1 >= 25){
|
||||
if(score.bad === 0){
|
||||
vp = "fullcombo"
|
||||
this.playSoundMeka("fullcombo", 1.350)
|
||||
}else{
|
||||
vp = "clear"
|
||||
}
|
||||
}else{
|
||||
vp = "fail"
|
||||
}
|
||||
@ -132,8 +141,8 @@ class Controller{
|
||||
this.scoresheet = new Scoresheet(this, this.getGlobalScore(), this.multiplayer)
|
||||
}
|
||||
}
|
||||
displayScore(score, notPlayed){
|
||||
this.view.displayScore(score, notPlayed)
|
||||
displayScore(score, notPlayed, bigNote){
|
||||
this.view.displayScore(score, notPlayed, bigNote)
|
||||
}
|
||||
songSelection(fadeIn){
|
||||
if(!fadeIn){
|
||||
|
@ -117,6 +117,10 @@ class Debug{
|
||||
break
|
||||
}
|
||||
}
|
||||
if(game.mainMusicPlaying){
|
||||
game.mainMusicPlaying = false
|
||||
game.mainAsset.stop()
|
||||
}
|
||||
}
|
||||
this.autoplayCheckbox.checked = this.controller.autoPlayEnabled
|
||||
}
|
||||
|
@ -1,49 +0,0 @@
|
||||
function element(){
|
||||
var parent
|
||||
var lasttag
|
||||
var createdtag
|
||||
var toreturn={}
|
||||
for(var i=0;i<arguments.length;i++){
|
||||
var current=arguments[i]
|
||||
if(current){
|
||||
if(current.nodeType){
|
||||
parent=lasttag=current
|
||||
}else if(Array.isArray(current)){
|
||||
lasttag=parent
|
||||
for(var j=0;j<current.length;j++){
|
||||
if(current[j]){
|
||||
if(j==0&&typeof current[j]=="string"){
|
||||
var tagname=current[0].split("#")
|
||||
lasttag=createdtag=document.createElement(tagname[0])
|
||||
if(tagname[1]){
|
||||
toreturn[tagname[1]]=createdtag
|
||||
}
|
||||
}else if(current[j].constructor==Object){
|
||||
if(lasttag){
|
||||
for(var value in current[j]){
|
||||
if(value!="style"&&value in lasttag){
|
||||
lasttag[value]=current[j][value]
|
||||
}else{
|
||||
lasttag.setAttribute(value,current[j][value])
|
||||
}
|
||||
}
|
||||
}
|
||||
}else{
|
||||
var returned=element(lasttag,current[j])
|
||||
for(var k in returned){
|
||||
toreturn[k]=returned[k]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}else if(current){
|
||||
createdtag=document.createTextNode(current)
|
||||
}
|
||||
if(parent&&createdtag){
|
||||
parent.appendChild(createdtag)
|
||||
}
|
||||
createdtag=0
|
||||
}
|
||||
}
|
||||
return toreturn
|
||||
}
|
@ -116,9 +116,6 @@ class Game{
|
||||
}
|
||||
}
|
||||
}
|
||||
setHPGain(gain){
|
||||
this.HPGain = gain
|
||||
}
|
||||
checkPlays(){
|
||||
var circles = this.songData.circles
|
||||
var circle = circles[this.currentCircle]
|
||||
@ -200,14 +197,15 @@ class Game{
|
||||
if(circleStatus === 230 || circleStatus === 450){
|
||||
score = circleStatus
|
||||
}
|
||||
this.controller.displayScore(score)
|
||||
circle.played(score, score === 0 ? typeDai : keyDai)
|
||||
this.controller.displayScore(score, false, typeDai && keyDai)
|
||||
}else{
|
||||
this.controller.displayScore(score, true)
|
||||
circle.played(-1, typeDai)
|
||||
this.controller.displayScore(score, true, false)
|
||||
}
|
||||
this.updateCombo(score)
|
||||
this.updateGlobalScore(score, typeDai && keyDai ? 2 : 1, circle.gogoTime)
|
||||
this.updateCurrentCircle()
|
||||
circle.played(score, score === 0 ? typeDai : keyDai)
|
||||
if(this.controller.multiplayer == 1){
|
||||
p2.send("note", {
|
||||
score: score,
|
||||
|
@ -111,7 +111,7 @@ class Keyboard{
|
||||
this.controller.togglePauseMenu()
|
||||
for(var key in this.keyTime){
|
||||
this.keys[key] = null
|
||||
this.keyTime[key] = null
|
||||
this.keyTime[key] = -Infinity
|
||||
}
|
||||
})
|
||||
var moveMenuMinus = () => {
|
||||
|
@ -94,7 +94,7 @@ class loadSong{
|
||||
this.clean()
|
||||
loader.changePage("game")
|
||||
var taikoGame1 = new Controller(this.selectedSong, this.songData, false, 1, this.touchEnabled)
|
||||
var taikoGame2 = new Controller(this.selectedSong2, this.song2Data, true, 2)
|
||||
var taikoGame2 = new Controller(this.selectedSong2, this.song2Data, true, 2, this.touchEnabled)
|
||||
taikoGame1.run(taikoGame2)
|
||||
}
|
||||
})
|
||||
|
@ -1,42 +0,0 @@
|
||||
class ScalableCanvas{
|
||||
constructor(id, width, height, noStyle){
|
||||
var oldCanvas = document.getElementById(id)
|
||||
if(oldCanvas){
|
||||
this.canvas = oldCanvas
|
||||
}else{
|
||||
this.canvas = document.createElement("canvas")
|
||||
this.canvas.id = id
|
||||
}
|
||||
this.ctx = this.canvas.getContext("2d")
|
||||
this.rescale()
|
||||
this.resize(width, height, noStyle)
|
||||
}
|
||||
resize(width, height, noStyle){
|
||||
if(width != this.width || height != this.height){
|
||||
this.width = width
|
||||
this.height = height
|
||||
this.scaledWidth = width * this.scale
|
||||
this.canvas.width = this.scaledWidth
|
||||
this.scaledHeight = height * this.scale
|
||||
this.canvas.height = this.scaledHeight
|
||||
if(noStyle || this.scale == 1){
|
||||
if(this.canvas.style.width){
|
||||
this.canvas.style.width = ""
|
||||
}
|
||||
if(this.canvas.style.height){
|
||||
this.canvas.style.height = ""
|
||||
}
|
||||
}else{
|
||||
this.canvas.style.width = width + "px"
|
||||
this.canvas.style.height = height + "px"
|
||||
}
|
||||
}
|
||||
}
|
||||
rescale(){
|
||||
var scale = window.devicePixelRatio || 1
|
||||
if(scale != this.scale){
|
||||
this.ctx.scale(scale, scale)
|
||||
this.scale = scale
|
||||
}
|
||||
}
|
||||
}
|
@ -416,16 +416,25 @@ class Scoresheet{
|
||||
results = p2.results
|
||||
ctx.translate(0, p2Offset)
|
||||
}
|
||||
ctx.drawImage(assets.image["hp-bar-bg"],
|
||||
552, 120, 688, 48
|
||||
)
|
||||
var gauge = results.gauge / 100
|
||||
if(gauge > 0){
|
||||
ctx.drawImage(assets.image["hp-bar-colour"],
|
||||
0, 0, 650 * gauge, 40,
|
||||
557, 127, 635 * gauge, 37,
|
||||
)
|
||||
}
|
||||
var gaugePercent = Math.round(results.gauge / 2) / 50
|
||||
var w = 712
|
||||
this.draw.gauge({
|
||||
ctx: ctx,
|
||||
x: 558 + w,
|
||||
y: 116,
|
||||
clear: 25 / 50,
|
||||
percentage: gaugePercent,
|
||||
font: this.font,
|
||||
scale: w / 788,
|
||||
scoresheet: true
|
||||
})
|
||||
this.draw.soul({
|
||||
ctx: ctx,
|
||||
x: 1215,
|
||||
y: 144,
|
||||
scale: 36 / 42,
|
||||
cleared: gaugePercent - 1 / 50 >= 25 / 50
|
||||
})
|
||||
}
|
||||
ctx.restore()
|
||||
}
|
||||
@ -441,10 +450,8 @@ class Scoresheet{
|
||||
results = p2.results
|
||||
}
|
||||
var crownType = null
|
||||
if(results.bad === "0"){
|
||||
crownType = "gold"
|
||||
}else if(results.gauge >= 50){
|
||||
crownType = "silver"
|
||||
if(Math.round(results.gauge / 2) - 1 >= 25){
|
||||
crownType = results.bad === "0" ? "gold" : "silver"
|
||||
}
|
||||
if(crownType !== null){
|
||||
noCrownResultWait = 0;
|
||||
|
@ -156,6 +156,21 @@ class SongSelect{
|
||||
letterBorder: 12
|
||||
}
|
||||
|
||||
this.diffOptions = [{
|
||||
text: "もどる",
|
||||
fill: "#efb058",
|
||||
iconName: "back",
|
||||
iconFill: "#f7d39c",
|
||||
letterSpacing: 4
|
||||
}, {
|
||||
text: "演奏オプション",
|
||||
fill: "#b2e442",
|
||||
iconName: "options",
|
||||
iconFill: "#d9f19f",
|
||||
letterSpacing: 0
|
||||
}]
|
||||
this.optionsList = ["なし", "オート", "ネットプレイ"]
|
||||
|
||||
this.draw = new CanvasDraw()
|
||||
this.songTitleCache = new CanvasCache()
|
||||
this.selectTextCache = new CanvasCache()
|
||||
@ -185,7 +200,7 @@ class SongSelect{
|
||||
this.playBgm(false)
|
||||
}
|
||||
if("selectedDiff" in localStorage){
|
||||
this.selectedDiff = Math.min(Math.max(0, localStorage["selectedDiff"] |0), 4)
|
||||
this.selectedDiff = Math.min(Math.max(0, localStorage["selectedDiff"] |0), this.diffOptions.length + 3)
|
||||
}
|
||||
|
||||
this.songSelect = document.getElementById("song-select")
|
||||
@ -202,7 +217,8 @@ class SongSelect{
|
||||
ura: 0,
|
||||
moveHover: null,
|
||||
locked: true,
|
||||
hasPointer: false
|
||||
hasPointer: false,
|
||||
options: 0
|
||||
}
|
||||
this.songSelecting = {
|
||||
speed: 800,
|
||||
@ -218,6 +234,8 @@ class SongSelect{
|
||||
"8": ["a"],
|
||||
"37": ["l", "lb", "lt", "lsl"],
|
||||
"39": ["r", "rb", "rt", "lsr"],
|
||||
"38": ["u", "lsu"],
|
||||
"40": ["d", "lsd"],
|
||||
"ctrl": ["y"],
|
||||
"shift": ["x"]
|
||||
})
|
||||
@ -259,10 +277,14 @@ class SongSelect{
|
||||
// Enter, Space, F, J
|
||||
cancel: code == 27 || code == 8,
|
||||
// Esc, Backspace
|
||||
left: code == 68,
|
||||
left: code == 37 || code == 68,
|
||||
// Left, D
|
||||
right: code == 75
|
||||
right: code == 39 || code == 75,
|
||||
// Right, K
|
||||
up: code == 38,
|
||||
// Up
|
||||
down: code == 40
|
||||
// Down
|
||||
}
|
||||
if(key.cancel && event){
|
||||
event.preventDefault()
|
||||
@ -281,8 +303,10 @@ class SongSelect{
|
||||
if(key.confirm){
|
||||
if(this.selectedDiff === 0){
|
||||
this.toSongSelect()
|
||||
}else if(this.selectedDiff === 1){
|
||||
this.toOptions(1)
|
||||
}else{
|
||||
this.toLoadSong(this.selectedDiff - 1, modifiers.shift, modifiers.ctrl)
|
||||
this.toLoadSong(this.selectedDiff - this.diffOptions.length, modifiers.shift, modifiers.ctrl)
|
||||
}
|
||||
}else if(key.cancel){
|
||||
this.toSongSelect()
|
||||
@ -290,6 +314,8 @@ class SongSelect{
|
||||
this.moveToDiff(-1)
|
||||
}else if(key.right){
|
||||
this.moveToDiff(1)
|
||||
}else if(this.selectedDiff === 1 && (key.up || key.down)){
|
||||
this.toOptions(key.up ? -1 : 1)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -319,20 +345,21 @@ class SongSelect{
|
||||
}
|
||||
}else if(this.state.screen === "difficulty"){
|
||||
var moveBy = this.diffSelMouse(mouse.x, mouse.y)
|
||||
if(
|
||||
moveBy === 0
|
||||
|| mouse.x < 55 || mouse.x > 967
|
||||
|| mouse.y < 40 || mouse.y > 540
|
||||
){
|
||||
if(mouse.x < 55 || mouse.x > 967 || mouse.y < 40 || mouse.y > 540){
|
||||
this.toSongSelect()
|
||||
}else if(moveBy === 5){
|
||||
}else if(moveBy === 0){
|
||||
this.selectedDiff = 0
|
||||
this.toSongSelect()
|
||||
}else if(moveBy === 1){
|
||||
this.toOptions(1)
|
||||
}else if(moveBy === this.diffOptions.length + 4){
|
||||
this.state.ura = !this.state.ura
|
||||
assets.sounds["ka"].play()
|
||||
if(this.selectedDiff === 5 && !this.state.ura){
|
||||
if(this.selectedDiff === this.diffOptions.length + 4 && !this.state.ura){
|
||||
this.state.move = -1
|
||||
}
|
||||
}else if(moveBy !== null){
|
||||
this.toLoadSong(moveBy - 1, shift, ctrl, touch)
|
||||
this.toLoadSong(moveBy - this.diffOptions.length, shift, ctrl, touch)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -393,12 +420,12 @@ class SongSelect{
|
||||
}
|
||||
diffSelMouse(x, y){
|
||||
if(this.state.locked === 0){
|
||||
if(100 < x && x < 160 && 120 < y && y < 420){
|
||||
return 0
|
||||
if(95 < x && x < 239 && 118 < y && y < 422){
|
||||
return Math.floor((x - 95) / ((239 - 95) / 2))
|
||||
}else if(422 < x && x < 922 && 95 < y && y < 524){
|
||||
var moveBy = Math.floor((x - 422) / ((922 - 422) / 5)) + 1
|
||||
var moveBy = Math.floor((x - 422) / ((922 - 422) / 5)) + this.diffOptions.length
|
||||
var currentSong = this.songs[this.selectedSong]
|
||||
if(this.state.ura && moveBy === 4 || currentSong.stars[moveBy - 1]){
|
||||
if(this.state.ura && moveBy === this.diffOptions + 3 || currentSong.stars[moveBy - this.diffOptions.length]){
|
||||
return moveBy
|
||||
}
|
||||
}
|
||||
@ -451,8 +478,8 @@ class SongSelect{
|
||||
this.state.locked = true
|
||||
this.state.moveHover = null
|
||||
this.state.ura = 0
|
||||
if(this.selectedDiff === 5){
|
||||
this.selectedDiff = 4
|
||||
if(this.selectedDiff === this.diffOptions.length + 4){
|
||||
this.selectedDiff = this.diffOptions.length + 3
|
||||
}
|
||||
|
||||
assets.sounds["don"].play()
|
||||
@ -497,11 +524,22 @@ class SongSelect{
|
||||
assets.sounds["don"].play()
|
||||
|
||||
localStorage["selectedSong"] = this.selectedSong
|
||||
localStorage["selectedDiff"] = difficulty + 1
|
||||
localStorage["selectedDiff"] = difficulty + this.diffOptions.length
|
||||
|
||||
if(difficulty === 3 && this.state.ura){
|
||||
difficulty = 4
|
||||
}
|
||||
var autoplay = false
|
||||
var multiplayer = false
|
||||
if(this.state.options === 1){
|
||||
autoplay = true
|
||||
}else if(this.state.options === 2){
|
||||
multiplayer = true
|
||||
}else if(shift){
|
||||
autoplay = shift
|
||||
}else{
|
||||
multiplayer = ctrl
|
||||
}
|
||||
|
||||
new loadSong({
|
||||
"title": selectedSong.title,
|
||||
@ -510,7 +548,12 @@ class SongSelect{
|
||||
"category": selectedSong.category,
|
||||
"type": selectedSong.type,
|
||||
"offset": selectedSong.offset
|
||||
}, shift, ctrl, touch)
|
||||
}, autoplay, multiplayer, touch)
|
||||
}
|
||||
toOptions(moveBy){
|
||||
assets.sounds["ka"].play()
|
||||
this.selectedDiff = 1
|
||||
this.state.options = this.mod(this.optionsList.length, this.state.options + moveBy)
|
||||
}
|
||||
toTitleScreen(){
|
||||
assets.sounds["cancel"].play()
|
||||
@ -745,25 +788,25 @@ class SongSelect{
|
||||
do{
|
||||
if(hasUra && this.state.move > 0){
|
||||
this.selectedDiff += this.state.move
|
||||
if(this.selectedDiff > 5){
|
||||
if(this.selectedDiff > this.diffOptions.length + 4){
|
||||
this.state.ura = !this.state.ura
|
||||
if(this.state.ura){
|
||||
this.selectedDiff = previousSelection === 4 ? 5 : previousSelection
|
||||
this.selectedDiff = previousSelection === this.diffOptions.length + 3 ? this.diffOptions.length + 4 : previousSelection
|
||||
break
|
||||
}else{
|
||||
this.state.move = -1
|
||||
}
|
||||
}
|
||||
}else{
|
||||
this.selectedDiff = this.mod(6, this.selectedDiff + this.state.move)
|
||||
this.selectedDiff = this.mod(this.diffOptions.length + 5, this.selectedDiff + this.state.move)
|
||||
}
|
||||
}while(
|
||||
this.selectedDiff !== 0 && !currentSong.stars[this.selectedDiff - 1]
|
||||
|| this.selectedDiff === 4 && this.state.ura
|
||||
|| this.selectedDiff === 5 && !this.state.ura
|
||||
this.selectedDiff >= this.diffOptions.length && !currentSong.stars[this.selectedDiff - this.diffOptions.length]
|
||||
|| this.selectedDiff === this.diffOptions.length + 3 && this.state.ura
|
||||
|| this.selectedDiff === this.diffOptions.length + 4 && !this.state.ura
|
||||
)
|
||||
this.state.move = 0
|
||||
}else if(!currentSong.stars[this.selectedDiff - 1]){
|
||||
}else if(this.selectedDiff < 0 || this.selectedDiff >= this.diffOptions.length && !currentSong.stars[this.selectedDiff - this.diffOptions.length]){
|
||||
this.selectedDiff = 0
|
||||
}
|
||||
}
|
||||
@ -897,70 +940,80 @@ class SongSelect{
|
||||
})
|
||||
var opened = 1
|
||||
var songSel = false
|
||||
var _x = x + 62
|
||||
var _y = y + 67
|
||||
ctx.fillStyle = "#efb058"
|
||||
ctx.lineWidth = 5
|
||||
this.draw.roundedRect({
|
||||
ctx: ctx,
|
||||
x: _x - 28,
|
||||
y: _y,
|
||||
w: 56,
|
||||
h: 298,
|
||||
radius: 24
|
||||
})
|
||||
ctx.fill()
|
||||
ctx.stroke()
|
||||
ctx.fillStyle = "#f7d39c"
|
||||
ctx.beginPath()
|
||||
ctx.arc(_x, _y + 28, 20, 0, Math.PI * 2)
|
||||
ctx.fill()
|
||||
this.draw.diffOptionsIcon({
|
||||
ctx: ctx,
|
||||
x: _x,
|
||||
y: _y + 28
|
||||
})
|
||||
|
||||
this.draw.verticalText({
|
||||
ctx: ctx,
|
||||
text: "もどる",
|
||||
x: _x,
|
||||
y: _y + 57,
|
||||
width: 56,
|
||||
height: 220,
|
||||
fill: "#fff",
|
||||
outline: "#000",
|
||||
outlineSize: this.songAsset.letterBorder,
|
||||
letterBorder: 4,
|
||||
fontSize: 28,
|
||||
fontFamily: this.font,
|
||||
letterSpacing: 4
|
||||
})
|
||||
var highlight = 0
|
||||
if(this.state.moveHover === 0){
|
||||
highlight = 2
|
||||
}else if(this.selectedDiff === 0){
|
||||
highlight = 1
|
||||
}
|
||||
if(highlight){
|
||||
this.draw.highlight({
|
||||
for(var i = 0; i < this.diffOptions.length; i++){
|
||||
var _x = x + 62 + i * 72
|
||||
var _y = y + 67
|
||||
ctx.fillStyle = this.diffOptions[i].fill
|
||||
ctx.lineWidth = 5
|
||||
this.draw.roundedRect({
|
||||
ctx: ctx,
|
||||
x: _x - 32,
|
||||
y: _y - 3,
|
||||
w: 64,
|
||||
h: 304,
|
||||
animate: highlight === 1,
|
||||
animateMS: this.state.moveMS,
|
||||
opacity: highlight === 2 ? 0.8 : 1,
|
||||
x: _x - 28,
|
||||
y: _y,
|
||||
w: 56,
|
||||
h: 298,
|
||||
radius: 24
|
||||
})
|
||||
if(this.selectedDiff === 0){
|
||||
this.draw.diffCursor({
|
||||
ctx.fill()
|
||||
ctx.stroke()
|
||||
ctx.fillStyle = this.diffOptions[i].iconFill
|
||||
ctx.beginPath()
|
||||
ctx.arc(_x, _y + 28, 20, 0, Math.PI * 2)
|
||||
ctx.fill()
|
||||
this.draw.diffOptionsIcon({
|
||||
ctx: ctx,
|
||||
x: _x,
|
||||
y: _y + 28,
|
||||
iconName: this.diffOptions[i].iconName
|
||||
})
|
||||
|
||||
var text = this.diffOptions[i].text
|
||||
if(this.diffOptions[i].iconName === "options" && (this.selectedDiff === i || this.state.options !== 0)){
|
||||
text = this.optionsList[this.state.options]
|
||||
}
|
||||
|
||||
this.draw.verticalText({
|
||||
ctx: ctx,
|
||||
text: text,
|
||||
x: _x,
|
||||
y: _y + 57,
|
||||
width: 56,
|
||||
height: 220,
|
||||
fill: "#fff",
|
||||
outline: "#000",
|
||||
outlineSize: this.songAsset.letterBorder,
|
||||
letterBorder: 4,
|
||||
fontSize: 28,
|
||||
fontFamily: this.font,
|
||||
letterSpacing: this.diffOptions[i].letterSpacing
|
||||
})
|
||||
|
||||
var highlight = 0
|
||||
if(this.state.moveHover === i){
|
||||
highlight = 2
|
||||
}else if(this.selectedDiff === i){
|
||||
highlight = 1
|
||||
}
|
||||
if(highlight){
|
||||
this.draw.highlight({
|
||||
ctx: ctx,
|
||||
font: this.font,
|
||||
x: _x,
|
||||
y: _y - 45
|
||||
x: _x - 32,
|
||||
y: _y - 3,
|
||||
w: 64,
|
||||
h: 304,
|
||||
animate: highlight === 1,
|
||||
animateMS: this.state.moveMS,
|
||||
opacity: highlight === 2 ? 0.8 : 1,
|
||||
radius: 24
|
||||
})
|
||||
if(this.selectedDiff === i && !this.touchEnabled){
|
||||
this.draw.diffCursor({
|
||||
ctx: ctx,
|
||||
font: this.font,
|
||||
x: _x,
|
||||
y: _y - 45
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1057,8 +1110,8 @@ class SongSelect{
|
||||
})
|
||||
}
|
||||
}
|
||||
var currentDiff = this.selectedDiff - 1
|
||||
if(this.selectedDiff === 5){
|
||||
var currentDiff = this.selectedDiff - this.diffOptions.length
|
||||
if(this.selectedDiff === 4 + this.diffOptions.length){
|
||||
currentDiff = 3
|
||||
}
|
||||
if(i === currentSong.p2Cursor){
|
||||
@ -1074,12 +1127,12 @@ class SongSelect{
|
||||
}
|
||||
if(!songSel){
|
||||
var highlight = 0
|
||||
if(this.state.moveHover - 1 === i){
|
||||
if(this.state.moveHover - this.diffOptions.length === i){
|
||||
highlight = 2
|
||||
}else if(currentDiff === i){
|
||||
highlight = 1
|
||||
}
|
||||
if(currentDiff === i){
|
||||
if(currentDiff === i && !this.touchEnabled){
|
||||
this.draw.diffCursor({
|
||||
ctx: ctx,
|
||||
font: this.font,
|
||||
|
@ -1,97 +1,752 @@
|
||||
class View{
|
||||
constructor(controller, bg, songTitle, songDifficulty){
|
||||
class View{
|
||||
constructor(controller){
|
||||
this.controller = controller
|
||||
this.bg = bg
|
||||
this.songTitle = songTitle
|
||||
this.songDifficulty = songDifficulty
|
||||
|
||||
this.canvas = document.getElementById("canvas")
|
||||
this.ctx = this.canvas.getContext("2d")
|
||||
|
||||
this.pauseMenu = document.getElementById("pause-menu")
|
||||
this.cursor = document.getElementById("cursor")
|
||||
this.gameDiv = document.getElementById("game")
|
||||
|
||||
var docW = document.body.offsetWidth
|
||||
var docH = document.body.offsetHeight
|
||||
if(this.controller.multiplayer === 2){
|
||||
this.canvas = new ScalableCanvas("canvas-p2", docW, docH / 3 * 2)
|
||||
this.canvas.canvas.style.position = "absolute"
|
||||
this.canvas.canvas.style.top = "33%"
|
||||
this.gameDiv.appendChild(this.canvas.canvas)
|
||||
}else{
|
||||
this.canvas = new ScalableCanvas("canvas", docW, docH)
|
||||
this.portraitClass = false
|
||||
this.touchp2Class = false
|
||||
|
||||
this.currentScore = {
|
||||
ms: -Infinity,
|
||||
type: 0
|
||||
}
|
||||
this.winW = this.canvas.scaledWidth
|
||||
this.winH = this.canvas.scaledHeight
|
||||
if(this.controller.multiplayer === 2){
|
||||
this.winH = this.winH / 2 * 3
|
||||
this.noteFace = {
|
||||
small: 0,
|
||||
big: 3
|
||||
}
|
||||
this.ctx = this.canvas.ctx
|
||||
|
||||
this.taikoSquareW = this.winW / 4
|
||||
this.slotX = this.taikoSquareW + 100
|
||||
|
||||
this.currentScore = 0
|
||||
this.special = ""
|
||||
this.scoreDispCount = -1
|
||||
this.scoreOpacity = 1
|
||||
|
||||
this.lastMeasure = 0
|
||||
this.currentTimingPoint = 0
|
||||
//Distance to be done by the circle
|
||||
this.distanceForCircle = this.winW - this.slotX
|
||||
|
||||
this.currentCircleFace = 0
|
||||
this.currentDonFace = 0
|
||||
this.currentBigDonFace = 1
|
||||
this.nextBeat = 0
|
||||
this.gogoTime = 0
|
||||
this.gogoTimeStarted = -Infinity
|
||||
|
||||
this.drumroll = []
|
||||
|
||||
this.beatInterval = this.controller.parsedSongData.beatInfo.beatInterval
|
||||
this.font = "TnT, Meiryo, sans-serif"
|
||||
|
||||
this.draw = new CanvasDraw()
|
||||
this.assets = new ViewAssets(this)
|
||||
|
||||
this.titleCache = new CanvasCache()
|
||||
this.comboCache = new CanvasCache()
|
||||
|
||||
this.multiplayer = this.controller.multiplayer
|
||||
|
||||
this.touchEnabled = this.controller.touchEnabled
|
||||
this.touch = -Infinity
|
||||
|
||||
if(this.controller.touchEnabled){
|
||||
this.touchEnabled = true
|
||||
|
||||
this.touchDrumDiv = document.getElementById("touch-drum")
|
||||
this.touchDrumImg = document.getElementById("touch-drum-img")
|
||||
this.gameDiv.classList.add("touch-visible")
|
||||
document.getElementById("version").classList.add("version-hide")
|
||||
|
||||
pageEvents.add(this.canvas.canvas, "touchstart", this.ontouch.bind(this))
|
||||
|
||||
this.touchFullBtn = document.getElementById("touch-full-btn")
|
||||
pageEvents.add(this.touchFullBtn, "touchend", toggleFullscreen)
|
||||
if(!fullScreenSupported){
|
||||
this.touchFullBtn.style.display = "none"
|
||||
}
|
||||
|
||||
this.touchPauseBtn = document.getElementById("touch-pause-btn")
|
||||
pageEvents.add(this.touchPauseBtn, "touchend", () => {
|
||||
this.controller.togglePauseMenu()
|
||||
if(this.multiplayer !== 2){
|
||||
pageEvents.add(window, "resize", () => {
|
||||
if(this.controller.game.isPaused()){
|
||||
this.refresh()
|
||||
setTimeout(this.refresh.bind(this), 100)
|
||||
}
|
||||
})
|
||||
|
||||
if(this.controller.touchEnabled){
|
||||
this.touchDrumDiv = document.getElementById("touch-drum")
|
||||
this.touchDrumImg = document.getElementById("touch-drum-img")
|
||||
this.gameDiv.classList.add("touch-visible")
|
||||
document.getElementById("version").classList.add("version-hide")
|
||||
|
||||
pageEvents.add(this.canvas, "touchstart", this.ontouch.bind(this))
|
||||
|
||||
this.touchFullBtn = document.getElementById("touch-full-btn")
|
||||
pageEvents.add(this.touchFullBtn, "touchend", toggleFullscreen)
|
||||
if(!fullScreenSupported){
|
||||
this.touchFullBtn.style.display = "none"
|
||||
}
|
||||
|
||||
this.touchPauseBtn = document.getElementById("touch-pause-btn")
|
||||
pageEvents.add(this.touchPauseBtn, "touchend", () => {
|
||||
this.controller.togglePauseMenu()
|
||||
})
|
||||
if(this.multiplayer){
|
||||
this.touchPauseBtn.style.display = "none"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
run(){
|
||||
this.ctx.font = "normal 14pt TnT, Meiryo, sans-serif"
|
||||
this.setBackground()
|
||||
|
||||
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()
|
||||
pageEvents.mouseAdd(this, this.onmousemove.bind(this))
|
||||
|
||||
this.refresh()
|
||||
}
|
||||
refresh(){
|
||||
var ctx = this.ctx
|
||||
|
||||
var winW = innerWidth
|
||||
var winH = lastHeight
|
||||
|
||||
if(winW / 32 > winH / 9){
|
||||
winW = winH / 9 * 32
|
||||
}
|
||||
|
||||
this.portrait = winW < winH
|
||||
var touchMultiplayer = this.touchEnabled && this.multiplayer && !this.portrait
|
||||
|
||||
this.pixelRatio = window.devicePixelRatio || 1
|
||||
winW *= this.pixelRatio
|
||||
winH *= this.pixelRatio
|
||||
if(this.portrait){
|
||||
var ratioX = winW / 720
|
||||
var ratioY = winH / 1280
|
||||
}else{
|
||||
var ratioX = winW / 1280
|
||||
var ratioY = winH / 720
|
||||
}
|
||||
var ratio = (ratioX < ratioY ? ratioX : ratioY)
|
||||
|
||||
if(this.winW !== winW || this.winH !== winH){
|
||||
this.winW = winW
|
||||
this.winH = winH
|
||||
this.ratio = ratio
|
||||
|
||||
if(this.multiplayer !== 2){
|
||||
this.canvas.width = winW
|
||||
this.canvas.height = winH
|
||||
ctx.scale(ratio, ratio)
|
||||
this.canvas.style.width = (winW / this.pixelRatio) + "px"
|
||||
this.canvas.style.height = (winH / this.pixelRatio) + "px"
|
||||
|
||||
this.titleCache.resize(640, 80, ratio)
|
||||
}
|
||||
this.fillComboCache()
|
||||
}else if(this.multiplayer !== 2){
|
||||
ctx.clearRect(0, 0, winW / ratio, winH / ratio)
|
||||
}
|
||||
winW /= ratio
|
||||
winH /= ratio
|
||||
var ms = this.getMS()
|
||||
|
||||
if(this.portrait){
|
||||
var frameTop = winH / 2 - 1280 / 2
|
||||
var frameLeft = winW / 2 - 720 / 2
|
||||
}else{
|
||||
var frameTop = winH / 2 - 720 / 2
|
||||
var frameLeft = winW / 2 - 1280 / 2
|
||||
}
|
||||
if(this.multiplayer === 2){
|
||||
frameTop += this.multiplayer === 2 ? 165 : 176
|
||||
}
|
||||
if(touchMultiplayer){
|
||||
if(!this.touchp2Class){
|
||||
this.touchp2Class = true
|
||||
this.gameDiv.classList.add("touchp2")
|
||||
}
|
||||
frameTop -= 90
|
||||
}else if(this.touchp2Class){
|
||||
this.touchp2Class = false
|
||||
this.gameDiv.classList.remove("touchp2")
|
||||
}
|
||||
|
||||
ctx.save()
|
||||
ctx.translate(0, frameTop)
|
||||
|
||||
this.drawGogoTime()
|
||||
|
||||
if(!touchMultiplayer){
|
||||
this.assets.drawAssets("background")
|
||||
}
|
||||
|
||||
if(this.multiplayer !== 2){
|
||||
this.titleCache.get({
|
||||
ctx: ctx,
|
||||
x: winW - (touchMultiplayer && fullScreenSupported ? 750 : 650),
|
||||
y: touchMultiplayer ? 75 : 10,
|
||||
w: 640,
|
||||
h: 80,
|
||||
id: "title"
|
||||
}, ctx => {
|
||||
this.draw.layeredText({
|
||||
ctx: ctx,
|
||||
text: this.controller.selectedSong.title,
|
||||
fontSize: 40,
|
||||
fontFamily: this.font,
|
||||
x: 620,
|
||||
y: 20,
|
||||
width: 600,
|
||||
align: "right"
|
||||
}, [
|
||||
{outline: "#000", letterBorder: 10},
|
||||
{fill: "#fff"}
|
||||
])
|
||||
})
|
||||
}
|
||||
|
||||
var score = this.controller.getGlobalScore()
|
||||
var gaugePercent = Math.round(score.gauge / 2) / 50
|
||||
|
||||
if(this.multiplayer === 2){
|
||||
var scoreImg = "bg_score_p2"
|
||||
var scoreFill = "#6bbec0"
|
||||
}else{
|
||||
var scoreImg = "bg_score_p1"
|
||||
var scoreFill = "#fa4529"
|
||||
}
|
||||
|
||||
if(this.portrait){
|
||||
// Portrait
|
||||
|
||||
if(!this.portraitClass){
|
||||
this.portraitClass = true
|
||||
this.gameDiv.classList.add("portrait")
|
||||
}
|
||||
|
||||
this.slotPos = {
|
||||
x: 66,
|
||||
y: frameTop + 375,
|
||||
size: 100,
|
||||
paddingLeft: 0
|
||||
}
|
||||
this.scorePos = {x: 363, y: frameTop + (this.multiplayer === 2 ? 520 : 227)}
|
||||
|
||||
var animPos = {
|
||||
x1: this.slotPos.x + 13,
|
||||
y1: this.slotPos.y + (this.multiplayer === 2 ? 27 : -27),
|
||||
x2: winW - 38,
|
||||
y2: frameTop + (this.multiplayer === 2 ? 484 : 293)
|
||||
}
|
||||
var taikoPos = {
|
||||
x: 19,
|
||||
y: frameTop + (this.multiplayer === 2 ? 464 : 184),
|
||||
w: 111,
|
||||
h: 130
|
||||
}
|
||||
|
||||
ctx.fillStyle = "#000"
|
||||
ctx.fillRect(
|
||||
0,
|
||||
this.multiplayer === 2 ? 306 : 288,
|
||||
winW,
|
||||
this.multiplayer === 1 ? 184 : 183
|
||||
)
|
||||
ctx.beginPath()
|
||||
if(this.multiplayer === 2){
|
||||
ctx.moveTo(0, 467)
|
||||
ctx.lineTo(384, 467)
|
||||
ctx.lineTo(384, 512)
|
||||
ctx.lineTo(184, 560)
|
||||
ctx.lineTo(0, 560)
|
||||
}else{
|
||||
ctx.moveTo(0, 217)
|
||||
ctx.lineTo(184, 217)
|
||||
ctx.lineTo(384, 265)
|
||||
ctx.lineTo(384, 309)
|
||||
ctx.lineTo(0, 309)
|
||||
}
|
||||
ctx.fill()
|
||||
|
||||
// Left side
|
||||
ctx.fillStyle = scoreFill
|
||||
var leftSide = (ctx, mul) => {
|
||||
ctx.beginPath()
|
||||
if(this.multiplayer === 2){
|
||||
ctx.moveTo(0, 468 * mul)
|
||||
ctx.lineTo(380 * mul, 468 * mul)
|
||||
ctx.lineTo(380 * mul, 512 * mul)
|
||||
ctx.lineTo(184 * mul, 556 * mul)
|
||||
ctx.lineTo(0, 556 * mul)
|
||||
}else{
|
||||
ctx.moveTo(0, 221 * mul)
|
||||
ctx.lineTo(184 * mul, 221 * mul)
|
||||
ctx.lineTo(380 * mul, 265 * mul)
|
||||
ctx.lineTo(380 * mul, 309 * mul)
|
||||
ctx.lineTo(0, 309 * mul)
|
||||
}
|
||||
}
|
||||
leftSide(ctx, 1)
|
||||
ctx.fill()
|
||||
ctx.globalAlpha = 0.5
|
||||
this.draw.pattern({
|
||||
ctx: ctx,
|
||||
img: assets.image[scoreImg],
|
||||
shape: leftSide,
|
||||
dx: 0,
|
||||
dy: 45,
|
||||
scale: 1.55
|
||||
})
|
||||
ctx.globalAlpha = 1
|
||||
|
||||
// Score background
|
||||
ctx.fillStyle = "#000"
|
||||
ctx.beginPath()
|
||||
if(this.multiplayer === 2){
|
||||
this.draw.roundedCorner(ctx, 184, 512, 20, 0)
|
||||
ctx.lineTo(384, 512)
|
||||
this.draw.roundedCorner(ctx, 384, 560, 12, 2)
|
||||
ctx.lineTo(184, 560)
|
||||
}else{
|
||||
ctx.moveTo(184, 217)
|
||||
this.draw.roundedCorner(ctx, 384, 217, 12, 1)
|
||||
ctx.lineTo(384, 265)
|
||||
this.draw.roundedCorner(ctx, 184, 265, 20, 3)
|
||||
}
|
||||
ctx.fill()
|
||||
|
||||
// Difficulty
|
||||
var badgeImg = assets.image["muzu_" + this.controller.selectedSong.difficulty]
|
||||
var badgeW = badgeImg.width / badgeImg.height * 53
|
||||
ctx.drawImage(badgeImg,
|
||||
157 - badgeW / 2,
|
||||
this.multiplayer === 2 ? 497 : 228,
|
||||
badgeW,
|
||||
53
|
||||
)
|
||||
|
||||
// Badges
|
||||
if(this.controller.autoPlayEnabled && !this.controller.multiplayer){
|
||||
this.ctx.drawImage(assets.image["badge_auto"],
|
||||
183,
|
||||
this.multiplayer === 2 ? 490 : 265,
|
||||
23,
|
||||
23
|
||||
)
|
||||
}
|
||||
|
||||
// Gauge
|
||||
ctx.fillStyle = "#000"
|
||||
ctx.beginPath()
|
||||
var gaugeX = winW - 788 * 0.7 - 32
|
||||
if(this.multiplayer === 2){
|
||||
ctx.moveTo(gaugeX, 464)
|
||||
ctx.lineTo(winW, 464)
|
||||
ctx.lineTo(winW, 489)
|
||||
this.draw.roundedCorner(ctx, gaugeX, 489, 12, 3)
|
||||
}else{
|
||||
this.draw.roundedCorner(ctx, gaugeX, 288, 12, 0)
|
||||
ctx.lineTo(winW, 288)
|
||||
ctx.lineTo(winW, 314)
|
||||
ctx.lineTo(gaugeX, 314)
|
||||
}
|
||||
ctx.fill()
|
||||
this.draw.gauge({
|
||||
ctx: ctx,
|
||||
x: winW,
|
||||
y: this.multiplayer === 2 ? 468 : 273,
|
||||
clear: 25 / 50,
|
||||
percentage: gaugePercent,
|
||||
font: this.font,
|
||||
scale: 0.7,
|
||||
multiplayer: this.multiplayer === 2
|
||||
})
|
||||
this.draw.soul({
|
||||
ctx: ctx,
|
||||
x: winW - 40,
|
||||
y: this.multiplayer === 2 ? 484 : 293,
|
||||
scale: 0.75,
|
||||
cleared: gaugePercent - 1 / 50 >= 25 / 50
|
||||
})
|
||||
|
||||
// Note bar
|
||||
ctx.fillStyle = "#2c2a2c"
|
||||
ctx.fillRect(0, 314, winW, 122)
|
||||
ctx.fillStyle = "#847f84"
|
||||
ctx.fillRect(0, 440, winW, 24)
|
||||
|
||||
}else{
|
||||
// Landscape
|
||||
|
||||
if(this.portraitClass){
|
||||
this.portraitClass = false
|
||||
this.gameDiv.classList.remove("portrait")
|
||||
}
|
||||
|
||||
this.slotPos = {
|
||||
x: 413,
|
||||
y: frameTop + 257,
|
||||
size: 106,
|
||||
paddingLeft: 332
|
||||
}
|
||||
this.scorePos = {
|
||||
x: 155,
|
||||
y: frameTop + (this.multiplayer === 2 ? 318 : 193)
|
||||
}
|
||||
|
||||
var animPos = {
|
||||
x1: this.slotPos.x + 14,
|
||||
y1: this.slotPos.y + (this.multiplayer === 2 ? 29 : -29),
|
||||
x2: winW - 55,
|
||||
y2: frameTop + (this.multiplayer === 2 ? 378 : 165)
|
||||
}
|
||||
var taikoPos = {x: 179, y: frameTop + 190, w: 138, h: 162}
|
||||
|
||||
ctx.fillStyle = "#000"
|
||||
ctx.fillRect(
|
||||
0,
|
||||
184,
|
||||
winW,
|
||||
this.multiplayer === 1 ? 177 : 176
|
||||
)
|
||||
ctx.beginPath()
|
||||
if(this.multiplayer === 2){
|
||||
ctx.moveTo(328, 351)
|
||||
ctx.lineTo(winW, 351)
|
||||
ctx.lineTo(winW, 385)
|
||||
this.draw.roundedCorner(ctx, 328, 385, 10, 3)
|
||||
}else{
|
||||
ctx.moveTo(328, 192)
|
||||
this.draw.roundedCorner(ctx, 328, 158, 10, 0)
|
||||
ctx.lineTo(winW, 158)
|
||||
ctx.lineTo(winW, 192)
|
||||
}
|
||||
ctx.fill()
|
||||
|
||||
// Gauge
|
||||
this.draw.gauge({
|
||||
ctx: ctx,
|
||||
x: winW,
|
||||
y: this.multiplayer === 2 ? 357 : 135,
|
||||
clear: 25 / 50,
|
||||
percentage: gaugePercent,
|
||||
font: this.font,
|
||||
multiplayer: this.multiplayer === 2
|
||||
})
|
||||
this.draw.soul({
|
||||
ctx: ctx,
|
||||
x: winW - 57,
|
||||
y: this.multiplayer === 2 ? 378 : 165,
|
||||
cleared: gaugePercent - 1 / 50 >= 25 / 50
|
||||
})
|
||||
|
||||
// Note bar
|
||||
ctx.fillStyle = "#2c2a2c"
|
||||
ctx.fillRect(332, 192, winW - 332, 130)
|
||||
ctx.fillStyle = "#847f84"
|
||||
ctx.fillRect(332, 326, winW - 332, 26)
|
||||
|
||||
// Left side
|
||||
ctx.fillStyle = scoreFill
|
||||
ctx.fillRect(0, 192, 328, 160)
|
||||
ctx.globalAlpha = 0.5
|
||||
this.draw.pattern({
|
||||
ctx: ctx,
|
||||
img: assets.image[scoreImg],
|
||||
x: 0,
|
||||
y: 192,
|
||||
w: 328,
|
||||
h: 160,
|
||||
dx: 0,
|
||||
dy: 45,
|
||||
scale: 1.55
|
||||
})
|
||||
ctx.globalAlpha = 1
|
||||
|
||||
// Difficulty
|
||||
var badgeImg = assets.image["muzu_" + this.controller.selectedSong.difficulty]
|
||||
var badgeW = badgeImg.width / badgeImg.height * 120
|
||||
ctx.drawImage(badgeImg,
|
||||
87 - badgeW / 2, this.multiplayer === 2 ? 194 : 232,
|
||||
badgeW, 120
|
||||
)
|
||||
|
||||
// Badges
|
||||
if(this.controller.autoPlayEnabled && !this.controller.multiplayer){
|
||||
this.ctx.drawImage(assets.image["badge_auto"],
|
||||
125, 235, 34, 34
|
||||
)
|
||||
}
|
||||
|
||||
// Score background
|
||||
ctx.fillStyle = "#000"
|
||||
ctx.beginPath()
|
||||
if(this.multiplayer === 2){
|
||||
ctx.moveTo(0, 312)
|
||||
this.draw.roundedCorner(ctx, 176, 312, 20, 1)
|
||||
ctx.lineTo(176, 353)
|
||||
ctx.lineTo(0, 353)
|
||||
}else{
|
||||
ctx.moveTo(0, 191)
|
||||
ctx.lineTo(176, 191)
|
||||
this.draw.roundedCorner(ctx, 176, 232, 20, 2)
|
||||
ctx.lineTo(0, 232)
|
||||
}
|
||||
ctx.fill()
|
||||
}
|
||||
|
||||
ctx.restore()
|
||||
|
||||
animPos.w = animPos.x2 - animPos.x1
|
||||
animPos.h = animPos.y1 - animPos.y2
|
||||
this.animateBezier = [{
|
||||
// 427, 228
|
||||
x: animPos.x1,
|
||||
y: animPos.y1
|
||||
}, {
|
||||
// 560, 10
|
||||
x: animPos.x1 + animPos.w / 6,
|
||||
y: animPos.y1 - animPos.h * (this.multiplayer === 2 ? 2.5 : 3.5)
|
||||
}, {
|
||||
// 940, -150
|
||||
x: animPos.x2 - animPos.w / 3,
|
||||
y: animPos.y2 - animPos.h * (this.multiplayer === 2 ? 3.5 : 5)
|
||||
}, {
|
||||
// 1225, 165
|
||||
x: animPos.x2,
|
||||
y: animPos.y2
|
||||
}]
|
||||
|
||||
var touchTop = frameTop + (touchMultiplayer ? 135 : 0)
|
||||
this.touchDrum = (() => {
|
||||
var sw = 842
|
||||
var sh = 340
|
||||
var x = 0
|
||||
var y = this.portrait ? touchTop + 477 : touchTop + 365
|
||||
var paddingTop = 13
|
||||
var w = winW
|
||||
var maxH = winH - y
|
||||
var h = maxH - paddingTop
|
||||
if(w / h >= sw / sh){
|
||||
w = h / sh * sw
|
||||
x = (winW - w) / 2
|
||||
y += paddingTop
|
||||
}else{
|
||||
h = w / sw * sh
|
||||
y = y + (maxH - h)
|
||||
}
|
||||
return {
|
||||
x: x, y: y, w: w, h: h
|
||||
}
|
||||
})()
|
||||
this.touchCircle = {
|
||||
x: winW / 2,
|
||||
y: winH + this.touchDrum.h * 0.1,
|
||||
rx: this.touchDrum.w / 2 - this.touchDrum.h * 0.03,
|
||||
ry: this.touchDrum.h * 1.07
|
||||
}
|
||||
|
||||
if(this.multiplayer !== 2){
|
||||
this.mouseIdle()
|
||||
this.drawTouch()
|
||||
}
|
||||
|
||||
// Score
|
||||
ctx.save()
|
||||
ctx.font = "30px " + this.font
|
||||
ctx.fillStyle = "#fff"
|
||||
ctx.strokeStyle = "#fff"
|
||||
ctx.lineWidth = 0.3
|
||||
ctx.textAlign = "center"
|
||||
ctx.textBaseline = "top"
|
||||
var glyph = 29
|
||||
var pointsText = score.points.toString().split("")
|
||||
ctx.translate(this.scorePos.x, this.scorePos.y)
|
||||
ctx.scale(0.7, 1)
|
||||
for(var i in pointsText){
|
||||
var x = glyph * (i - pointsText.length + 1)
|
||||
ctx.strokeText(pointsText[i], x, 0)
|
||||
ctx.fillText(pointsText[i], x, 0)
|
||||
}
|
||||
ctx.restore()
|
||||
|
||||
// Bar pressed keys
|
||||
var keyTime = this.controller.getKeyTime()
|
||||
var sound = keyTime["don"] > keyTime["ka"] ? "don" : "ka"
|
||||
var padding = this.slotPos.paddingLeft
|
||||
var mul = this.slotPos.size / 106
|
||||
var barY = this.slotPos.y - 65 * mul
|
||||
var barH = 130 * mul
|
||||
|
||||
if(this.gogoTime || ms <= this.gogoTimeStarted + 100){
|
||||
var grd = ctx.createLinearGradient(0, 0, this.winW, 0)
|
||||
grd.addColorStop(0, "#512a2c")
|
||||
grd.addColorStop(0.46, "#6f2a2d")
|
||||
grd.addColorStop(0.76, "#8a4763")
|
||||
grd.addColorStop(1, "#2c2a2c")
|
||||
ctx.fillStyle = grd
|
||||
if(!this.touchEnabled){
|
||||
var alpha = Math.min(100, ms - this.gogoTimeStarted) / 100
|
||||
if(!this.gogoTime){
|
||||
alpha = 1 - alpha
|
||||
}
|
||||
ctx.globalAlpha = alpha
|
||||
}
|
||||
ctx.fillRect(padding, barY, winW - padding, barH)
|
||||
}
|
||||
if(keyTime[sound] > ms - 200){
|
||||
var gradients = {
|
||||
"don": ["#f54c25", "#232323"],
|
||||
"ka": ["#75cee9", "#232323"]
|
||||
}
|
||||
var grd = ctx.createLinearGradient(0, 0, this.winW, 0)
|
||||
grd.addColorStop(0, gradients[sound][0])
|
||||
grd.addColorStop(1, gradients[sound][1])
|
||||
ctx.fillStyle = grd
|
||||
ctx.globalAlpha = 1 - (ms - keyTime[sound]) / 200
|
||||
ctx.fillRect(padding, barY, winW - padding, barH)
|
||||
}
|
||||
ctx.globalAlpha = 1
|
||||
|
||||
// Taiko
|
||||
ctx.drawImage(assets.image["taiko"],
|
||||
0, 0, 138, 162,
|
||||
taikoPos.x, taikoPos.y, taikoPos.w, taikoPos.h
|
||||
)
|
||||
|
||||
// Taiko pressed keys
|
||||
var kbd = this.controller.getBindings()
|
||||
var keys = ["ka_l", "ka_r", "don_l", "don_r"]
|
||||
|
||||
for(var i = 0; i < keys.length; i++){
|
||||
var keyMS = ms - keyTime[kbd[keys[i]]]
|
||||
if(keyMS < 130){
|
||||
if(keyMS > 70 && !this.touchEnabled){
|
||||
ctx.globalAlpha = this.draw.easeOut(1 - (keyMS - 70) / 60)
|
||||
}
|
||||
ctx.drawImage(assets.image["taiko"],
|
||||
0, 162 * (i + 1), 138, 162,
|
||||
taikoPos.x, taikoPos.y, taikoPos.w, taikoPos.h
|
||||
)
|
||||
}
|
||||
}
|
||||
ctx.globalAlpha = 1
|
||||
|
||||
// Combo
|
||||
var scoreMS = ms - this.currentScore.ms
|
||||
|
||||
var comboCount = this.controller.getCombo()
|
||||
if(comboCount >= 10){
|
||||
var comboText = comboCount.toString().split("")
|
||||
var mul = this.portrait ? 0.8 : 1
|
||||
var comboX = taikoPos.x + taikoPos.w / 2
|
||||
var comboY = taikoPos.y + taikoPos.h * 0.09
|
||||
var comboScale = 0
|
||||
if(this.currentScore !== 0 && scoreMS < 100){
|
||||
comboScale = this.draw.fade(scoreMS / 100)
|
||||
}
|
||||
var glyphW = 51
|
||||
var glyphH = 64
|
||||
var letterSpacing = (comboText.length >= 4 ? 38 : 42) * mul
|
||||
var orange = comboCount >= 100 ? "1" : "0"
|
||||
|
||||
var w = glyphW * mul
|
||||
var h = glyphH * mul * (1 + comboScale / 8)
|
||||
|
||||
for(var i in comboText){
|
||||
var textX = comboX + letterSpacing * (i - (comboText.length - 1) / 2)
|
||||
this.comboCache.get({
|
||||
ctx: ctx,
|
||||
x: textX - w / 2,
|
||||
y: comboY + glyphH * mul - h,
|
||||
w: w,
|
||||
h: h,
|
||||
id: orange + "combo" + comboText[i]
|
||||
})
|
||||
}
|
||||
|
||||
var fontSize = 24 * mul
|
||||
var comboTextY = taikoPos.y + taikoPos.h * 0.63
|
||||
if(orange === "1"){
|
||||
var grd = ctx.createLinearGradient(
|
||||
0,
|
||||
comboTextY - fontSize * 0.6,
|
||||
0,
|
||||
comboTextY + fontSize * 0.1
|
||||
)
|
||||
grd.addColorStop(0, "#ff2000")
|
||||
grd.addColorStop(0.5, "#ffc321")
|
||||
grd.addColorStop(1, "#ffedb7")
|
||||
ctx.fillStyle = grd
|
||||
}else{
|
||||
ctx.fillStyle = "#fff"
|
||||
}
|
||||
ctx.font = fontSize + "px " + this.font
|
||||
ctx.lineWidth = 7 * mul
|
||||
ctx.textAlign = "center"
|
||||
ctx.strokeText("コンボ", comboX, comboTextY)
|
||||
ctx.fillText("コンボ", comboX, comboTextY)
|
||||
}
|
||||
|
||||
// Slot
|
||||
this.draw.slot(ctx, this.slotPos.x, this.slotPos.y, this.slotPos.size)
|
||||
|
||||
// Measures
|
||||
ctx.save()
|
||||
ctx.rect(this.slotPos.paddingLeft, 0, winW - this.slotPos.paddingLeft, winH)
|
||||
ctx.clip()
|
||||
this.drawMeasures()
|
||||
ctx.restore()
|
||||
|
||||
// Go go time fire
|
||||
this.assets.drawAssets("bar")
|
||||
|
||||
// Hit notes shadow
|
||||
if(scoreMS < 300 && this.currentScore.type){
|
||||
var fadeOut = scoreMS > 120 && !this.touchEnabled
|
||||
if(fadeOut){
|
||||
ctx.globalAlpha = 1 - (scoreMS - 120) / 180
|
||||
}
|
||||
var scoreId = this.currentScore.type === 230 ? 0 : 1
|
||||
if(this.currentScore.bigNote){
|
||||
scoreId += 2
|
||||
}
|
||||
ctx.drawImage(assets.image["notes_hit"],
|
||||
0, 128 * scoreId, 128, 128,
|
||||
this.slotPos.x - 64, this.slotPos.y - 64,
|
||||
128, 128
|
||||
)
|
||||
if(fadeOut){
|
||||
ctx.globalAlpha = 1
|
||||
}
|
||||
}
|
||||
|
||||
// Future notes
|
||||
this.updateNoteFaces()
|
||||
ctx.save()
|
||||
ctx.rect(this.slotPos.paddingLeft, 0, winW - this.slotPos.paddingLeft, winH)
|
||||
ctx.clip()
|
||||
|
||||
this.drawCircles(this.controller.getCircles())
|
||||
ctx.restore()
|
||||
|
||||
// Hit notes explosion
|
||||
|
||||
|
||||
// Good, OK, Bad
|
||||
if(scoreMS < 300){
|
||||
var mul = this.slotPos.size / 106
|
||||
var scores = {
|
||||
"0": "bad",
|
||||
"230": "ok",
|
||||
"450": "good"
|
||||
}
|
||||
var yOffset = scoreMS < 70 ? scoreMS * (13 / 70) : 0
|
||||
var fadeOut = scoreMS > 250 && !this.touchEnabled
|
||||
if(fadeOut){
|
||||
ctx.globalAlpha = 1 - (scoreMS - 250) / 50
|
||||
}
|
||||
this.draw.score({
|
||||
ctx: ctx,
|
||||
score: scores[this.currentScore.type],
|
||||
x: this.slotPos.x,
|
||||
y: this.slotPos.y - 98 * mul - yOffset,
|
||||
scale: 1.35 * mul,
|
||||
align: "center"
|
||||
})
|
||||
if(fadeOut){
|
||||
ctx.globalAlpha = 1
|
||||
}
|
||||
}
|
||||
|
||||
// Animating notes
|
||||
this.drawAnimatedCircles(this.controller.getCircles())
|
||||
this.drawAnimatedCircles(this.drumroll)
|
||||
|
||||
// Go-go time fireworks
|
||||
if(!this.touchEnabled && !this.portrait && !this.multiplayer){
|
||||
this.assets.drawAssets("foreground")
|
||||
}
|
||||
}
|
||||
setBackground(){
|
||||
var gameDiv = document.getElementById("game")
|
||||
var selectedSong = this.controller.selectedSong
|
||||
var bg = "/songs/" + selectedSong.folder + "/bg.png"
|
||||
if(selectedSong.defaultBg){
|
||||
var categories = {
|
||||
"J-POP": 0,
|
||||
@ -106,399 +761,69 @@ class View{
|
||||
if(selectedSong.category in categories){
|
||||
catId = categories[selectedSong.category]
|
||||
}
|
||||
this.bg = assets.image["bg_genre_" + catId].src
|
||||
bg = assets.image["bg_genre_" + catId].src
|
||||
gameDiv.classList.add("default-bg")
|
||||
}
|
||||
gameDiv.style.backgroundImage = "url('" + this.bg + "')"
|
||||
gameDiv.style.backgroundImage = "url('" + bg + "')"
|
||||
}
|
||||
positionning(){
|
||||
var docW = document.body.offsetWidth
|
||||
var docH = document.body.offsetHeight
|
||||
this.canvas.rescale()
|
||||
if(this.controller.multiplayer === 2){
|
||||
docH = docH / 3 * 2
|
||||
}
|
||||
this.canvas.resize(docW, docH)
|
||||
this.winW = this.canvas.scaledWidth
|
||||
this.winH = this.canvas.scaledHeight
|
||||
if(this.controller.multiplayer === 2){
|
||||
this.winH = this.winH / 2 * 3
|
||||
}
|
||||
this.barY = 0.25 * this.winH
|
||||
this.barH = 0.23 * this.winH
|
||||
this.lyricsBarH = 0.2 * this.barH
|
||||
this.taikoSquareW = this.winW / 4
|
||||
this.taikoH = this.barH
|
||||
this.taikoW = this.taikoH / 1.2
|
||||
this.taikoX = this.taikoSquareW * 0.76 - this.taikoW / 2
|
||||
this.taikoY = this.barY + 5
|
||||
this.slotX = this.taikoSquareW + this.barH * 0.5
|
||||
this.scoreSquareW = this.taikoSquareW * 0.55
|
||||
this.scoreSquareH = this.barH * 0.25
|
||||
this.circleSize = this.barH * 0.18
|
||||
this.bigCircleSize = this.circleSize * (5 / 3)
|
||||
this.circleY = this.barY + (this.barH - this.lyricsBarH) / 2
|
||||
this.lyricsSize = this.lyricsBarH * 0.6
|
||||
var HPBarRatio = 703 / 51
|
||||
this.HPBarW = this.taikoSquareW * 2.475
|
||||
this.HPBarH = this.barH * 0.35
|
||||
if(this.HPBarW/this.HPBarH > HPBarRatio){
|
||||
this.HPBarW = this.HPBarH * HPBarRatio
|
||||
}else{
|
||||
this.HPBarH = this.HPBarW / HPBarRatio
|
||||
}
|
||||
this.HPBarX = this.winW - this.HPBarW
|
||||
this.HPBarY = this.barY - this.HPBarH
|
||||
this.HPbarColX = this.HPBarX + this.HPBarW * 0.008
|
||||
this.HPbarColY = this.HPBarY + this.HPBarH * 0.14
|
||||
this.HPBarColMaxW = this.HPBarW * 0.925
|
||||
this.HPBarColH = this.HPBarH * 0.8
|
||||
var diffRatio = 176 / 120
|
||||
this.diffH = this.winH * 0.16
|
||||
this.diffW = this.diffH * diffRatio
|
||||
this.diffX = this.taikoX * 0.10
|
||||
this.diffY = this.taikoY * 1.05 + this.taikoH * 0.19
|
||||
this.touchDrum = (() => {
|
||||
var sw = 842
|
||||
var sh = 340
|
||||
var x = 0
|
||||
var y = this.barY + this.barH + 5
|
||||
var paddingTop = this.barH * 0.1
|
||||
var w = this.winW
|
||||
var maxH = this.winH - (this.barY + this.barH + 5)
|
||||
var h = maxH - paddingTop
|
||||
if(w / h >= sw / sh){
|
||||
w = h / sh * sw
|
||||
x = (this.winW - w) / 2
|
||||
y += paddingTop
|
||||
}else{
|
||||
h = w / sw * sh
|
||||
y = y + (maxH - h)
|
||||
}
|
||||
return {
|
||||
x: x, y: y, w: w, h: h
|
||||
}
|
||||
})()
|
||||
this.touchCircle = (() => {
|
||||
return {
|
||||
x: this.winW / 2,
|
||||
y: this.winH + this.touchDrum.h * 0.1,
|
||||
rx: this.touchDrum.w / 2 - this.touchDrum.h * 0.03,
|
||||
ry: this.touchDrum.h * 1.07
|
||||
}
|
||||
})()
|
||||
}
|
||||
refresh(){
|
||||
this.positionning()
|
||||
this.distanceForCircle = this.winW - this.slotX
|
||||
|
||||
drawMeasures(){
|
||||
var measures = this.controller.parsedSongData.measures
|
||||
var ms = this.getMS()
|
||||
var mul = this.slotPos.size / 106
|
||||
var distanceForCircle = this.winW / this.ratio - this.slotPos.x
|
||||
var measureY = this.slotPos.y - 65 * mul
|
||||
var measureH = 130 * mul
|
||||
|
||||
this.ctx.clearRect(0, 0, this.canvas.scaledWidth, this.canvas.scaledHeight)
|
||||
|
||||
// Draw
|
||||
this.assets.drawAssets("background")
|
||||
this.drawBar()
|
||||
this.drawSlot()
|
||||
this.drawHPBar()
|
||||
this.assets.drawAssets("bar")
|
||||
this.drawMeasures()
|
||||
this.drawScore()
|
||||
this.drawCircles(this.controller.getCircles())
|
||||
this.drawCircles(this.drumroll)
|
||||
this.drawTaikoSquare()
|
||||
this.drawDifficulty()
|
||||
this.drawPressedKeys()
|
||||
this.drawCombo()
|
||||
this.drawGlobalScore()
|
||||
this.updateDonFaces()
|
||||
this.drawGogoTime()
|
||||
this.mouseIdle()
|
||||
if(!this.touchEnabled){
|
||||
this.assets.drawAssets("foreground")
|
||||
}
|
||||
this.drawTouch()
|
||||
//this.drawTime()
|
||||
measures.forEach(measure => {
|
||||
var timeForDistance = this.posToMs(distanceForCircle, measure.speed)
|
||||
if(ms >= measure.ms - timeForDistance && ms <= measure.ms + 350){
|
||||
var measureX = this.slotPos.x + this.msToPos(measure.ms - ms, measure.speed)
|
||||
this.ctx.strokeStyle = "#bdbdbd"
|
||||
this.ctx.lineWidth = 3
|
||||
this.ctx.beginPath()
|
||||
this.ctx.moveTo(measureX, measureY)
|
||||
this.ctx.lineTo(measureX, measureY + measureH)
|
||||
this.ctx.stroke()
|
||||
}
|
||||
})
|
||||
}
|
||||
updateDonFaces(){
|
||||
var ms = this.controller.getElapsedTime()
|
||||
updateNoteFaces(){
|
||||
var ms = this.getMS()
|
||||
while(ms >= this.nextBeat){
|
||||
this.nextBeat += this.beatInterval
|
||||
if(this.controller.getCombo() >= 50){
|
||||
var face = Math.floor(ms / this.beatInterval) % 2
|
||||
this.currentBigDonFace = face
|
||||
this.currentDonFace = face
|
||||
}else{
|
||||
this.currentBigDonFace = 1
|
||||
this.currentDonFace = 0
|
||||
}
|
||||
}
|
||||
}
|
||||
drawHPBar(){
|
||||
var z = this.canvas.scale
|
||||
|
||||
var bottomSquareX = this.taikoSquareW
|
||||
var borderSize = this.HPBarH * 0.2
|
||||
this.ctx.fillStyle = "#000"
|
||||
this.ctx.beginPath()
|
||||
// Right hand black square
|
||||
this.ctx.fillRect(
|
||||
this.HPBarX + this.HPBarW - this.HPBarY * 0.2,
|
||||
this.HPBarY,
|
||||
this.HPBarW * 0.2,
|
||||
this.HPBarH
|
||||
)
|
||||
this.ctx.fillRect(
|
||||
bottomSquareX + borderSize,
|
||||
this.HPBarY + 0.435 * this.HPBarH,
|
||||
this.winW - bottomSquareX - borderSize,
|
||||
this.HPBarH / 2 + 2 * z
|
||||
)
|
||||
this.ctx.fillRect(
|
||||
bottomSquareX,
|
||||
this.HPBarY + 0.68 * this.HPBarH,
|
||||
this.HPBarW * 0.8,
|
||||
this.HPBarH / 4 + 2 * z
|
||||
)
|
||||
this.ctx.arc(
|
||||
bottomSquareX+borderSize,
|
||||
this.HPBarY+ 0.435 * this.HPBarH + borderSize,
|
||||
borderSize,
|
||||
0,
|
||||
Math.PI * 2
|
||||
)
|
||||
this.ctx.fill()
|
||||
this.ctx.closePath()
|
||||
|
||||
this.ctx.fillOpacity = 0.5
|
||||
this.ctx.drawImage(assets.image["hp-bar-bg"],
|
||||
this.HPBarX, this.HPBarY,
|
||||
this.HPBarW, this.HPBarH
|
||||
)
|
||||
this.ctx.fillOpacity = 1
|
||||
var hpBar = this.getHP()
|
||||
this.ctx.drawImage(assets.image["hp-bar-colour"],
|
||||
0, 0,
|
||||
Math.max(1, hpBar.imgW), 40,
|
||||
this.HPbarColX, this.HPbarColY,
|
||||
hpBar.canvasW, this.HPBarColH
|
||||
)
|
||||
}
|
||||
getHP(){
|
||||
var circles = this.controller.getCircles()
|
||||
var currentCircle = this.controller.getCurrentCircle()
|
||||
var gauge = this.controller.getGlobalScore().gauge
|
||||
var width = Math.floor(gauge * 650 / 1000) * 10
|
||||
return {
|
||||
imgW: width,
|
||||
canvasW: width / 650 * this.HPBarColMaxW
|
||||
}
|
||||
}
|
||||
drawMeasures(){
|
||||
var measures = this.controller.parsedSongData.measures
|
||||
var currentTime = this.controller.getElapsedTime()
|
||||
|
||||
measures.forEach((measure, index)=>{
|
||||
var timeForDistance = this.posToMs(this.distanceForCircle, measure.speed)
|
||||
if(currentTime >= measure.ms - timeForDistance && currentTime <= measure.ms + 350){
|
||||
this.drawMeasure(measure)
|
||||
}
|
||||
})
|
||||
}
|
||||
drawMeasure(measure){
|
||||
var z = this.canvas.scale
|
||||
var currentTime = this.controller.getElapsedTime()
|
||||
var measureX = this.slotX + this.msToPos(measure.ms - currentTime, measure.speed)
|
||||
this.ctx.strokeStyle = "#bab8b8"
|
||||
this.ctx.lineWidth = 2
|
||||
this.ctx.beginPath()
|
||||
this.ctx.moveTo(measureX, this.barY + 5 * z)
|
||||
this.ctx.lineTo(measureX, this.barY + this.barH - this.lyricsBarH - 5 * z)
|
||||
this.ctx.closePath()
|
||||
this.ctx.stroke()
|
||||
}
|
||||
drawCombo(){
|
||||
var comboCount = this.controller.getCombo()
|
||||
if(comboCount >= 10){
|
||||
var comboX = this.taikoX + this.taikoW / 2
|
||||
var comboY = this.barY + this.barH / 2
|
||||
var fontSize = this.taikoH * 0.4
|
||||
this.ctx.font = "normal " + fontSize + "px TnT, Meiryo, sans-serif"
|
||||
this.ctx.textAlign = "center"
|
||||
this.ctx.strokeStyle = "#000"
|
||||
this.ctx.lineWidth = fontSize / 10
|
||||
var glyph = this.ctx.measureText("0").width
|
||||
var comboText = comboCount.toString().split("")
|
||||
for(var i in comboText){
|
||||
var textX = comboX + glyph * (i - (comboText.length - 1) / 2)
|
||||
if(comboCount >= 100){
|
||||
var grd = this.ctx.createLinearGradient(
|
||||
textX - glyph * 0.2,
|
||||
comboY - fontSize * 0.8,
|
||||
textX + glyph * 0.2,
|
||||
comboY - fontSize * 0.2
|
||||
)
|
||||
grd.addColorStop(0, "#f00")
|
||||
grd.addColorStop(1, "#fe0")
|
||||
this.ctx.fillStyle = grd
|
||||
}else{
|
||||
this.ctx.fillStyle = "#fff"
|
||||
this.noteFace = {
|
||||
small: face,
|
||||
big: face + 2
|
||||
}
|
||||
this.strokeFillText(comboText[i],
|
||||
textX,
|
||||
comboY
|
||||
)
|
||||
}
|
||||
|
||||
var fontSize = this.taikoH * 0.12
|
||||
if(comboCount >= 100){
|
||||
var grd = this.ctx.createLinearGradient(0, comboY + fontSize * 0.5, 0, comboY + fontSize * 1.5)
|
||||
grd.addColorStop(0, "#f00")
|
||||
grd.addColorStop(1, "#fe0")
|
||||
this.ctx.fillStyle = grd
|
||||
}else{
|
||||
this.ctx.fillStyle = "#fff"
|
||||
this.noteFace = {
|
||||
small: 0,
|
||||
big: 3
|
||||
}
|
||||
}
|
||||
this.ctx.font = "normal " + fontSize + "px TnT, Meiryo, sans-serif"
|
||||
this.ctx.lineWidth = fontSize / 5
|
||||
this.strokeFillText("コンボ",
|
||||
comboX,
|
||||
comboY + fontSize * 1.5
|
||||
)
|
||||
|
||||
this.scoreDispCount++
|
||||
}
|
||||
}
|
||||
strokeFillText(text, x, y){
|
||||
this.ctx.strokeText(text, x, y)
|
||||
this.ctx.fillText(text, x, y)
|
||||
}
|
||||
drawGlobalScore(){
|
||||
// Draw score square
|
||||
this.ctx.fillStyle="#000"
|
||||
this.ctx.beginPath()
|
||||
this.ctx.fillRect(0, this.barY, this.scoreSquareW, this.scoreSquareH - 10)
|
||||
this.ctx.fillRect(0, this.barY, this.scoreSquareW - 10, this.scoreSquareH)
|
||||
this.ctx.arc(
|
||||
this.scoreSquareW - 10,
|
||||
this.barY + this.scoreSquareH - 10,
|
||||
10,
|
||||
0,
|
||||
Math.PI * 2
|
||||
)
|
||||
this.ctx.fill()
|
||||
this.ctx.closePath()
|
||||
|
||||
var fontSize = 0.7 * this.scoreSquareH
|
||||
// Draw score text
|
||||
this.ctx.font = "normal " + fontSize + "px TnT, Meiryo, sans-serif"
|
||||
this.ctx.fillStyle = "#fff"
|
||||
this.ctx.textAlign = "center"
|
||||
var glyph = this.ctx.measureText("0").width
|
||||
var pointsText = this.controller.getGlobalScore().points.toString().split("")
|
||||
for(var i in pointsText){
|
||||
this.ctx.fillText(pointsText[i],
|
||||
this.scoreSquareW - 30 + glyph * (i - pointsText.length + 1),
|
||||
this.barY + this.scoreSquareH * 0.7
|
||||
)
|
||||
}
|
||||
}
|
||||
drawPressedKeys(){
|
||||
var ms = this.controller.getElapsedTime()
|
||||
var keyTime = this.controller.getKeyTime()
|
||||
var kbd = this.controller.getBindings()
|
||||
|
||||
if(keyTime[kbd["ka_l"]] > ms - 150){
|
||||
var elemW = 0.45 * this.taikoW
|
||||
this.ctx.globalAlpha = Math.min(1, 4 - (ms - keyTime[kbd["ka_l"]]) / 37.5)
|
||||
this.ctx.drawImage(assets.image["taiko-key-blue"],
|
||||
0, 0, 68, 124,
|
||||
this.taikoX + this.taikoW * 0.05,
|
||||
this.taikoY + this.taikoH * 0.03,
|
||||
elemW,
|
||||
124 / 68 * elemW
|
||||
)
|
||||
}
|
||||
if(keyTime[kbd["don_l"]] > ms - 150){
|
||||
var elemW = 0.35 * this.taikoW
|
||||
this.ctx.globalAlpha = Math.min(1, 4 - (ms - keyTime[kbd["don_l"]]) / 37.5)
|
||||
this.ctx.drawImage(assets.image["taiko-key-red"],
|
||||
0, 0, 53, 100,
|
||||
this.taikoX + this.taikoW * 0.15,
|
||||
this.taikoY + this.taikoH * 0.09,
|
||||
elemW,
|
||||
100 / 53 * elemW
|
||||
)
|
||||
}
|
||||
if(keyTime[kbd["don_r"]] > ms - 150){
|
||||
var elemW = 0.35 * this.taikoW
|
||||
this.ctx.globalAlpha = Math.min(1, 4 - (ms - keyTime[kbd["don_r"]]) / 37.5)
|
||||
this.ctx.drawImage(assets.image["taiko-key-red"],
|
||||
53, 0, 53, 100,
|
||||
this.taikoX + this.taikoW * 0.15 + elemW,
|
||||
this.taikoY + this.taikoH * 0.09,
|
||||
elemW,
|
||||
100 / 53 * elemW
|
||||
)
|
||||
}
|
||||
if(keyTime[kbd["ka_r"]] > ms - 150){
|
||||
var elemW = 0.45 * this.taikoW
|
||||
this.ctx.globalAlpha = Math.min(1, 4 - (ms - keyTime[kbd["ka_r"]]) / 37.5)
|
||||
this.ctx.drawImage(assets.image["taiko-key-blue"],
|
||||
68, 0, 68, 124,
|
||||
this.taikoX + this.taikoW * 0.05 + elemW,
|
||||
this.taikoY + this.taikoH * 0.03,
|
||||
elemW,
|
||||
124 / 68 * elemW
|
||||
)
|
||||
}
|
||||
this.ctx.globalAlpha = 1
|
||||
}
|
||||
displayScore(score, notPlayed){
|
||||
this.currentScore = score
|
||||
this.special = notPlayed ? "-b" : ""
|
||||
this.scoreDispCount = 0
|
||||
this.scoreOpacity = 1
|
||||
}
|
||||
drawScore(){
|
||||
if(this.scoreDispCount >= 0 && this.scoreDispCount <= 20){
|
||||
this.ctx.globalAlpha = this.scoreOpacity
|
||||
var scoreIMG = assets.image["score-" + this.currentScore + this.special]
|
||||
this.ctx.drawImage(scoreIMG,
|
||||
this.slotX - this.barH / 2,
|
||||
this.barY + (this.barH - this.lyricsBarH) / 2 - this.barH / 2,
|
||||
this.barH,
|
||||
this.barH
|
||||
)
|
||||
this.scoreDispCount++
|
||||
if(this.scoreOpacity - 0.1 >= 0 && this.currentScore != 0){
|
||||
this.scoreOpacity -= 0.1
|
||||
}
|
||||
}else if(this.scoreDispCount === 21){
|
||||
this.scoreDispCount = -1
|
||||
}
|
||||
this.ctx.globalAlpha = 1
|
||||
}
|
||||
posToMs(pos, speed){
|
||||
return 140 / this.circleSize * pos / speed
|
||||
}
|
||||
msToPos(ms, speed){
|
||||
return speed / (140 / this.circleSize) * ms
|
||||
}
|
||||
drawCircles(circles){
|
||||
var distanceForCircle = this.winW / this.ratio - this.slotPos.x
|
||||
var ms = this.controller.getElapsedTime()
|
||||
|
||||
for(var i = circles.length; i--;){
|
||||
var circle = circles[i]
|
||||
var ms = this.controller.getElapsedTime()
|
||||
var speed = circle.getSpeed()
|
||||
|
||||
var timeForDistance = this.posToMs(this.distanceForCircle + this.bigCircleSize / 2, speed)
|
||||
var timeForDistance = this.posToMs(distanceForCircle + this.slotPos.size / 2, speed)
|
||||
var startingTime = circle.getMS() - timeForDistance
|
||||
var finishTime = circle.getEndTime() + this.posToMs(this.slotX - this.taikoSquareW + this.bigCircleSize * 3, speed)
|
||||
var finishTime = circle.getEndTime() + this.posToMs(this.slotPos.x - this.slotPos.paddingLeft + this.slotPos.size * 2, speed)
|
||||
|
||||
if(circle.getPlayed() <= 0 || circle.getScore() === 0){
|
||||
if(ms >= startingTime && ms <= finishTime && circle.getPlayed() !== -1){
|
||||
this.drawCircle(circle)
|
||||
}
|
||||
}else if(!circle.isAnimated()){
|
||||
// Start animation to HP bar
|
||||
// Start animation to gauge
|
||||
circle.animate(ms)
|
||||
}
|
||||
if(ms >= circle.ms && !circle.gogoChecked){
|
||||
@ -507,28 +832,27 @@ class View{
|
||||
}
|
||||
circle.gogoChecked = true
|
||||
}
|
||||
}
|
||||
}
|
||||
drawAnimatedCircles(circles){
|
||||
var ms = this.controller.getElapsedTime()
|
||||
|
||||
for(var i = 0; i < circles.length; i++){
|
||||
var circle = circles[i]
|
||||
|
||||
if(circle.isAnimated()){
|
||||
|
||||
var animT = circle.getAnimT()
|
||||
var animationDuration = 400
|
||||
if(ms <= animT + animationDuration){
|
||||
var curveDistance = this.HPBarX + this.HPBarW - this.slotX - this.HPBarColH / 2
|
||||
var animPoint = (ms - animT) / animationDuration
|
||||
var bezierPoint = this.calcBezierPoint(this.easeOut(animPoint), [{
|
||||
x: this.slotX + this.circleSize * 0.4,
|
||||
y: this.circleY - this.circleSize * 0.8
|
||||
}, {
|
||||
x: this.slotX + curveDistance * 0.15,
|
||||
y: this.barH * 0.5
|
||||
}, {
|
||||
x: this.slotX + curveDistance * 0.35,
|
||||
y: 0
|
||||
}, {
|
||||
x: this.slotX + curveDistance,
|
||||
y: this.HPbarColY + this.HPBarColH / 2
|
||||
}])
|
||||
if(ms < animT + 490){
|
||||
|
||||
var animPoint = (ms - animT) / 490
|
||||
var bezierPoint = this.calcBezierPoint(this.draw.easeOut(animPoint), this.animateBezier)
|
||||
this.drawCircle(circle, {x: bezierPoint.x, y: bezierPoint.y})
|
||||
}
|
||||
else{
|
||||
|
||||
}else if(ms < animT + 810){
|
||||
var pos = this.animateBezier[3]
|
||||
this.drawCircle(circle, pos, (ms - animT - 490) / 160)
|
||||
}else{
|
||||
circle.endAnimation()
|
||||
}
|
||||
}
|
||||
@ -536,6 +860,7 @@ class View{
|
||||
}
|
||||
calcBezierPoint(t, data){
|
||||
var at = 1 - t
|
||||
data = data.slice()
|
||||
|
||||
for(var i = 1; i < data.length; i++){
|
||||
for(var k = 0; k < data.length - i; k++){
|
||||
@ -547,11 +872,14 @@ class View{
|
||||
}
|
||||
return data[0]
|
||||
}
|
||||
easeOut(pos){
|
||||
return Math.sin(Math.PI / 2 * pos)
|
||||
}
|
||||
drawCircle(circle, circlePos){
|
||||
var z = this.canvas.scale
|
||||
drawCircle(circle, circlePos, fade){
|
||||
var ctx = this.ctx
|
||||
var mul = this.slotPos.size / 106
|
||||
|
||||
var bigCircleSize = 106 * mul / 2
|
||||
var circleSize = 70 * mul / 2
|
||||
var lyricsSize = 20 * mul
|
||||
|
||||
var fill, size, faceID
|
||||
var type = circle.getType()
|
||||
var ms = this.controller.getElapsedTime()
|
||||
@ -560,54 +888,57 @@ class View{
|
||||
var animated = circle.isAnimated()
|
||||
var speed = circle.getSpeed()
|
||||
var played = circle.getPlayed()
|
||||
var drumroll = 0
|
||||
var endX = 0
|
||||
|
||||
if(!circlePos){
|
||||
circlePos = {
|
||||
x: this.slotX + this.msToPos(circleMs - ms, speed),
|
||||
y: this.circleY
|
||||
x: this.slotPos.x + this.msToPos(circleMs - ms, speed),
|
||||
y: this.slotPos.y
|
||||
}
|
||||
}
|
||||
if(animated){
|
||||
var currentDonFace = 0
|
||||
var currentBigDonFace = 1
|
||||
var noteFace = {
|
||||
small: 0,
|
||||
big: 3
|
||||
}
|
||||
}else{
|
||||
var currentDonFace = this.currentDonFace
|
||||
var currentBigDonFace = this.currentBigDonFace
|
||||
var noteFace = this.noteFace
|
||||
}
|
||||
if(type === "don" || type === "daiDon" && played === 1){
|
||||
fill = "#f34728"
|
||||
size = this.circleSize
|
||||
faceID = "don-" + currentDonFace
|
||||
size = circleSize
|
||||
faceID = noteFace.small
|
||||
}else if(type === "ka" || type === "daiKa" && played === 1){
|
||||
fill = "#65bdbb"
|
||||
size = this.circleSize
|
||||
faceID = "don-" + currentDonFace
|
||||
size = circleSize
|
||||
faceID = noteFace.small
|
||||
}else if(type === "daiDon"){
|
||||
fill = "#f34728"
|
||||
size = this.bigCircleSize
|
||||
faceID = "big-don-" + currentBigDonFace
|
||||
size = bigCircleSize
|
||||
faceID = noteFace.big
|
||||
}else if(type === "daiKa"){
|
||||
fill = "#65bdbb"
|
||||
size = this.bigCircleSize
|
||||
faceID = "big-don-" + currentBigDonFace
|
||||
size = bigCircleSize
|
||||
faceID = noteFace.big
|
||||
}else if(type === "balloon"){
|
||||
if(animated){
|
||||
fill = "#f34728"
|
||||
size = this.bigCircleSize * 0.8
|
||||
faceID = "big-don-" + currentBigDonFace
|
||||
size = bigCircleSize * 0.8
|
||||
faceID = noteFace.big
|
||||
}else{
|
||||
fill = "#f87700"
|
||||
size = this.circleSize
|
||||
faceID = "don-" + currentDonFace
|
||||
size = circleSize
|
||||
faceID = noteFace.small
|
||||
var h = size * 1.8
|
||||
if(circleMs < ms && ms <= endTime){
|
||||
circlePos.x = this.slotX
|
||||
circlePos.x = this.slotPos.x
|
||||
}else if(ms > endTime){
|
||||
circlePos.x = this.slotX + this.msToPos(endTime - ms, speed)
|
||||
circlePos.x = this.slotPos.x + this.msToPos(endTime - ms, speed)
|
||||
}
|
||||
this.ctx.drawImage(assets.image["balloon"],
|
||||
circlePos.x + size - 3,
|
||||
circlePos.y - h / 2,
|
||||
ctx.drawImage(assets.image["balloon"],
|
||||
circlePos.x + size - 4,
|
||||
circlePos.y - h / 2 + 2,
|
||||
h / 61 * 115,
|
||||
h
|
||||
)
|
||||
@ -615,188 +946,165 @@ class View{
|
||||
}else if(type === "drumroll" || type === "daiDrumroll"){
|
||||
fill = "#f3b500"
|
||||
if(type == "drumroll"){
|
||||
size = this.circleSize
|
||||
faceID = "don-" + currentDonFace
|
||||
size = circleSize
|
||||
faceID = noteFace.small
|
||||
}else{
|
||||
size = this.bigCircleSize
|
||||
faceID = "big-don-" + currentBigDonFace
|
||||
size = bigCircleSize
|
||||
faceID = noteFace.big
|
||||
}
|
||||
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()
|
||||
endX = this.msToPos(endTime - circleMs, speed)
|
||||
drumroll = endX > 50 ? 2 : 1
|
||||
|
||||
ctx.fillStyle = fill
|
||||
ctx.strokeStyle = "#000"
|
||||
ctx.lineWidth = 3
|
||||
ctx.beginPath()
|
||||
ctx.moveTo(circlePos.x, circlePos.y - size + 1.5)
|
||||
ctx.arc(circlePos.x + endX, circlePos.y, size - 1.5, Math.PI / -2, Math.PI / 2)
|
||||
ctx.lineTo(circlePos.x, circlePos.y + size - 1.5)
|
||||
ctx.fill()
|
||||
ctx.stroke()
|
||||
}
|
||||
if(!fade || fade < 1){
|
||||
// Main circle
|
||||
ctx.fillStyle = fill
|
||||
ctx.beginPath()
|
||||
ctx.arc(circlePos.x, circlePos.y, size - 1, 0, Math.PI * 2)
|
||||
ctx.fill()
|
||||
// Face on circle
|
||||
var drawSize = size
|
||||
if(faceID < 2){
|
||||
drawSize *= bigCircleSize / circleSize
|
||||
}
|
||||
ctx.drawImage(assets.image[drumroll ? "notes_drumroll" : "notes"],
|
||||
0, 172 * faceID,
|
||||
172, 172,
|
||||
circlePos.x - drawSize - 4,
|
||||
circlePos.y - drawSize - 4,
|
||||
drawSize * 2 + 8,
|
||||
drawSize * 2 + 8
|
||||
)
|
||||
}
|
||||
if(fade && !this.touchEnabled){
|
||||
ctx.globalAlpha = this.draw.easeOut(fade < 1 ? fade : 2 - fade)
|
||||
ctx.fillStyle = "#fff"
|
||||
ctx.beginPath()
|
||||
ctx.arc(circlePos.x, circlePos.y, size - 1, 0, Math.PI * 2)
|
||||
ctx.fill()
|
||||
ctx.globalAlpha = 1
|
||||
}
|
||||
// Main circle
|
||||
this.ctx.fillStyle = fill
|
||||
this.ctx.beginPath()
|
||||
this.ctx.arc(circlePos.x, circlePos.y, size, 0, Math.PI * 2)
|
||||
this.ctx.closePath()
|
||||
this.ctx.fill()
|
||||
// Face on circle
|
||||
this.ctx.drawImage(assets.image[faceID],
|
||||
circlePos.x - size - 2,
|
||||
circlePos.y - size - 4,
|
||||
size * 2 + 5,
|
||||
size * 2 + 6
|
||||
)
|
||||
if(!circle.isAnimated()){
|
||||
// Text
|
||||
this.ctx.font = "normal bold " + this.lyricsSize + "px Kozuka"
|
||||
this.ctx.textAlign = "center"
|
||||
this.ctx.strokeStyle = "#000"
|
||||
this.ctx.lineWidth = this.lyricsSize / 5
|
||||
this.ctx.fillStyle = "#fff"
|
||||
this.strokeFillText(circle.getText(),
|
||||
circlePos.x,
|
||||
this.barY + this.barH - this.lyricsBarH * 0.3
|
||||
)
|
||||
}
|
||||
}
|
||||
togglePauseMenu(){
|
||||
if(this.controller.game.isPaused()){
|
||||
this.pauseMenu.style.display = "block"
|
||||
this.lastMousemove = this.controller.getElapsedTime()
|
||||
this.cursorHidden = false
|
||||
this.mouseIdle()
|
||||
}else{
|
||||
this.pauseMenu.style.display = ""
|
||||
}
|
||||
}
|
||||
drawDifficulty(){
|
||||
this.ctx.drawImage(assets.image["muzu_" + this.songDifficulty],
|
||||
this.diffX, this.diffY,
|
||||
this.diffW, this.diffH
|
||||
)
|
||||
if(this.controller.autoPlayEnabled && !this.controller.multiplayer){
|
||||
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.taikoX, this.taikoY,
|
||||
this.taikoW, this.taikoH
|
||||
)
|
||||
}
|
||||
drawTime(){
|
||||
var z = this.canvas.scale
|
||||
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.fillStyle = "#000"
|
||||
this.ctx.fillRect(this.winW - 110 * z, this.winH - 60 * z, this.winW, this.winH)
|
||||
|
||||
this.ctx.globalAlpha = 1
|
||||
this.ctx.fillStyle = "#fff"
|
||||
|
||||
var formatedH = ("0" + time.hour).slice(-2)
|
||||
var formatedM = ("0" + time.min).slice(-2)
|
||||
var formatedS = ("0" + time.sec).slice(-2)
|
||||
|
||||
this.ctx.font = "normal " + (this.barH / 12) + "px Kozuka"
|
||||
this.ctx.textAlign = "right"
|
||||
this.ctx.fillText(sign + formatedH + ":" + formatedM + ":" + formatedS,
|
||||
this.winW - 10 * z, this.winH - 30 * z
|
||||
)
|
||||
this.ctx.fillText(sign + Math.floor(ms), this.winW - 10 * z, this.winH - 10 * z)
|
||||
}
|
||||
drawBar(){
|
||||
this.ctx.strokeStyle = "#000"
|
||||
this.ctx.fillStyle = "#232323"
|
||||
this.ctx.lineWidth = 10
|
||||
this.ctx.beginPath()
|
||||
this.ctx.rect(0, this.barY, this.winW, this.barH)
|
||||
this.ctx.closePath()
|
||||
this.ctx.fill()
|
||||
|
||||
var ms = this.controller.getElapsedTime()
|
||||
var keyTime = this.controller.getKeyTime()
|
||||
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() - this.gogoTimeStarted) / 100
|
||||
if(!this.gogoTime){
|
||||
alpha = 1 - alpha
|
||||
var text = circle.getText()
|
||||
var textX = circlePos.x
|
||||
var textY = circlePos.y + 83 * mul
|
||||
ctx.font = lyricsSize + "px Kozuka"
|
||||
ctx.textBaseline = "middle"
|
||||
ctx.textAlign = "center"
|
||||
|
||||
if(drumroll === 2){
|
||||
var longText = text.split("ー")
|
||||
text = longText[0]
|
||||
var text0Width = ctx.measureText(longText[0]).width
|
||||
var text1Width = ctx.measureText(longText[1]).width
|
||||
}
|
||||
this.ctx.globalAlpha = alpha
|
||||
this.ctx.fill()
|
||||
this.ctx.globalAlpha = 1
|
||||
}
|
||||
if(keyTime[sound] > ms - 200){
|
||||
var gradients = {
|
||||
"don": ["#f54c25", "#232323"],
|
||||
"ka": ["#75cee9", "#232323"]
|
||||
|
||||
ctx.fillStyle = "#fff"
|
||||
ctx.strokeStyle = "#000"
|
||||
ctx.lineWidth = 5
|
||||
ctx.strokeText(text, textX, textY)
|
||||
|
||||
if(drumroll === 2){
|
||||
ctx.strokeText(longText[1], textX + endX, textY)
|
||||
|
||||
ctx.lineWidth = 4
|
||||
var x1 = textX + text0Width / 2
|
||||
var x2 = textX + endX - text1Width / 2
|
||||
ctx.beginPath()
|
||||
ctx.moveTo(x1, textY - 2)
|
||||
ctx.lineTo(x2, textY - 2)
|
||||
ctx.lineTo(x2, textY + 1)
|
||||
ctx.lineTo(x1, textY + 1)
|
||||
ctx.closePath()
|
||||
ctx.stroke()
|
||||
ctx.fill()
|
||||
}
|
||||
|
||||
ctx.strokeStyle = "#fff"
|
||||
ctx.lineWidth = 0.5
|
||||
|
||||
ctx.strokeText(text, textX, textY)
|
||||
ctx.fillText(text, textX, textY)
|
||||
|
||||
if(drumroll){
|
||||
ctx.strokeText(longText[1], textX + endX, textY)
|
||||
ctx.fillText(longText[1], textX + endX, textY)
|
||||
}
|
||||
var grd = this.ctx.createLinearGradient(0, this.barY, this.winW, this.barH)
|
||||
grd.addColorStop(0, gradients[sound][0])
|
||||
grd.addColorStop(1, gradients[sound][1])
|
||||
this.ctx.fillStyle = grd
|
||||
this.ctx.rect(0, this.barY, this.winW, this.barH)
|
||||
this.ctx.globalAlpha = 1 - (ms - keyTime[sound]) / 200
|
||||
this.ctx.fill()
|
||||
this.ctx.globalAlpha = 1
|
||||
}
|
||||
this.ctx.stroke()
|
||||
// Lyrics bar
|
||||
this.ctx.fillStyle = "#888888"
|
||||
this.ctx.beginPath()
|
||||
this.ctx.rect(0, this.barY + this.barH - this.lyricsBarH, this.winW, this.lyricsBarH)
|
||||
this.ctx.closePath()
|
||||
this.ctx.fill()
|
||||
this.ctx.stroke()
|
||||
}
|
||||
drawSlot(){
|
||||
// Main circle
|
||||
this.ctx.fillStyle = "#6f6f6e"
|
||||
this.ctx.beginPath()
|
||||
this.ctx.arc(this.slotX, this.circleY, this.circleSize - 0.2 * this.circleSize, 0, 2 * Math.PI)
|
||||
this.ctx.closePath()
|
||||
this.ctx.fill()
|
||||
// Big stroke circle
|
||||
this.ctx.strokeStyle = "#9e9f9f"
|
||||
this.ctx.lineWidth = 3
|
||||
this.ctx.beginPath()
|
||||
this.ctx.arc(this.slotX, this.circleY, this.circleSize, 0, 2 * Math.PI)
|
||||
this.ctx.closePath()
|
||||
this.ctx.stroke()
|
||||
// Bigger stroke circle
|
||||
this.ctx.strokeStyle = "#6f6f6e"
|
||||
this.ctx.lineWidth = 3
|
||||
this.ctx.beginPath()
|
||||
this.ctx.arc(this.slotX, this.circleY, this.bigCircleSize, 0, 2 * Math.PI)
|
||||
this.ctx.closePath()
|
||||
this.ctx.stroke()
|
||||
}
|
||||
drawTaikoSquare(){
|
||||
// Taiko square
|
||||
this.ctx.lineWidth = 7
|
||||
this.ctx.fillStyle = "#ff3c00"
|
||||
this.ctx.strokeStyle = "#000"
|
||||
this.ctx.beginPath()
|
||||
this.ctx.rect(0,this.barY, this.taikoSquareW,this.barH)
|
||||
this.ctx.fill()
|
||||
this.ctx.closePath()
|
||||
this.ctx.stroke()
|
||||
fillComboCache(){
|
||||
var fontSize = 58
|
||||
var letterSpacing = fontSize * 0.67
|
||||
var glyphW = 50
|
||||
var glyphH = 64
|
||||
var textX = 11
|
||||
var textY = 5
|
||||
var letterBorder = fontSize * 0.15
|
||||
|
||||
this.comboCache.resize((glyphW + 1) * 20, glyphH + 1, this.ratio)
|
||||
for(var orange = 0; orange < 2; orange++){
|
||||
for(var i = 0; i < 10; i++){
|
||||
this.comboCache.set({
|
||||
w: glyphW,
|
||||
h: glyphH,
|
||||
id: orange + "combo" + i
|
||||
}, ctx => {
|
||||
ctx.scale(0.9, 1)
|
||||
if(orange){
|
||||
var grd = ctx.createLinearGradient(
|
||||
(glyphW - glyphH) / 2,
|
||||
0,
|
||||
(glyphW + glyphH) / 2,
|
||||
glyphH
|
||||
)
|
||||
grd.addColorStop(0.3, "#ff2000")
|
||||
grd.addColorStop(0.5, "#ffc321")
|
||||
grd.addColorStop(0.6, "#ffedb7")
|
||||
grd.addColorStop(0.8, "#ffffce")
|
||||
var fill = grd
|
||||
}else{
|
||||
var fill = "#fff"
|
||||
}
|
||||
this.draw.layeredText({
|
||||
ctx: ctx,
|
||||
text: i.toString(),
|
||||
fontSize: fontSize,
|
||||
fontFamily: this.font,
|
||||
x: textX,
|
||||
y: textY
|
||||
}, [
|
||||
{x: -2, y: -1, outline: "#000", letterBorder: letterBorder},
|
||||
{x: 3.5, y: 1.5},
|
||||
{x: 3, y: 1},
|
||||
{},
|
||||
{x: -2, y: -1, fill: "#fff"},
|
||||
{x: 3.5, y: 1.5, fill: fill},
|
||||
{x: 3, y: 1, fill: "rgba(0, 0, 0, 0.5)"},
|
||||
{fill: fill}
|
||||
])
|
||||
})
|
||||
}
|
||||
}
|
||||
this.globalAlpha = 0
|
||||
this.comboCache.get({
|
||||
ctx: this.ctx,
|
||||
x: 0,
|
||||
y: 0,
|
||||
w: 54,
|
||||
h: 77,
|
||||
id: "combo0"
|
||||
})
|
||||
this.globalAlpha = 1
|
||||
}
|
||||
toggleGogoTime(circle){
|
||||
this.gogoTime = circle.gogoTime
|
||||
@ -823,7 +1131,7 @@ class View{
|
||||
}
|
||||
}
|
||||
drawGogoTime(){
|
||||
var ms = this.controller.getElapsedTime()
|
||||
var ms = this.getMS()
|
||||
|
||||
if(this.gogoTime){
|
||||
var circles = this.controller.parsedSongData.circles
|
||||
@ -837,7 +1145,9 @@ class View{
|
||||
}
|
||||
}else{
|
||||
var animation = this.assets.don.getAnimation()
|
||||
if(animation === "gogo" || this.controller.getGlobalScore().gauge >= 50 && animation === "normal"){
|
||||
var gauge = this.controller.getGlobalScore().gauge
|
||||
var cleared = Math.round(gauge / 2) - 1 >= 25
|
||||
if(animation === "gogo" || cleared && animation === "normal" || !cleared && animation === "clear"){
|
||||
this.assets.don.normalAnimation()
|
||||
}
|
||||
if(ms >= this.gogoTimeStarted + 100){
|
||||
@ -864,12 +1174,38 @@ class View{
|
||||
don.setAnimationEnd(length, don.normalAnimation)
|
||||
}
|
||||
}
|
||||
displayScore(score, notPlayed, bigNote){
|
||||
if(!notPlayed){
|
||||
this.currentScore.ms = this.getMS()
|
||||
this.currentScore.type = score
|
||||
this.currentScore.bigNote = bigNote
|
||||
}
|
||||
}
|
||||
posToMs(pos, speed){
|
||||
var circleSize = 70 * this.slotPos.size / 106 / 2
|
||||
return 140 / circleSize * pos / speed
|
||||
}
|
||||
msToPos(ms, speed){
|
||||
var circleSize = 70 * this.slotPos.size / 106 / 2
|
||||
return speed / (140 / circleSize) * ms
|
||||
}
|
||||
togglePauseMenu(){
|
||||
if(this.controller.game.isPaused()){
|
||||
this.pauseMenu.style.display = "block"
|
||||
this.lastMousemove = this.controller.getElapsedTime()
|
||||
this.cursorHidden = false
|
||||
this.mouseIdle()
|
||||
}else{
|
||||
this.pauseMenu.style.display = ""
|
||||
}
|
||||
}
|
||||
drawTouch(){
|
||||
if(this.touchEnabled){
|
||||
var ms = this.controller.getElapsedTime()
|
||||
var ms = this.getMS()
|
||||
var mul = this.ratio / this.pixelRatio
|
||||
|
||||
var drumWidth = this.touchDrum.w / this.canvas.scale
|
||||
var drumHeight = this.touchDrum.h / this.canvas.scale
|
||||
var drumWidth = this.touchDrum.w * mul
|
||||
var drumHeight = this.touchDrum.h * mul
|
||||
if(drumHeight !== this.touchDrumHeight || drumWidth !== this.touchDrumWidth){
|
||||
this.touchDrumWidth = drumWidth
|
||||
this.touchDrumHeight = drumHeight
|
||||
@ -890,9 +1226,8 @@ class View{
|
||||
ontouch(event){
|
||||
for(let touch of event.changedTouches){
|
||||
event.preventDefault()
|
||||
var scale = this.canvas.scale
|
||||
var pageX = touch.pageX * scale
|
||||
var pageY = touch.pageY * scale
|
||||
var pageX = touch.pageX * this.pixelRatio
|
||||
var pageY = touch.pageY * this.pixelRatio
|
||||
|
||||
var c = this.touchCircle
|
||||
var pi = Math.PI
|
||||
@ -947,17 +1282,17 @@ class View{
|
||||
this.beatInterval = beatMS
|
||||
this.assets.changeBeatInterval(beatMS)
|
||||
}
|
||||
getMS(){
|
||||
return this.controller.getElapsedTime()
|
||||
}
|
||||
clean(){
|
||||
pageEvents.mouseRemove(this)
|
||||
if(this.controller.multiplayer === 2){
|
||||
if(this.canvas){
|
||||
this.canvas.canvas.parentNode.removeChild(this.canvas.canvas)
|
||||
}
|
||||
}else{
|
||||
this.cursor.parentNode.removeChild(this.cursor)
|
||||
this.comboCache.clean()
|
||||
|
||||
if(this.multiplayer !== 2){
|
||||
pageEvents.remove(window, "resize")
|
||||
}
|
||||
if(this.touchEnabled){
|
||||
pageEvents.remove(this.canvas.canvas, "touchstart")
|
||||
pageEvents.remove(this.canvas, "touchstart")
|
||||
pageEvents.remove(this.touchFullBtn, "touchend")
|
||||
pageEvents.remove(this.touchPauseBtn, "touchend")
|
||||
this.gameDiv.classList.remove("touch-visible")
|
||||
|
@ -9,17 +9,17 @@ class ViewAssets{
|
||||
var imgw = 360
|
||||
var imgh = 184
|
||||
var scale = 165
|
||||
var w = (this.view.barH * imgw) / scale
|
||||
var h = (this.view.barH * imgh) / scale
|
||||
var w = imgw
|
||||
var h = imgh
|
||||
return {
|
||||
sx: Math.floor(frame / 10) * imgw,
|
||||
sy: (frame % 10) * imgh,
|
||||
sy: (frame % 10) * imgh + 1,
|
||||
sw: imgw,
|
||||
sh: imgh,
|
||||
x: this.view.taikoSquareW - w + this.view.barH * 0.2,
|
||||
y: this.view.barY - h,
|
||||
sh: imgh - 1,
|
||||
x: view.portrait ? -60 : 0,
|
||||
y: view.portrait ? (view.multiplayer === 2 ? 560 : 35) : (view.multiplayer === 2 ? 360 : 2),
|
||||
w: w,
|
||||
h: h
|
||||
h: h - 1
|
||||
}
|
||||
})
|
||||
this.don.addFrames("normal", [
|
||||
@ -41,7 +41,7 @@ class ViewAssets{
|
||||
var length = this.don.getAnimationLength("gogo")
|
||||
this.don.setUpdateSpeed(4 / length)
|
||||
this.don.setAnimation("gogo")
|
||||
}else if(this.controller.getGlobalScore().gauge >= 50){
|
||||
}else if(Math.round(this.controller.getGlobalScore().gauge / 2) - 1 >= 25){
|
||||
this.don.setAnimationStart(0)
|
||||
var length = this.don.getAnimationLength("clear")
|
||||
this.don.setUpdateSpeed(2 / length)
|
||||
@ -58,31 +58,31 @@ class ViewAssets{
|
||||
this.fire = this.createAsset("bar", frame => {
|
||||
var imgw = 360
|
||||
var imgh = 370
|
||||
var scale = 175
|
||||
var ms = this.controller.getElapsedTime()
|
||||
var scale = 130
|
||||
var ms = this.view.getMS()
|
||||
var elapsed = ms - this.view.gogoTimeStarted
|
||||
|
||||
var mul = this.view.slotPos.size / 106
|
||||
var barH = 130 * mul
|
||||
|
||||
if(this.view.gogoTime){
|
||||
var grow = 3 - Math.min(200, elapsed) / 100
|
||||
this.ctx.globalAlpha = Math.min(200, elapsed) / 200
|
||||
}else{
|
||||
var grow = 1 - Math.min(100, elapsed) / 100
|
||||
}
|
||||
var w = (this.view.barH * imgw) / scale * grow
|
||||
var h = (this.view.barH * imgh) / scale * grow
|
||||
var w = (barH * imgw) / scale * grow
|
||||
var h = (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,
|
||||
x: this.view.slotPos.x - w / 2,
|
||||
y: this.view.slotPos.y - h / 2,
|
||||
w: w,
|
||||
h: h,
|
||||
callback: () => {
|
||||
this.ctx.globalCompositeOperation = "source-over"
|
||||
this.ctx.globalAlpha = 1
|
||||
}
|
||||
h: h
|
||||
}
|
||||
})
|
||||
this.fire.addFrames("normal", 7, "fire_anim")
|
||||
@ -93,15 +93,17 @@ class ViewAssets{
|
||||
var imgw = 230
|
||||
var imgh = 460
|
||||
var scale = 165
|
||||
var w = (this.view.barH * imgw) / scale
|
||||
var h = (this.view.barH * imgh) / scale
|
||||
var w = imgw
|
||||
var h = imgh
|
||||
var winW = this.view.winW / this.view.ratio
|
||||
var winH = this.view.winH / this.view.ratio
|
||||
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,
|
||||
x: winW / 4 * i - w / 2 * (i / 2),
|
||||
y: winH - h,
|
||||
w: w,
|
||||
h: h
|
||||
}
|
||||
@ -118,13 +120,11 @@ class ViewAssets{
|
||||
return asset
|
||||
}
|
||||
drawAssets(layer){
|
||||
if(this.controller.multiplayer !== 2 || layer === "bar"){
|
||||
this.allAssets.forEach(asset => {
|
||||
if(layer === asset.layer){
|
||||
asset.draw()
|
||||
}
|
||||
})
|
||||
}
|
||||
this.allAssets.forEach(asset => {
|
||||
if(layer === asset.layer){
|
||||
asset.draw()
|
||||
}
|
||||
})
|
||||
}
|
||||
changeBeatInterval(beatMS, initial){
|
||||
this.allAssets.forEach(asset => {
|
||||
|
@ -1,5 +1,4 @@
|
||||
<div id="game">
|
||||
<h3 alt="" class="stroke-sub game-song"></h3>
|
||||
<div id="touch-drum">
|
||||
<img id="touch-drum-img" src="/assets/img/touch_drum.png">
|
||||
</div>
|
||||
|
@ -39,8 +39,6 @@
|
||||
<script src="/src/js/mekadon.js?{{version.commit_short}}"></script>
|
||||
<script src="/src/js/gamepad.js?{{version.commit_short}}"></script>
|
||||
<script src="/src/js/tutorial.js?{{version.commit_short}}"></script>
|
||||
<script src="/src/js/scalablecanvas.js?{{version.commit_short}}"></script>
|
||||
<script src="/src/js/element.js?{{version.commit_short}}"></script>
|
||||
<script src="/src/js/soundbuffer.js?{{version.commit_short}}"></script>
|
||||
<script src="/src/js/p2.js?{{version.commit_short}}"></script>
|
||||
<script src="/src/js/canvasasset.js?{{version.commit_short}}"></script>
|
||||
|
Loading…
Reference in New Issue
Block a user