2018-10-25 22:18:41 +08:00
|
|
|
|
class View{
|
|
|
|
|
constructor(controller){
|
2018-09-06 00:46:26 +08:00
|
|
|
|
this.controller = controller
|
2018-10-25 22:18:41 +08:00
|
|
|
|
|
|
|
|
|
this.canvas = document.getElementById("canvas")
|
|
|
|
|
this.ctx = this.canvas.getContext("2d")
|
2019-11-28 14:04:40 +08:00
|
|
|
|
var resolution = settings.getItem("resolution")
|
|
|
|
|
var noSmoothing = resolution === "low" || resolution === "lowest"
|
|
|
|
|
if(noSmoothing){
|
|
|
|
|
this.ctx.imageSmoothingEnabled = false
|
|
|
|
|
}
|
|
|
|
|
if(resolution === "lowest"){
|
|
|
|
|
this.canvas.style.imageRendering = "pixelated"
|
|
|
|
|
}
|
2018-09-06 00:46:26 +08:00
|
|
|
|
|
2018-10-06 01:03:59 +08:00
|
|
|
|
this.gameDiv = document.getElementById("game")
|
2019-01-01 09:16:55 +08:00
|
|
|
|
this.songBg = document.getElementById("songbg")
|
|
|
|
|
this.songStage = document.getElementById("song-stage")
|
2018-09-18 06:37:59 +08:00
|
|
|
|
|
2020-03-05 23:58:49 +08:00
|
|
|
|
this.rules = this.controller.game.rules
|
2018-10-25 22:18:41 +08:00
|
|
|
|
this.portraitClass = false
|
|
|
|
|
this.touchp2Class = false
|
2018-12-03 00:36:04 +08:00
|
|
|
|
this.darkDonBg = false
|
2018-10-25 22:18:41 +08:00
|
|
|
|
|
2019-01-05 15:44:28 +08:00
|
|
|
|
this.pauseOptions = strings.pauseOptions
|
2019-01-22 03:08:02 +08:00
|
|
|
|
this.difficulty = {
|
|
|
|
|
"easy": 0,
|
|
|
|
|
"normal": 1,
|
|
|
|
|
"hard": 2,
|
|
|
|
|
"oni": 3,
|
|
|
|
|
"ura": 4
|
|
|
|
|
}
|
2018-11-12 18:32:02 +08:00
|
|
|
|
|
2018-10-25 22:18:41 +08:00
|
|
|
|
this.currentScore = {
|
|
|
|
|
ms: -Infinity,
|
|
|
|
|
type: 0
|
2018-09-13 01:10:00 +08:00
|
|
|
|
}
|
2018-10-25 22:18:41 +08:00
|
|
|
|
this.noteFace = {
|
|
|
|
|
small: 0,
|
|
|
|
|
big: 3
|
2018-09-14 06:55:23 +08:00
|
|
|
|
}
|
2018-11-12 18:32:02 +08:00
|
|
|
|
this.state = {
|
|
|
|
|
pausePos: 0,
|
|
|
|
|
moveMS: 0,
|
|
|
|
|
moveHover: null,
|
|
|
|
|
hasPointer: false
|
|
|
|
|
}
|
2018-09-06 00:46:26 +08:00
|
|
|
|
this.nextBeat = 0
|
2018-09-20 07:20:26 +08:00
|
|
|
|
this.gogoTime = 0
|
2019-11-28 14:04:40 +08:00
|
|
|
|
this.gogoTimeStarted = -Infinity
|
2018-09-15 22:34:53 +08:00
|
|
|
|
this.drumroll = []
|
2019-02-15 06:10:34 +08:00
|
|
|
|
this.touchEvents = 0
|
2019-02-18 00:26:46 +08:00
|
|
|
|
if(this.controller.parsedSongData.branches){
|
|
|
|
|
this.branch = "normal"
|
|
|
|
|
this.branchAnimate = {
|
|
|
|
|
ms: -Infinity,
|
|
|
|
|
fromBranch: "normal"
|
|
|
|
|
}
|
|
|
|
|
this.branchMap = {
|
2019-02-21 04:48:21 +08:00
|
|
|
|
"normal": {
|
|
|
|
|
"bg": "rgba(0, 0, 0, 0)",
|
|
|
|
|
"text": "#d3d3d3",
|
|
|
|
|
"stroke": "#393939",
|
|
|
|
|
"shadow": "#000"
|
|
|
|
|
},
|
|
|
|
|
"advanced": {
|
|
|
|
|
"bg": "rgba(29, 129, 189, 0.4)",
|
|
|
|
|
"text": "#94d7e7",
|
|
|
|
|
"stroke": "#315973",
|
|
|
|
|
"shadow": "#082031"
|
|
|
|
|
},
|
|
|
|
|
"master": {
|
|
|
|
|
"bg": "rgba(230, 29, 189, 0.4)",
|
|
|
|
|
"text": "#f796ef",
|
|
|
|
|
"stroke": "#7e2e6e",
|
|
|
|
|
"shadow": "#3e0836"
|
|
|
|
|
}
|
2019-02-18 00:26:46 +08:00
|
|
|
|
}
|
|
|
|
|
}
|
2018-09-15 22:34:53 +08:00
|
|
|
|
|
2019-11-28 14:04:40 +08:00
|
|
|
|
if(this.controller.calibrationMode){
|
|
|
|
|
this.beatInterval = 512
|
|
|
|
|
}else{
|
|
|
|
|
this.beatInterval = this.controller.parsedSongData.beatInfo.beatInterval
|
|
|
|
|
}
|
2019-01-21 23:47:22 +08:00
|
|
|
|
this.font = strings.font
|
2018-10-25 22:18:41 +08:00
|
|
|
|
|
2019-11-28 14:04:40 +08:00
|
|
|
|
this.draw = new CanvasDraw(noSmoothing)
|
2018-09-20 07:20:26 +08:00
|
|
|
|
this.assets = new ViewAssets(this)
|
2018-10-06 01:03:59 +08:00
|
|
|
|
|
2019-11-28 14:04:40 +08:00
|
|
|
|
this.titleCache = new CanvasCache(noSmoothing)
|
|
|
|
|
this.comboCache = new CanvasCache(noSmoothing)
|
|
|
|
|
this.pauseCache = new CanvasCache(noSmoothing)
|
|
|
|
|
this.branchCache = new CanvasCache(noSmoothing)
|
2020-03-13 10:34:54 +08:00
|
|
|
|
this.nameplateCache = new CanvasCache(noSmoothing)
|
2018-10-25 22:18:41 +08:00
|
|
|
|
|
|
|
|
|
this.multiplayer = this.controller.multiplayer
|
2020-03-14 12:50:04 +08:00
|
|
|
|
if(this.multiplayer === 2){
|
|
|
|
|
this.player = p2.player === 2 ? 1 : 2
|
|
|
|
|
}else{
|
|
|
|
|
this.player = this.controller.multiplayer ? p2.player : 1
|
|
|
|
|
}
|
2018-10-25 22:18:41 +08:00
|
|
|
|
|
|
|
|
|
this.touchEnabled = this.controller.touchEnabled
|
2018-10-06 21:24:23 +08:00
|
|
|
|
this.touch = -Infinity
|
2019-04-05 04:40:11 +08:00
|
|
|
|
this.touchAnimation = settings.getItem("touchAnimation")
|
2018-10-06 01:03:59 +08:00
|
|
|
|
|
2019-11-28 14:04:40 +08:00
|
|
|
|
versionDiv.classList.add("version-hide")
|
|
|
|
|
loader.screen.parentNode.insertBefore(versionDiv, loader.screen)
|
|
|
|
|
|
2018-10-25 22:18:41 +08:00
|
|
|
|
if(this.multiplayer !== 2){
|
2018-10-06 01:03:59 +08:00
|
|
|
|
|
2018-10-25 22:18:41 +08:00
|
|
|
|
if(this.controller.touchEnabled){
|
|
|
|
|
this.touchDrumDiv = document.getElementById("touch-drum")
|
|
|
|
|
this.touchDrumImg = document.getElementById("touch-drum-img")
|
2018-10-28 02:35:04 +08:00
|
|
|
|
|
2019-04-05 04:40:11 +08:00
|
|
|
|
this.setBgImage(this.touchDrumImg, assets.image["touch_drum"].src)
|
|
|
|
|
|
2018-10-28 02:35:04 +08:00
|
|
|
|
if(this.controller.autoPlayEnabled){
|
|
|
|
|
this.touchDrumDiv.style.display = "none"
|
|
|
|
|
}
|
2018-11-15 16:42:22 +08:00
|
|
|
|
pageEvents.add(this.canvas, "touchstart", this.ontouch.bind(this))
|
2018-10-28 02:35:04 +08:00
|
|
|
|
|
2018-10-25 22:18:41 +08:00
|
|
|
|
this.gameDiv.classList.add("touch-visible")
|
|
|
|
|
|
|
|
|
|
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", () => {
|
2018-11-12 18:32:02 +08:00
|
|
|
|
this.controller.togglePause()
|
2018-10-25 22:18:41 +08:00
|
|
|
|
})
|
|
|
|
|
if(this.multiplayer){
|
|
|
|
|
this.touchPauseBtn.style.display = "none"
|
|
|
|
|
}
|
2018-10-13 02:04:28 +08:00
|
|
|
|
}
|
2018-10-06 01:03:59 +08:00
|
|
|
|
}
|
2018-11-24 03:44:14 +08:00
|
|
|
|
if(this.multiplayer){
|
|
|
|
|
this.gameDiv.classList.add("multiplayer")
|
|
|
|
|
}else{
|
2018-11-14 02:44:04 +08:00
|
|
|
|
pageEvents.add(this.canvas, "mousedown", this.onmousedown.bind(this))
|
2018-11-12 18:32:02 +08:00
|
|
|
|
}
|
2018-09-06 00:46:26 +08:00
|
|
|
|
}
|
|
|
|
|
run(){
|
2018-11-24 03:44:14 +08:00
|
|
|
|
if(this.multiplayer !== 2){
|
|
|
|
|
this.setBackground()
|
|
|
|
|
}
|
2018-12-02 23:25:42 +08:00
|
|
|
|
this.setDonBg()
|
2018-09-18 21:59:40 +08:00
|
|
|
|
|
2019-02-21 04:48:21 +08:00
|
|
|
|
this.startTime = this.controller.game.getAccurateTime()
|
|
|
|
|
this.lastMousemove = this.startTime
|
2018-09-18 21:59:40 +08:00
|
|
|
|
pageEvents.mouseAdd(this, this.onmousemove.bind(this))
|
|
|
|
|
|
2018-09-06 00:46:26 +08:00
|
|
|
|
this.refresh()
|
|
|
|
|
}
|
2018-10-25 22:18:41 +08:00
|
|
|
|
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
|
2019-04-05 04:40:11 +08:00
|
|
|
|
var resolution = settings.getItem("resolution")
|
|
|
|
|
if(resolution === "medium"){
|
|
|
|
|
this.pixelRatio *= 0.75
|
|
|
|
|
}else if(resolution === "low"){
|
|
|
|
|
this.pixelRatio *= 0.5
|
|
|
|
|
}else if(resolution === "lowest"){
|
|
|
|
|
this.pixelRatio *= 0.25
|
|
|
|
|
}
|
2018-10-25 22:18:41 +08:00
|
|
|
|
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)
|
|
|
|
|
|
2019-02-21 04:48:21 +08:00
|
|
|
|
var resized = false
|
2018-10-25 22:18:41 +08:00
|
|
|
|
if(this.winW !== winW || this.winH !== winH){
|
|
|
|
|
this.winW = winW
|
|
|
|
|
this.winH = winH
|
|
|
|
|
this.ratio = ratio
|
|
|
|
|
|
2020-03-14 12:50:04 +08:00
|
|
|
|
if(this.player !== 2){
|
2018-10-25 22:18:41 +08:00
|
|
|
|
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"
|
2018-11-21 17:02:53 +08:00
|
|
|
|
this.titleCache.resize(640, 90, ratio)
|
2018-09-27 09:04:01 +08:00
|
|
|
|
}
|
2018-11-12 18:32:02 +08:00
|
|
|
|
if(!this.multiplayer){
|
|
|
|
|
this.pauseCache.resize(81 * this.pauseOptions.length * 2, 464, ratio)
|
|
|
|
|
}
|
2020-03-13 10:34:54 +08:00
|
|
|
|
if(this.portrait){
|
|
|
|
|
this.nameplateCache.resize(220, 54, ratio + 0.2)
|
|
|
|
|
}else{
|
|
|
|
|
this.nameplateCache.resize(274, 67, ratio + 0.2)
|
|
|
|
|
}
|
2018-10-25 22:18:41 +08:00
|
|
|
|
this.fillComboCache()
|
2018-12-02 23:25:42 +08:00
|
|
|
|
this.setDonBgHeight()
|
2020-03-30 14:50:34 +08:00
|
|
|
|
if(this.controller.lyrics){
|
|
|
|
|
this.controller.lyrics.setScale(ratio / this.pixelRatio)
|
|
|
|
|
}
|
2019-02-21 04:48:21 +08:00
|
|
|
|
resized = true
|
2018-11-12 18:32:02 +08:00
|
|
|
|
}else if(this.controller.game.paused && !document.hasFocus()){
|
|
|
|
|
return
|
2020-03-14 12:50:04 +08:00
|
|
|
|
}else if(this.player !== 2){
|
2018-10-25 22:18:41 +08:00
|
|
|
|
ctx.clearRect(0, 0, winW / ratio, winH / ratio)
|
|
|
|
|
}
|
|
|
|
|
winW /= ratio
|
|
|
|
|
winH /= ratio
|
2019-01-16 20:33:42 +08:00
|
|
|
|
if(!this.controller.game.paused){
|
|
|
|
|
this.ms = this.controller.game.getAccurateTime()
|
|
|
|
|
}
|
|
|
|
|
var ms = this.ms
|
2018-10-25 22:18:41 +08:00
|
|
|
|
|
|
|
|
|
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
|
|
|
|
|
}
|
2020-03-14 12:50:04 +08:00
|
|
|
|
if(this.player === 2){
|
|
|
|
|
frameTop += 165
|
2018-10-25 22:18:41 +08:00
|
|
|
|
}
|
|
|
|
|
if(touchMultiplayer){
|
|
|
|
|
if(!this.touchp2Class){
|
|
|
|
|
this.touchp2Class = true
|
|
|
|
|
this.gameDiv.classList.add("touchp2")
|
2018-12-02 23:25:42 +08:00
|
|
|
|
this.setDonBgHeight()
|
2018-09-27 09:04:01 +08:00
|
|
|
|
}
|
2018-10-25 22:18:41 +08:00
|
|
|
|
frameTop -= 90
|
|
|
|
|
}else if(this.touchp2Class){
|
|
|
|
|
this.touchp2Class = false
|
|
|
|
|
this.gameDiv.classList.remove("touchp2")
|
2018-12-02 23:25:42 +08:00
|
|
|
|
this.setDonBgHeight()
|
2018-09-27 09:04:01 +08:00
|
|
|
|
}
|
2018-10-25 22:18:41 +08:00
|
|
|
|
|
2020-03-30 14:50:34 +08:00
|
|
|
|
if(this.controller.lyrics){
|
|
|
|
|
this.controller.lyrics.update(ms)
|
|
|
|
|
}
|
|
|
|
|
|
2018-10-25 22:18:41 +08:00
|
|
|
|
ctx.save()
|
|
|
|
|
ctx.translate(0, frameTop)
|
|
|
|
|
|
|
|
|
|
this.drawGogoTime()
|
|
|
|
|
|
2020-03-14 12:50:04 +08:00
|
|
|
|
if(!touchMultiplayer || this.player === 1 && frameTop >= 0){
|
2018-10-25 22:18:41 +08:00
|
|
|
|
this.assets.drawAssets("background")
|
|
|
|
|
}
|
|
|
|
|
|
2020-03-14 12:50:04 +08:00
|
|
|
|
if(this.player !== 2){
|
2018-10-25 22:18:41 +08:00
|
|
|
|
this.titleCache.get({
|
|
|
|
|
ctx: ctx,
|
|
|
|
|
x: winW - (touchMultiplayer && fullScreenSupported ? 750 : 650),
|
|
|
|
|
y: touchMultiplayer ? 75 : 10,
|
|
|
|
|
w: 640,
|
2018-11-21 17:02:53 +08:00
|
|
|
|
h: 90,
|
2018-10-25 22:18:41 +08:00
|
|
|
|
id: "title"
|
|
|
|
|
}, ctx => {
|
2018-11-21 17:02:53 +08:00
|
|
|
|
var selectedSong = this.controller.selectedSong
|
|
|
|
|
|
2018-10-25 22:18:41 +08:00
|
|
|
|
this.draw.layeredText({
|
|
|
|
|
ctx: ctx,
|
2018-11-21 17:02:53 +08:00
|
|
|
|
text: selectedSong.title,
|
2018-10-25 22:18:41 +08:00
|
|
|
|
fontSize: 40,
|
|
|
|
|
fontFamily: this.font,
|
|
|
|
|
x: 620,
|
|
|
|
|
y: 20,
|
|
|
|
|
width: 600,
|
|
|
|
|
align: "right"
|
|
|
|
|
}, [
|
|
|
|
|
{outline: "#000", letterBorder: 10},
|
|
|
|
|
{fill: "#fff"}
|
|
|
|
|
])
|
2018-11-21 17:02:53 +08:00
|
|
|
|
|
|
|
|
|
if(selectedSong.category){
|
|
|
|
|
var _w = 142
|
|
|
|
|
var _h = 22
|
|
|
|
|
var _x = 628 - _w
|
|
|
|
|
var _y = 88 - _h
|
2020-04-16 06:40:13 +08:00
|
|
|
|
if(assets.categories.find(cat=>cat.title == selectedSong.category)){
|
|
|
|
|
ctx.fillStyle = assets.categories.find(cat=>cat.title == selectedSong.category).songSkin.outline
|
2018-11-21 17:02:53 +08:00
|
|
|
|
}else{
|
2020-04-16 06:40:13 +08:00
|
|
|
|
ctx.fillStyle = assets.categories.find(cat=>cat.title == 'default').songSkin.outline
|
2018-11-21 17:02:53 +08:00
|
|
|
|
}
|
|
|
|
|
this.draw.roundedRect({
|
|
|
|
|
ctx: ctx,
|
|
|
|
|
x: _x, y: _y,
|
|
|
|
|
w: _w, h: _h,
|
|
|
|
|
radius: 11
|
|
|
|
|
})
|
|
|
|
|
ctx.fill()
|
|
|
|
|
|
2019-01-21 23:47:22 +08:00
|
|
|
|
if(selectedSong.category in strings.categories){
|
|
|
|
|
var categoryName = strings.categories[selectedSong.category]
|
|
|
|
|
}else{
|
|
|
|
|
var categoryName = selectedSong.category
|
|
|
|
|
}
|
2018-11-21 17:02:53 +08:00
|
|
|
|
this.draw.layeredText({
|
|
|
|
|
ctx: ctx,
|
2019-01-21 23:47:22 +08:00
|
|
|
|
text: categoryName,
|
2018-11-21 17:02:53 +08:00
|
|
|
|
fontSize: 15,
|
|
|
|
|
fontFamily: this.font,
|
|
|
|
|
align: "center",
|
2018-11-21 18:50:48 +08:00
|
|
|
|
baseline: "middle",
|
2018-11-21 17:02:53 +08:00
|
|
|
|
x: _x + _w / 2,
|
2018-11-21 18:50:48 +08:00
|
|
|
|
y: _y + _h / 2,
|
2018-11-21 17:02:53 +08:00
|
|
|
|
width: 122
|
|
|
|
|
}, [
|
|
|
|
|
{fill: "#fff"}
|
|
|
|
|
])
|
|
|
|
|
}
|
2018-10-25 22:18:41 +08:00
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var score = this.controller.getGlobalScore()
|
2020-03-09 20:36:57 +08:00
|
|
|
|
var gaugePercent = this.rules.gaugePercent(score.gauge)
|
2018-10-25 22:18:41 +08:00
|
|
|
|
|
2020-03-14 12:50:04 +08:00
|
|
|
|
if(this.player === 2){
|
2018-10-25 22:18:41 +08:00
|
|
|
|
var scoreImg = "bg_score_p2"
|
|
|
|
|
var scoreFill = "#6bbec0"
|
2018-09-06 00:46:26 +08:00
|
|
|
|
}else{
|
2018-10-25 22:18:41 +08:00
|
|
|
|
var scoreImg = "bg_score_p1"
|
|
|
|
|
var scoreFill = "#fa4529"
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if(this.portrait){
|
|
|
|
|
// Portrait
|
|
|
|
|
|
|
|
|
|
if(!this.portraitClass){
|
|
|
|
|
this.portraitClass = true
|
|
|
|
|
this.gameDiv.classList.add("portrait")
|
2018-12-02 23:25:42 +08:00
|
|
|
|
this.setDonBgHeight()
|
2018-10-25 22:18:41 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
this.slotPos = {
|
|
|
|
|
x: 66,
|
|
|
|
|
y: frameTop + 375,
|
|
|
|
|
size: 100,
|
|
|
|
|
paddingLeft: 0
|
|
|
|
|
}
|
2020-03-14 12:50:04 +08:00
|
|
|
|
this.scorePos = {x: 363, y: frameTop + (this.player === 2 ? 520 : 227)}
|
2018-10-25 22:18:41 +08:00
|
|
|
|
|
|
|
|
|
var animPos = {
|
|
|
|
|
x1: this.slotPos.x + 13,
|
2020-03-14 12:50:04 +08:00
|
|
|
|
y1: this.slotPos.y + (this.player === 2 ? 27 : -27),
|
2018-10-25 22:18:41 +08:00
|
|
|
|
x2: winW - 38,
|
2020-03-14 12:50:04 +08:00
|
|
|
|
y2: frameTop + (this.player === 2 ? 484 : 293)
|
2018-10-25 22:18:41 +08:00
|
|
|
|
}
|
|
|
|
|
var taikoPos = {
|
|
|
|
|
x: 19,
|
2020-03-14 12:50:04 +08:00
|
|
|
|
y: frameTop + (this.player === 2 ? 464 : 184),
|
2018-10-25 22:18:41 +08:00
|
|
|
|
w: 111,
|
|
|
|
|
h: 130
|
|
|
|
|
}
|
|
|
|
|
|
2020-03-13 13:32:53 +08:00
|
|
|
|
this.nameplateCache.get({
|
|
|
|
|
ctx: ctx,
|
|
|
|
|
x: 167,
|
2020-03-14 12:50:04 +08:00
|
|
|
|
y: this.player === 2 ? 565 : 160,
|
2020-03-13 13:32:53 +08:00
|
|
|
|
w: 219,
|
|
|
|
|
h: 53,
|
|
|
|
|
id: "1p",
|
|
|
|
|
}, ctx => {
|
2020-03-14 12:50:04 +08:00
|
|
|
|
var defaultName = this.player === 1 ? strings.defaultName : strings.default2PName
|
2020-03-13 13:32:53 +08:00
|
|
|
|
if(this.multiplayer === 2){
|
2020-03-14 12:50:04 +08:00
|
|
|
|
var name = p2.name || defaultName
|
2020-03-13 13:32:53 +08:00
|
|
|
|
}else{
|
2020-03-14 12:50:04 +08:00
|
|
|
|
var name = account.loggedIn ? account.displayName : defaultName
|
2020-03-13 13:32:53 +08:00
|
|
|
|
}
|
|
|
|
|
this.draw.nameplate({
|
2020-03-13 10:34:54 +08:00
|
|
|
|
ctx: ctx,
|
2020-03-13 13:32:53 +08:00
|
|
|
|
x: 3,
|
|
|
|
|
y: 3,
|
|
|
|
|
scale: 0.8,
|
|
|
|
|
name: name,
|
|
|
|
|
font: this.font,
|
2020-03-14 12:50:04 +08:00
|
|
|
|
blue: this.player === 2
|
2020-03-13 10:34:54 +08:00
|
|
|
|
})
|
2020-03-13 13:32:53 +08:00
|
|
|
|
})
|
2020-03-13 10:34:54 +08:00
|
|
|
|
|
2018-10-25 22:18:41 +08:00
|
|
|
|
ctx.fillStyle = "#000"
|
|
|
|
|
ctx.fillRect(
|
|
|
|
|
0,
|
2020-03-14 12:50:04 +08:00
|
|
|
|
this.player === 2 ? 306 : 288,
|
2018-10-25 22:18:41 +08:00
|
|
|
|
winW,
|
2020-03-14 12:50:04 +08:00
|
|
|
|
this.player === 1 ? 184 : 183
|
2018-10-25 22:18:41 +08:00
|
|
|
|
)
|
|
|
|
|
ctx.beginPath()
|
2020-03-14 12:50:04 +08:00
|
|
|
|
if(this.player === 2){
|
2018-10-25 22:18:41 +08:00
|
|
|
|
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()
|
2020-03-14 12:50:04 +08:00
|
|
|
|
if(this.player === 2){
|
2018-10-25 22:18:41 +08:00
|
|
|
|
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()
|
2020-03-14 12:50:04 +08:00
|
|
|
|
if(this.player === 2){
|
2018-10-25 22:18:41 +08:00
|
|
|
|
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
|
2019-11-28 14:04:40 +08:00
|
|
|
|
if(this.controller.selectedSong.difficulty){
|
|
|
|
|
ctx.drawImage(assets.image["difficulty"],
|
|
|
|
|
0, 144 * this.difficulty[this.controller.selectedSong.difficulty],
|
|
|
|
|
168, 143,
|
2020-03-14 12:50:04 +08:00
|
|
|
|
126, this.player === 2 ? 497 : 228,
|
2019-11-28 14:04:40 +08:00
|
|
|
|
62, 53
|
|
|
|
|
)
|
|
|
|
|
}
|
2018-10-25 22:18:41 +08:00
|
|
|
|
|
|
|
|
|
// Badges
|
2020-03-14 12:50:04 +08:00
|
|
|
|
if(this.controller.autoPlayEnabled && !this.multiplayer){
|
2018-10-25 22:18:41 +08:00
|
|
|
|
this.ctx.drawImage(assets.image["badge_auto"],
|
|
|
|
|
183,
|
2020-03-14 12:50:04 +08:00
|
|
|
|
this.player === 2 ? 490 : 265,
|
2018-10-25 22:18:41 +08:00
|
|
|
|
23,
|
|
|
|
|
23
|
|
|
|
|
)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Gauge
|
|
|
|
|
ctx.fillStyle = "#000"
|
|
|
|
|
ctx.beginPath()
|
|
|
|
|
var gaugeX = winW - 788 * 0.7 - 32
|
2020-03-14 12:50:04 +08:00
|
|
|
|
if(this.player === 2){
|
2018-10-25 22:18:41 +08:00
|
|
|
|
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,
|
2020-03-14 12:50:04 +08:00
|
|
|
|
y: this.player === 2 ? 468 : 273,
|
2020-03-05 23:58:49 +08:00
|
|
|
|
clear: this.rules.gaugeClear,
|
2018-10-25 22:18:41 +08:00
|
|
|
|
percentage: gaugePercent,
|
|
|
|
|
font: this.font,
|
|
|
|
|
scale: 0.7,
|
2020-03-14 12:50:04 +08:00
|
|
|
|
multiplayer: this.player === 2,
|
|
|
|
|
blue: this.player === 2
|
2018-10-25 22:18:41 +08:00
|
|
|
|
})
|
|
|
|
|
this.draw.soul({
|
|
|
|
|
ctx: ctx,
|
|
|
|
|
x: winW - 40,
|
2020-03-14 12:50:04 +08:00
|
|
|
|
y: this.player === 2 ? 484 : 293,
|
2018-10-25 22:18:41 +08:00
|
|
|
|
scale: 0.75,
|
2020-03-05 23:58:49 +08:00
|
|
|
|
cleared: this.rules.clearReached(score.gauge)
|
2018-10-25 22:18:41 +08:00
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
// 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")
|
2018-12-02 23:25:42 +08:00
|
|
|
|
this.setDonBgHeight()
|
2018-10-25 22:18:41 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
this.slotPos = {
|
|
|
|
|
x: 413,
|
|
|
|
|
y: frameTop + 257,
|
|
|
|
|
size: 106,
|
|
|
|
|
paddingLeft: 332
|
|
|
|
|
}
|
|
|
|
|
this.scorePos = {
|
|
|
|
|
x: 155,
|
2020-03-14 12:50:04 +08:00
|
|
|
|
y: frameTop + (this.player === 2 ? 318 : 193)
|
2018-10-25 22:18:41 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var animPos = {
|
|
|
|
|
x1: this.slotPos.x + 14,
|
2020-03-14 12:50:04 +08:00
|
|
|
|
y1: this.slotPos.y + (this.player === 2 ? 29 : -29),
|
2018-10-25 22:18:41 +08:00
|
|
|
|
x2: winW - 55,
|
2020-03-14 12:50:04 +08:00
|
|
|
|
y2: frameTop + (this.player === 2 ? 378 : 165)
|
2018-10-25 22:18:41 +08:00
|
|
|
|
}
|
|
|
|
|
var taikoPos = {x: 179, y: frameTop + 190, w: 138, h: 162}
|
|
|
|
|
|
2020-03-13 10:34:54 +08:00
|
|
|
|
this.nameplateCache.get({
|
|
|
|
|
ctx: ctx,
|
|
|
|
|
x: 320,
|
2020-03-14 12:50:04 +08:00
|
|
|
|
y: this.player === 2 ? 460 : 20,
|
2020-03-13 10:34:54 +08:00
|
|
|
|
w: 273,
|
|
|
|
|
h: 66,
|
|
|
|
|
id: "1p",
|
|
|
|
|
}, ctx => {
|
2020-03-14 12:50:04 +08:00
|
|
|
|
var defaultName = this.player === 1 ? strings.defaultName : strings.default2PName
|
2020-03-13 10:34:54 +08:00
|
|
|
|
if(this.multiplayer === 2){
|
2020-03-14 12:50:04 +08:00
|
|
|
|
var name = p2.name || defaultName
|
2020-03-13 10:34:54 +08:00
|
|
|
|
}else{
|
2020-03-14 12:50:04 +08:00
|
|
|
|
var name = account.loggedIn ? account.displayName : defaultName
|
2020-03-13 10:34:54 +08:00
|
|
|
|
}
|
|
|
|
|
this.draw.nameplate({
|
|
|
|
|
ctx: ctx,
|
|
|
|
|
x: 3,
|
|
|
|
|
y: 3,
|
|
|
|
|
name: name,
|
|
|
|
|
font: this.font,
|
2020-03-14 12:50:04 +08:00
|
|
|
|
blue: this.player === 2
|
2020-03-13 10:34:54 +08:00
|
|
|
|
})
|
|
|
|
|
})
|
|
|
|
|
|
2018-10-25 22:18:41 +08:00
|
|
|
|
ctx.fillStyle = "#000"
|
|
|
|
|
ctx.fillRect(
|
|
|
|
|
0,
|
|
|
|
|
184,
|
|
|
|
|
winW,
|
2020-03-14 12:50:04 +08:00
|
|
|
|
this.multiplayer && this.player === 1 ? 177 : 176
|
2018-10-25 22:18:41 +08:00
|
|
|
|
)
|
|
|
|
|
ctx.beginPath()
|
2020-03-14 12:50:04 +08:00
|
|
|
|
if(this.player === 2){
|
2018-10-25 22:18:41 +08:00
|
|
|
|
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,
|
2020-03-14 12:50:04 +08:00
|
|
|
|
y: this.player === 2 ? 357 : 135,
|
2020-03-05 23:58:49 +08:00
|
|
|
|
clear: this.rules.gaugeClear,
|
2018-10-25 22:18:41 +08:00
|
|
|
|
percentage: gaugePercent,
|
|
|
|
|
font: this.font,
|
2020-03-14 12:50:04 +08:00
|
|
|
|
multiplayer: this.player === 2,
|
|
|
|
|
blue: this.player === 2
|
2018-10-25 22:18:41 +08:00
|
|
|
|
})
|
|
|
|
|
this.draw.soul({
|
|
|
|
|
ctx: ctx,
|
|
|
|
|
x: winW - 57,
|
2020-03-14 12:50:04 +08:00
|
|
|
|
y: this.player === 2 ? 378 : 165,
|
2020-03-05 23:58:49 +08:00
|
|
|
|
cleared: this.rules.clearReached(score.gauge)
|
2018-10-25 22:18:41 +08:00
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
// 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
|
2019-11-28 14:04:40 +08:00
|
|
|
|
if(this.controller.selectedSong.difficulty){
|
|
|
|
|
ctx.drawImage(assets.image["difficulty"],
|
|
|
|
|
0, 144 * this.difficulty[this.controller.selectedSong.difficulty],
|
|
|
|
|
168, 143,
|
2020-03-14 12:50:04 +08:00
|
|
|
|
16, this.player === 2 ? 194 : 232,
|
2019-11-28 14:04:40 +08:00
|
|
|
|
141, 120
|
|
|
|
|
)
|
|
|
|
|
var diff = this.controller.selectedSong.difficulty
|
|
|
|
|
var text = strings[diff === "ura" ? "oni" : diff]
|
|
|
|
|
ctx.font = this.draw.bold(this.font) + "20px " + this.font
|
|
|
|
|
ctx.textAlign = "center"
|
|
|
|
|
ctx.textBaseline = "bottom"
|
|
|
|
|
ctx.strokeStyle = "#000"
|
|
|
|
|
ctx.fillStyle = "#fff"
|
|
|
|
|
ctx.lineWidth = 7
|
|
|
|
|
ctx.miterLimit = 1
|
2020-03-14 12:50:04 +08:00
|
|
|
|
ctx.strokeText(text, 87, this.player === 2 ? 310 : 348)
|
|
|
|
|
ctx.fillText(text, 87, this.player === 2 ? 310 : 348)
|
2019-11-28 14:04:40 +08:00
|
|
|
|
ctx.miterLimit = 10
|
|
|
|
|
}
|
2018-10-25 22:18:41 +08:00
|
|
|
|
|
|
|
|
|
// Badges
|
2020-03-14 12:50:04 +08:00
|
|
|
|
if(this.controller.autoPlayEnabled && !this.multiplayer){
|
2018-10-25 22:18:41 +08:00
|
|
|
|
this.ctx.drawImage(assets.image["badge_auto"],
|
|
|
|
|
125, 235, 34, 34
|
|
|
|
|
)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Score background
|
|
|
|
|
ctx.fillStyle = "#000"
|
|
|
|
|
ctx.beginPath()
|
2020-03-14 12:50:04 +08:00
|
|
|
|
if(this.player === 2){
|
2018-10-25 22:18:41 +08:00
|
|
|
|
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,
|
2020-03-14 12:50:04 +08:00
|
|
|
|
y: animPos.y1 - animPos.h * (this.player === 2 ? 2.5 : 3.5)
|
2018-10-25 22:18:41 +08:00
|
|
|
|
}, {
|
|
|
|
|
// 940, -150
|
|
|
|
|
x: animPos.x2 - animPos.w / 3,
|
2020-03-14 12:50:04 +08:00
|
|
|
|
y: animPos.y2 - animPos.h * (this.player === 2 ? 3.5 : 5)
|
2018-10-25 22:18:41 +08:00
|
|
|
|
}, {
|
|
|
|
|
// 1225, 165
|
|
|
|
|
x: animPos.x2,
|
|
|
|
|
y: animPos.y2
|
|
|
|
|
}]
|
|
|
|
|
|
|
|
|
|
var touchTop = frameTop + (touchMultiplayer ? 135 : 0)
|
2018-10-06 01:03:59 +08:00
|
|
|
|
this.touchDrum = (() => {
|
|
|
|
|
var sw = 842
|
|
|
|
|
var sh = 340
|
|
|
|
|
var x = 0
|
2018-10-25 22:18:41 +08:00
|
|
|
|
var y = this.portrait ? touchTop + 477 : touchTop + 365
|
|
|
|
|
var paddingTop = 13
|
|
|
|
|
var w = winW
|
|
|
|
|
var maxH = winH - y
|
2018-10-06 01:03:59 +08:00
|
|
|
|
var h = maxH - paddingTop
|
|
|
|
|
if(w / h >= sw / sh){
|
|
|
|
|
w = h / sh * sw
|
2018-10-25 22:18:41 +08:00
|
|
|
|
x = (winW - w) / 2
|
2018-10-06 01:03:59 +08:00
|
|
|
|
y += paddingTop
|
|
|
|
|
}else{
|
|
|
|
|
h = w / sw * sh
|
|
|
|
|
y = y + (maxH - h)
|
|
|
|
|
}
|
|
|
|
|
return {
|
|
|
|
|
x: x, y: y, w: w, h: h
|
|
|
|
|
}
|
|
|
|
|
})()
|
2018-10-25 22:18:41 +08:00
|
|
|
|
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
|
|
|
|
|
}
|
2018-09-06 00:46:26 +08:00
|
|
|
|
|
2018-10-25 22:18:41 +08:00
|
|
|
|
if(this.multiplayer !== 2){
|
|
|
|
|
this.mouseIdle()
|
|
|
|
|
this.drawTouch()
|
|
|
|
|
}
|
2018-09-09 12:09:15 +08:00
|
|
|
|
|
2018-10-25 22:18:41 +08:00
|
|
|
|
// Score
|
|
|
|
|
ctx.save()
|
2019-01-21 23:47:22 +08:00
|
|
|
|
ctx.font = "30px TnT, Meiryo, sans-serif"
|
2018-10-25 22:18:41 +08:00
|
|
|
|
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)
|
2018-10-06 01:03:59 +08:00
|
|
|
|
}
|
2018-10-25 22:18:41 +08:00
|
|
|
|
ctx.restore()
|
|
|
|
|
|
2019-02-21 04:48:21 +08:00
|
|
|
|
// Branch background
|
2018-10-25 22:18:41 +08:00
|
|
|
|
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
|
|
|
|
|
|
2019-02-21 04:48:21 +08:00
|
|
|
|
if(this.branchAnimate && ms <= this.branchAnimate.ms + 300){
|
|
|
|
|
var alpha = Math.max(0, (ms - this.branchAnimate.ms) / 300)
|
|
|
|
|
ctx.globalAlpha = 1 - alpha
|
|
|
|
|
ctx.fillStyle = this.branchMap[this.branchAnimate.fromBranch].bg
|
|
|
|
|
ctx.fillRect(padding, barY, winW - padding, barH)
|
|
|
|
|
ctx.globalAlpha = alpha
|
|
|
|
|
}
|
|
|
|
|
if(this.branch){
|
|
|
|
|
ctx.fillStyle = this.branchMap[this.branch].bg
|
|
|
|
|
ctx.fillRect(padding, barY, winW - padding, barH)
|
|
|
|
|
ctx.globalAlpha = 1
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Current branch text
|
|
|
|
|
if(this.branch){
|
|
|
|
|
if(resized){
|
|
|
|
|
this.fillBranchCache()
|
|
|
|
|
}
|
|
|
|
|
var textW = Math.floor(260 * mul)
|
|
|
|
|
var textH = Math.floor(barH)
|
|
|
|
|
var textX = winW - textW
|
|
|
|
|
var oldOffset = 0
|
|
|
|
|
var newOffset = 0
|
|
|
|
|
var elapsed = ms - this.startTime
|
|
|
|
|
if(elapsed < 250){
|
|
|
|
|
textX = winW
|
|
|
|
|
}else if(elapsed < 500){
|
|
|
|
|
textX += (1 - this.draw.easeOutBack((elapsed - 250) / 250)) * textW
|
|
|
|
|
}
|
|
|
|
|
if(this.branchAnimate && ms - this.branchAnimate.ms < 310 && ms >= this.branchAnimate.ms){
|
|
|
|
|
var fromBranch = this.branchAnimate.fromBranch
|
|
|
|
|
var elapsed = ms - this.branchAnimate.ms
|
|
|
|
|
var reverse = fromBranch === "master" || fromBranch === "advanced" && this.branch === "normal" ? -1 : 1
|
|
|
|
|
if(elapsed < 65){
|
|
|
|
|
oldOffset = elapsed / 65 * 12 * mul * reverse
|
|
|
|
|
ctx.globalAlpha = 1
|
|
|
|
|
var newAlpha = 0
|
|
|
|
|
}else if(elapsed < 215){
|
|
|
|
|
var animPoint = (elapsed - 65) / 150
|
|
|
|
|
oldOffset = (12 - animPoint * 48) * mul * reverse
|
|
|
|
|
newOffset = (36 - animPoint * 48) * mul * reverse
|
|
|
|
|
ctx.globalAlpha = this.draw.easeIn(1 - animPoint)
|
|
|
|
|
var newAlpha = this.draw.easeIn(animPoint)
|
|
|
|
|
}else{
|
|
|
|
|
newOffset = (1 - (elapsed - 215) / 95) * -12 * mul * reverse
|
|
|
|
|
ctx.globalAlpha = 0
|
|
|
|
|
var newAlpha = 1
|
|
|
|
|
}
|
|
|
|
|
this.branchCache.get({
|
|
|
|
|
ctx: ctx,
|
|
|
|
|
x: textX, y: barY + oldOffset,
|
|
|
|
|
w: textW, h: textH,
|
|
|
|
|
id: fromBranch
|
|
|
|
|
})
|
|
|
|
|
ctx.globalAlpha = newAlpha
|
|
|
|
|
}
|
|
|
|
|
this.branchCache.get({
|
|
|
|
|
ctx: ctx,
|
|
|
|
|
x: textX, y: barY + newOffset,
|
|
|
|
|
w: textW, h: textH,
|
|
|
|
|
id: this.branch
|
|
|
|
|
})
|
|
|
|
|
ctx.globalAlpha = 1
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Go go time background
|
2018-10-25 22:18:41 +08:00
|
|
|
|
if(this.gogoTime || ms <= this.gogoTimeStarted + 100){
|
2019-01-07 03:59:49 +08:00
|
|
|
|
var grd = ctx.createLinearGradient(padding, 0, winW, 0)
|
2019-02-21 04:48:21 +08:00
|
|
|
|
grd.addColorStop(0, "rgba(255, 0, 0, 0.16)")
|
|
|
|
|
grd.addColorStop(0.45, "rgba(255, 0, 0, 0.28)")
|
|
|
|
|
grd.addColorStop(0.77, "rgba(255, 83, 157, 0.4)")
|
|
|
|
|
grd.addColorStop(1, "rgba(255, 83, 157, 0)")
|
2018-10-25 22:18:41 +08:00
|
|
|
|
ctx.fillStyle = grd
|
|
|
|
|
if(!this.touchEnabled){
|
|
|
|
|
var alpha = Math.min(100, ms - this.gogoTimeStarted) / 100
|
|
|
|
|
if(!this.gogoTime){
|
|
|
|
|
alpha = 1 - alpha
|
|
|
|
|
}
|
|
|
|
|
ctx.globalAlpha = alpha
|
2018-09-06 00:46:26 +08:00
|
|
|
|
}
|
2018-10-25 22:18:41 +08:00
|
|
|
|
ctx.fillRect(padding, barY, winW - padding, barH)
|
2018-09-06 00:46:26 +08:00
|
|
|
|
}
|
2019-02-21 04:48:21 +08:00
|
|
|
|
|
|
|
|
|
// Bar pressed keys
|
2018-12-13 17:18:52 +08:00
|
|
|
|
if(keyTime[sound] > ms - 130){
|
2018-10-25 22:18:41 +08:00
|
|
|
|
var gradients = {
|
2018-12-13 17:18:52 +08:00
|
|
|
|
"don": "255, 0, 0",
|
|
|
|
|
"ka": "0, 170, 255"
|
|
|
|
|
}
|
|
|
|
|
var yellow = "255, 231, 0"
|
|
|
|
|
var currentGradient = gradients[sound]
|
|
|
|
|
ctx.globalCompositeOperation = "lighter"
|
|
|
|
|
do{
|
2019-01-07 03:59:49 +08:00
|
|
|
|
var grd = ctx.createLinearGradient(padding, 0, winW, 0)
|
2018-12-13 17:18:52 +08:00
|
|
|
|
grd.addColorStop(0, "rgb(" + currentGradient + ")")
|
|
|
|
|
grd.addColorStop(1, "rgba(" + currentGradient + ", 0)")
|
|
|
|
|
ctx.fillStyle = grd
|
|
|
|
|
ctx.globalAlpha = (1 - (ms - keyTime[sound]) / 130) / 5
|
|
|
|
|
ctx.fillRect(padding, barY, winW - padding, barH)
|
|
|
|
|
}while(this.currentScore.ms > ms - 130 && currentGradient !== yellow && (currentGradient = yellow))
|
|
|
|
|
ctx.globalCompositeOperation = "source-over"
|
2018-10-25 22:18:41 +08:00
|
|
|
|
}
|
|
|
|
|
ctx.globalAlpha = 1
|
2018-09-06 00:46:26 +08:00
|
|
|
|
|
2018-10-25 22:18:41 +08:00
|
|
|
|
// Taiko
|
|
|
|
|
ctx.drawImage(assets.image["taiko"],
|
|
|
|
|
0, 0, 138, 162,
|
|
|
|
|
taikoPos.x, taikoPos.y, taikoPos.w, taikoPos.h
|
2018-09-06 00:46:26 +08:00
|
|
|
|
)
|
|
|
|
|
|
2018-10-25 22:18:41 +08:00
|
|
|
|
// Taiko pressed keys
|
|
|
|
|
var keys = ["ka_l", "ka_r", "don_l", "don_r"]
|
|
|
|
|
|
|
|
|
|
for(var i = 0; i < keys.length; i++){
|
2019-04-17 02:06:41 +08:00
|
|
|
|
var keyMS = ms - keyTime[keys[i]]
|
2018-10-25 22:18:41 +08:00
|
|
|
|
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
|
|
|
|
|
)
|
2015-07-17 16:22:46 +08:00
|
|
|
|
}
|
2018-10-25 22:18:41 +08:00
|
|
|
|
}
|
|
|
|
|
ctx.globalAlpha = 1
|
|
|
|
|
|
|
|
|
|
// Combo
|
|
|
|
|
var scoreMS = ms - this.currentScore.ms
|
|
|
|
|
|
2018-09-06 00:46:26 +08:00
|
|
|
|
var comboCount = this.controller.getCombo()
|
|
|
|
|
if(comboCount >= 10){
|
2018-10-09 14:59:36 +08:00
|
|
|
|
var comboText = comboCount.toString().split("")
|
2018-10-25 22:18:41 +08:00
|
|
|
|
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
|
Custom scripting, #song=, translations
- A song can be linked directly by adding "#song=<id>" to the url, replace `<id>` with the id in the database, after loading it jumps immediately jumps to the difficulty selection
- Added tutorial translations
- Fixed song preview not playing
- Use text fallback for the logo when there are no vectors
- Increased combo cache by 1 pixel
- A custom javascript file can be loaded from config.json by defining "custom_js" value
- Added lots of events to help writing custom js files: `version-link, title-screen, language-change, song-select, song-select-move, song-select-difficulty, song-select-back, about, about-link, tutorial, import-songs, import-songs-default, session, session-start, session-end, debug, load-song, load-song-player2, load-song-unfocused, load-song-cancel, load-song-error, game-start, key-events, p2-game-end, p2-disconnected, p2-abandoned, pause, unpause, pause-restart, pause-song-select, game-lag, scoresheet, scoresheet-player2`
- Event syntax example:
```js
addEventListener("game-start", event => {
console.log("game-start", event.detail)
})
```
2019-02-14 17:32:45 +08:00
|
|
|
|
var glyphH = 65
|
2018-10-25 22:18:41 +08:00
|
|
|
|
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)
|
|
|
|
|
|
2018-09-06 00:46:26 +08:00
|
|
|
|
for(var i in comboText){
|
2018-10-25 22:18:41 +08:00
|
|
|
|
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]
|
|
|
|
|
})
|
2015-07-17 16:22:46 +08:00
|
|
|
|
}
|
2018-09-06 00:46:26 +08:00
|
|
|
|
|
2018-10-25 22:18:41 +08:00
|
|
|
|
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
|
2018-09-06 01:35:57 +08:00
|
|
|
|
}else{
|
2018-10-25 22:18:41 +08:00
|
|
|
|
ctx.fillStyle = "#fff"
|
2018-09-06 00:46:26 +08:00
|
|
|
|
}
|
2019-01-21 23:47:22 +08:00
|
|
|
|
ctx.font = this.draw.bold(this.font) + fontSize + "px " + this.font
|
2018-10-25 22:18:41 +08:00
|
|
|
|
ctx.lineWidth = 7 * mul
|
|
|
|
|
ctx.textAlign = "center"
|
2019-01-21 23:47:22 +08:00
|
|
|
|
ctx.miterLimit = 1
|
2019-02-21 04:48:21 +08:00
|
|
|
|
ctx.strokeStyle = "#000"
|
2019-01-21 23:47:22 +08:00
|
|
|
|
ctx.strokeText(strings.combo, comboX, comboTextY)
|
|
|
|
|
ctx.miterLimit = 10
|
|
|
|
|
ctx.fillText(strings.combo, comboX, comboTextY)
|
2015-07-17 16:22:46 +08:00
|
|
|
|
}
|
|
|
|
|
|
2018-10-25 22:18:41 +08:00
|
|
|
|
// Slot
|
|
|
|
|
this.draw.slot(ctx, this.slotPos.x, this.slotPos.y, this.slotPos.size)
|
|
|
|
|
|
|
|
|
|
// Measures
|
|
|
|
|
ctx.save()
|
2018-12-13 17:18:52 +08:00
|
|
|
|
ctx.beginPath()
|
2018-10-25 22:18:41 +08:00
|
|
|
|
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
|
2018-09-06 00:46:26 +08:00
|
|
|
|
)
|
2018-10-25 22:18:41 +08:00
|
|
|
|
if(fadeOut){
|
|
|
|
|
ctx.globalAlpha = 1
|
|
|
|
|
}
|
2018-09-06 00:46:26 +08:00
|
|
|
|
}
|
2018-10-25 22:18:41 +08:00
|
|
|
|
|
|
|
|
|
// Future notes
|
|
|
|
|
this.updateNoteFaces()
|
|
|
|
|
ctx.save()
|
2018-12-13 17:18:52 +08:00
|
|
|
|
ctx.beginPath()
|
2018-10-25 22:18:41 +08:00
|
|
|
|
ctx.rect(this.slotPos.paddingLeft, 0, winW - this.slotPos.paddingLeft, winH)
|
|
|
|
|
ctx.clip()
|
|
|
|
|
|
|
|
|
|
this.drawCircles(this.controller.getCircles())
|
2019-11-28 14:04:40 +08:00
|
|
|
|
if(this.controller.game.calibrationState === "video"){
|
|
|
|
|
if(ms % this.beatInterval < 1000 / 60 * 5){
|
|
|
|
|
this.drawCircle({
|
|
|
|
|
ms: ms,
|
|
|
|
|
type: "don",
|
|
|
|
|
endTime: ms + 100,
|
|
|
|
|
speed: 0
|
|
|
|
|
}, {
|
|
|
|
|
x: this.slotPos.x,
|
|
|
|
|
y: this.slotPos.y
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2018-10-25 22:18:41 +08:00
|
|
|
|
ctx.restore()
|
|
|
|
|
|
|
|
|
|
// Hit notes explosion
|
2018-11-15 16:42:22 +08:00
|
|
|
|
this.assets.drawAssets("notes")
|
2018-10-25 22:18:41 +08:00
|
|
|
|
|
|
|
|
|
// 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
|
|
|
|
|
}
|
2018-09-06 00:46:26 +08:00
|
|
|
|
}
|
2018-10-25 22:18:41 +08:00
|
|
|
|
|
|
|
|
|
// 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")
|
2018-09-06 00:46:26 +08:00
|
|
|
|
}
|
2018-11-12 18:32:02 +08:00
|
|
|
|
|
|
|
|
|
// Pause screen
|
|
|
|
|
if(!this.multiplayer && this.controller.game.paused){
|
|
|
|
|
ctx.fillStyle = "rgba(0, 0, 0, 0.5)"
|
|
|
|
|
ctx.fillRect(0, 0, winW, winH)
|
|
|
|
|
|
2018-12-13 17:18:52 +08:00
|
|
|
|
ctx.save()
|
2018-11-12 18:32:02 +08:00
|
|
|
|
if(this.portrait){
|
2018-12-13 17:18:52 +08:00
|
|
|
|
ctx.translate(frameLeft - 242, frameTop + 308)
|
2018-11-12 18:32:02 +08:00
|
|
|
|
var pauseScale = 720 / 766
|
|
|
|
|
ctx.scale(pauseScale, pauseScale)
|
2018-12-13 17:18:52 +08:00
|
|
|
|
}else{
|
|
|
|
|
ctx.translate(frameLeft, frameTop)
|
2018-11-12 18:32:02 +08:00
|
|
|
|
}
|
|
|
|
|
|
2019-11-28 14:04:40 +08:00
|
|
|
|
var state = this.controller.game.calibrationState
|
|
|
|
|
if(state && state in strings.calibration){
|
|
|
|
|
var boldTitle = strings.calibration[state].title
|
|
|
|
|
}
|
|
|
|
|
if(boldTitle){
|
|
|
|
|
this.draw.layeredText({
|
|
|
|
|
ctx: ctx,
|
|
|
|
|
text: boldTitle,
|
|
|
|
|
fontSize: 35,
|
|
|
|
|
fontFamily: this.font,
|
|
|
|
|
x: 300,
|
|
|
|
|
y: 70
|
|
|
|
|
}, [
|
|
|
|
|
{outline: "#fff", letterBorder: 22}
|
|
|
|
|
])
|
|
|
|
|
}
|
2018-11-12 18:32:02 +08:00
|
|
|
|
var pauseRect = (ctx, mul) => {
|
|
|
|
|
this.draw.roundedRect({
|
|
|
|
|
ctx: ctx,
|
2018-12-13 17:18:52 +08:00
|
|
|
|
x: 269 * mul,
|
|
|
|
|
y: 93 * mul,
|
2018-11-12 18:32:02 +08:00
|
|
|
|
w: 742 * mul,
|
|
|
|
|
h: 494 * mul,
|
|
|
|
|
radius: 17 * mul
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
pauseRect(ctx, 1)
|
|
|
|
|
ctx.strokeStyle = "#fff"
|
|
|
|
|
ctx.lineWidth = 24
|
|
|
|
|
ctx.stroke()
|
|
|
|
|
ctx.strokeStyle = "#000"
|
|
|
|
|
ctx.lineWidth = 12
|
|
|
|
|
ctx.stroke()
|
|
|
|
|
this.draw.pattern({
|
|
|
|
|
ctx: ctx,
|
|
|
|
|
img: assets.image["bg_pause"],
|
|
|
|
|
shape: pauseRect,
|
2018-12-13 17:18:52 +08:00
|
|
|
|
dx: 68,
|
|
|
|
|
dy: 11
|
2018-11-12 18:32:02 +08:00
|
|
|
|
})
|
2019-11-28 14:04:40 +08:00
|
|
|
|
if(boldTitle){
|
|
|
|
|
this.draw.layeredText({
|
|
|
|
|
ctx: ctx,
|
|
|
|
|
text: boldTitle,
|
|
|
|
|
fontSize: 35,
|
|
|
|
|
fontFamily: this.font,
|
|
|
|
|
x: 300,
|
|
|
|
|
y: 70
|
|
|
|
|
}, [
|
|
|
|
|
{outline: "#000", letterBorder: 10},
|
|
|
|
|
{fill: "#fff"}
|
|
|
|
|
])
|
|
|
|
|
}
|
2018-11-12 18:32:02 +08:00
|
|
|
|
|
2019-11-28 14:04:40 +08:00
|
|
|
|
switch(state){
|
|
|
|
|
case "audioHelp":
|
|
|
|
|
case "videoHelp":
|
|
|
|
|
case "results":
|
|
|
|
|
var content = state === "audioHelp" && this.touchEnabled ? "contentAlt" : "content"
|
|
|
|
|
if(state === "audioHelp"){
|
|
|
|
|
var kbdSettings = settings.getItem("keyboardSettings")
|
|
|
|
|
var keys = [
|
|
|
|
|
kbdSettings.don_l[0].toUpperCase(),
|
|
|
|
|
kbdSettings.don_r[0].toUpperCase()
|
|
|
|
|
]
|
|
|
|
|
var substitute = (config, index, width) => {
|
|
|
|
|
var ctx = config.ctx
|
|
|
|
|
var bold = this.draw.bold(config.fontFamily)
|
|
|
|
|
ctx.font = bold + (config.fontSize * 0.66) + "px " + config.fontFamily
|
|
|
|
|
var w = config.fontSize * 0.6 + ctx.measureText(keys[index]).width
|
|
|
|
|
if(width){
|
|
|
|
|
return w
|
|
|
|
|
}else{
|
|
|
|
|
var h = 30
|
|
|
|
|
ctx.lineWidth = 3
|
|
|
|
|
ctx.strokeStyle = "rgba(0, 0, 0, 0.2)"
|
|
|
|
|
this.draw.roundedRect({
|
|
|
|
|
ctx: ctx,
|
|
|
|
|
x: 0, y: 1, w: w, h: h,
|
|
|
|
|
radius: 3
|
|
|
|
|
})
|
|
|
|
|
ctx.stroke()
|
|
|
|
|
ctx.strokeStyle = "#ccc"
|
|
|
|
|
ctx.fillStyle = "#fff"
|
|
|
|
|
this.draw.roundedRect({
|
|
|
|
|
ctx: ctx,
|
|
|
|
|
x: 0, y: 0, w: w, h: h,
|
|
|
|
|
radius: 3
|
|
|
|
|
})
|
|
|
|
|
ctx.stroke()
|
|
|
|
|
ctx.fill()
|
|
|
|
|
ctx.fillStyle = "#f7f7f7"
|
|
|
|
|
ctx.fillRect(2, 2, w - 4, h - 4)
|
|
|
|
|
|
|
|
|
|
ctx.fillStyle = "#333"
|
|
|
|
|
ctx.textBaseline = "middle"
|
|
|
|
|
ctx.textAlign = "center"
|
|
|
|
|
ctx.fillText(keys[index], w / 2, h / 2)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}else if(state === "results"){
|
|
|
|
|
var progress = this.controller.game.calibrationProgress
|
|
|
|
|
var latency = [
|
|
|
|
|
progress.audio,
|
|
|
|
|
progress.video
|
|
|
|
|
]
|
|
|
|
|
var substitute = (config, index, width) => {
|
|
|
|
|
var ctx = config.ctx
|
|
|
|
|
var bold = this.draw.bold(config.fontFamily)
|
|
|
|
|
ctx.font = bold + (config.fontSize * 1.1) + "px " + config.fontFamily
|
|
|
|
|
var text = this.addMs(latency[index])
|
|
|
|
|
if(width){
|
|
|
|
|
return ctx.measureText(text).width
|
|
|
|
|
}else{
|
|
|
|
|
ctx.fillText(text, 0, 0)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}else{
|
|
|
|
|
var substitute = null
|
|
|
|
|
}
|
|
|
|
|
this.draw.wrappingText({
|
2018-11-12 18:32:02 +08:00
|
|
|
|
ctx: ctx,
|
2019-11-28 14:04:40 +08:00
|
|
|
|
text: strings.calibration[state][content],
|
|
|
|
|
fontSize: 30,
|
|
|
|
|
fontFamily: this.font,
|
|
|
|
|
x: 300,
|
|
|
|
|
y: 130,
|
|
|
|
|
width: 680,
|
|
|
|
|
height: 240,
|
|
|
|
|
lineHeight: 35,
|
|
|
|
|
fill: "#000",
|
|
|
|
|
verticalAlign: "middle",
|
|
|
|
|
substitute: substitute
|
2018-11-12 18:32:02 +08:00
|
|
|
|
})
|
2019-11-28 14:04:40 +08:00
|
|
|
|
|
|
|
|
|
var _x = 640
|
|
|
|
|
var _w = 464
|
|
|
|
|
var _h = 80
|
|
|
|
|
for(var i = 0; i < this.pauseOptions.length; i++){
|
|
|
|
|
var text = this.pauseOptions[i]
|
|
|
|
|
var _y = 470 - 90 * (this.pauseOptions.length - i - 1)
|
|
|
|
|
if(this.state.moveHover !== null){
|
|
|
|
|
var selected = i === this.state.moveHover
|
|
|
|
|
}else{
|
|
|
|
|
var selected = i === this.state.pausePos
|
|
|
|
|
}
|
|
|
|
|
if(selected){
|
|
|
|
|
ctx.fillStyle = "#ffb447"
|
|
|
|
|
this.draw.roundedRect({
|
|
|
|
|
ctx: ctx,
|
|
|
|
|
x: _x - _w / 2,
|
|
|
|
|
y: _y,
|
|
|
|
|
w: _w,
|
|
|
|
|
h: _h,
|
|
|
|
|
radius: 30
|
|
|
|
|
})
|
|
|
|
|
ctx.fill()
|
|
|
|
|
}
|
|
|
|
|
if(selected){
|
|
|
|
|
var layers = [
|
|
|
|
|
{outline: "#000", letterBorder: 10},
|
|
|
|
|
{fill: "#fff"}
|
|
|
|
|
]
|
|
|
|
|
}else{
|
|
|
|
|
var layers = [
|
|
|
|
|
{fill: "#000"}
|
|
|
|
|
]
|
|
|
|
|
}
|
|
|
|
|
this.draw.layeredText({
|
|
|
|
|
ctx: ctx,
|
|
|
|
|
text: text,
|
|
|
|
|
x: _x,
|
|
|
|
|
y: _y + 18,
|
|
|
|
|
width: _w,
|
|
|
|
|
height: _h - 54,
|
|
|
|
|
fontSize: 40,
|
|
|
|
|
fontFamily: this.font,
|
|
|
|
|
letterSpacing: -1,
|
|
|
|
|
align: "center"
|
|
|
|
|
}, layers)
|
|
|
|
|
|
|
|
|
|
var highlight = 0
|
|
|
|
|
if(this.state.moveHover === i){
|
|
|
|
|
highlight = 2
|
|
|
|
|
}else if(selected){
|
|
|
|
|
highlight = 1
|
|
|
|
|
}
|
|
|
|
|
if(highlight){
|
|
|
|
|
this.draw.highlight({
|
|
|
|
|
ctx: ctx,
|
|
|
|
|
x: _x - _w / 2 - 3.5,
|
|
|
|
|
y: _y - 3.5,
|
|
|
|
|
w: _w + 7,
|
|
|
|
|
h: _h + 7,
|
|
|
|
|
animate: highlight === 1,
|
|
|
|
|
animateMS: this.state.moveMS,
|
|
|
|
|
opacity: highlight === 2 ? 0.8 : 1,
|
|
|
|
|
radius: 30
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
break
|
|
|
|
|
case "audioComplete":
|
|
|
|
|
case "videoComplete":
|
|
|
|
|
this.draw.wrappingText({
|
2018-11-12 18:32:02 +08:00
|
|
|
|
ctx: ctx,
|
2019-11-28 14:04:40 +08:00
|
|
|
|
text: strings.calibration[state],
|
2018-11-12 18:32:02 +08:00
|
|
|
|
fontSize: 40,
|
|
|
|
|
fontFamily: this.font,
|
2019-11-28 14:04:40 +08:00
|
|
|
|
x: 300,
|
|
|
|
|
y: 130,
|
|
|
|
|
width: 680,
|
|
|
|
|
height: 420,
|
|
|
|
|
lineHeight: 47,
|
|
|
|
|
fill: "#000",
|
|
|
|
|
verticalAlign: "middle",
|
|
|
|
|
textAlign: "center",
|
2018-11-12 18:32:02 +08:00
|
|
|
|
})
|
2019-11-28 14:04:40 +08:00
|
|
|
|
break
|
|
|
|
|
default:
|
|
|
|
|
ctx.drawImage(assets.image["mimizu"],
|
|
|
|
|
313, 247, 136, 315
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
var _y = 108
|
|
|
|
|
var _w = 80
|
|
|
|
|
var _h = 464
|
|
|
|
|
for(var i = 0; i < this.pauseOptions.length; i++){
|
|
|
|
|
var text = this.pauseOptions[i]
|
|
|
|
|
if(this.controller.calibrationMode && i === this.pauseOptions.length - 1){
|
|
|
|
|
text = strings.calibration.back
|
|
|
|
|
}
|
|
|
|
|
var _x = 520 + 110 * i
|
|
|
|
|
if(this.state.moveHover !== null){
|
|
|
|
|
var selected = i === this.state.moveHover
|
|
|
|
|
}else{
|
|
|
|
|
var selected = i === this.state.pausePos
|
|
|
|
|
}
|
|
|
|
|
if(selected){
|
|
|
|
|
ctx.fillStyle = "#ffb447"
|
|
|
|
|
this.draw.roundedRect({
|
|
|
|
|
ctx: ctx,
|
|
|
|
|
x: _x - _w / 2,
|
|
|
|
|
y: _y,
|
|
|
|
|
w: _w,
|
|
|
|
|
h: _h,
|
|
|
|
|
radius: 30
|
|
|
|
|
})
|
|
|
|
|
ctx.fill()
|
|
|
|
|
}
|
|
|
|
|
this.pauseCache.get({
|
|
|
|
|
ctx: ctx,
|
|
|
|
|
x: _x - _w / 2,
|
|
|
|
|
y: _y,
|
|
|
|
|
w: _w,
|
|
|
|
|
h: _h,
|
|
|
|
|
id: text + (selected ? "1" : "0")
|
|
|
|
|
}, ctx => {
|
|
|
|
|
var textConfig = {
|
|
|
|
|
ctx: ctx,
|
|
|
|
|
text: text,
|
|
|
|
|
x: _w / 2,
|
|
|
|
|
y: 18,
|
|
|
|
|
width: _w,
|
|
|
|
|
height: _h - 54,
|
|
|
|
|
fontSize: 40,
|
|
|
|
|
fontFamily: this.font,
|
|
|
|
|
letterSpacing: -1
|
|
|
|
|
}
|
|
|
|
|
if(selected){
|
|
|
|
|
textConfig.fill = "#fff"
|
|
|
|
|
textConfig.outline = "#000"
|
|
|
|
|
textConfig.outlineSize = 10
|
|
|
|
|
}else{
|
|
|
|
|
textConfig.fill = "#000"
|
|
|
|
|
}
|
|
|
|
|
this.draw.verticalText(textConfig)
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
var highlight = 0
|
|
|
|
|
if(this.state.moveHover === i){
|
|
|
|
|
highlight = 2
|
|
|
|
|
}else if(selected){
|
|
|
|
|
highlight = 1
|
|
|
|
|
}
|
|
|
|
|
if(highlight){
|
|
|
|
|
this.draw.highlight({
|
|
|
|
|
ctx: ctx,
|
|
|
|
|
x: _x - _w / 2 - 3.5,
|
|
|
|
|
y: _y - 3.5,
|
|
|
|
|
w: _w + 7,
|
|
|
|
|
h: _h + 7,
|
|
|
|
|
animate: highlight === 1,
|
|
|
|
|
animateMS: this.state.moveMS,
|
|
|
|
|
opacity: highlight === 2 ? 0.8 : 1,
|
|
|
|
|
radius: 30
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
break
|
2018-11-12 18:32:02 +08:00
|
|
|
|
}
|
|
|
|
|
|
2018-12-13 17:18:52 +08:00
|
|
|
|
ctx.restore()
|
2018-11-12 18:32:02 +08:00
|
|
|
|
}
|
2018-09-06 00:46:26 +08:00
|
|
|
|
}
|
2019-11-28 14:04:40 +08:00
|
|
|
|
addMs(input){
|
|
|
|
|
var split = strings.calibration.ms.split("%s")
|
|
|
|
|
var index = 0
|
|
|
|
|
var output = ""
|
|
|
|
|
var inputStrings = [(input > 0 ? "+" : "") + input.toString()]
|
|
|
|
|
split.forEach((string, i) => {
|
|
|
|
|
if(i !== 0){
|
|
|
|
|
output += inputStrings[index++]
|
|
|
|
|
}
|
|
|
|
|
output += string
|
|
|
|
|
})
|
|
|
|
|
return output
|
|
|
|
|
}
|
2018-10-25 22:18:41 +08:00
|
|
|
|
setBackground(){
|
|
|
|
|
var selectedSong = this.controller.selectedSong
|
2018-11-26 06:42:24 +08:00
|
|
|
|
var songSkinName = selectedSong.songSkin.name
|
2019-01-01 09:16:55 +08:00
|
|
|
|
var supportsBlend = "mixBlendMode" in this.songBg.style
|
2018-12-02 23:25:42 +08:00
|
|
|
|
var songLayers = [document.getElementById("layer1"), document.getElementById("layer2")]
|
2019-02-24 20:04:14 +08:00
|
|
|
|
var prefix = ""
|
2018-11-26 06:42:24 +08:00
|
|
|
|
|
|
|
|
|
if(!selectedSong.songSkin.song){
|
2018-11-24 00:53:29 +08:00
|
|
|
|
var id = selectedSong.songBg
|
2019-01-01 09:16:55 +08:00
|
|
|
|
this.songBg.classList.add("songbg-" + id)
|
2019-02-24 20:04:14 +08:00
|
|
|
|
this.setLayers(songLayers, "bg_song_" + id + (supportsBlend ? "" : "a"), supportsBlend)
|
2018-11-26 06:42:24 +08:00
|
|
|
|
}else if(selectedSong.songSkin.song !== "none"){
|
2019-02-24 20:04:14 +08:00
|
|
|
|
var prefix = selectedSong.songSkin.prefix || ""
|
2018-11-26 06:42:24 +08:00
|
|
|
|
var notStatic = selectedSong.songSkin.song !== "static"
|
|
|
|
|
if(notStatic){
|
2019-01-01 09:16:55 +08:00
|
|
|
|
this.songBg.classList.add("songbg-" + selectedSong.songSkin.song)
|
2018-11-26 06:42:24 +08:00
|
|
|
|
}
|
2019-02-03 20:04:25 +08:00
|
|
|
|
this.setLayers(songLayers, prefix + "bg_song_" + songSkinName + (notStatic ? "_" : ""), notStatic)
|
2015-07-17 16:22:46 +08:00
|
|
|
|
}
|
2018-11-24 02:52:24 +08:00
|
|
|
|
|
2018-11-26 06:42:24 +08:00
|
|
|
|
if(!selectedSong.songSkin.stage){
|
2019-01-01 09:16:55 +08:00
|
|
|
|
this.songStage.classList.add("song-stage-" + selectedSong.songStage)
|
2019-04-05 04:40:11 +08:00
|
|
|
|
this.setBgImage(this.songStage, assets.image["bg_stage_" + selectedSong.songStage].src)
|
2018-11-26 06:42:24 +08:00
|
|
|
|
}else if(selectedSong.songSkin.stage !== "none"){
|
2019-02-24 20:04:14 +08:00
|
|
|
|
var prefix = selectedSong.songSkin.prefix || ""
|
2019-02-03 20:04:25 +08:00
|
|
|
|
this.setBgImage(this.songStage, assets.image[prefix + "bg_stage_" + songSkinName].src)
|
2018-11-26 06:42:24 +08:00
|
|
|
|
}
|
|
|
|
|
}
|
2018-12-02 23:25:42 +08:00
|
|
|
|
setDonBg(){
|
|
|
|
|
var selectedSong = this.controller.selectedSong
|
|
|
|
|
var songSkinName = selectedSong.songSkin.name
|
|
|
|
|
var donLayers = []
|
2020-03-14 12:50:04 +08:00
|
|
|
|
var filename = !selectedSong.songSkin.don && this.player === 2 ? "bg_don2_" : "bg_don_"
|
2019-02-24 20:04:14 +08:00
|
|
|
|
var prefix = ""
|
2018-12-02 23:25:42 +08:00
|
|
|
|
|
|
|
|
|
this.donBg = document.createElement("div")
|
|
|
|
|
this.donBg.classList.add("donbg")
|
2020-03-14 12:50:04 +08:00
|
|
|
|
if(this.player === 2){
|
2018-12-02 23:25:42 +08:00
|
|
|
|
this.donBg.classList.add("donbg-bottom")
|
|
|
|
|
}
|
2018-12-03 00:36:04 +08:00
|
|
|
|
for(var layer = 1; layer <= 3; layer++){
|
2018-12-02 23:25:42 +08:00
|
|
|
|
var donLayer = document.createElement("div")
|
|
|
|
|
donLayer.classList.add("donlayer" + layer)
|
|
|
|
|
this.donBg.appendChild(donLayer)
|
2018-12-03 00:36:04 +08:00
|
|
|
|
if(layer !== 3){
|
|
|
|
|
donLayers.push(donLayer)
|
|
|
|
|
}
|
2018-12-02 23:25:42 +08:00
|
|
|
|
}
|
2019-01-01 09:16:55 +08:00
|
|
|
|
this.songBg.parentNode.insertBefore(this.donBg, this.songBg)
|
2018-12-02 23:25:42 +08:00
|
|
|
|
var asset1, asset2
|
|
|
|
|
if(!selectedSong.songSkin.don){
|
|
|
|
|
this.donBg.classList.add("donbg-" + selectedSong.donBg)
|
2019-02-24 20:04:14 +08:00
|
|
|
|
this.setLayers(donLayers, filename + selectedSong.donBg, true)
|
2018-12-03 00:36:04 +08:00
|
|
|
|
asset1 = filename + selectedSong.donBg + "a"
|
|
|
|
|
asset2 = filename + selectedSong.donBg + "b"
|
2018-12-02 23:25:42 +08:00
|
|
|
|
}else if(selectedSong.songSkin.don !== "none"){
|
2019-02-24 20:04:14 +08:00
|
|
|
|
var prefix = selectedSong.songSkin.prefix || ""
|
2018-12-02 23:25:42 +08:00
|
|
|
|
var notStatic = selectedSong.songSkin.don !== "static"
|
|
|
|
|
if(notStatic){
|
|
|
|
|
this.donBg.classList.add("donbg-" + selectedSong.songSkin.don)
|
2018-12-03 00:36:04 +08:00
|
|
|
|
asset1 = filename + songSkinName + "_a"
|
|
|
|
|
asset2 = filename + songSkinName + "_b"
|
2018-12-02 23:25:42 +08:00
|
|
|
|
}else{
|
2018-12-03 00:36:04 +08:00
|
|
|
|
asset1 = filename + songSkinName
|
|
|
|
|
asset2 = filename + songSkinName
|
2018-12-02 23:25:42 +08:00
|
|
|
|
}
|
2019-02-03 20:04:25 +08:00
|
|
|
|
this.setLayers(donLayers, prefix + filename + songSkinName + (notStatic ? "_" : ""), notStatic)
|
|
|
|
|
}else{
|
|
|
|
|
return
|
2018-12-02 23:25:42 +08:00
|
|
|
|
}
|
2019-02-03 20:04:25 +08:00
|
|
|
|
var w1 = assets.image[prefix + asset1].width
|
|
|
|
|
var w2 = assets.image[prefix + asset2].width
|
2019-01-28 09:57:18 +08:00
|
|
|
|
this.donBg.style.setProperty("--sw", w1 > w2 ? w1 : w2)
|
|
|
|
|
this.donBg.style.setProperty("--sw1", w1)
|
|
|
|
|
this.donBg.style.setProperty("--sw2", w2)
|
2019-02-03 20:04:25 +08:00
|
|
|
|
this.donBg.style.setProperty("--sh1", assets.image[prefix + asset1].height)
|
|
|
|
|
this.donBg.style.setProperty("--sh2", assets.image[prefix + asset2].height)
|
2018-12-02 23:25:42 +08:00
|
|
|
|
}
|
|
|
|
|
setDonBgHeight(){
|
|
|
|
|
this.donBg.style.setProperty("--h", getComputedStyle(this.donBg).height)
|
2019-04-05 04:40:11 +08:00
|
|
|
|
var gameDiv = this.gameDiv
|
|
|
|
|
gameDiv.classList.add("fix-animations")
|
2019-03-06 05:48:30 +08:00
|
|
|
|
setTimeout(()=>{
|
2019-04-05 04:40:11 +08:00
|
|
|
|
gameDiv.classList.remove("fix-animations")
|
2019-03-06 05:48:30 +08:00
|
|
|
|
}, 50)
|
2018-12-02 23:25:42 +08:00
|
|
|
|
}
|
|
|
|
|
setLayers(elements, file, ab){
|
2018-11-26 06:42:24 +08:00
|
|
|
|
if(ab){
|
2018-12-02 23:25:42 +08:00
|
|
|
|
this.setBgImage(elements[0], assets.image[file + "a"].src)
|
|
|
|
|
this.setBgImage(elements[1], assets.image[file + "b"].src)
|
2018-11-26 06:42:24 +08:00
|
|
|
|
}else{
|
2018-12-02 23:25:42 +08:00
|
|
|
|
this.setBgImage(elements[0], assets.image[file].src)
|
2018-11-26 06:42:24 +08:00
|
|
|
|
}
|
2018-11-24 00:53:29 +08:00
|
|
|
|
}
|
|
|
|
|
setBgImage(element, url){
|
|
|
|
|
element.style.backgroundImage = "url('" + url + "')"
|
2018-09-06 00:46:26 +08:00
|
|
|
|
}
|
2018-10-25 22:18:41 +08:00
|
|
|
|
|
|
|
|
|
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
|
|
|
|
|
|
|
|
|
|
measures.forEach(measure => {
|
|
|
|
|
var timeForDistance = this.posToMs(distanceForCircle, measure.speed)
|
2019-11-28 14:04:40 +08:00
|
|
|
|
var startingTime = measure.ms - timeForDistance + this.controller.videoLatency
|
|
|
|
|
var finishTime = measure.ms + this.posToMs(this.slotPos.x - this.slotPos.paddingLeft + 3, measure.speed) + this.controller.videoLatency
|
2019-02-18 00:26:46 +08:00
|
|
|
|
if(measure.visible && (!measure.branch || measure.branch.active) && ms >= startingTime && ms <= finishTime){
|
2019-11-28 14:04:40 +08:00
|
|
|
|
var measureX = this.slotPos.x + this.msToPos(measure.ms - ms + this.controller.videoLatency, measure.speed)
|
2019-02-21 04:48:21 +08:00
|
|
|
|
this.ctx.strokeStyle = measure.branchFirst ? "#ff0" : "#bdbdbd"
|
2018-10-25 22:18:41 +08:00
|
|
|
|
this.ctx.lineWidth = 3
|
|
|
|
|
this.ctx.beginPath()
|
|
|
|
|
this.ctx.moveTo(measureX, measureY)
|
|
|
|
|
this.ctx.lineTo(measureX, measureY + measureH)
|
|
|
|
|
this.ctx.stroke()
|
|
|
|
|
}
|
2019-02-18 00:26:46 +08:00
|
|
|
|
if(this.multiplayer !== 2 && ms >= measure.ms && measure.nextBranch && !measure.viewChecked && measure.gameChecked){
|
|
|
|
|
measure.viewChecked = true
|
2019-02-21 04:48:21 +08:00
|
|
|
|
if(measure.nextBranch.active !== this.branch){
|
|
|
|
|
this.branchAnimate.ms = ms
|
|
|
|
|
this.branchAnimate.fromBranch = this.branch
|
2019-02-18 00:26:46 +08:00
|
|
|
|
}
|
|
|
|
|
this.branch = measure.nextBranch.active
|
|
|
|
|
}
|
2018-10-25 22:18:41 +08:00
|
|
|
|
})
|
2018-09-15 22:34:53 +08:00
|
|
|
|
}
|
2018-10-25 22:18:41 +08:00
|
|
|
|
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.noteFace = {
|
|
|
|
|
small: face,
|
|
|
|
|
big: face + 2
|
|
|
|
|
}
|
|
|
|
|
}else{
|
|
|
|
|
this.noteFace = {
|
|
|
|
|
small: 0,
|
|
|
|
|
big: 3
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2018-09-15 22:34:53 +08:00
|
|
|
|
}
|
|
|
|
|
drawCircles(circles){
|
2018-10-25 22:18:41 +08:00
|
|
|
|
var distanceForCircle = this.winW / this.ratio - this.slotPos.x
|
2019-01-16 20:33:42 +08:00
|
|
|
|
var ms = this.getMS()
|
2018-10-25 22:18:41 +08:00
|
|
|
|
|
2018-09-06 00:46:26 +08:00
|
|
|
|
for(var i = circles.length; i--;){
|
|
|
|
|
var circle = circles[i]
|
2019-02-18 00:26:46 +08:00
|
|
|
|
var speed = circle.speed
|
2015-07-17 16:22:46 +08:00
|
|
|
|
|
2018-10-25 22:18:41 +08:00
|
|
|
|
var timeForDistance = this.posToMs(distanceForCircle + this.slotPos.size / 2, speed)
|
2019-11-28 14:04:40 +08:00
|
|
|
|
var startingTime = circle.ms - timeForDistance + this.controller.videoLatency
|
|
|
|
|
var finishTime = circle.endTime + this.posToMs(this.slotPos.x - this.slotPos.paddingLeft + this.slotPos.size * 2, speed) + this.controller.videoLatency
|
2018-09-06 00:46:26 +08:00
|
|
|
|
|
2019-02-18 00:26:46 +08:00
|
|
|
|
if(circle.isPlayed <= 0 || circle.score === 0){
|
|
|
|
|
if((!circle.branch || circle.branch.active) && ms >= startingTime && ms <= finishTime && circle.isPlayed !== -1){
|
2018-09-15 22:34:53 +08:00
|
|
|
|
this.drawCircle(circle)
|
|
|
|
|
}
|
2019-02-18 00:26:46 +08:00
|
|
|
|
}else if(!circle.animating){
|
2018-10-25 22:18:41 +08:00
|
|
|
|
// Start animation to gauge
|
2018-10-08 02:58:42 +08:00
|
|
|
|
circle.animate(ms)
|
2018-09-06 00:46:26 +08:00
|
|
|
|
}
|
2020-03-15 23:00:23 +08:00
|
|
|
|
}
|
|
|
|
|
var game = this.controller.game
|
|
|
|
|
for(var i = 0; i < game.songData.events.length; i++){
|
|
|
|
|
var event = game.songData.events[i]
|
|
|
|
|
if(ms - this.controller.audioLatency >= event.ms && !event.beatMSCopied && (!event.branch || event.branch.active)){
|
|
|
|
|
if(this.beatInterval !== event.beatMS){
|
|
|
|
|
this.changeBeatInterval(event.beatMS)
|
2020-03-12 12:59:28 +08:00
|
|
|
|
}
|
2020-03-15 23:00:23 +08:00
|
|
|
|
event.beatMSCopied = true
|
2020-03-12 12:59:28 +08:00
|
|
|
|
}
|
2020-03-15 23:00:23 +08:00
|
|
|
|
if(ms - this.controller.audioLatency >= event.ms && !event.gogoChecked && (!event.branch || event.branch.active)){
|
|
|
|
|
if(this.gogoTime != event.gogoTime){
|
|
|
|
|
this.toggleGogoTime(event)
|
2018-09-20 07:20:26 +08:00
|
|
|
|
}
|
2020-03-15 23:00:23 +08:00
|
|
|
|
event.gogoChecked = true
|
2018-09-20 07:20:26 +08:00
|
|
|
|
}
|
2018-10-25 22:18:41 +08:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
drawAnimatedCircles(circles){
|
2019-01-16 20:33:42 +08:00
|
|
|
|
var ms = this.getMS()
|
2018-10-25 22:18:41 +08:00
|
|
|
|
|
|
|
|
|
for(var i = 0; i < circles.length; i++){
|
|
|
|
|
var circle = circles[i]
|
|
|
|
|
|
2019-02-18 00:26:46 +08:00
|
|
|
|
if(circle.animating){
|
2018-10-25 22:18:41 +08:00
|
|
|
|
|
2019-02-18 00:26:46 +08:00
|
|
|
|
var animT = circle.animT
|
2018-10-25 22:18:41 +08:00
|
|
|
|
if(ms < animT + 490){
|
|
|
|
|
|
2019-01-27 02:29:13 +08:00
|
|
|
|
if(circle.fixedPos){
|
|
|
|
|
circle.fixedPos = false
|
|
|
|
|
circle.animT = ms
|
|
|
|
|
animT = ms
|
|
|
|
|
}
|
2018-10-25 22:18:41 +08:00
|
|
|
|
var animPoint = (ms - animT) / 490
|
|
|
|
|
var bezierPoint = this.calcBezierPoint(this.draw.easeOut(animPoint), this.animateBezier)
|
2018-09-15 22:34:53 +08:00
|
|
|
|
this.drawCircle(circle, {x: bezierPoint.x, y: bezierPoint.y})
|
2018-10-25 22:18:41 +08:00
|
|
|
|
|
|
|
|
|
}else if(ms < animT + 810){
|
|
|
|
|
var pos = this.animateBezier[3]
|
|
|
|
|
this.drawCircle(circle, pos, (ms - animT - 490) / 160)
|
|
|
|
|
}else{
|
2019-02-18 00:26:46 +08:00
|
|
|
|
circle.animationEnded = true
|
2015-07-17 16:22:46 +08:00
|
|
|
|
}
|
|
|
|
|
}
|
2018-09-06 00:46:26 +08:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
calcBezierPoint(t, data){
|
|
|
|
|
var at = 1 - t
|
2018-10-25 22:18:41 +08:00
|
|
|
|
data = data.slice()
|
2015-07-17 16:22:46 +08:00
|
|
|
|
|
2018-09-06 00:46:26 +08:00
|
|
|
|
for(var i = 1; i < data.length; i++){
|
|
|
|
|
for(var k = 0; k < data.length - i; k++){
|
2015-07-17 16:22:46 +08:00
|
|
|
|
data[k] = {
|
2018-09-06 00:46:26 +08:00
|
|
|
|
x: data[k].x * at + data[k + 1].x * t,
|
|
|
|
|
y: data[k].y * at + data[k + 1].y * t
|
|
|
|
|
}
|
2015-07-17 16:22:46 +08:00
|
|
|
|
}
|
|
|
|
|
}
|
2018-09-06 00:46:26 +08:00
|
|
|
|
return data[0]
|
2015-07-17 16:22:46 +08:00
|
|
|
|
}
|
2018-10-25 22:18:41 +08:00
|
|
|
|
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
|
|
|
|
|
|
2018-09-06 00:46:26 +08:00
|
|
|
|
var fill, size, faceID
|
2019-02-18 00:26:46 +08:00
|
|
|
|
var type = circle.type
|
2019-01-16 20:33:42 +08:00
|
|
|
|
var ms = this.getMS()
|
2019-02-18 00:26:46 +08:00
|
|
|
|
var circleMs = circle.ms
|
|
|
|
|
var endTime = circle.endTime
|
|
|
|
|
var animated = circle.animating
|
|
|
|
|
var speed = circle.speed
|
|
|
|
|
var played = circle.isPlayed
|
2018-10-25 22:18:41 +08:00
|
|
|
|
var drumroll = 0
|
|
|
|
|
var endX = 0
|
2018-09-15 22:34:53 +08:00
|
|
|
|
|
2018-09-06 00:46:26 +08:00
|
|
|
|
if(!circlePos){
|
|
|
|
|
circlePos = {
|
2019-11-28 14:04:40 +08:00
|
|
|
|
x: this.slotPos.x + this.msToPos(circleMs - ms + this.controller.videoLatency, speed),
|
2018-10-25 22:18:41 +08:00
|
|
|
|
y: this.slotPos.y
|
2018-09-06 00:46:26 +08:00
|
|
|
|
}
|
|
|
|
|
}
|
2018-09-15 22:34:53 +08:00
|
|
|
|
if(animated){
|
2018-10-25 22:18:41 +08:00
|
|
|
|
var noteFace = {
|
|
|
|
|
small: 0,
|
|
|
|
|
big: 3
|
|
|
|
|
}
|
2018-09-06 00:46:26 +08:00
|
|
|
|
}else{
|
2018-10-25 22:18:41 +08:00
|
|
|
|
var noteFace = this.noteFace
|
2018-09-06 00:46:26 +08:00
|
|
|
|
}
|
2018-09-19 01:33:18 +08:00
|
|
|
|
if(type === "don" || type === "daiDon" && played === 1){
|
|
|
|
|
fill = "#f34728"
|
2018-10-25 22:18:41 +08:00
|
|
|
|
size = circleSize
|
|
|
|
|
faceID = noteFace.small
|
2018-09-19 01:33:18 +08:00
|
|
|
|
}else if(type === "ka" || type === "daiKa" && played === 1){
|
|
|
|
|
fill = "#65bdbb"
|
2018-10-25 22:18:41 +08:00
|
|
|
|
size = circleSize
|
|
|
|
|
faceID = noteFace.small
|
2018-09-19 01:33:18 +08:00
|
|
|
|
}else if(type === "daiDon"){
|
|
|
|
|
fill = "#f34728"
|
2018-10-25 22:18:41 +08:00
|
|
|
|
size = bigCircleSize
|
|
|
|
|
faceID = noteFace.big
|
2018-09-19 01:33:18 +08:00
|
|
|
|
}else if(type === "daiKa"){
|
|
|
|
|
fill = "#65bdbb"
|
2018-10-25 22:18:41 +08:00
|
|
|
|
size = bigCircleSize
|
|
|
|
|
faceID = noteFace.big
|
2018-09-19 01:33:18 +08:00
|
|
|
|
}else if(type === "balloon"){
|
|
|
|
|
if(animated){
|
2018-09-15 22:34:53 +08:00
|
|
|
|
fill = "#f34728"
|
2018-10-25 22:18:41 +08:00
|
|
|
|
size = bigCircleSize * 0.8
|
|
|
|
|
faceID = noteFace.big
|
2018-09-19 01:33:18 +08:00
|
|
|
|
}else{
|
2018-09-15 22:34:53 +08:00
|
|
|
|
fill = "#f87700"
|
2018-10-25 22:18:41 +08:00
|
|
|
|
size = circleSize
|
|
|
|
|
faceID = noteFace.small
|
2018-09-15 22:34:53 +08:00
|
|
|
|
var h = size * 1.8
|
2019-11-28 14:04:40 +08:00
|
|
|
|
if(circleMs + this.controller.audioLatency < ms && ms <= endTime + this.controller.audioLatency){
|
2018-10-25 22:18:41 +08:00
|
|
|
|
circlePos.x = this.slotPos.x
|
2019-11-28 14:04:40 +08:00
|
|
|
|
}else if(ms > endTime + this.controller.audioLatency){
|
|
|
|
|
circlePos.x = this.slotPos.x + this.msToPos(endTime - ms + this.controller.audioLatency, speed)
|
2018-09-15 22:34:53 +08:00
|
|
|
|
}
|
2018-10-25 22:18:41 +08:00
|
|
|
|
ctx.drawImage(assets.image["balloon"],
|
|
|
|
|
circlePos.x + size - 4,
|
|
|
|
|
circlePos.y - h / 2 + 2,
|
2018-09-15 22:34:53 +08:00
|
|
|
|
h / 61 * 115,
|
|
|
|
|
h
|
|
|
|
|
)
|
2018-09-19 01:33:18 +08:00
|
|
|
|
}
|
|
|
|
|
}else if(type === "drumroll" || type === "daiDrumroll"){
|
|
|
|
|
fill = "#f3b500"
|
|
|
|
|
if(type == "drumroll"){
|
2018-10-25 22:18:41 +08:00
|
|
|
|
size = circleSize
|
|
|
|
|
faceID = noteFace.small
|
2018-09-19 01:33:18 +08:00
|
|
|
|
}else{
|
2018-10-25 22:18:41 +08:00
|
|
|
|
size = bigCircleSize
|
|
|
|
|
faceID = noteFace.big
|
2018-09-19 01:33:18 +08:00
|
|
|
|
}
|
2018-10-25 22:18:41 +08:00
|
|
|
|
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()
|
2018-09-06 00:46:26 +08:00
|
|
|
|
}
|
2018-10-25 22:18:41 +08:00
|
|
|
|
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
|
2018-10-03 22:22:40 +08:00
|
|
|
|
)
|
|
|
|
|
}
|
2018-10-25 22:18:41 +08:00
|
|
|
|
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
|
|
|
|
|
}
|
2019-03-16 05:34:48 +08:00
|
|
|
|
if(!circle.animating && circle.text){
|
2018-10-25 22:18:41 +08:00
|
|
|
|
// Text
|
2019-02-18 00:26:46 +08:00
|
|
|
|
var text = circle.text
|
2018-10-25 22:18:41 +08:00
|
|
|
|
var textX = circlePos.x
|
|
|
|
|
var textY = circlePos.y + 83 * mul
|
2019-01-21 23:47:22 +08:00
|
|
|
|
ctx.font = lyricsSize + "px Kozuka, Microsoft YaHei, sans-serif"
|
2018-10-25 22:18:41 +08:00
|
|
|
|
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
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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)
|
|
|
|
|
|
2018-10-28 02:35:04 +08:00
|
|
|
|
if(drumroll === 2){
|
2018-10-25 22:18:41 +08:00
|
|
|
|
ctx.strokeText(longText[1], textX + endX, textY)
|
|
|
|
|
ctx.fillText(longText[1], textX + endX, textY)
|
|
|
|
|
}
|
2018-10-03 17:48:18 +08:00
|
|
|
|
}
|
2018-09-06 00:46:26 +08:00
|
|
|
|
}
|
2018-10-25 22:18:41 +08:00
|
|
|
|
fillComboCache(){
|
|
|
|
|
var fontSize = 58
|
|
|
|
|
var letterSpacing = fontSize * 0.67
|
Custom scripting, #song=, translations
- A song can be linked directly by adding "#song=<id>" to the url, replace `<id>` with the id in the database, after loading it jumps immediately jumps to the difficulty selection
- Added tutorial translations
- Fixed song preview not playing
- Use text fallback for the logo when there are no vectors
- Increased combo cache by 1 pixel
- A custom javascript file can be loaded from config.json by defining "custom_js" value
- Added lots of events to help writing custom js files: `version-link, title-screen, language-change, song-select, song-select-move, song-select-difficulty, song-select-back, about, about-link, tutorial, import-songs, import-songs-default, session, session-start, session-end, debug, load-song, load-song-player2, load-song-unfocused, load-song-cancel, load-song-error, game-start, key-events, p2-game-end, p2-disconnected, p2-abandoned, pause, unpause, pause-restart, pause-song-select, game-lag, scoresheet, scoresheet-player2`
- Event syntax example:
```js
addEventListener("game-start", event => {
console.log("game-start", event.detail)
})
```
2019-02-14 17:32:45 +08:00
|
|
|
|
var glyphW = 51
|
|
|
|
|
var glyphH = 65
|
2018-11-21 18:50:48 +08:00
|
|
|
|
var textX = 5
|
2018-10-25 22:18:41 +08:00
|
|
|
|
var textY = 5
|
|
|
|
|
var letterBorder = fontSize * 0.15
|
2018-09-06 00:46:26 +08:00
|
|
|
|
|
2018-10-25 22:18:41 +08:00
|
|
|
|
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,
|
2019-01-21 23:47:22 +08:00
|
|
|
|
fontFamily: "TnT, Meiryo, sans-serif",
|
2018-10-25 22:18:41 +08:00
|
|
|
|
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}
|
|
|
|
|
])
|
|
|
|
|
})
|
2018-09-20 07:20:26 +08:00
|
|
|
|
}
|
|
|
|
|
}
|
2018-10-25 22:18:41 +08:00
|
|
|
|
this.globalAlpha = 0
|
|
|
|
|
this.comboCache.get({
|
|
|
|
|
ctx: this.ctx,
|
|
|
|
|
x: 0,
|
|
|
|
|
y: 0,
|
|
|
|
|
w: 54,
|
|
|
|
|
h: 77,
|
|
|
|
|
id: "combo0"
|
|
|
|
|
})
|
|
|
|
|
this.globalAlpha = 1
|
2018-09-06 00:46:26 +08:00
|
|
|
|
}
|
2019-02-21 04:48:21 +08:00
|
|
|
|
fillBranchCache(){
|
|
|
|
|
var mul = this.slotPos.size / 106
|
|
|
|
|
var textW = Math.floor(260 * mul)
|
|
|
|
|
var barH = Math.floor(130 * mul)
|
|
|
|
|
var branchNames = this.controller.game.branchNames
|
|
|
|
|
var textX = textW - 33 * mul
|
|
|
|
|
var textY = 63 * mul
|
|
|
|
|
var fontSize = (strings.id === "en" ? 33 : (strings.id === "ko" ? 38 : 43)) * mul
|
|
|
|
|
this.branchCache.resize((textW + 1), (barH + 1) * 3, this.ratio)
|
|
|
|
|
for(var i in branchNames){
|
|
|
|
|
this.branchCache.set({
|
|
|
|
|
w: textW,
|
|
|
|
|
h: barH,
|
|
|
|
|
id: branchNames[i]
|
|
|
|
|
}, ctx => {
|
|
|
|
|
var currentMap = this.branchMap[branchNames[i]]
|
|
|
|
|
ctx.font = this.draw.bold(this.font) + fontSize + "px " + this.font
|
|
|
|
|
ctx.lineJoin = "round"
|
|
|
|
|
ctx.miterLimit = 1
|
|
|
|
|
ctx.textAlign = "right"
|
|
|
|
|
ctx.textBaseline = "middle"
|
|
|
|
|
ctx.lineWidth = 8 * mul
|
|
|
|
|
ctx.strokeStyle = currentMap.shadow
|
|
|
|
|
ctx.strokeText(strings.branch[branchNames[i]], textX, textY + 4 * mul)
|
|
|
|
|
ctx.strokeStyle = currentMap.stroke
|
|
|
|
|
ctx.strokeText(strings.branch[branchNames[i]], textX, textY)
|
|
|
|
|
ctx.fillStyle = currentMap.text
|
|
|
|
|
ctx.fillText(strings.branch[branchNames[i]], textX, textY)
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
}
|
2018-09-20 07:20:26 +08:00
|
|
|
|
toggleGogoTime(circle){
|
2020-03-12 12:59:28 +08:00
|
|
|
|
var startMS = circle.ms + this.controller.audioLatency
|
2018-09-20 07:20:26 +08:00
|
|
|
|
this.gogoTime = circle.gogoTime
|
2019-11-28 14:04:40 +08:00
|
|
|
|
if(circle.gogoTime || this.gogoTimeStarted !== -Infinity){
|
2020-03-12 12:59:28 +08:00
|
|
|
|
this.gogoTimeStarted = startMS
|
2019-11-28 14:04:40 +08:00
|
|
|
|
}
|
2018-09-20 21:11:19 +08:00
|
|
|
|
|
2018-09-20 07:20:26 +08:00
|
|
|
|
if(this.gogoTime){
|
|
|
|
|
this.assets.fireworks.forEach(fireworksAsset => {
|
|
|
|
|
fireworksAsset.setAnimation("normal")
|
2020-03-12 12:59:28 +08:00
|
|
|
|
fireworksAsset.setAnimationStart(startMS)
|
2018-09-20 07:20:26 +08:00
|
|
|
|
var length = fireworksAsset.getAnimationLength("normal")
|
2018-10-12 04:24:18 +08:00
|
|
|
|
fireworksAsset.setAnimationEnd(length, () => {
|
2018-09-20 07:20:26 +08:00
|
|
|
|
fireworksAsset.setAnimation(false)
|
|
|
|
|
})
|
|
|
|
|
})
|
|
|
|
|
this.assets.fire.setAnimation("normal")
|
|
|
|
|
var don = this.assets.don
|
|
|
|
|
don.setAnimation("gogostart")
|
2018-09-20 21:11:19 +08:00
|
|
|
|
var length = don.getAnimationLength("gogo")
|
2018-10-12 04:24:18 +08:00
|
|
|
|
don.setUpdateSpeed(4 / length)
|
2020-03-12 12:59:28 +08:00
|
|
|
|
var start = startMS - (startMS % this.beatInterval)
|
2018-09-20 21:11:19 +08:00
|
|
|
|
don.setAnimationStart(start)
|
2018-09-20 07:20:26 +08:00
|
|
|
|
var length = don.getAnimationLength("gogostart")
|
2018-10-12 04:24:18 +08:00
|
|
|
|
don.setAnimationEnd(length, don.normalAnimation)
|
2018-09-14 06:55:23 +08:00
|
|
|
|
}
|
|
|
|
|
}
|
2018-09-20 07:20:26 +08:00
|
|
|
|
drawGogoTime(){
|
2018-10-25 22:18:41 +08:00
|
|
|
|
var ms = this.getMS()
|
2018-09-20 21:11:19 +08:00
|
|
|
|
|
2018-09-20 07:20:26 +08:00
|
|
|
|
if(this.gogoTime){
|
|
|
|
|
var circles = this.controller.parsedSongData.circles
|
|
|
|
|
var lastCircle = circles[circles.length - 1]
|
2019-02-18 00:26:46 +08:00
|
|
|
|
var endTime = lastCircle.endTime + 3000
|
2018-09-20 07:20:26 +08:00
|
|
|
|
if(ms >= endTime){
|
|
|
|
|
this.toggleGogoTime({
|
|
|
|
|
gogoTime: 0,
|
|
|
|
|
ms: endTime
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
}else{
|
2018-09-26 08:26:42 +08:00
|
|
|
|
var animation = this.assets.don.getAnimation()
|
2020-03-05 23:58:49 +08:00
|
|
|
|
var score = this.controller.getGlobalScore()
|
|
|
|
|
var cleared = this.rules.clearReached(score.gauge)
|
2018-10-25 22:18:41 +08:00
|
|
|
|
if(animation === "gogo" || cleared && animation === "normal" || !cleared && animation === "clear"){
|
2018-09-20 21:11:19 +08:00
|
|
|
|
this.assets.don.normalAnimation()
|
2018-09-20 07:20:26 +08:00
|
|
|
|
}
|
|
|
|
|
if(ms >= this.gogoTimeStarted + 100){
|
|
|
|
|
this.assets.fire.setAnimation(false)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2018-09-14 06:55:23 +08:00
|
|
|
|
updateCombo(combo){
|
2018-09-20 07:20:26 +08:00
|
|
|
|
var don = this.assets.don
|
|
|
|
|
var animation = don.getAnimation()
|
|
|
|
|
if(
|
|
|
|
|
combo > 0
|
|
|
|
|
&& combo % 10 === 0
|
|
|
|
|
&& animation !== "10combo"
|
|
|
|
|
&& animation !== "gogostart"
|
|
|
|
|
&& animation !== "gogo"
|
|
|
|
|
){
|
|
|
|
|
don.setAnimation("10combo")
|
2019-01-16 20:33:42 +08:00
|
|
|
|
var ms = this.getMS()
|
2018-09-20 07:20:26 +08:00
|
|
|
|
don.setAnimationStart(ms)
|
2018-09-26 08:26:42 +08:00
|
|
|
|
var length = don.getAnimationLength("normal")
|
2018-10-12 04:24:18 +08:00
|
|
|
|
don.setUpdateSpeed(4 / length)
|
2018-09-20 07:20:26 +08:00
|
|
|
|
var length = don.getAnimationLength("10combo")
|
2018-10-12 04:24:18 +08:00
|
|
|
|
don.setAnimationEnd(length, don.normalAnimation)
|
2018-09-14 06:55:23 +08:00
|
|
|
|
}
|
|
|
|
|
}
|
2018-10-25 22:18:41 +08:00
|
|
|
|
displayScore(score, notPlayed, bigNote){
|
|
|
|
|
if(!notPlayed){
|
|
|
|
|
this.currentScore.ms = this.getMS()
|
|
|
|
|
this.currentScore.type = score
|
|
|
|
|
this.currentScore.bigNote = bigNote
|
2018-11-15 16:42:22 +08:00
|
|
|
|
|
|
|
|
|
if(score > 0){
|
|
|
|
|
var explosion = this.assets.explosion
|
|
|
|
|
explosion.type = (bigNote ? 0 : 2) + (score === 450 ? 0 : 1)
|
|
|
|
|
explosion.setAnimation("normal")
|
|
|
|
|
explosion.setAnimationStart(this.getMS())
|
|
|
|
|
explosion.setAnimationEnd(bigNote ? 14 : 7, () => {
|
|
|
|
|
explosion.setAnimation(false)
|
|
|
|
|
})
|
|
|
|
|
}
|
2018-12-03 00:53:12 +08:00
|
|
|
|
this.setDarkBg(score === 0)
|
2018-12-03 00:36:04 +08:00
|
|
|
|
}else{
|
2018-12-03 00:53:12 +08:00
|
|
|
|
this.setDarkBg(true)
|
2018-12-03 00:36:04 +08:00
|
|
|
|
}
|
2018-12-03 00:53:12 +08:00
|
|
|
|
}
|
|
|
|
|
setDarkBg(miss){
|
2018-12-03 00:36:04 +08:00
|
|
|
|
if(!miss && this.darkDonBg){
|
|
|
|
|
this.darkDonBg = false
|
|
|
|
|
this.donBg.classList.remove("donbg-dark")
|
|
|
|
|
}else if(miss && !this.darkDonBg){
|
|
|
|
|
this.darkDonBg = true
|
|
|
|
|
this.donBg.classList.add("donbg-dark")
|
2018-10-25 22:18:41 +08:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
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
|
|
|
|
|
}
|
2018-10-06 01:03:59 +08:00
|
|
|
|
drawTouch(){
|
|
|
|
|
if(this.touchEnabled){
|
2018-10-25 22:18:41 +08:00
|
|
|
|
var ms = this.getMS()
|
|
|
|
|
var mul = this.ratio / this.pixelRatio
|
2018-10-06 01:03:59 +08:00
|
|
|
|
|
2018-10-25 22:18:41 +08:00
|
|
|
|
var drumWidth = this.touchDrum.w * mul
|
|
|
|
|
var drumHeight = this.touchDrum.h * mul
|
2018-10-06 01:03:59 +08:00
|
|
|
|
if(drumHeight !== this.touchDrumHeight || drumWidth !== this.touchDrumWidth){
|
|
|
|
|
this.touchDrumWidth = drumWidth
|
|
|
|
|
this.touchDrumHeight = drumHeight
|
|
|
|
|
this.touchDrumDiv.style.width = drumWidth + "px"
|
|
|
|
|
this.touchDrumDiv.style.height = drumHeight + "px"
|
|
|
|
|
}
|
2019-04-05 04:40:11 +08:00
|
|
|
|
if(this.touchAnimation){
|
|
|
|
|
if(this.touch > ms - 100){
|
|
|
|
|
if(!this.drumPadding){
|
|
|
|
|
this.drumPadding = true
|
|
|
|
|
this.touchDrumImg.style.backgroundPositionY = "7px"
|
|
|
|
|
}
|
|
|
|
|
}else if(this.drumPadding){
|
|
|
|
|
this.drumPadding = false
|
|
|
|
|
this.touchDrumImg.style.backgroundPositionY = ""
|
2018-10-06 01:03:59 +08:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
ontouch(event){
|
2018-11-27 07:05:02 +08:00
|
|
|
|
if(!("changedTouches" in event)){
|
|
|
|
|
event.changedTouches = [event]
|
|
|
|
|
}
|
|
|
|
|
for(var i = 0; i < event.changedTouches.length; i++){
|
|
|
|
|
var touch = event.changedTouches[i]
|
2018-10-06 01:03:59 +08:00
|
|
|
|
event.preventDefault()
|
2018-11-14 02:44:04 +08:00
|
|
|
|
if(this.controller.game.paused){
|
2018-11-27 07:05:02 +08:00
|
|
|
|
var mouse = this.mouseOffset(touch.pageX, touch.pageY)
|
2018-11-14 02:44:04 +08:00
|
|
|
|
var moveTo = this.pauseMouse(mouse.x, mouse.y)
|
|
|
|
|
if(moveTo !== null){
|
|
|
|
|
this.pauseConfirm(moveTo)
|
2018-10-06 21:24:23 +08:00
|
|
|
|
}
|
2018-11-15 16:42:22 +08:00
|
|
|
|
}else if(!this.controller.autoPlayEnabled){
|
2018-11-14 02:44:04 +08:00
|
|
|
|
var pageX = touch.pageX * this.pixelRatio
|
|
|
|
|
var pageY = touch.pageY * this.pixelRatio
|
|
|
|
|
|
|
|
|
|
var c = this.touchCircle
|
|
|
|
|
var pi = Math.PI
|
|
|
|
|
var inPath = () => this.ctx.isPointInPath(pageX, pageY)
|
|
|
|
|
|
|
|
|
|
this.ctx.beginPath()
|
|
|
|
|
this.ctx.ellipse(c.x, c.y, c.rx, c.ry, 0, pi, 0)
|
|
|
|
|
|
|
|
|
|
if(inPath()){
|
|
|
|
|
if(pageX < this.winW / 2){
|
|
|
|
|
this.touchNote("don_l")
|
|
|
|
|
}else{
|
|
|
|
|
this.touchNote("don_r")
|
|
|
|
|
}
|
2018-10-06 01:03:59 +08:00
|
|
|
|
}else{
|
2018-11-14 02:44:04 +08:00
|
|
|
|
if(pageX < this.winW / 2){
|
|
|
|
|
this.touchNote("ka_l")
|
|
|
|
|
}else{
|
|
|
|
|
this.touchNote("ka_r")
|
|
|
|
|
}
|
2018-10-06 01:03:59 +08:00
|
|
|
|
}
|
2019-02-15 06:10:34 +08:00
|
|
|
|
this.touchEvents++
|
2018-10-06 01:03:59 +08:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
touchNote(note){
|
|
|
|
|
var keyboard = this.controller.keyboard
|
|
|
|
|
var ms = this.controller.game.getAccurateTime()
|
2018-10-06 21:24:23 +08:00
|
|
|
|
this.touch = ms
|
2019-04-17 02:06:41 +08:00
|
|
|
|
keyboard.setKey(false, note)
|
|
|
|
|
keyboard.setKey(true, note, ms)
|
2018-10-06 01:03:59 +08:00
|
|
|
|
}
|
2018-11-12 18:32:02 +08:00
|
|
|
|
mod(length, index){
|
|
|
|
|
return ((index % length) + length) % length
|
|
|
|
|
}
|
|
|
|
|
pauseMove(pos, absolute){
|
|
|
|
|
if(absolute){
|
|
|
|
|
this.state.pausePos = pos
|
|
|
|
|
}else{
|
|
|
|
|
this.state.pausePos = this.mod(this.pauseOptions.length, this.state.pausePos + pos)
|
|
|
|
|
}
|
2018-12-13 17:18:52 +08:00
|
|
|
|
this.state.moveMS = Date.now() - (absolute ? 0 : 500)
|
2018-11-12 18:32:02 +08:00
|
|
|
|
this.state.moveHover = null
|
|
|
|
|
}
|
|
|
|
|
pauseConfirm(pos){
|
|
|
|
|
if(typeof pos === "undefined"){
|
|
|
|
|
pos = this.state.pausePos
|
|
|
|
|
}
|
2019-11-28 14:04:40 +08:00
|
|
|
|
var game = this.controller.game
|
|
|
|
|
var state = game.calibrationState
|
|
|
|
|
switch(state){
|
|
|
|
|
case "audioHelp":
|
|
|
|
|
pos = pos === 0 ? 2 : 0
|
|
|
|
|
break
|
|
|
|
|
case "videoHelp":
|
|
|
|
|
if(pos === 0){
|
|
|
|
|
assets.sounds["se_don"].play()
|
|
|
|
|
game.calibrationReset("audio")
|
|
|
|
|
return
|
|
|
|
|
}else{
|
|
|
|
|
pos = 0
|
|
|
|
|
}
|
|
|
|
|
break
|
|
|
|
|
case "results":
|
|
|
|
|
if(pos === 0){
|
|
|
|
|
assets.sounds["se_don"].play()
|
|
|
|
|
game.calibrationReset("video")
|
|
|
|
|
return
|
|
|
|
|
}else{
|
|
|
|
|
var input = settings.getItem("latency")
|
|
|
|
|
var output = {}
|
|
|
|
|
var progress = game.calibrationProgress
|
|
|
|
|
for(var i in input){
|
|
|
|
|
if(i === "audio" || i === "video"){
|
|
|
|
|
output[i] = progress[i]
|
|
|
|
|
}else{
|
|
|
|
|
output[i] = input[i]
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
settings.setItem("latency", output)
|
|
|
|
|
pos = 2
|
|
|
|
|
}
|
|
|
|
|
break
|
|
|
|
|
}
|
2018-11-12 18:32:02 +08:00
|
|
|
|
switch(pos){
|
|
|
|
|
case 1:
|
2019-11-28 14:04:40 +08:00
|
|
|
|
this.controller.playSound("se_don", 0, true)
|
|
|
|
|
if(state === "video"){
|
|
|
|
|
game.calibrationReset(state)
|
|
|
|
|
}else{
|
|
|
|
|
this.controller.restartSong()
|
|
|
|
|
}
|
Custom scripting, #song=, translations
- A song can be linked directly by adding "#song=<id>" to the url, replace `<id>` with the id in the database, after loading it jumps immediately jumps to the difficulty selection
- Added tutorial translations
- Fixed song preview not playing
- Use text fallback for the logo when there are no vectors
- Increased combo cache by 1 pixel
- A custom javascript file can be loaded from config.json by defining "custom_js" value
- Added lots of events to help writing custom js files: `version-link, title-screen, language-change, song-select, song-select-move, song-select-difficulty, song-select-back, about, about-link, tutorial, import-songs, import-songs-default, session, session-start, session-end, debug, load-song, load-song-player2, load-song-unfocused, load-song-cancel, load-song-error, game-start, key-events, p2-game-end, p2-disconnected, p2-abandoned, pause, unpause, pause-restart, pause-song-select, game-lag, scoresheet, scoresheet-player2`
- Event syntax example:
```js
addEventListener("game-start", event => {
console.log("game-start", event.detail)
})
```
2019-02-14 17:32:45 +08:00
|
|
|
|
pageEvents.send("pause-restart")
|
|
|
|
|
break
|
2018-11-12 18:32:02 +08:00
|
|
|
|
case 2:
|
2019-11-28 14:04:40 +08:00
|
|
|
|
this.controller.playSound("se_don", 0, true)
|
Custom scripting, #song=, translations
- A song can be linked directly by adding "#song=<id>" to the url, replace `<id>` with the id in the database, after loading it jumps immediately jumps to the difficulty selection
- Added tutorial translations
- Fixed song preview not playing
- Use text fallback for the logo when there are no vectors
- Increased combo cache by 1 pixel
- A custom javascript file can be loaded from config.json by defining "custom_js" value
- Added lots of events to help writing custom js files: `version-link, title-screen, language-change, song-select, song-select-move, song-select-difficulty, song-select-back, about, about-link, tutorial, import-songs, import-songs-default, session, session-start, session-end, debug, load-song, load-song-player2, load-song-unfocused, load-song-cancel, load-song-error, game-start, key-events, p2-game-end, p2-disconnected, p2-abandoned, pause, unpause, pause-restart, pause-song-select, game-lag, scoresheet, scoresheet-player2`
- Event syntax example:
```js
addEventListener("game-start", event => {
console.log("game-start", event.detail)
})
```
2019-02-14 17:32:45 +08:00
|
|
|
|
this.controller.songSelection()
|
|
|
|
|
pageEvents.send("pause-song-select")
|
|
|
|
|
break
|
2018-11-12 18:32:02 +08:00
|
|
|
|
default:
|
2019-11-28 14:04:40 +08:00
|
|
|
|
this.controller.togglePause(false)
|
Custom scripting, #song=, translations
- A song can be linked directly by adding "#song=<id>" to the url, replace `<id>` with the id in the database, after loading it jumps immediately jumps to the difficulty selection
- Added tutorial translations
- Fixed song preview not playing
- Use text fallback for the logo when there are no vectors
- Increased combo cache by 1 pixel
- A custom javascript file can be loaded from config.json by defining "custom_js" value
- Added lots of events to help writing custom js files: `version-link, title-screen, language-change, song-select, song-select-move, song-select-difficulty, song-select-back, about, about-link, tutorial, import-songs, import-songs-default, session, session-start, session-end, debug, load-song, load-song-player2, load-song-unfocused, load-song-cancel, load-song-error, game-start, key-events, p2-game-end, p2-disconnected, p2-abandoned, pause, unpause, pause-restart, pause-song-select, game-lag, scoresheet, scoresheet-player2`
- Event syntax example:
```js
addEventListener("game-start", event => {
console.log("game-start", event.detail)
})
```
2019-02-14 17:32:45 +08:00
|
|
|
|
break
|
2018-11-12 18:32:02 +08:00
|
|
|
|
}
|
2019-11-28 14:04:40 +08:00
|
|
|
|
return true
|
2018-11-12 18:32:02 +08:00
|
|
|
|
}
|
|
|
|
|
onmousedown(event){
|
|
|
|
|
if(this.controller.game.paused){
|
2018-11-14 02:44:04 +08:00
|
|
|
|
if(event.which !== 1){
|
|
|
|
|
return
|
2018-11-12 18:32:02 +08:00
|
|
|
|
}
|
2018-11-14 02:44:04 +08:00
|
|
|
|
var mouse = this.mouseOffset(event.offsetX, event.offsetY)
|
2018-11-12 18:32:02 +08:00
|
|
|
|
var moveTo = this.pauseMouse(mouse.x, mouse.y)
|
|
|
|
|
if(moveTo !== null){
|
|
|
|
|
this.pauseConfirm(moveTo)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2018-09-18 21:59:40 +08:00
|
|
|
|
onmousemove(event){
|
2018-11-24 22:09:08 +08:00
|
|
|
|
this.lastMousemove = this.getMS()
|
2018-09-18 21:59:40 +08:00
|
|
|
|
this.cursorHidden = false
|
2018-11-12 18:32:02 +08:00
|
|
|
|
|
|
|
|
|
if(!this.multiplayer && this.controller.game.paused){
|
|
|
|
|
var mouse = this.mouseOffset(event.offsetX, event.offsetY)
|
|
|
|
|
var moveTo = this.pauseMouse(mouse.x, mouse.y)
|
|
|
|
|
if(moveTo === null && this.state.moveHover === this.state.pausePos){
|
2018-12-13 17:18:52 +08:00
|
|
|
|
this.state.moveMS = Date.now() - 500
|
2018-11-12 18:32:02 +08:00
|
|
|
|
}
|
|
|
|
|
this.state.moveHover = moveTo
|
|
|
|
|
this.pointer(moveTo !== null)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
mouseOffset(offsetX, offsetY){
|
|
|
|
|
return {
|
|
|
|
|
x: (offsetX * this.pixelRatio - this.winW / 2) / this.ratio + (this.portrait ? 720 : 1280) / 2,
|
|
|
|
|
y: (offsetY * this.pixelRatio - this.winH / 2) / this.ratio + (this.portrait ? 1280 : 720) / 2
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
pointer(enabled){
|
|
|
|
|
if(!this.canvas){
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
if(enabled && this.state.hasPointer === false){
|
|
|
|
|
this.canvas.style.cursor = "pointer"
|
|
|
|
|
this.state.hasPointer = true
|
|
|
|
|
}else if(!enabled && this.state.hasPointer === true){
|
|
|
|
|
this.canvas.style.cursor = ""
|
|
|
|
|
this.state.hasPointer = false
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
pauseMouse(x, y){
|
|
|
|
|
if(this.portrait){
|
|
|
|
|
var pauseScale = 766 / 720
|
|
|
|
|
x = x * pauseScale + 257
|
|
|
|
|
y = y * pauseScale - 328
|
|
|
|
|
}
|
2019-11-28 14:04:40 +08:00
|
|
|
|
switch(this.controller.game.calibrationState){
|
|
|
|
|
case "audioHelp":
|
|
|
|
|
case "videoHelp":
|
|
|
|
|
case "results":
|
|
|
|
|
if(554 - 90 * this.pauseOptions.length <= y && y <= 554 && 404 <= x && x <= 876){
|
|
|
|
|
return Math.floor((y - 554 + 90 * this.pauseOptions.length) / 90)
|
|
|
|
|
}
|
|
|
|
|
break
|
|
|
|
|
default:
|
|
|
|
|
if(104 <= y && y <= 575 && 465 <= x && x <= 465 + 110 * this.pauseOptions.length){
|
|
|
|
|
return Math.floor((x - 465) / 110)
|
|
|
|
|
}
|
|
|
|
|
break
|
2018-11-12 18:32:02 +08:00
|
|
|
|
}
|
|
|
|
|
return null
|
2018-09-18 21:59:40 +08:00
|
|
|
|
}
|
|
|
|
|
mouseIdle(){
|
|
|
|
|
var lastMouse = pageEvents.getMouse()
|
2019-11-28 14:04:40 +08:00
|
|
|
|
if(lastMouse && !this.cursorHidden && !this.state.hasPointer){
|
2018-11-24 22:09:08 +08:00
|
|
|
|
if(this.getMS() >= this.lastMousemove + 2000){
|
2019-11-28 14:04:40 +08:00
|
|
|
|
this.canvas.style.cursor = "none"
|
2018-09-18 21:59:40 +08:00
|
|
|
|
this.cursorHidden = true
|
|
|
|
|
}else{
|
2019-11-28 14:04:40 +08:00
|
|
|
|
this.canvas.style.cursor = ""
|
2018-09-18 21:59:40 +08:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2018-10-12 04:24:18 +08:00
|
|
|
|
changeBeatInterval(beatMS){
|
|
|
|
|
this.beatInterval = beatMS
|
|
|
|
|
this.assets.changeBeatInterval(beatMS)
|
|
|
|
|
}
|
2018-10-25 22:18:41 +08:00
|
|
|
|
getMS(){
|
2019-01-16 20:33:42 +08:00
|
|
|
|
return this.ms
|
2018-10-25 22:18:41 +08:00
|
|
|
|
}
|
2018-09-18 06:37:59 +08:00
|
|
|
|
clean(){
|
2018-10-25 23:50:10 +08:00
|
|
|
|
this.draw.clean()
|
|
|
|
|
this.assets.clean()
|
|
|
|
|
this.titleCache.clean()
|
2018-10-25 22:18:41 +08:00
|
|
|
|
this.comboCache.clean()
|
2019-03-22 18:47:10 +08:00
|
|
|
|
this.pauseCache.clean()
|
|
|
|
|
this.branchCache.clean()
|
2018-10-25 22:18:41 +08:00
|
|
|
|
|
2019-11-28 14:04:40 +08:00
|
|
|
|
versionDiv.classList.remove("version-hide")
|
|
|
|
|
loader.screen.parentNode.appendChild(versionDiv)
|
2018-10-25 22:18:41 +08:00
|
|
|
|
if(this.multiplayer !== 2){
|
2018-10-25 23:50:10 +08:00
|
|
|
|
if(this.touchEnabled){
|
|
|
|
|
pageEvents.remove(this.canvas, "touchstart")
|
|
|
|
|
pageEvents.remove(this.touchPauseBtn, "touchend")
|
2019-01-01 09:16:55 +08:00
|
|
|
|
this.gameDiv.classList.add("touch-results")
|
|
|
|
|
this.touchDrumDiv.parentNode.removeChild(this.touchDrumDiv)
|
2018-10-25 23:50:10 +08:00
|
|
|
|
delete this.touchDrumDiv
|
|
|
|
|
delete this.touchDrumImg
|
|
|
|
|
delete this.touchFullBtn
|
|
|
|
|
delete this.touchPauseBtn
|
|
|
|
|
}
|
2018-10-06 01:03:59 +08:00
|
|
|
|
}
|
2018-11-12 18:32:02 +08:00
|
|
|
|
if(!this.multiplayer){
|
2018-11-14 02:44:04 +08:00
|
|
|
|
pageEvents.remove(this.canvas, "mousedown")
|
2019-01-02 12:26:24 +08:00
|
|
|
|
this.songBg.parentNode.removeChild(this.songBg)
|
|
|
|
|
this.songStage.parentNode.removeChild(this.songStage)
|
2019-01-02 12:32:33 +08:00
|
|
|
|
this.donBg.parentNode.removeChild(this.donBg)
|
|
|
|
|
delete this.donBg
|
|
|
|
|
delete this.songBg
|
|
|
|
|
delete this.songStage
|
2018-11-12 18:32:02 +08:00
|
|
|
|
}
|
2018-10-25 23:50:10 +08:00
|
|
|
|
pageEvents.mouseRemove(this)
|
2019-01-02 12:26:24 +08:00
|
|
|
|
|
2018-09-18 06:37:59 +08:00
|
|
|
|
delete this.pauseMenu
|
2018-10-06 01:03:59 +08:00
|
|
|
|
delete this.gameDiv
|
2018-09-18 06:37:59 +08:00
|
|
|
|
delete this.canvas
|
|
|
|
|
delete this.ctx
|
|
|
|
|
}
|
2018-09-09 12:09:15 +08:00
|
|
|
|
}
|