mirror of
https://github.com/yuukiwww/taiko-web.git
synced 2024-10-22 17:05:49 +02:00
P2: Multiplayer improvements
This commit is contained in:
parent
1619622257
commit
25d705ffcf
@ -32,3 +32,8 @@
|
|||||||
text-align: center;
|
text-align: center;
|
||||||
z-index: 1;
|
z-index: 1;
|
||||||
}
|
}
|
||||||
|
#p2-cancel-button{
|
||||||
|
display: none;
|
||||||
|
position: absolute;
|
||||||
|
bottom: -55px;
|
||||||
|
}
|
||||||
|
@ -170,6 +170,7 @@ kbd{
|
|||||||
}
|
}
|
||||||
.taibtn{
|
.taibtn{
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
|
background: #f6ead4;
|
||||||
padding: 0.4em 0.4em;
|
padding: 0.4em 0.4em;
|
||||||
border-radius: 0.5em;
|
border-radius: 0.5em;
|
||||||
border: 0.1em rgba(218, 205, 178, 1) solid;
|
border: 0.1em rgba(218, 205, 178, 1) solid;
|
||||||
|
@ -16,6 +16,7 @@ class Circle{
|
|||||||
this.lastFrame = this.ms + 100
|
this.lastFrame = this.ms + 100
|
||||||
this.animationEnded = false
|
this.animationEnded = false
|
||||||
this.timesHit = 0
|
this.timesHit = 0
|
||||||
|
this.timesKa = 0
|
||||||
this.requiredHits = config.requiredHits || 0
|
this.requiredHits = config.requiredHits || 0
|
||||||
this.rendaPlayed = false
|
this.rendaPlayed = false
|
||||||
this.gogoTime = config.gogoTime
|
this.gogoTime = config.gogoTime
|
||||||
@ -57,8 +58,11 @@ class Circle{
|
|||||||
this.score = score
|
this.score = score
|
||||||
this.isPlayed = score <= 0 ? score - 1 : (big ? 2 : 1)
|
this.isPlayed = score <= 0 ? score - 1 : (big ? 2 : 1)
|
||||||
}
|
}
|
||||||
hit(){
|
hit(keysKa){
|
||||||
this.timesHit++
|
this.timesHit++
|
||||||
|
if(keysKa){
|
||||||
|
this.timesKa++
|
||||||
|
}
|
||||||
}
|
}
|
||||||
getScore(){
|
getScore(){
|
||||||
return this.score
|
return this.score
|
||||||
|
@ -32,13 +32,13 @@ class Controller{
|
|||||||
run(syncWith){
|
run(syncWith){
|
||||||
this.game.run()
|
this.game.run()
|
||||||
this.view.run()
|
this.view.run()
|
||||||
this.startMainLoop()
|
|
||||||
if(syncWith){
|
if(syncWith){
|
||||||
syncWith.run()
|
syncWith.run()
|
||||||
syncWith.game.elapsedTime = this.game.elapsedTime
|
syncWith.game.elapsedTime = this.game.elapsedTime
|
||||||
syncWith.game.startDate = this.game.startDate
|
syncWith.game.startDate = this.game.startDate
|
||||||
this.syncWith = syncWith
|
this.syncWith = syncWith
|
||||||
}
|
}
|
||||||
|
this.startMainLoop()
|
||||||
if(!this.multiplayer){
|
if(!this.multiplayer){
|
||||||
debugObj.controller = this
|
debugObj.controller = this
|
||||||
if(debugObj.debug){
|
if(debugObj.debug){
|
||||||
|
@ -54,7 +54,9 @@ class Game{
|
|||||||
this.checkPlays()
|
this.checkPlays()
|
||||||
// Event operations
|
// Event operations
|
||||||
this.whenFadeoutMusic()
|
this.whenFadeoutMusic()
|
||||||
this.whenLastCirclePlayed()
|
if(this.controller.multiplayer !== 2){
|
||||||
|
this.whenLastCirclePlayed()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
getCircles(){
|
getCircles(){
|
||||||
return this.songData.circles
|
return this.songData.circles
|
||||||
@ -91,9 +93,13 @@ class Game{
|
|||||||
circle.played(-1, false)
|
circle.played(-1, false)
|
||||||
this.updateCurrentCircle()
|
this.updateCurrentCircle()
|
||||||
if(this.controller.multiplayer === 1){
|
if(this.controller.multiplayer === 1){
|
||||||
p2.send("drumroll", {
|
var value = {
|
||||||
pace: (ms - circle.getMS()) / circle.timesHit
|
pace: (ms - circle.getMS()) / circle.timesHit
|
||||||
})
|
}
|
||||||
|
if(type === "drumroll" || type === "daiDrumroll"){
|
||||||
|
value.kaAmount = circle.timesKa / circle.timesHit
|
||||||
|
}
|
||||||
|
p2.send("drumroll", value)
|
||||||
}
|
}
|
||||||
}else{
|
}else{
|
||||||
var currentScore = 0
|
var currentScore = 0
|
||||||
@ -207,11 +213,15 @@ class Game{
|
|||||||
this.updateGlobalScore(score, typeDai && keyDai ? 2 : 1, circle.gogoTime)
|
this.updateGlobalScore(score, typeDai && keyDai ? 2 : 1, circle.gogoTime)
|
||||||
this.updateCurrentCircle()
|
this.updateCurrentCircle()
|
||||||
if(this.controller.multiplayer == 1){
|
if(this.controller.multiplayer == 1){
|
||||||
p2.send("note", {
|
var value = {
|
||||||
score: score,
|
score: score,
|
||||||
ms: circle.getMS() - currentTime,
|
ms: circle.getMS() - currentTime,
|
||||||
dai: typeDai ? keyDai ? 2 : 1 : 0
|
dai: typeDai ? keyDai ? 2 : 1 : 0
|
||||||
})
|
}
|
||||||
|
if((!keysDon || !typeDon) && (!keysKa || !typeKa)){
|
||||||
|
value.reverse = true
|
||||||
|
}
|
||||||
|
p2.send("note", value)
|
||||||
}
|
}
|
||||||
}else{
|
}else{
|
||||||
if(circle.getMS() > currentTime || currentTime > circle.getEndTime()){
|
if(circle.getMS() > currentTime || currentTime > circle.getEndTime()){
|
||||||
@ -223,9 +233,9 @@ class Game{
|
|||||||
this.checkBalloon(circle)
|
this.checkBalloon(circle)
|
||||||
}
|
}
|
||||||
}else if((keysDon || keysKa) && (type === "drumroll" || type === "daiDrumroll")){
|
}else if((keysDon || keysKa) && (type === "drumroll" || type === "daiDrumroll")){
|
||||||
this.checkDrumroll(circle)
|
this.checkDrumroll(circle, keysKa)
|
||||||
if(keyDai){
|
if(keyDai){
|
||||||
this.checkDrumroll(circle)
|
this.checkDrumroll(circle, keysKa)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -249,11 +259,11 @@ class Game{
|
|||||||
this.globalScore.drumroll ++
|
this.globalScore.drumroll ++
|
||||||
this.globalScore.points += score
|
this.globalScore.points += score
|
||||||
}
|
}
|
||||||
checkDrumroll(circle){
|
checkDrumroll(circle, keysKa){
|
||||||
var ms = this.elapsedTime
|
var ms = this.elapsedTime
|
||||||
var dai = circle.getType() === "daiDrumroll"
|
var dai = circle.getType() === "daiDrumroll"
|
||||||
var score = 100
|
var score = 100
|
||||||
circle.hit()
|
circle.hit(keysKa)
|
||||||
var keyTime = this.controller.getKeyTime()
|
var keyTime = this.controller.getKeyTime()
|
||||||
if(circle.getType() === "drumroll"){
|
if(circle.getType() === "drumroll"){
|
||||||
var sound = keyTime["don"] > keyTime["ka"] ? "don" : "ka"
|
var sound = keyTime["don"] > keyTime["ka"] ? "don" : "ka"
|
||||||
@ -275,11 +285,24 @@ class Game{
|
|||||||
this.globalScore.points += score * (dai ? 2 : 1)
|
this.globalScore.points += score * (dai ? 2 : 1)
|
||||||
}
|
}
|
||||||
whenLastCirclePlayed(){
|
whenLastCirclePlayed(){
|
||||||
var circles = this.songData.circles
|
|
||||||
var lastCircle = circles[circles.length - 1]
|
|
||||||
var ms = this.elapsedTime
|
var ms = this.elapsedTime
|
||||||
if(!this.fadeOutStarted && ms >= lastCircle.getEndTime() + 2000){
|
if(!this.lastCircle){
|
||||||
|
var circles = this.songData.circles
|
||||||
|
this.lastCircle = circles[circles.length - 1].getEndTime()
|
||||||
|
if(this.controller.multiplayer){
|
||||||
|
var syncWith = this.controller.syncWith
|
||||||
|
var syncCircles = syncWith.game.songData.circles
|
||||||
|
var syncLastCircle = syncCircles[syncCircles.length - 1].getEndTime()
|
||||||
|
if(syncLastCircle > this.lastCircle){
|
||||||
|
this.lastCircle = syncLastCircle
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(!this.fadeOutStarted && ms >= this.lastCircle + 2000){
|
||||||
this.fadeOutStarted = ms
|
this.fadeOutStarted = ms
|
||||||
|
if(this.controller.multiplayer){
|
||||||
|
this.controller.syncWith.game.fadeOutStarted = ms
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
whenFadeoutMusic(){
|
whenFadeoutMusic(){
|
||||||
|
@ -65,12 +65,18 @@ class loadSong{
|
|||||||
loadingText.firstChild.data = waitingText
|
loadingText.firstChild.data = waitingText
|
||||||
loadingText.setAttribute("alt", waitingText)
|
loadingText.setAttribute("alt", waitingText)
|
||||||
|
|
||||||
|
this.cancelButton = document.getElementById("p2-cancel-button")
|
||||||
|
this.cancelButton.style.display = "inline-block"
|
||||||
|
pageEvents.add(this.cancelButton, ["mousedown", "touchstart"], this.cancelLoad.bind(this))
|
||||||
|
|
||||||
this.song2Data = this.songData
|
this.song2Data = this.songData
|
||||||
this.selectedSong2 = this.selectedSong
|
this.selectedSong2 = this.selectedSong
|
||||||
pageEvents.add(p2, "message", event => {
|
pageEvents.add(p2, "message", event => {
|
||||||
if(event.type === "gameload"){
|
if(event.type === "gameload"){
|
||||||
|
this.cancelButton.style.display = ""
|
||||||
|
|
||||||
if(event.value === this.selectedSong.difficulty){
|
if(event.value === this.selectedSong.difficulty){
|
||||||
p2.send("gamestart")
|
this.startMultiplayer()
|
||||||
}else{
|
}else{
|
||||||
this.selectedSong2 = {
|
this.selectedSong2 = {
|
||||||
title: this.selectedSong.title,
|
title: this.selectedSong.title,
|
||||||
@ -80,13 +86,13 @@ class loadSong{
|
|||||||
offset: this.selectedSong.offset
|
offset: this.selectedSong.offset
|
||||||
}
|
}
|
||||||
if(this.selectedSong.type === "tja"){
|
if(this.selectedSong.type === "tja"){
|
||||||
p2.send("gamestart")
|
this.startMultiplayer()
|
||||||
}else{
|
}else{
|
||||||
loader.ajax(this.getSongPath(this.selectedSong2)).then(data => {
|
loader.ajax(this.getSongPath(this.selectedSong2)).then(data => {
|
||||||
this.song2Data = data.replace(/\0/g, "").split("\n")
|
this.song2Data = data.replace(/\0/g, "").split("\n")
|
||||||
p2.send("gamestart")
|
this.startMultiplayer()
|
||||||
}, () => {
|
}, () => {
|
||||||
p2.send("gamestart")
|
this.startMultiplayer()
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -97,6 +103,9 @@ class loadSong{
|
|||||||
var taikoGame1 = new Controller(this.selectedSong, this.songData, false, 1, this.touchEnabled)
|
var taikoGame1 = new Controller(this.selectedSong, this.songData, false, 1, this.touchEnabled)
|
||||||
var taikoGame2 = new Controller(this.selectedSong2, this.song2Data, true, 2, this.touchEnabled)
|
var taikoGame2 = new Controller(this.selectedSong2, this.song2Data, true, 2, this.touchEnabled)
|
||||||
taikoGame1.run(taikoGame2)
|
taikoGame1.run(taikoGame2)
|
||||||
|
}else if(event.type === "left" || event.type === "gameend"){
|
||||||
|
this.clean()
|
||||||
|
new SongSelect(false, false, this.touchEnabled)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
p2.send("join", {
|
p2.send("join", {
|
||||||
@ -110,7 +119,37 @@ class loadSong{
|
|||||||
taikoGame.run()
|
taikoGame.run()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
startMultiplayer(repeat){
|
||||||
|
if(document.hasFocus()){
|
||||||
|
p2.send("gamestart")
|
||||||
|
}else{
|
||||||
|
if(!repeat){
|
||||||
|
for(var i = 0; i < 3; i++){
|
||||||
|
assets.sounds["note_don"].play(i * 0.2)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
setTimeout(() => {
|
||||||
|
this.startMultiplayer(true)
|
||||||
|
}, 100)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
cancelLoad(event){
|
||||||
|
if(event.type === "mousedown"){
|
||||||
|
if(event.which !== 1){
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}else{
|
||||||
|
event.preventDefault()
|
||||||
|
}
|
||||||
|
p2.send("leave")
|
||||||
|
assets.sounds["don"].play()
|
||||||
|
this.cancelButton.style.pointerEvents = "none"
|
||||||
|
}
|
||||||
clean(){
|
clean(){
|
||||||
pageEvents.remove(p2, "message")
|
pageEvents.remove(p2, "message")
|
||||||
|
if(this.cancelButton){
|
||||||
|
pageEvents.remove(this.cancelButton, ["mousedown", "touchstart"])
|
||||||
|
delete this.cancelButton
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -20,15 +20,19 @@ class Mekadon{
|
|||||||
this.playAt(circle, 0, 450)
|
this.playAt(circle, 0, 450)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
playAt(circle, ms, score, dai){
|
playAt(circle, ms, score, dai, reverse){
|
||||||
var currentMs = circle.getMS() - this.getMS()
|
var currentMs = circle.getMS() - this.getMS()
|
||||||
if(ms > currentMs - 10){
|
if(ms > currentMs - 10){
|
||||||
return this.playNow(circle, score, dai)
|
return this.playNow(circle, score, dai, reverse)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
playDrumrollAt(circle, ms, pace){
|
playDrumrollAt(circle, ms, pace, kaAmount){
|
||||||
if(pace && this.getMS() >= this.lastHit + pace){
|
if(pace && this.getMS() >= this.lastHit + pace){
|
||||||
this.playAt(circle, ms)
|
var score = 1
|
||||||
|
if(kaAmount > 0){
|
||||||
|
score = Math.random() > kaAmount ? 1 : 2
|
||||||
|
}
|
||||||
|
this.playAt(circle, ms, score)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
miss(circle){
|
miss(circle){
|
||||||
@ -41,7 +45,7 @@ class Mekadon{
|
|||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
playNow(circle, score, dai){
|
playNow(circle, score, dai, reverse){
|
||||||
var kbd = this.controller.getBindings()
|
var kbd = this.controller.getBindings()
|
||||||
var type = circle.getType()
|
var type = circle.getType()
|
||||||
var keyDai = false
|
var keyDai = false
|
||||||
@ -54,12 +58,19 @@ class Mekadon{
|
|||||||
var ms = circle.getMS()
|
var ms = circle.getMS()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(reverse){
|
||||||
|
if(type === "don" || type === "daiDon"){
|
||||||
|
type = "ka"
|
||||||
|
}else if(type === "ka" || type === "daiKa"){
|
||||||
|
type = "don"
|
||||||
|
}
|
||||||
|
}
|
||||||
if(type == "daiDon" && playDai){
|
if(type == "daiDon" && playDai){
|
||||||
this.setKey(kbd["don_l"], ms)
|
this.setKey(kbd["don_l"], ms)
|
||||||
this.setKey(kbd["don_r"], ms)
|
this.setKey(kbd["don_r"], ms)
|
||||||
this.lr = false
|
this.lr = false
|
||||||
keyDai = true
|
keyDai = true
|
||||||
}else if(type == "don" || type == "daiDon" || drumrollNotes){
|
}else if(type == "don" || type == "daiDon" || drumrollNotes && score !== 2){
|
||||||
this.setKey(this.lr ? kbd["don_l"] : kbd["don_r"], ms)
|
this.setKey(this.lr ? kbd["don_l"] : kbd["don_r"], ms)
|
||||||
this.lr = !this.lr
|
this.lr = !this.lr
|
||||||
}else if(type == "daiKa" && playDai){
|
}else if(type == "daiKa" && playDai){
|
||||||
@ -67,7 +78,7 @@ class Mekadon{
|
|||||||
this.setKey(kbd["ka_r"], ms)
|
this.setKey(kbd["ka_r"], ms)
|
||||||
this.lr = false
|
this.lr = false
|
||||||
keyDai = true
|
keyDai = true
|
||||||
}else if(type == "ka" || type == "daiKa"){
|
}else if(type == "ka" || type == "daiKa" || drumrollNotes){
|
||||||
this.setKey(this.lr ? kbd["ka_l"] : kbd["ka_r"], ms)
|
this.setKey(this.lr ? kbd["ka_l"] : kbd["ka_r"], ms)
|
||||||
this.lr = !this.lr
|
this.lr = !this.lr
|
||||||
}
|
}
|
||||||
@ -77,7 +88,7 @@ class Mekadon{
|
|||||||
}
|
}
|
||||||
this.game.checkBalloon(circle)
|
this.game.checkBalloon(circle)
|
||||||
}else if(type === "drumroll" || type === "daiDrumroll"){
|
}else if(type === "drumroll" || type === "daiDrumroll"){
|
||||||
this.game.checkDrumroll(circle)
|
this.game.checkDrumroll(circle, score === 2)
|
||||||
}else{
|
}else{
|
||||||
this.controller.displayScore(score)
|
this.controller.displayScore(score)
|
||||||
this.game.updateCombo(score)
|
this.game.updateCombo(score)
|
||||||
|
@ -106,6 +106,7 @@ class P2Connection{
|
|||||||
this.notes = []
|
this.notes = []
|
||||||
this.drumrollPace = 45
|
this.drumrollPace = 45
|
||||||
this.dai = 2
|
this.dai = 2
|
||||||
|
this.kaAmount = 0
|
||||||
this.results = false
|
this.results = false
|
||||||
break
|
break
|
||||||
case "gameend":
|
case "gameend":
|
||||||
@ -130,6 +131,9 @@ class P2Connection{
|
|||||||
break
|
break
|
||||||
case "drumroll":
|
case "drumroll":
|
||||||
this.drumrollPace = response.value.pace
|
this.drumrollPace = response.value.pace
|
||||||
|
if("kaAmount" in response.value){
|
||||||
|
this.kaAmount = response.value.kaAmount
|
||||||
|
}
|
||||||
break
|
break
|
||||||
case "session":
|
case "session":
|
||||||
this.clearMessage("users")
|
this.clearMessage("users")
|
||||||
@ -160,7 +164,7 @@ class P2Connection{
|
|||||||
}
|
}
|
||||||
|
|
||||||
if(drumrollNotes){
|
if(drumrollNotes){
|
||||||
mekadon.playDrumrollAt(circle, 0, this.drumrollPace)
|
mekadon.playDrumrollAt(circle, 0, this.drumrollPace, type === "drumroll" || type === "daiDrumroll" ? this.kaAmount : 0)
|
||||||
}else if(this.notes.length === 0){
|
}else if(this.notes.length === 0){
|
||||||
mekadon.play(circle)
|
mekadon.play(circle)
|
||||||
}else{
|
}else{
|
||||||
@ -170,7 +174,7 @@ class P2Connection{
|
|||||||
if(circle.getType() === "daiDon" || circle.getType() === "daiKa"){
|
if(circle.getType() === "daiDon" || circle.getType() === "daiKa"){
|
||||||
dai = this.dai
|
dai = this.dai
|
||||||
}
|
}
|
||||||
if(mekadon.playAt(circle, note.ms, note.score, dai)){
|
if(mekadon.playAt(circle, note.ms, note.score, dai, note.reverse)){
|
||||||
this.notes.shift()
|
this.notes.shift()
|
||||||
}
|
}
|
||||||
}else{
|
}else{
|
||||||
|
@ -2,5 +2,6 @@
|
|||||||
<div id="loading-song">
|
<div id="loading-song">
|
||||||
<div id="loading-don"></div>
|
<div id="loading-don"></div>
|
||||||
<div class="loading-text stroke-sub" alt="Loading...">Loading...</div>
|
<div class="loading-text stroke-sub" alt="Loading...">Loading...</div>
|
||||||
|
<div id="p2-cancel-button" class="taibtn stroke-sub" alt="Cancel">Cancel</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
31
server.py
31
server.py
@ -145,15 +145,30 @@ async def connection(ws, path):
|
|||||||
await ws.send(msgobj("gameend"))
|
await ws.send(msgobj("gameend"))
|
||||||
elif action == "waiting" or action == "loading" or action == "loaded":
|
elif action == "waiting" or action == "loading" or action == "loaded":
|
||||||
# Waiting for another user
|
# Waiting for another user
|
||||||
if type == "leave" and not user["session"]:
|
if type == "leave":
|
||||||
# Stop waiting
|
# Stop waiting
|
||||||
del server_status["waiting"][user["gameid"]]
|
if user["session"]:
|
||||||
del user["gameid"]
|
if "other_user" in user and "ws" in user["other_user"]:
|
||||||
user["action"] = "ready"
|
user["action"] = "songsel"
|
||||||
await asyncio.wait([
|
await asyncio.wait([
|
||||||
ws.send(msgobj("left")),
|
ws.send(msgobj("left")),
|
||||||
notify_status()
|
user["other_user"]["ws"].send(msgobj("users", []))
|
||||||
])
|
])
|
||||||
|
else:
|
||||||
|
user["action"] = "ready"
|
||||||
|
user["session"] = False
|
||||||
|
await asyncio.wait([
|
||||||
|
ws.send(msgobj("gameend")),
|
||||||
|
ws.send(status_event())
|
||||||
|
])
|
||||||
|
else:
|
||||||
|
del server_status["waiting"][user["gameid"]]
|
||||||
|
del user["gameid"]
|
||||||
|
user["action"] = "ready"
|
||||||
|
await asyncio.wait([
|
||||||
|
ws.send(msgobj("left")),
|
||||||
|
notify_status()
|
||||||
|
])
|
||||||
if action == "loading":
|
if action == "loading":
|
||||||
if type == "gamestart":
|
if type == "gamestart":
|
||||||
user["action"] = "loaded"
|
user["action"] = "loaded"
|
||||||
|
Loading…
Reference in New Issue
Block a user