Merge pull request #72 from LoveEevee/p2-multiplayer-improvements

P2: Multiplayer improvements
This commit is contained in:
Bui 2018-11-13 10:05:47 +00:00 committed by GitHub
commit 2e00290af4
11 changed files with 139 additions and 37 deletions

View File

@ -32,3 +32,8 @@
text-align: center;
z-index: 1;
}
#p2-cancel-button{
display: none;
position: absolute;
bottom: -55px;
}

View File

@ -170,6 +170,7 @@ kbd{
}
.taibtn{
display: inline-block;
background: #f6ead4;
padding: 0.4em 0.4em;
border-radius: 0.5em;
border: 0.1em rgba(218, 205, 178, 1) solid;

View File

@ -65,7 +65,8 @@ var assets = {
"title.ogg",
"pause.wav",
"cancel.wav",
"results.ogg"
"results.ogg",
"sanka.wav"
],
"audioSfxLR": [
"note_don.ogg",

View File

@ -16,6 +16,7 @@ class Circle{
this.lastFrame = this.ms + 100
this.animationEnded = false
this.timesHit = 0
this.timesKa = 0
this.requiredHits = config.requiredHits || 0
this.rendaPlayed = false
this.gogoTime = config.gogoTime
@ -57,8 +58,11 @@ class Circle{
this.score = score
this.isPlayed = score <= 0 ? score - 1 : (big ? 2 : 1)
}
hit(){
hit(keysKa){
this.timesHit++
if(keysKa){
this.timesKa++
}
}
getScore(){
return this.score

View File

@ -32,13 +32,13 @@ class Controller{
run(syncWith){
this.game.run()
this.view.run()
this.startMainLoop()
if(syncWith){
syncWith.run()
syncWith.game.elapsedTime = this.game.elapsedTime
syncWith.game.startDate = this.game.startDate
this.syncWith = syncWith
}
this.startMainLoop()
if(!this.multiplayer){
debugObj.controller = this
if(debugObj.debug){

View File

@ -54,7 +54,9 @@ class Game{
this.checkPlays()
// Event operations
this.whenFadeoutMusic()
this.whenLastCirclePlayed()
if(this.controller.multiplayer !== 2){
this.whenLastCirclePlayed()
}
}
getCircles(){
return this.songData.circles
@ -91,9 +93,13 @@ class Game{
circle.played(-1, false)
this.updateCurrentCircle()
if(this.controller.multiplayer === 1){
p2.send("drumroll", {
var value = {
pace: (ms - circle.getMS()) / circle.timesHit
})
}
if(type === "drumroll" || type === "daiDrumroll"){
value.kaAmount = circle.timesKa / circle.timesHit
}
p2.send("drumroll", value)
}
}else{
var currentScore = 0
@ -207,11 +213,15 @@ class Game{
this.updateGlobalScore(score, typeDai && keyDai ? 2 : 1, circle.gogoTime)
this.updateCurrentCircle()
if(this.controller.multiplayer == 1){
p2.send("note", {
var value = {
score: score,
ms: circle.getMS() - currentTime,
dai: typeDai ? keyDai ? 2 : 1 : 0
})
}
if((!keysDon || !typeDon) && (!keysKa || !typeKa)){
value.reverse = true
}
p2.send("note", value)
}
}else{
if(circle.getMS() > currentTime || currentTime > circle.getEndTime()){
@ -223,9 +233,9 @@ class Game{
this.checkBalloon(circle)
}
}else if((keysDon || keysKa) && (type === "drumroll" || type === "daiDrumroll")){
this.checkDrumroll(circle)
this.checkDrumroll(circle, keysKa)
if(keyDai){
this.checkDrumroll(circle)
this.checkDrumroll(circle, keysKa)
}
}
}
@ -249,11 +259,11 @@ class Game{
this.globalScore.drumroll ++
this.globalScore.points += score
}
checkDrumroll(circle){
checkDrumroll(circle, keysKa){
var ms = this.elapsedTime
var dai = circle.getType() === "daiDrumroll"
var score = 100
circle.hit()
circle.hit(keysKa)
var keyTime = this.controller.getKeyTime()
if(circle.getType() === "drumroll"){
var sound = keyTime["don"] > keyTime["ka"] ? "don" : "ka"
@ -275,11 +285,24 @@ class Game{
this.globalScore.points += score * (dai ? 2 : 1)
}
whenLastCirclePlayed(){
var circles = this.songData.circles
var lastCircle = circles[circles.length - 1]
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
if(this.controller.multiplayer){
this.controller.syncWith.game.fadeOutStarted = ms
}
}
}
whenFadeoutMusic(){

View File

@ -65,12 +65,18 @@ class loadSong{
loadingText.firstChild.data = 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.selectedSong2 = this.selectedSong
pageEvents.add(p2, "message", event => {
if(event.type === "gameload"){
this.cancelButton.style.display = ""
if(event.value === this.selectedSong.difficulty){
p2.send("gamestart")
this.startMultiplayer()
}else{
this.selectedSong2 = {
title: this.selectedSong.title,
@ -80,13 +86,13 @@ class loadSong{
offset: this.selectedSong.offset
}
if(this.selectedSong.type === "tja"){
p2.send("gamestart")
this.startMultiplayer()
}else{
loader.ajax(this.getSongPath(this.selectedSong2)).then(data => {
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 taikoGame2 = new Controller(this.selectedSong2, this.song2Data, true, 2, this.touchEnabled)
taikoGame1.run(taikoGame2)
}else if(event.type === "left" || event.type === "gameend"){
this.clean()
new SongSelect(false, false, this.touchEnabled)
}
})
p2.send("join", {
@ -110,7 +119,35 @@ class loadSong{
taikoGame.run()
}
}
startMultiplayer(repeat){
if(document.hasFocus()){
p2.send("gamestart")
}else{
if(!repeat){
assets.sounds["sanka"].play()
}
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(){
pageEvents.remove(p2, "message")
if(this.cancelButton){
pageEvents.remove(this.cancelButton, ["mousedown", "touchstart"])
delete this.cancelButton
}
}
}

View File

@ -20,15 +20,19 @@ class Mekadon{
this.playAt(circle, 0, 450)
}
}
playAt(circle, ms, score, dai){
playAt(circle, ms, score, dai, reverse){
var currentMs = circle.getMS() - this.getMS()
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){
this.playAt(circle, ms)
var score = 1
if(kaAmount > 0){
score = Math.random() > kaAmount ? 1 : 2
}
this.playAt(circle, ms, score)
}
}
miss(circle){
@ -41,7 +45,7 @@ class Mekadon{
return true
}
}
playNow(circle, score, dai){
playNow(circle, score, dai, reverse){
var kbd = this.controller.getBindings()
var type = circle.getType()
var keyDai = false
@ -54,12 +58,19 @@ class Mekadon{
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){
this.setKey(kbd["don_l"], ms)
this.setKey(kbd["don_r"], ms)
this.lr = false
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.lr = !this.lr
}else if(type == "daiKa" && playDai){
@ -67,7 +78,7 @@ class Mekadon{
this.setKey(kbd["ka_r"], ms)
this.lr = false
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.lr = !this.lr
}
@ -77,7 +88,7 @@ class Mekadon{
}
this.game.checkBalloon(circle)
}else if(type === "drumroll" || type === "daiDrumroll"){
this.game.checkDrumroll(circle)
this.game.checkDrumroll(circle, score === 2)
}else{
this.controller.displayScore(score)
this.game.updateCombo(score)

View File

@ -106,6 +106,7 @@ class P2Connection{
this.notes = []
this.drumrollPace = 45
this.dai = 2
this.kaAmount = 0
this.results = false
break
case "gameend":
@ -130,6 +131,9 @@ class P2Connection{
break
case "drumroll":
this.drumrollPace = response.value.pace
if("kaAmount" in response.value){
this.kaAmount = response.value.kaAmount
}
break
case "session":
this.clearMessage("users")
@ -160,7 +164,7 @@ class P2Connection{
}
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){
mekadon.play(circle)
}else{
@ -170,7 +174,7 @@ class P2Connection{
if(circle.getType() === "daiDon" || circle.getType() === "daiKa"){
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()
}
}else{

View File

@ -2,5 +2,6 @@
<div id="loading-song">
<div id="loading-don"></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>

View File

@ -145,15 +145,30 @@ async def connection(ws, path):
await ws.send(msgobj("gameend"))
elif action == "waiting" or action == "loading" or action == "loaded":
# Waiting for another user
if type == "leave" and not user["session"]:
if type == "leave":
# Stop waiting
del server_status["waiting"][user["gameid"]]
del user["gameid"]
user["action"] = "ready"
await asyncio.wait([
ws.send(msgobj("left")),
notify_status()
])
if user["session"]:
if "other_user" in user and "ws" in user["other_user"]:
user["action"] = "songsel"
await asyncio.wait([
ws.send(msgobj("left")),
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 type == "gamestart":
user["action"] = "loaded"