mirror of
https://github.com/jiojciojsioe3/a3cjroijsiojiorj.git
synced 2024-12-23 01:36:14 +08:00
commit
a899fd5cfe
@ -1,8 +0,0 @@
|
||||
@font-face{
|
||||
font-family: TnT;
|
||||
src: url("TnT.ttf") format("truetype");
|
||||
}
|
||||
@font-face{
|
||||
font-family: Kozuka;
|
||||
src: url("Kozuka.otf") format("truetype");
|
||||
}
|
@ -31,6 +31,8 @@
|
||||
|
||||
this.items = []
|
||||
|
||||
this.getLink(this.linkIssues).innerText = strings.about.issues
|
||||
this.linkIssues.setAttribute("alt", strings.about.issues)
|
||||
var versionUrl = gameConfig._version.url
|
||||
this.getLink(this.linkIssues).href = versionUrl + "issues"
|
||||
this.items.push(this.linkIssues)
|
||||
|
@ -1,6 +1,5 @@
|
||||
var assets = {
|
||||
"js": [
|
||||
"lib/fontdetect.min.js",
|
||||
"lib/md5.min.js",
|
||||
"loadsong.js",
|
||||
"parseosu.js",
|
||||
@ -44,7 +43,6 @@ var assets = {
|
||||
"view.css"
|
||||
],
|
||||
"assetsCss": [
|
||||
"fonts/fonts.css",
|
||||
"img/img.css"
|
||||
],
|
||||
"img": [
|
||||
@ -126,10 +124,10 @@ var assets = {
|
||||
"bgm_setsume.mp3",
|
||||
"bgm_settings.mp3"
|
||||
],
|
||||
"fonts": [
|
||||
"Kozuka",
|
||||
"TnT"
|
||||
],
|
||||
"fonts": {
|
||||
"Kozuka": "Kozuka.otf",
|
||||
"TnT": "TnT.ttf"
|
||||
},
|
||||
"views": [
|
||||
"game.html",
|
||||
"loadsong.html",
|
||||
|
@ -47,6 +47,9 @@ function browserSupport(){
|
||||
var el = document.createElement("a")
|
||||
el.style.setProperty("--a", 1)
|
||||
return el.style.length !== 0
|
||||
},
|
||||
"Font Loading API": function(){
|
||||
return typeof FontFace === "function"
|
||||
}
|
||||
}
|
||||
failedTests = []
|
||||
|
@ -4,6 +4,7 @@ class CanvasCache{
|
||||
if(w){
|
||||
this.resize(w, h, scale)
|
||||
}
|
||||
this.index = Number.MIN_SAFE_INTEGER
|
||||
}
|
||||
resize(w, h, scale){
|
||||
if(this.canvas){
|
||||
@ -33,7 +34,7 @@ class CanvasCache{
|
||||
return
|
||||
}
|
||||
var saved = false
|
||||
var time = Date.now()
|
||||
var index = this.index++
|
||||
if(!img){
|
||||
var w = config.w
|
||||
var h = config.h
|
||||
@ -44,11 +45,11 @@ class CanvasCache{
|
||||
}
|
||||
if(this.y + h > this.h){
|
||||
var clear = true
|
||||
var oldest = {time: time}
|
||||
var oldest = {index: index}
|
||||
this.map.forEach((oldImg, id) => {
|
||||
if(oldImg.time < oldest.time){
|
||||
if(oldImg.index < oldest.index){
|
||||
oldest.id = id
|
||||
oldest.time = oldImg.time
|
||||
oldest.index = oldImg.index
|
||||
}
|
||||
})
|
||||
var oldImg = this.map.get(oldest.id)
|
||||
@ -84,7 +85,7 @@ class CanvasCache{
|
||||
this.map.set(config.id, img)
|
||||
callback(this.ctx)
|
||||
}
|
||||
img.time = time
|
||||
img.index = index
|
||||
if(setOnly){
|
||||
this.ctx.restore()
|
||||
return
|
||||
|
@ -1304,7 +1304,7 @@
|
||||
ctx.globalAlpha = 1 - config.shine
|
||||
}
|
||||
|
||||
ctx.strokeStyle = config.type ? "#000" : "rgba(255, 193, 0, 0.5)"
|
||||
ctx.strokeStyle = config.type ? "#000" : "#ffc616"
|
||||
ctx.lineWidth = 18
|
||||
ctx.stroke(this.crownPath)
|
||||
|
||||
@ -1362,12 +1362,21 @@
|
||||
ctx.fillStyle = "#000"
|
||||
ctx.beginPath()
|
||||
if(config.scoresheet){
|
||||
ctx.moveTo(-4, 26)
|
||||
ctx.lineTo(gaugeClear - 4, 26)
|
||||
this.roundedCorner(ctx, gaugeClear - 4, 4, 13, 0)
|
||||
this.roundedCorner(ctx, 760, 4, 13, 1)
|
||||
ctx.lineTo(760, 56)
|
||||
ctx.lineTo(-4, 56)
|
||||
if(config.multiplayer){
|
||||
ctx.moveTo(-4, -4)
|
||||
ctx.lineTo(760, -4)
|
||||
this.roundedCorner(ctx, 760, 48, 13, 2)
|
||||
this.roundedCorner(ctx, gaugeClear - 4, 48, 13, 3)
|
||||
ctx.lineTo(gaugeClear - 4, 26)
|
||||
ctx.lineTo(-4, 26)
|
||||
}else{
|
||||
ctx.moveTo(-4, 26)
|
||||
ctx.lineTo(gaugeClear - 4, 26)
|
||||
this.roundedCorner(ctx, gaugeClear - 4, 4, 13, 0)
|
||||
this.roundedCorner(ctx, 760, 4, 13, 1)
|
||||
ctx.lineTo(760, 56)
|
||||
ctx.lineTo(-4, 56)
|
||||
}
|
||||
}else if(config.multiplayer){
|
||||
ctx.moveTo(gaugeClear - 7, 27)
|
||||
ctx.lineTo(788, 27)
|
||||
@ -1381,42 +1390,44 @@
|
||||
}
|
||||
ctx.fill()
|
||||
|
||||
if(gaugeFilled <= gaugeClear){
|
||||
if(gaugeFilled < gaugeClear){
|
||||
ctx.fillStyle = config.blue ? "#184d55" : "#680000"
|
||||
var x = Math.max(0, gaugeFilled - 5)
|
||||
ctx.fillRect(x, firstTop, gaugeClear - x + 2, 22)
|
||||
ctx.fillRect(x, firstTop, gaugeClear - x + 2 + (gaugeClear < gaugeW ? 0 : -7), 22)
|
||||
}
|
||||
if(gaugeFilled > 0){
|
||||
var w = Math.min(gaugeClear + 1, gaugeFilled - 4)
|
||||
var w = Math.min(gaugeW - 5, gaugeClear + 1, gaugeFilled - 4)
|
||||
ctx.fillStyle = config.blue ? "#00edff" : "#ff3408"
|
||||
ctx.fillRect(0, firstTop + 2, w, 20)
|
||||
ctx.fillStyle = config.blue ? "#9cffff" : "#ffa191"
|
||||
ctx.fillRect(0, firstTop, w, 3)
|
||||
}
|
||||
if(gaugeFilled < gaugeW - 4){
|
||||
ctx.fillStyle = "#684900"
|
||||
var x = Math.max(gaugeClear + 9, gaugeFilled - gaugeClear + 9)
|
||||
ctx.fillRect(x, secondTop, gaugeW - 4 - x, 44)
|
||||
if(gaugeClear < gaugeW){
|
||||
if(gaugeFilled < gaugeW - 4){
|
||||
ctx.fillStyle = "#684900"
|
||||
var x = Math.max(gaugeClear + 9, gaugeFilled - gaugeClear + 9)
|
||||
ctx.fillRect(x, secondTop, gaugeW - 4 - x, 44)
|
||||
}
|
||||
if(gaugeFilled > gaugeClear + 14){
|
||||
var w = Math.min(gaugeW - 4, gaugeFilled - gaugeClear - 14)
|
||||
ctx.fillStyle = "#ff0"
|
||||
ctx.fillRect(gaugeClear + 9, secondTop + 2, w, 42)
|
||||
ctx.fillStyle = "#fff"
|
||||
ctx.fillRect(gaugeClear + 9, secondTop, w, 3)
|
||||
}
|
||||
ctx.fillStyle = cleared ? "#ff0" : "#684900"
|
||||
ctx.beginPath()
|
||||
if(config.multiplayer){
|
||||
this.roundedCorner(ctx, gaugeClear, secondTop + 44, 10, 3)
|
||||
ctx.lineTo(gaugeClear, secondTop)
|
||||
ctx.lineTo(gaugeClear + 10, secondTop)
|
||||
}else{
|
||||
ctx.moveTo(gaugeClear, secondTop + 44)
|
||||
this.roundedCorner(ctx, gaugeClear, secondTop, 10, 0)
|
||||
ctx.lineTo(gaugeClear + 10, secondTop + 44)
|
||||
}
|
||||
ctx.fill()
|
||||
}
|
||||
if(gaugeFilled > gaugeClear + 14){
|
||||
var w = Math.min(gaugeW - 4, gaugeFilled - gaugeClear - 14)
|
||||
ctx.fillStyle = "#ff0"
|
||||
ctx.fillRect(gaugeClear + 9, secondTop + 2, w, 42)
|
||||
ctx.fillStyle = "#fff"
|
||||
ctx.fillRect(gaugeClear + 9, secondTop, w, 3)
|
||||
}
|
||||
ctx.fillStyle = cleared ? "#ff0" : "#684900"
|
||||
ctx.beginPath()
|
||||
if(config.multiplayer){
|
||||
this.roundedCorner(ctx, gaugeClear, secondTop + 44, 10, 3)
|
||||
ctx.lineTo(gaugeClear, secondTop)
|
||||
ctx.lineTo(gaugeClear + 10, secondTop)
|
||||
}else{
|
||||
ctx.moveTo(gaugeClear, secondTop + 44)
|
||||
this.roundedCorner(ctx, gaugeClear, secondTop, 10, 0)
|
||||
ctx.lineTo(gaugeClear + 10, secondTop + 44)
|
||||
}
|
||||
ctx.fill()
|
||||
if(cleared){
|
||||
ctx.save()
|
||||
ctx.clip()
|
||||
@ -1430,7 +1441,7 @@
|
||||
ctx.lineWidth = 5
|
||||
for(var i = 0; i < 49; i++){
|
||||
var x = 14 + i * 14 - ctx.lineWidth / 2
|
||||
if(i === 26){
|
||||
if(i === config.clear * 50 - 1){
|
||||
ctx.stroke()
|
||||
ctx.beginPath()
|
||||
ctx.lineWidth = 4
|
||||
@ -1439,18 +1450,20 @@
|
||||
ctx.lineTo(x, x < gaugeClear ? firstTop + 22 : secondTop + 44)
|
||||
}
|
||||
ctx.stroke()
|
||||
this.layeredText({
|
||||
ctx: ctx,
|
||||
text: strings.clear,
|
||||
fontSize: 18,
|
||||
fontFamily: config.font,
|
||||
x: gaugeClear + 3,
|
||||
y: config.multiplayer ? 22 : 11,
|
||||
letterSpacing: -2
|
||||
}, [
|
||||
{scale: [1.1, 1.01], outline: "#000", letterBorder: 6},
|
||||
{scale: [1.11, 1], fill: cleared ? "#fff" : "#737373"}
|
||||
])
|
||||
if(config.clear < 47 / 50){
|
||||
this.layeredText({
|
||||
ctx: ctx,
|
||||
text: strings.clear,
|
||||
fontSize: 18,
|
||||
fontFamily: config.font,
|
||||
x: gaugeClear + 3,
|
||||
y: config.multiplayer ? 22 : 11,
|
||||
letterSpacing: -2
|
||||
}, [
|
||||
{scale: [1.1, 1.01], outline: "#000", letterBorder: 6},
|
||||
{scale: [1.11, 1], fill: cleared ? "#fff" : "#737373"}
|
||||
])
|
||||
}
|
||||
|
||||
ctx.restore()
|
||||
}
|
||||
|
@ -3,6 +3,7 @@ class Controller{
|
||||
this.selectedSong = selectedSong
|
||||
this.songData = songData
|
||||
this.autoPlayEnabled = autoPlayEnabled
|
||||
this.saveScore = !autoPlayEnabled
|
||||
this.multiplayer = multiplayer
|
||||
this.touchEnabled = touchEnabled
|
||||
this.snd = this.multiplayer ? "_p" + this.multiplayer : ""
|
||||
|
@ -17,6 +17,7 @@ class Debug{
|
||||
this.branchSelect = this.branchSelectDiv.getElementsByTagName("select")[0]
|
||||
this.branchResetBtn = this.branchSelectDiv.getElementsByClassName("reset")[0]
|
||||
this.volumeDiv = this.byClass("music-volume")
|
||||
this.restartLabel = this.byClass("change-restart-label")
|
||||
this.restartCheckbox = this.byClass("change-restart")
|
||||
this.autoplayLabel = this.byClass("autoplay-label")
|
||||
this.autoplayCheckbox = this.byClass("autoplay")
|
||||
@ -24,15 +25,19 @@ class Debug{
|
||||
this.exitBtn = this.byClass("exit-btn")
|
||||
|
||||
this.moving = false
|
||||
pageEvents.add(window, ["mousedown", "mouseup", "blur"], this.stopMove.bind(this))
|
||||
this.windowSymbol = Symbol()
|
||||
pageEvents.add(window, ["mousedown", "mouseup", "touchstart", "touchend", "blur", "resize"], this.stopMove.bind(this), this.windowSymbol)
|
||||
pageEvents.mouseAdd(this, this.onMove.bind(this))
|
||||
pageEvents.add(this.titleDiv, "mousedown", this.startMove.bind(this))
|
||||
pageEvents.add(this.minimiseDiv, "click", this.minimise.bind(this))
|
||||
pageEvents.add(this.restartBtn, "click", this.restartSong.bind(this))
|
||||
pageEvents.add(this.exitBtn, "click", this.clean.bind(this))
|
||||
pageEvents.add(window, "touchmove", this.onMove.bind(this))
|
||||
pageEvents.add(this.titleDiv, ["mousedown", "touchstart"], this.startMove.bind(this))
|
||||
pageEvents.add(this.minimiseDiv, ["click", "touchstart"], this.minimise.bind(this))
|
||||
pageEvents.add(this.restartBtn, ["click", "touchstart"], this.restartSong.bind(this))
|
||||
pageEvents.add(this.exitBtn, ["click", "touchstart"], this.clean.bind(this))
|
||||
pageEvents.add(this.restartLabel, "touchstart", this.touchBox.bind(this))
|
||||
pageEvents.add(this.autoplayLabel, "touchstart", this.touchBox.bind(this))
|
||||
pageEvents.add(this.autoplayCheckbox, "change", this.toggleAutoplay.bind(this))
|
||||
pageEvents.add(this.branchSelect, "change", this.branchChange.bind(this))
|
||||
pageEvents.add(this.branchResetBtn, "click", this.branchReset.bind(this))
|
||||
pageEvents.add(this.branchResetBtn, ["click", "touchstart"], this.branchReset.bind(this))
|
||||
|
||||
this.offsetSlider = new InputSlider(this.offsetDiv, -60, 60, 3)
|
||||
this.offsetSlider.onchange(this.offsetChange.bind(this))
|
||||
@ -54,24 +59,38 @@ class Debug{
|
||||
return this.debugDiv.getElementsByClassName(name)[0]
|
||||
}
|
||||
startMove(event){
|
||||
if(event.which === 1){
|
||||
if(event.which === 1 || event.type === "touchstart"){
|
||||
event.stopPropagation()
|
||||
this.moving = {
|
||||
x: event.offsetX,
|
||||
y: event.offsetY
|
||||
}
|
||||
var divPos = this.debugDiv.getBoundingClientRect()
|
||||
var click = event.type === "touchstart" ? event.changedTouches[0] : event
|
||||
var x = click.pageX - divPos.left
|
||||
var y = click.pageY - divPos.top
|
||||
this.moving = {x: x, y: y}
|
||||
}
|
||||
}
|
||||
onMove(event){
|
||||
if(this.moving){
|
||||
var x = event.clientX - this.moving.x
|
||||
var y = event.clientY - this.moving.y
|
||||
var click = event.type === "touchmove" ? event.changedTouches[0] : event
|
||||
var x = click.clientX - this.moving.x
|
||||
var y = click.clientY - this.moving.y
|
||||
this.moveTo(x, y)
|
||||
}
|
||||
}
|
||||
stopMove(event){
|
||||
var x = event.clientX - this.moving.x
|
||||
var y = event.clientY - this.moving.y
|
||||
if(!event || event.type === "resize"){
|
||||
var divPos = this.debugDiv.getBoundingClientRect()
|
||||
var x = divPos.left
|
||||
var y = divPos.top
|
||||
}else{
|
||||
var click = event.type === "touchstart" || event.type === "touchend" ? event.changedTouches[0] : event
|
||||
if(event.type == "blur"){
|
||||
var x = this.moving.x
|
||||
var y = this.moving.y
|
||||
}else{
|
||||
var x = click.clientX - this.moving.x
|
||||
var y = click.clientY - this.moving.y
|
||||
}
|
||||
}
|
||||
var w = this.debugDiv.offsetWidth
|
||||
var h = this.debugDiv.offsetHeight
|
||||
if(x + w > innerWidth){
|
||||
@ -95,6 +114,7 @@ class Debug{
|
||||
restore(){
|
||||
debugObj.state = "open"
|
||||
this.debugDiv.style.display = ""
|
||||
this.stopMove()
|
||||
}
|
||||
minimise(){
|
||||
debugObj.state = "minimised"
|
||||
@ -156,6 +176,7 @@ class Debug{
|
||||
this.branchHideDiv.style.display = ""
|
||||
this.controller = null
|
||||
}
|
||||
this.stopMove()
|
||||
}
|
||||
offsetChange(value, noRestart){
|
||||
if(this.controller){
|
||||
@ -197,10 +218,12 @@ class Debug{
|
||||
this.controller.restartSong()
|
||||
}
|
||||
}
|
||||
toggleAutoplay(){
|
||||
toggleAutoplay(event){
|
||||
if(this.controller){
|
||||
this.controller.autoPlayEnabled = this.autoplayCheckbox.checked
|
||||
if(!this.controller.autoPlayEnabled){
|
||||
if(this.controller.autoPlayEnabled){
|
||||
this.controller.saveScore = false
|
||||
}else{
|
||||
var keyboard = debugObj.controller.keyboard
|
||||
keyboard.setKey(false, "don_l")
|
||||
keyboard.setKey(false, "don_r")
|
||||
@ -229,21 +252,30 @@ class Debug{
|
||||
this.branchSelect.value = "auto"
|
||||
this.branchChange(null, noRestart)
|
||||
}
|
||||
touchBox(event){
|
||||
event.currentTarget.click()
|
||||
}
|
||||
clean(){
|
||||
this.offsetSlider.clean()
|
||||
this.measureNumSlider.clean()
|
||||
this.volumeSlider.clean()
|
||||
|
||||
pageEvents.remove(window, ["mousedown", "mouseup", "blur"])
|
||||
pageEvents.remove(window, ["mousedown", "mouseup", "touchstart", "touchend", "blur", "resize"], this.windowSymbol)
|
||||
pageEvents.mouseRemove(this)
|
||||
pageEvents.remove(this.titleDiv, "mousedown")
|
||||
pageEvents.remove(this.title, "mousedown")
|
||||
pageEvents.remove(this.minimiseDiv, "click")
|
||||
pageEvents.remove(this.restartBtn, "click")
|
||||
pageEvents.remove(this.exitBtn, "click")
|
||||
pageEvents.remove(window, "touchmove")
|
||||
pageEvents.remove(this.titleDiv, ["mousedown", "touchstart"])
|
||||
pageEvents.remove(this.minimiseDiv, ["click", "touchstart"])
|
||||
pageEvents.remove(this.restartBtn, ["click", "touchstart"])
|
||||
pageEvents.remove(this.exitBtn, ["click", "touchstart"])
|
||||
pageEvents.remove(this.restartLabel, "touchstart")
|
||||
pageEvents.remove(this.autoplayLabel, "touchstart")
|
||||
pageEvents.remove(this.autoplayCheckbox, "change")
|
||||
pageEvents.remove(this.branchSelect, "change")
|
||||
pageEvents.remove(this.branchResetBtn, "click")
|
||||
pageEvents.remove(this.branchResetBtn, ["click", "touchstart"])
|
||||
|
||||
delete this.offsetSlider
|
||||
delete this.measureNumSlider
|
||||
delete this.volumeSlider
|
||||
delete this.titleDiv
|
||||
delete this.minimiseDiv
|
||||
delete this.offsetDiv
|
||||
@ -259,6 +291,7 @@ class Debug{
|
||||
delete this.restartBtn
|
||||
delete this.exitBtn
|
||||
delete this.controller
|
||||
delete this.windowSymbol
|
||||
|
||||
debugObj.state = "closed"
|
||||
debugObj.debug = null
|
||||
@ -281,10 +314,22 @@ class InputSlider{
|
||||
this.value = null
|
||||
this.defaultValue = null
|
||||
this.callbacks = []
|
||||
this.touchEnd = []
|
||||
this.windowSymbol = Symbol()
|
||||
pageEvents.add(this.input, ["touchstart", "touchend"], event => {
|
||||
event.stopPropagation()
|
||||
})
|
||||
pageEvents.add(window, ["mouseup", "touchstart", "touchend", "blur"], event => {
|
||||
if(event.type !== "touchstart"){
|
||||
this.touchEnd.forEach(func => func(event))
|
||||
}else if(event.target !== this.input){
|
||||
this.input.blur()
|
||||
}
|
||||
}, this.windowSymbol)
|
||||
|
||||
pageEvents.add(this.plus, "click", this.add.bind(this))
|
||||
pageEvents.add(this.minus, "click", this.subtract.bind(this))
|
||||
pageEvents.add(this.reset, "click", this.resetValue.bind(this))
|
||||
this.addTouchRepeat(this.plus, this.add.bind(this))
|
||||
this.addTouchRepeat(this.minus, this.subtract.bind(this))
|
||||
this.addTouch(this.reset, this.resetValue.bind(this))
|
||||
pageEvents.add(this.input, "change", this.manualSet.bind(this))
|
||||
pageEvents.add(this.input, "keydown", this.captureKeys.bind(this))
|
||||
}
|
||||
@ -364,15 +409,49 @@ class InputSlider{
|
||||
captureKeys(event){
|
||||
event.stopPropagation()
|
||||
}
|
||||
addTouch(element, callback){
|
||||
pageEvents.add(element, ["mousedown", "touchstart"], event => {
|
||||
if(event.type === "touchstart"){
|
||||
event.preventDefault()
|
||||
}else if(event.which !== 1){
|
||||
return
|
||||
}
|
||||
callback(event)
|
||||
})
|
||||
}
|
||||
addTouchRepeat(element, callback){
|
||||
this.addTouch(element, event => {
|
||||
var active = true
|
||||
var func = () => {
|
||||
active = false
|
||||
this.touchEnd.splice(this.touchEnd.indexOf(func), 1)
|
||||
}
|
||||
this.touchEnd.push(func)
|
||||
var repeat = delay => {
|
||||
if(active && this.touchEnd){
|
||||
callback(event)
|
||||
setTimeout(() => repeat(50), delay)
|
||||
}
|
||||
}
|
||||
repeat(400)
|
||||
})
|
||||
}
|
||||
removeTouch(element){
|
||||
pageEvents.remove(element, ["mousedown", "touchstart"])
|
||||
}
|
||||
clean(){
|
||||
pageEvents.remove(this.plus, "click")
|
||||
pageEvents.remove(this.minus, "click")
|
||||
pageEvents.remove(this.reset, "click")
|
||||
pageEvents.remove(this.input, ["change", "keydown"])
|
||||
this.removeTouch(this.plus)
|
||||
this.removeTouch(this.minus)
|
||||
this.removeTouch(this.reset)
|
||||
pageEvents.remove(this.input, ["touchstart", "touchend"])
|
||||
pageEvents.remove(window, ["mouseup", "touchstart", "touchend", "blur"], this.windowSymbol)
|
||||
pageEvents.remove(this.input, ["touchstart", "change", "keydown"])
|
||||
|
||||
delete this.input
|
||||
delete this.reset
|
||||
delete this.plus
|
||||
delete this.minus
|
||||
delete this.windowSymbol
|
||||
delete this.touchEnd
|
||||
}
|
||||
}
|
||||
|
@ -811,7 +811,7 @@ class Game{
|
||||
offsets.push(offset)
|
||||
progress.hit++
|
||||
progress.last = current
|
||||
this.globalScore.gauge = 100 / (progress.requirement / progress.hit)
|
||||
this.globalScore.gauge = 10000 / (progress.requirement / progress.hit)
|
||||
}
|
||||
}
|
||||
calibrationReset(to, togglePause){
|
||||
|
@ -13,6 +13,7 @@ class GameRules{
|
||||
case "hard":
|
||||
case "oni":
|
||||
case "ura":
|
||||
default:
|
||||
this.good = 3 / 2 * frame
|
||||
this.ok = 9 / 2 * frame
|
||||
this.bad = 13 / 2 * frame
|
||||
@ -30,6 +31,9 @@ class GameRules{
|
||||
case "ura":
|
||||
this.gaugeClear = 40 / 50
|
||||
break
|
||||
default:
|
||||
this.gaugeClear = 51 / 50
|
||||
break
|
||||
}
|
||||
|
||||
this.daiLeniency = 2 * frame
|
||||
@ -61,8 +65,10 @@ class GameRules{
|
||||
}
|
||||
return {good: good, ok: ok, bad: bad}
|
||||
}
|
||||
gaugePercent(gauge){
|
||||
return Math.floor(gauge / 200) / 50
|
||||
}
|
||||
clearReached(gauge){
|
||||
var gaugePercent = Math.round(gauge / 200) / 50
|
||||
return gaugePercent >= this.gaugeClear
|
||||
return this.gaugePercent(gauge) >= this.gaugeClear
|
||||
}
|
||||
}
|
||||
|
@ -269,7 +269,7 @@
|
||||
songObj.subtitle_lang = subtitleLangArray.join("\n")
|
||||
}
|
||||
if(!songObj.category){
|
||||
songObj.category = category || this.getCategory(file)
|
||||
songObj.category = category || this.getCategory(file, [songTitle || songObj.title, file.name.slice(0, file.name.lastIndexOf("."))])
|
||||
}
|
||||
if(songObj.stars.length !== 0){
|
||||
this.songs[index] = songObj
|
||||
@ -277,7 +277,7 @@
|
||||
var hash = md5.base64(event.target.result).slice(0, -2)
|
||||
songObj.hash = hash
|
||||
scoreStorage.songTitles[songObj.title] = hash
|
||||
var score = scoreStorage.get(hash)
|
||||
var score = scoreStorage.get(hash, false, true)
|
||||
if(score){
|
||||
score.title = songObj.title
|
||||
}
|
||||
@ -307,7 +307,7 @@
|
||||
music: this.otherFiles[dir + osu.generalInfo.AudioFilename.toLowerCase()] || "muted"
|
||||
}
|
||||
var filename = file.name.slice(0, file.name.lastIndexOf("."))
|
||||
var title = osu.metadata.TitleUnicode || osu.metadata.Title
|
||||
var title = osu.metadata.TitleUnicode || osu.metadata.Title || file.name.slice(0, file.name.lastIndexOf("."))
|
||||
if(title){
|
||||
var suffix = ""
|
||||
var matches = filename.match(/\[.+?\]$/)
|
||||
@ -320,11 +320,11 @@
|
||||
songObj.title = filename
|
||||
}
|
||||
this.songs[index] = songObj
|
||||
songObj.category = category || this.getCategory(file)
|
||||
songObj.category = category || this.getCategory(file, [osu.metadata.TitleUnicode, osu.metadata.Title, file.name.slice(0, file.name.lastIndexOf("."))])
|
||||
var hash = md5.base64(event.target.result).slice(0, -2)
|
||||
songObj.hash = hash
|
||||
scoreStorage.songTitles[songObj.title] = hash
|
||||
var score = scoreStorage.get(hash)
|
||||
var score = scoreStorage.get(hash, false, true)
|
||||
if(score){
|
||||
score.title = songObj.title
|
||||
}
|
||||
@ -394,12 +394,21 @@
|
||||
return name.slice(0, name.lastIndexOf("."))
|
||||
}
|
||||
|
||||
getCategory(file){
|
||||
getCategory(file, exclude){
|
||||
var path = file.webkitRelativePath.toLowerCase().split("/")
|
||||
for(var i = path.length - 2; i >= 0; i--){
|
||||
for(var cat in this.categories){
|
||||
if(path[i].indexOf(cat) !== -1){
|
||||
return this.categories[cat]
|
||||
var hasTitle = false
|
||||
for(var j in exclude){
|
||||
if(path[i].indexOf(exclude[j].toLowerCase()) !== -1){
|
||||
hasTitle = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if(!hasTitle){
|
||||
for(var cat in this.categories){
|
||||
if(path[i].indexOf(cat) !== -1){
|
||||
return this.categories[cat]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
1
public/src/js/lib/fontdetect.min.js
vendored
1
public/src/js/lib/fontdetect.min.js
vendored
@ -1 +0,0 @@
|
||||
FontDetect=function(){function e(){if(!n){n=!0;var e=document.body,t=document.body.firstChild,i=document.createElement("div");i.id="fontdetectHelper",r=document.createElement("span"),r.innerText="abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ",i.appendChild(r),e.insertBefore(i,t),i.style.position="absolute",i.style.visibility="hidden",i.style.top="-200px",i.style.left="-100000px",i.style.width="100000px",i.style.height="200px",i.style.fontSize="100px"}}function t(e,t){return e instanceof Element?window.getComputedStyle(e).getPropertyValue(t):window.jQuery?$(e).css(t):""}var n=!1,i=["serif","sans-serif","monospace","cursive","fantasy"],r=null;return{onFontLoaded:function(t,i,r,o){if(t){var s=o&&o.msInterval?o.msInterval:100,a=o&&o.msTimeout?o.msTimeout:2e3;if(i||r){if(n||e(),this.isFontLoaded(t))return void(i&&i(t));var l=this,f=(new Date).getTime(),d=setInterval(function(){if(l.isFontLoaded(t))return clearInterval(d),void i(t);var e=(new Date).getTime();e-f>a&&(clearInterval(d),r&&r(t))},s)}}},isFontLoaded:function(t){var o=0,s=0;n||e();for(var a=0;a<i.length;++a){if(r.style.fontFamily='"'+t+'",'+i[a],o=r.offsetWidth,a>0&&o!=s)return!1;s=o}return!0},whichFont:function(e){for(var n=t(e,"font-family"),r=n.split(","),o=r.shift();o;){o=o.replace(/^\s*['"]?\s*([^'"]*)\s*['"]?\s*$/,"$1");for(var s=0;s<i.length;s++)if(o==i[s])return o;if(this.isFontLoaded(o))return o;o=r.shift()}return null}}}();
|
@ -20,6 +20,7 @@ class Loader{
|
||||
}
|
||||
run(){
|
||||
this.promises = []
|
||||
this.loaderDiv = document.querySelector("#loader")
|
||||
this.loaderPercentage = document.querySelector("#loader .percentage")
|
||||
this.loaderProgress = document.querySelector("#loader .progress")
|
||||
|
||||
@ -70,12 +71,11 @@ class Loader{
|
||||
checkStyles()
|
||||
}))
|
||||
|
||||
assets.fonts.forEach(name => {
|
||||
var font = document.createElement("h1")
|
||||
font.style.fontFamily = name
|
||||
font.appendChild(document.createTextNode("I am a font"))
|
||||
this.assetsDiv.appendChild(font)
|
||||
})
|
||||
for(var name in assets.fonts){
|
||||
this.addPromise(new FontFace(name, "url('" + gameConfig.assets_baseurl + "fonts/" + assets.fonts[name] + "')").load().then(font => {
|
||||
document.fonts.add(font)
|
||||
}))
|
||||
}
|
||||
|
||||
assets.img.forEach(name => {
|
||||
var id = this.getFilename(name)
|
||||
@ -105,7 +105,6 @@ class Loader{
|
||||
|
||||
this.afterJSCount =
|
||||
["blurPerformance", "P2Connection"].length +
|
||||
assets.fonts.length +
|
||||
assets.audioSfx.length +
|
||||
assets.audioMusic.length +
|
||||
assets.audioSfxLR.length +
|
||||
@ -130,12 +129,6 @@ class Loader{
|
||||
|
||||
this.afterJSCount = 0
|
||||
|
||||
assets.fonts.forEach(name => {
|
||||
this.addPromise(new Promise(resolve => {
|
||||
FontDetect.onFontLoaded(name, resolve, resolve, {msTimeout: Infinity})
|
||||
}))
|
||||
})
|
||||
|
||||
assets.audioSfx.forEach(name => {
|
||||
this.addPromise(this.loadSound(name, snd.sfxGain))
|
||||
})
|
||||
@ -213,7 +206,7 @@ class Loader{
|
||||
song.hash = song.title
|
||||
}
|
||||
scoreStorage.songTitles[song.title] = song.hash
|
||||
var score = scoreStorage.get(song.hash)
|
||||
var score = scoreStorage.get(song.hash, false, true)
|
||||
if(score){
|
||||
score.title = song.title
|
||||
}
|
||||
@ -248,12 +241,38 @@ class Loader{
|
||||
return name.slice(0, name.lastIndexOf("."))
|
||||
}
|
||||
errorMsg(error){
|
||||
if(Array.isArray(error) && error[1] instanceof HTMLElement){
|
||||
error = error[0] + ": " + error[1].outerHTML
|
||||
}
|
||||
console.error(error)
|
||||
pageEvents.send("loader-error", error)
|
||||
this.error = true
|
||||
this.loaderPercentage.appendChild(document.createElement("br"))
|
||||
this.loaderPercentage.appendChild(document.createTextNode("An error occurred, please refresh"))
|
||||
this.clean()
|
||||
if(!this.error){
|
||||
this.error = true
|
||||
this.loaderDiv.classList.add("loaderError")
|
||||
if(typeof allStrings === "object"){
|
||||
var lang = localStorage.lang
|
||||
if(!lang){
|
||||
var userLang = navigator.languages.slice()
|
||||
userLang.unshift(navigator.language)
|
||||
for(var i in userLang){
|
||||
for(var j in allStrings){
|
||||
if(allStrings[j].regex.test(userLang[i])){
|
||||
lang = j
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if(!lang){
|
||||
lang = "en"
|
||||
}
|
||||
var errorOccured = allStrings[lang].errorOccured
|
||||
}else{
|
||||
var errorOccured = "An error occurred, please refresh"
|
||||
}
|
||||
this.loaderPercentage.appendChild(document.createElement("br"))
|
||||
this.loaderPercentage.appendChild(document.createTextNode(errorOccured))
|
||||
this.clean()
|
||||
}
|
||||
}
|
||||
assetLoaded(){
|
||||
if(!this.error){
|
||||
|
@ -160,7 +160,7 @@ class LoadSong{
|
||||
console.error(error)
|
||||
pageEvents.send("load-song-error", error)
|
||||
errorMessage(new Error(error).stack)
|
||||
alert("An error occurred, please refresh")
|
||||
alert(strings.errorOccured)
|
||||
})
|
||||
}
|
||||
loadSongBg(){
|
||||
|
@ -102,7 +102,7 @@ pageEvents.add(versionDiv, ["click", "touchend"], event => {
|
||||
resizeRoot()
|
||||
setInterval(resizeRoot, 100)
|
||||
pageEvents.keyAdd(debugObj, "all", "down", event => {
|
||||
if((event.keyCode === 186 || event.keyCode === 59) && event.ctrlKey && event.shiftKey && !event.altKey){
|
||||
if((event.keyCode === 186 || event.keyCode === 59) && event.ctrlKey && (event.shiftKey || event.altKey)){
|
||||
// Semicolon
|
||||
if(debugObj.state === "open"){
|
||||
debugObj.debug.minimise()
|
||||
|
@ -11,60 +11,62 @@ class PageEvents{
|
||||
this.add(window, "blur", this.blurEvent.bind(this))
|
||||
this.kbd = []
|
||||
}
|
||||
add(target, type, callback){
|
||||
add(target, type, callback, symbol){
|
||||
if(Array.isArray(type)){
|
||||
type.forEach(type => this.add(target, type, callback))
|
||||
type.forEach(type => this.add(target, type, callback, symbol))
|
||||
return
|
||||
}
|
||||
this.remove(target, type)
|
||||
var addedEvent = this.allEvents.get(target)
|
||||
var addedEvent = this.allEvents.get(symbol || target)
|
||||
if(!addedEvent){
|
||||
addedEvent = new Map()
|
||||
this.allEvents.set(target, addedEvent)
|
||||
this.allEvents.set(symbol || target, addedEvent)
|
||||
}
|
||||
addedEvent.set(type, callback)
|
||||
return target.addEventListener(type, callback)
|
||||
}
|
||||
remove(target, type){
|
||||
remove(target, type, symbol){
|
||||
if(Array.isArray(type)){
|
||||
type.forEach(type => this.remove(target, type))
|
||||
type.forEach(type => this.remove(target, type, symbol))
|
||||
return
|
||||
}
|
||||
var addedEvent = this.allEvents.get(target)
|
||||
var addedEvent = this.allEvents.get(symbol || target)
|
||||
if(addedEvent){
|
||||
var callback = addedEvent.get(type)
|
||||
if(callback){
|
||||
target.removeEventListener(type, callback)
|
||||
addedEvent.delete(type)
|
||||
if(addedEvent.size == 0){
|
||||
return this.allEvents.delete(target)
|
||||
return this.allEvents.delete(symbol || target)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
once(target, type){
|
||||
once(target, type, symbol){
|
||||
return new Promise(resolve => {
|
||||
this.add(target, type, event => {
|
||||
this.remove(target, type)
|
||||
return resolve(event)
|
||||
})
|
||||
}, symbol)
|
||||
})
|
||||
}
|
||||
race(){
|
||||
var symbols = []
|
||||
var target = arguments[0]
|
||||
return new Promise(resolve => {
|
||||
for(var i = 1;i < arguments.length; i++){
|
||||
symbols[i] = Symbol()
|
||||
let type = arguments[i]
|
||||
this.add(target, type, event => {
|
||||
resolve({
|
||||
type: type,
|
||||
event: event
|
||||
})
|
||||
})
|
||||
}, symbols[i])
|
||||
}
|
||||
}).then(response => {
|
||||
for(var i = 1;i < arguments.length; i++){
|
||||
this.remove(target, arguments[i])
|
||||
this.remove(target, arguments[i], symbols[i])
|
||||
}
|
||||
return response
|
||||
})
|
||||
|
@ -149,6 +149,7 @@
|
||||
var circles = []
|
||||
var circleID = 0
|
||||
var regexAZ = /[A-Z]/
|
||||
var regexSpace = /\s/
|
||||
var isAllDon = (note_chain, start_pos) => {
|
||||
for (var i = start_pos; i < note_chain.length; ++i) {
|
||||
var note = note_chain[i];
|
||||
@ -470,7 +471,7 @@
|
||||
bpm: bpm,
|
||||
scroll: scroll
|
||||
})
|
||||
}else{
|
||||
}else if(!regexSpace.test(symbol)){
|
||||
error = true
|
||||
}
|
||||
break
|
||||
|
@ -63,7 +63,8 @@ class Scoresheet{
|
||||
assets.sounds["v_results"].play()
|
||||
assets.sounds["bgm_result"].playLoop(3, false, 0, 0.847, 17.689)
|
||||
|
||||
if(p2.session){
|
||||
this.session = p2.session
|
||||
if(this.session){
|
||||
if(p2.getMessage("songsel")){
|
||||
this.toSongsel(true)
|
||||
}
|
||||
@ -324,14 +325,15 @@ class Scoresheet{
|
||||
var elapsed = 0
|
||||
}
|
||||
|
||||
var gaugePercent = Math.round(this.results.gauge / 200) / 50
|
||||
var gaugeClear = [this.controller.game.rules.gaugeClear]
|
||||
var rules = this.controller.game.rules
|
||||
var gaugePercent = rules.gaugePercent(this.results.gauge)
|
||||
var gaugeClear = [rules.gaugeClear]
|
||||
if(players === 2){
|
||||
gaugeClear.push(this.controller.syncWith.game.rules.gaugeClear)
|
||||
}
|
||||
var failedOffset = gaugePercent >= gaugeClear[0] ? 0 : -2000
|
||||
if(players === 2){
|
||||
var gauge2 = Math.round(p2.results.gauge / 200) / 50
|
||||
var gauge2 = this.controller.syncWith.game.rules.gaugePercent(p2.results.gauge)
|
||||
if(gauge2 > gaugePercent && failedOffset !== 0 && gauge2 >= gaugeClear[1]){
|
||||
failedOffset = 0
|
||||
}
|
||||
@ -343,7 +345,8 @@ class Scoresheet{
|
||||
if(p === 1){
|
||||
results = p2.results
|
||||
}
|
||||
var resultGauge = Math.round(results.gauge / 200) / 50
|
||||
var playerRules = p === 0 ? rules : this.controller.syncWith.game.rules
|
||||
var resultGauge = playerRules.gaugePercent(results.gauge)
|
||||
var clear = resultGauge >= gaugeClear[p]
|
||||
if(p === 1 || !this.multiplayer && clear){
|
||||
ctx.translate(0, 290)
|
||||
@ -368,8 +371,8 @@ class Scoresheet{
|
||||
if(elapsed >= 0){
|
||||
if(this.state.hasPointer === 0){
|
||||
this.state.hasPointer = 1
|
||||
if(!this.state.pointerLocked && !p2.session){
|
||||
this.canvas.style.cursor = "pointer"
|
||||
if(!this.state.pointerLocked){
|
||||
this.canvas.style.cursor = this.session ? "" : "pointer"
|
||||
}
|
||||
}
|
||||
ctx.save()
|
||||
@ -578,7 +581,7 @@ class Scoresheet{
|
||||
if(this.tetsuoHanaClass){
|
||||
this.tetsuoHana.classList.remove(this.tetsuoHanaClass)
|
||||
}
|
||||
this.tetsuoHanaClass = this.controller.game.rules.clearReached(this.results.gauge) ? "dance" : "failed"
|
||||
this.tetsuoHanaClass = rules.clearReached(this.results.gauge) ? "dance" : "failed"
|
||||
this.tetsuoHana.classList.add(this.tetsuoHanaClass)
|
||||
}
|
||||
}
|
||||
@ -597,26 +600,27 @@ class Scoresheet{
|
||||
results = p2.results
|
||||
ctx.translate(0, p2Offset)
|
||||
}
|
||||
var gaugePercent = Math.round(results.gauge / 200) / 50
|
||||
var gaugePercent = rules.gaugePercent(results.gauge)
|
||||
var w = 712
|
||||
this.draw.gauge({
|
||||
ctx: ctx,
|
||||
x: 558 + w,
|
||||
y: 116,
|
||||
y: p === 1 ? 124 : 116,
|
||||
clear: gaugeClear[p],
|
||||
percentage: gaugePercent,
|
||||
font: this.font,
|
||||
scale: w / 788,
|
||||
scoresheet: true,
|
||||
blue: p === 1
|
||||
blue: p === 1,
|
||||
multiplayer: p === 1
|
||||
})
|
||||
var rules = p === 0 ? this.controller.game.rules : this.controller.syncWith.game.rules
|
||||
var playerRules = p === 0 ? rules : this.controller.syncWith.game.rules
|
||||
this.draw.soul({
|
||||
ctx: ctx,
|
||||
x: 1215,
|
||||
y: 144,
|
||||
scale: 36 / 42,
|
||||
cleared: rules.clearReached(results.gauge)
|
||||
cleared: playerRules.clearReached(results.gauge)
|
||||
})
|
||||
}
|
||||
})
|
||||
@ -634,8 +638,8 @@ class Scoresheet{
|
||||
results = p2.results
|
||||
}
|
||||
var crownType = null
|
||||
var rules = p === 0 ? this.controller.game.rules : this.controller.syncWith.game.rules
|
||||
if(rules.clearReached(results.gauge)){
|
||||
var playerRules = p === 0 ? rules : this.controller.syncWith.game.rules
|
||||
if(playerRules.clearReached(results.gauge)){
|
||||
crownType = results.bad === "0" ? "gold" : "silver"
|
||||
}
|
||||
if(crownType !== null){
|
||||
@ -796,9 +800,13 @@ class Scoresheet{
|
||||
ctx.restore()
|
||||
}
|
||||
|
||||
if(p2.session && !this.state.scoreNext && this.state.screen === "scoresShown" && ms - this.state.screenMS >= 10000){
|
||||
if(this.session && !this.state.scoreNext && this.state.screen === "scoresShown" && ms - this.state.screenMS >= 10000){
|
||||
this.state.scoreNext = true
|
||||
p2.send("songsel")
|
||||
if(p2.session){
|
||||
p2.send("songsel")
|
||||
}else{
|
||||
this.toSongsel(true)
|
||||
}
|
||||
}
|
||||
|
||||
if(this.state.screen === "fadeOut"){
|
||||
@ -861,7 +869,7 @@ class Scoresheet{
|
||||
}
|
||||
|
||||
saveScore(){
|
||||
if(!this.controller.autoPlayEnabled){
|
||||
if(this.controller.saveScore){
|
||||
if(this.resultsObj.points < 0){
|
||||
this.resultsObj.points = 0
|
||||
}
|
||||
@ -903,7 +911,7 @@ class Scoresheet{
|
||||
if(this.multiplayer !== 2 && this.touchEnabled){
|
||||
pageEvents.remove(document.getElementById("touch-full-btn"), "touchend")
|
||||
}
|
||||
if(p2.session){
|
||||
if(this.session){
|
||||
pageEvents.remove(p2, "message")
|
||||
}
|
||||
if(!this.multiplayer){
|
||||
|
@ -167,9 +167,29 @@ class SettingsView{
|
||||
this.viewOuter.classList.add("touch-enabled")
|
||||
}
|
||||
this.touchEnd = []
|
||||
pageEvents.add(this.viewOuter, ["mouseup", "touchend"], event => {
|
||||
this.touchEnd.forEach(func => func(event))
|
||||
})
|
||||
this.windowSymbol = Symbol()
|
||||
this.touchMove = {
|
||||
active: false,
|
||||
x: 0,
|
||||
y: 0
|
||||
}
|
||||
pageEvents.add(window, ["mouseup", "touchstart", "touchmove", "touchend", "blur"], event => {
|
||||
var move = this.touchMove
|
||||
if(event.type === "touchstart"){
|
||||
var cursor = event.changedTouches[0]
|
||||
move.active = false
|
||||
move.x = cursor.pageX
|
||||
move.y = cursor.pageY
|
||||
}else if(event.type === "touchmove"){
|
||||
var cursor = event.changedTouches[0]
|
||||
if (Math.abs(move.x - cursor.pageX) > 10 || Math.abs(move.y - cursor.pageY) > 10){
|
||||
move.active = true
|
||||
}
|
||||
}else{
|
||||
this.touchEnd.forEach(func => func(event))
|
||||
move.active = false
|
||||
}
|
||||
}, this.windowSymbol)
|
||||
|
||||
var gamepadEnabled = false
|
||||
if("getGamepads" in navigator){
|
||||
@ -234,7 +254,7 @@ class SettingsView{
|
||||
this.selected = this.items.length
|
||||
settingBox.classList.add("selected")
|
||||
}
|
||||
this.addTouch(settingBox, event => this.setValue(i))
|
||||
this.addTouchEnd(settingBox, event => this.setValue(i))
|
||||
this.items.push({
|
||||
id: i,
|
||||
settingBox: settingBox,
|
||||
@ -365,9 +385,10 @@ class SettingsView{
|
||||
getElement(name){
|
||||
return loader.screen.getElementsByClassName(name)[0]
|
||||
}
|
||||
addTouch(element, callback){
|
||||
pageEvents.add(element, ["mousedown", "touchstart"], event => {
|
||||
if(event.type === "touchstart"){
|
||||
addTouch(element, callback, end){
|
||||
var touchEvent = end ? "touchend" : "touchstart"
|
||||
pageEvents.add(element, ["mousedown", touchEvent], event => {
|
||||
if(event.type === touchEvent){
|
||||
event.preventDefault()
|
||||
this.touched = true
|
||||
}else if(event.which !== 1){
|
||||
@ -375,9 +396,14 @@ class SettingsView{
|
||||
}else{
|
||||
this.touched = false
|
||||
}
|
||||
callback(event)
|
||||
if(event.type !== "touchend" || !this.touchMove.active){
|
||||
callback(event)
|
||||
}
|
||||
})
|
||||
}
|
||||
addTouchEnd(element, callback){
|
||||
this.addTouch(element, callback, true)
|
||||
}
|
||||
addTouchRepeat(element, callback){
|
||||
this.addTouch(element, event => {
|
||||
var active = true
|
||||
@ -398,6 +424,9 @@ class SettingsView{
|
||||
removeTouch(element){
|
||||
pageEvents.remove(element, ["mousedown", "touchstart"])
|
||||
}
|
||||
removeTouchEnd(element){
|
||||
pageEvents.remove(element, ["mousedown", "touchend"])
|
||||
}
|
||||
getValue(name, valueDiv){
|
||||
var current = settings.items[name]
|
||||
var value = settings.getItem(name)
|
||||
@ -879,9 +908,9 @@ class SettingsView{
|
||||
this.keyboard.clean()
|
||||
this.gamepad.clean()
|
||||
assets.sounds["bgm_settings"].stop()
|
||||
pageEvents.remove(this.viewOuter, ["mouseup", "touchend"])
|
||||
pageEvents.remove(window, ["mouseup", "touchstart", "touchmove", "touchend", "blur"], this.windowSymbol)
|
||||
for(var i in this.items){
|
||||
this.removeTouch(this.items[i].settingBox)
|
||||
this.removeTouchEnd(this.items[i].settingBox)
|
||||
}
|
||||
for(var i in this.latencyItems){
|
||||
this.removeTouch(this.latencyItems[i].settingBox)
|
||||
@ -899,6 +928,8 @@ class SettingsView{
|
||||
this.removeTouch(this.latencySettings)
|
||||
this.removeTouch(this.latencyDefaultButton)
|
||||
this.removeTouch(this.latencyEndButton)
|
||||
delete this.windowSymbol
|
||||
delete this.touchMove
|
||||
delete this.viewOuter
|
||||
delete this.touchEnd
|
||||
delete this.tutorialTitle
|
||||
|
@ -608,18 +608,25 @@ class SongSelect{
|
||||
this.pointer(false)
|
||||
}
|
||||
}
|
||||
|
||||
categoryJump(moveBy){
|
||||
if(this.state.locked === 1){
|
||||
return
|
||||
|
||||
categoryJump(moveBy, fromP2){
|
||||
if(p2.session && !fromP2){
|
||||
var ms = this.getMS()
|
||||
if(!this.state.selLock && ms > this.state.moveMS + 800){
|
||||
this.state.selLock = true
|
||||
p2.send("catjump", {
|
||||
song: this.selectedSong,
|
||||
move: moveBy
|
||||
})
|
||||
}
|
||||
}else if(this.state.locked !== 1 || fromP2){
|
||||
this.state.catJump = true
|
||||
this.state.move = moveBy;
|
||||
this.state.locked = 1
|
||||
|
||||
this.endPreview()
|
||||
this.playSound("se_jump")
|
||||
}
|
||||
|
||||
this.state.catJump = true
|
||||
this.state.move = moveBy;
|
||||
this.state.locked = 1
|
||||
|
||||
this.endPreview()
|
||||
this.playSound("se_jump")
|
||||
}
|
||||
|
||||
moveToDiff(moveBy){
|
||||
@ -925,7 +932,7 @@ class SongSelect{
|
||||
}
|
||||
|
||||
this.selectableText = ""
|
||||
}else if(!document.hasFocus()){
|
||||
}else if(!document.hasFocus() && !p2.session){
|
||||
this.pointer(false)
|
||||
return
|
||||
}else{
|
||||
@ -1128,7 +1135,15 @@ class SongSelect{
|
||||
disabled: p2.session && this.songs[index].action && this.songs[index].action !== "random"
|
||||
})
|
||||
}
|
||||
var startFrom
|
||||
for(var i = this.selectedSong + 1; ; i++){
|
||||
var _x = winW / 2 + (i - this.selectedSong - 1) * (this.songAsset.width + this.songAsset.marginLeft) + this.songAsset.marginLeft + selectedWidth / 2 + xOffset
|
||||
if(_x > winW){
|
||||
startFrom = i - 1
|
||||
break
|
||||
}
|
||||
}
|
||||
for(var i = startFrom; i > this.selectedSong ; i--){
|
||||
var highlight = 0
|
||||
if(i - this.selectedSong === this.state.moveHover){
|
||||
highlight = 1
|
||||
@ -1136,9 +1151,6 @@ class SongSelect{
|
||||
var index = this.mod(this.songs.length, i)
|
||||
var currentSong = this.songs[index]
|
||||
var _x = winW / 2 + (i - this.selectedSong - 1) * (this.songAsset.width + this.songAsset.marginLeft) + this.songAsset.marginLeft + selectedWidth / 2 + xOffset
|
||||
if(_x > winW){
|
||||
break
|
||||
}
|
||||
this.drawClosedSong({
|
||||
ctx: ctx,
|
||||
x: _x,
|
||||
@ -1150,6 +1162,43 @@ class SongSelect{
|
||||
}
|
||||
}
|
||||
|
||||
var currentSong = this.songs[this.selectedSong]
|
||||
var highlight = 0
|
||||
if(!currentSong.stars){
|
||||
highlight = 2
|
||||
}
|
||||
if(this.state.moveHover === 0){
|
||||
highlight = 1
|
||||
}
|
||||
var selectedSkin = this.songSkin.selected
|
||||
if(screen === "title" || screen === "titleFadeIn" || this.state.locked === 3){
|
||||
selectedSkin = currentSong.skin
|
||||
highlight = 2
|
||||
}else if(songSelMoving){
|
||||
selectedSkin = currentSong.skin
|
||||
highlight = 0
|
||||
}
|
||||
var selectedHeight = this.songAsset.height
|
||||
if(screen === "difficulty"){
|
||||
selectedWidth = this.songAsset.fullWidth
|
||||
selectedHeight = this.songAsset.fullHeight
|
||||
highlight = 0
|
||||
}
|
||||
|
||||
if(this.currentSongTitle !== currentSong.title){
|
||||
this.currentSongTitle = currentSong.title
|
||||
this.currentSongCache.clear()
|
||||
}
|
||||
|
||||
if(ms > this.state.screenMS + 2000 && selectedWidth === this.songAsset.width){
|
||||
this.drawSongCrown({
|
||||
ctx: ctx,
|
||||
song: currentSong,
|
||||
x: winW / 2 - selectedWidth / 2 + xOffset,
|
||||
y: songTop + this.songAsset.height - selectedHeight
|
||||
})
|
||||
}
|
||||
|
||||
if(screen === "title" || screen === "titleFadeIn" || screen === "song"){
|
||||
var textW = strings.id === "en" ? 350 : 280
|
||||
this.selectTextCache.get({
|
||||
@ -1230,35 +1279,7 @@ class SongSelect{
|
||||
})
|
||||
}
|
||||
|
||||
var currentSong = this.songs[this.selectedSong]
|
||||
var highlight = 0
|
||||
if(!currentSong.stars){
|
||||
highlight = 2
|
||||
}
|
||||
if(this.state.moveHover === 0){
|
||||
highlight = 1
|
||||
}
|
||||
var selectedSkin = this.songSkin.selected
|
||||
if(screen === "title" || screen === "titleFadeIn" || this.state.locked === 3){
|
||||
selectedSkin = currentSong.skin
|
||||
highlight = 2
|
||||
}else if(songSelMoving){
|
||||
selectedSkin = currentSong.skin
|
||||
highlight = 0
|
||||
}
|
||||
var selectedHeight = this.songAsset.height
|
||||
if(screen === "difficulty"){
|
||||
selectedWidth = this.songAsset.fullWidth
|
||||
selectedHeight = this.songAsset.fullHeight
|
||||
highlight = 0
|
||||
}
|
||||
|
||||
if(this.currentSongTitle !== currentSong.title){
|
||||
this.currentSongTitle = currentSong.title
|
||||
this.currentSongCache.clear()
|
||||
}
|
||||
|
||||
if(selectedWidth === this.songAsset.width){
|
||||
if(ms <= this.state.screenMS + 2000 && selectedWidth === this.songAsset.width){
|
||||
this.drawSongCrown({
|
||||
ctx: ctx,
|
||||
song: currentSong,
|
||||
@ -1398,7 +1419,7 @@ class SongSelect{
|
||||
}
|
||||
var drawDifficulty = (ctx, i, currentUra) => {
|
||||
if(currentSong.stars[i] || currentUra){
|
||||
var score = scoreStorage.get(currentSong.hash)
|
||||
var score = scoreStorage.get(currentSong.hash, false, true)
|
||||
var crownDiff = currentUra ? "ura" : this.difficultyId[i]
|
||||
var crownType = ""
|
||||
if(score && score[crownDiff]){
|
||||
@ -1585,6 +1606,8 @@ class SongSelect{
|
||||
alphaFade = this.draw.easeIn((fade - 0.45) * 20)
|
||||
}
|
||||
this.draw.alpha(alphaFade, ctx, ctx => {
|
||||
ctx.fillStyle = this.songSkin.selected.background
|
||||
ctx.fillRect(x + 7 + i * 60, y + 60, 52, 352)
|
||||
drawDifficulty(ctx, i, true)
|
||||
}, winW, winH)
|
||||
}else{
|
||||
@ -1990,7 +2013,7 @@ class SongSelect{
|
||||
drawSongCrown(config){
|
||||
if(!config.song.action && config.song.hash){
|
||||
var ctx = config.ctx
|
||||
var score = scoreStorage.get(config.song.hash)
|
||||
var score = scoreStorage.get(config.song.hash, false, true)
|
||||
for(var i = this.difficultyId.length; i--;){
|
||||
var diff = this.difficultyId[i]
|
||||
if(!score){
|
||||
@ -2140,13 +2163,19 @@ class SongSelect{
|
||||
onsongsel(response){
|
||||
if(response && response.value){
|
||||
var selected = false
|
||||
if("selected" in response.value){
|
||||
if(response.type === "songsel" && "selected" in response.value){
|
||||
selected = response.value.selected
|
||||
}
|
||||
if("song" in response.value){
|
||||
var song = +response.value.song
|
||||
if(song >= 0 && song < this.songs.length){
|
||||
if(!selected){
|
||||
if(response.type === "catjump"){
|
||||
var moveBy = response.value.move
|
||||
if(moveBy === -1 || moveBy === 1){
|
||||
this.selectedSong = song
|
||||
this.categoryJump(moveBy, true)
|
||||
}
|
||||
}else if(!selected){
|
||||
this.state.locked = true
|
||||
if(this.state.screen === "difficulty"){
|
||||
this.toSongSelect(true)
|
||||
@ -2174,6 +2203,16 @@ class SongSelect{
|
||||
}
|
||||
}
|
||||
}
|
||||
oncatjump(response){
|
||||
if(response && response.value){
|
||||
if("song" in response.value){
|
||||
var song = +response.value.song
|
||||
if(song >= 0 && song < this.songs.length){
|
||||
this.state.locked = true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
startP2(){
|
||||
this.onusers(p2.getMessage("users"))
|
||||
if(p2.session){
|
||||
@ -2183,7 +2222,7 @@ class SongSelect{
|
||||
if(response.type == "users"){
|
||||
this.onusers(response)
|
||||
}
|
||||
if(p2.session && response.type == "songsel"){
|
||||
if(p2.session && (response.type == "songsel" || response.type == "catjump")){
|
||||
this.onsongsel(response)
|
||||
this.state.selLock = false
|
||||
}
|
||||
|
@ -86,6 +86,7 @@
|
||||
this.maxCombo = "最大コンボ数"
|
||||
this.drumroll = "連打数"
|
||||
|
||||
this.errorOccured = "エラーが発生しました。再読み込みしてください。"
|
||||
this.tutorial = {
|
||||
basics: [
|
||||
"流れてくる音符がワクに重なったらバチで太鼓をたたこう!",
|
||||
@ -109,7 +110,8 @@
|
||||
"Gitリポジトリかメールでバグを報告してください。"
|
||||
],
|
||||
diagnosticWarning: "以下の端末診断情報も併せて報告してください!",
|
||||
issueTemplate: "###### 下記の問題を説明してください。 スクリーンショットと診断情報を含めてください。"
|
||||
issueTemplate: "###### 下記の問題を説明してください。 スクリーンショットと診断情報を含めてください。",
|
||||
issues: "課題"
|
||||
}
|
||||
this.session = {
|
||||
multiplayerSession: "オンラインセッション",
|
||||
@ -281,6 +283,7 @@ function StringsEn(){
|
||||
this.maxCombo = "MAX Combo"
|
||||
this.drumroll = "Drumroll"
|
||||
|
||||
this.errorOccured = "An error occurred, please refresh"
|
||||
this.tutorial = {
|
||||
basics: [
|
||||
"When a note overlaps the frame, that is your cue to hit the drum!",
|
||||
@ -304,7 +307,8 @@ function StringsEn(){
|
||||
"You can report bugs either via our Git repository or email."
|
||||
],
|
||||
diagnosticWarning: "Be sure to include the following diagnostic data!",
|
||||
issueTemplate: "###### Describe the problem you are having below. Please include a screenshot and the diagnostic information."
|
||||
issueTemplate: "###### Describe the problem you are having below. Please include a screenshot and the diagnostic information.",
|
||||
issues: "Issues"
|
||||
}
|
||||
this.session = {
|
||||
multiplayerSession: "Multiplayer Session",
|
||||
@ -426,10 +430,10 @@ function StringsCn(){
|
||||
this.hard = "困难"
|
||||
this.oni = "魔王"
|
||||
this.songBranch = "有谱面分歧"
|
||||
this.sessionStart = "开始在线会话!"
|
||||
this.sessionStart = "开始在线会话!"
|
||||
this.sessionEnd = "结束在线会话"
|
||||
this.loading = "加载中..."
|
||||
this.waitingForP2 = "Waiting for Another Player..."
|
||||
this.waitingForP2 = "正在等待对方玩家..."
|
||||
this.cancel = "取消"
|
||||
this.note = {
|
||||
don: "咚",
|
||||
@ -476,6 +480,7 @@ function StringsCn(){
|
||||
this.maxCombo = "最多连段数"
|
||||
this.drumroll = "连打数"
|
||||
|
||||
this.errorOccured = "An error occurred, please refresh"
|
||||
this.tutorial = {
|
||||
basics: [
|
||||
"当流动的音符将与框框重叠时就用鼓棒敲打太鼓吧",
|
||||
@ -499,11 +504,12 @@ function StringsCn(){
|
||||
"You can report bugs either via our Git repository or email."
|
||||
],
|
||||
diagnosticWarning: "Be sure to include the following diagnostic data!",
|
||||
issueTemplate: "###### Describe the problem you are having below. Please include a screenshot and the diagnostic information."
|
||||
issueTemplate: "###### Describe the problem you are having below. Please include a screenshot and the diagnostic information.",
|
||||
issues: "工单"
|
||||
}
|
||||
this.session = {
|
||||
multiplayerSession: "Multiplayer Session",
|
||||
linkTutorial: "Share this link with your friend to start playing together! Do not leave this screen while they join.",
|
||||
multiplayerSession: "在线会话",
|
||||
linkTutorial: "复制下方地址,给你的朋友即可开始一起游戏!当他们与您联系之前,请不要离开此页面。",
|
||||
cancel: "取消"
|
||||
}
|
||||
this.settings = {
|
||||
@ -624,7 +630,7 @@ function StringsTw(){
|
||||
this.sessionStart = "開始多人模式!"
|
||||
this.sessionEnd = "結束多人模式"
|
||||
this.loading = "讀取中..."
|
||||
this.waitingForP2 = "Waiting for Another Player..."
|
||||
this.waitingForP2 = "正在等待對方玩家..."
|
||||
this.cancel = "取消"
|
||||
this.note = {
|
||||
don: "咚",
|
||||
@ -671,6 +677,7 @@ function StringsTw(){
|
||||
this.maxCombo = "最多連段數"
|
||||
this.drumroll = "連打數"
|
||||
|
||||
this.errorOccured = "An error occurred, please refresh"
|
||||
this.tutorial = {
|
||||
basics: [
|
||||
"當流動的音符將與框框重疊時就用鼓棒敲打太鼓吧",
|
||||
@ -694,11 +701,12 @@ function StringsTw(){
|
||||
"You can report bugs either via our Git repository or email."
|
||||
],
|
||||
diagnosticWarning: "Be sure to include the following diagnostic data!",
|
||||
issueTemplate: "###### Describe the problem you are having below. Please include a screenshot and the diagnostic information."
|
||||
issueTemplate: "###### Describe the problem you are having below. Please include a screenshot and the diagnostic information.",
|
||||
issues: "問題"
|
||||
}
|
||||
this.session = {
|
||||
multiplayerSession: "Multiplayer Session",
|
||||
linkTutorial: "Share this link with your friend to start playing together! Do not leave this screen while they join.",
|
||||
multiplayerSession: "多人模式",
|
||||
linkTutorial: "複製下方地址,給你的朋友即可開始一起遊戲!當他們與您聯繫之前,請不要離開此頁面。",
|
||||
cancel: "取消"
|
||||
}
|
||||
this.settings = {
|
||||
@ -866,6 +874,7 @@ function StringsKo(){
|
||||
this.maxCombo = "최대 콤보 수"
|
||||
this.drumroll = "연타 횟수"
|
||||
|
||||
this.errorOccured = "An error occurred, please refresh"
|
||||
this.tutorial = {
|
||||
basics: [
|
||||
"이동하는 음표가 테두리와 겹쳐졌을 때 북채로 태고를 두드리자!",
|
||||
@ -889,7 +898,8 @@ function StringsKo(){
|
||||
"You can report bugs either via our Git repository or email."
|
||||
],
|
||||
diagnosticWarning: "Be sure to include the following diagnostic data!",
|
||||
issueTemplate: "###### Describe the problem you are having below. Please include a screenshot and the diagnostic information."
|
||||
issueTemplate: "###### Describe the problem you are having below. Please include a screenshot and the diagnostic information.",
|
||||
issues: "이슈"
|
||||
}
|
||||
this.session = {
|
||||
multiplayerSession: "Multiplayer Session",
|
||||
|
@ -348,7 +348,7 @@
|
||||
}
|
||||
|
||||
var score = this.controller.getGlobalScore()
|
||||
var gaugePercent = Math.round(score.gauge / 200) / 50
|
||||
var gaugePercent = this.rules.gaugePercent(score.gauge)
|
||||
|
||||
if(this.multiplayer === 2){
|
||||
var scoreImg = "bg_score_p2"
|
||||
|
@ -4,8 +4,8 @@
|
||||
<div class="view-content"></div>
|
||||
<div id="diag-txt"></div>
|
||||
<div class="left-buttons">
|
||||
<div id="link-issues" class="taibtn stroke-sub link-btn" alt="Issues">
|
||||
<a target="_blank">Issues</a>
|
||||
<div id="link-issues" class="taibtn stroke-sub link-btn">
|
||||
<a target="_blank"></a>
|
||||
</div>
|
||||
<div id="link-email" class="taibtn stroke-sub link-btn">
|
||||
<a></a>
|
||||
|
@ -24,7 +24,7 @@
|
||||
<div class="music-volume input-slider">
|
||||
<span class="reset">x</span><input type="text" value="" readonly><span class="minus">-</span><span class="plus">+</span>
|
||||
</div>
|
||||
<label><input class="change-restart" type="checkbox">Restart on change</label>
|
||||
<label class="change-restart-label"><input class="change-restart" type="checkbox">Restart on change</label>
|
||||
<label class="autoplay-label"><input class="autoplay" type="checkbox">Auto play</label>
|
||||
<div class="bottom-btns">
|
||||
<div class="restart-btn">Restart song</div>
|
||||
|
25
server.py
25
server.py
@ -262,7 +262,7 @@ async def connection(ws, path):
|
||||
elif action == "songsel":
|
||||
# Session song selection
|
||||
if "other_user" in user and "ws" in user["other_user"]:
|
||||
if type == "songsel":
|
||||
if type == "songsel" or type == "catjump":
|
||||
# Change song select position
|
||||
if user["other_user"]["action"] == "songsel":
|
||||
sent_msg = msgobj(type, value)
|
||||
@ -336,7 +336,26 @@ async def connection(ws, path):
|
||||
|
||||
port = int(sys.argv[1]) if len(sys.argv) > 1 else 34802
|
||||
print('Starting server on port %d' % port)
|
||||
asyncio.get_event_loop().run_until_complete(
|
||||
loop = asyncio.get_event_loop()
|
||||
tasks = asyncio.gather(
|
||||
websockets.serve(connection, "localhost", port)
|
||||
)
|
||||
asyncio.get_event_loop().run_forever()
|
||||
try:
|
||||
loop.run_until_complete(tasks)
|
||||
loop.run_forever()
|
||||
except KeyboardInterrupt:
|
||||
print("Stopping server")
|
||||
def shutdown_exception_handler(loop, context):
|
||||
if "exception" not in context or not isinstance(context["exception"], asyncio.CancelledError):
|
||||
loop.default_exception_handler(context)
|
||||
loop.set_exception_handler(shutdown_exception_handler)
|
||||
tasks = asyncio.gather(*asyncio.all_tasks(loop=loop), loop=loop, return_exceptions=True)
|
||||
tasks.add_done_callback(lambda t: loop.stop())
|
||||
tasks.cancel()
|
||||
while not tasks.done() and not loop.is_closed():
|
||||
loop.run_forever()
|
||||
finally:
|
||||
if hasattr(loop, "shutdown_asyncgens"):
|
||||
loop.run_until_complete(loop.shutdown_asyncgens())
|
||||
loop.close()
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user