diff --git a/public/src/css/scoresheet.css b/public/src/css/scoresheet.css index f720af8..bfe06d4 100644 --- a/public/src/css/scoresheet.css +++ b/public/src/css/scoresheet.css @@ -1,32 +1,29 @@ -#scoresheet{ - width:100%; +.scoresheet{ + width:100%; height:100%; - background: #e84019; color:black; font-family: TnT; - background: url('/assets/img/bg-pattern-2.png'); + background: url("/assets/img/bg-pattern-2.png"); + position: absolute; } -#scoresheet h2{ - +.scoresheet h2{ position:absolute; top:1%; left:1%; font-size: 7vmin; margin:0; color: white; - } -#result-window{ +.result-window{ width:70%; margin:auto; } -#scoresheet button{ - - height: 15%; - width:20%; +.scoresheet button{ + height: 50%; + min-width:20%; position: absolute; display: inline-block; cursor: pointer; @@ -38,45 +35,50 @@ border-radius: 10px; outline: none; top:10%; + white-space: nowrap; } -#replay{ +.scoresheet .replay{ left:1%; } -#song-select{ +.scoresheet .song-select{ left:23%; } -#scoresheet button:hover{ +.scoresheet button:hover{ border-color:#fa5d3a; - color:white; - background:#0c6577; + color:white; + background:#0c6577; } -#result-bar{ - width: 100%; - height:40%; - position:absolute; - top:10%; - left:0; - border-bottom:10px inset #b6361d; - border-top:5px solid #b23111; +.scoresheet .result-bar{ + max-width: 120vh; + height: 71vh; min-height: 200px; - + display:flex; + flex-direction: column; + justify-content: center; + align-items: flex-end; + position: absolute; + left: 0; + right: 0; + margin: auto; } -#score-cont{ - position:absolute; +.scoresheet .score-cont{ + position:relative; right:1%; width:60%; height:80%; background:rgba(255,255,255,0.7); border-radius:15px; + margin: 10px; + max-height: 33vh; } -#score-hp-bar-bg{ - position: absolute; +.scoresheet .score-hp-bar-bg{ + position: relative; margin-top:2%; margin-left:5%; background: url("/assets/img/hp-bar-bg.png"); @@ -85,12 +87,12 @@ } -#score-hp-bar-colour{ +.scoresheet .score-hp-bar-colour{ position:absolute; padding: 0; } -#score-hp-bar-colour img{ +.scoresheet .score-hp-bar-colour img{ position:absolute; height: 100%; width: 100%; @@ -98,8 +100,8 @@ padding:0; } -#score-points{ - width:30%; +.scoresheet .score-points{ + min-width:30%; height:18%; background:black; border:5px solid #ae7a26; @@ -110,61 +112,95 @@ color: white; font-size: 5vmin; text-align: right; - padding-right:2%; + padding: .3% 1%; + white-space: nowrap; } -#score-details{ +.scoresheet .score-details{ position: absolute; right:5%; - width:50%; + width:70%; height:50%; color:white; - -webkit-text-stroke-width: 2px; - -webkit-text-stroke-color: black; - } -#score-details td{ +.scoresheet .score-details th, +.scoresheet .score-details td{ font-size: 3vmin; + font-weight: normal; + white-space: nowrap; +} + +.scoresheet .score-details td{ text-align: right; } -.floatLeft{ - text-align: left !important; +.scoresheet .value{ + width: 25%; } -.value{ - width:25%; -} - -#bottom-part{ +.scoresheet .bottom-part{ + position: fixed; width:100%; - position: absolute; + height:19vh; + bottom:0; -webkit-box-shadow: inset 0px 10px 20px -5px #ee6d46; -moz-box-shadow: inset 0px 10px 20px -5px #ee6d46; box-shadow: inset 0px 10px 20px -5px #ee6d46; + border-top:10px outset #b6361d; + box-sizing: border-box; } -#score-mark{ +.scoresheet .score-mark{ position: absolute; + top: 0; + bottom: 0; + right: 105%; + height: 40%; + margin: auto; } -.gradient-overlay{ +.scoresheet .gradient-overlay{ position:absolute; width:100%; height:100%; - background: -moz-linear-gradient(top, rgba(0,0,0,0) 0%, rgba(255,165,100,0.64) 62%, rgba(255,165,100,0.65) 63%); /* FF3.6+ */ - background: -webkit-gradient(linear, left top, left bottom, color-stop(0%,rgba(0,0,0,0)), color-stop(62%,rgba(255,165,100,0.64)), color-stop(63%,rgba(255,165,100,0.65))); /* Chrome,Safari4+ */ - background: -webkit-linear-gradient(top, rgba(0,0,0,0) 0%,rgba(255,165,100,0.64) 62%,rgba(255,165,100,0.65) 63%); /* Chrome10+,Safari5.1+ */ - background: -o-linear-gradient(top, rgba(0,0,0,0) 0%,rgba(255,165,100,0.64) 62%,rgba(255,165,100,0.65) 63%); /* Opera 11.10+ */ - background: -ms-linear-gradient(top, rgba(0,0,0,0) 0%,rgba(255,165,100,0.64) 62%,rgba(255,165,100,0.65) 63%); /* IE10+ */ - background: linear-gradient(to bottom, rgba(0,0,0,0) 0%,rgba(255,165,100,0.64) 62%,rgba(255,165,100,0.65) 63%); /* W3C */ - filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#00000000', endColorstr='#a6ffa564',GradientType=0 ); /* IE6-9 */ + background: linear-gradient(to bottom, rgba(0,0,0,0) 0%, rgba(255,165,100,0.64) 62%, rgba(255,165,100,0.65) 63%); } -#top-part{ +.scoresheet .top-part{ width:100%; - height:10%; + height:10vh; background:#e84019; + border-bottom:5px solid #b23111; + box-sizing: border-box; +} + +.header-great, +.header-fail{ + color: transparent; +} +.header-great::after, +.header-fail::after{ + content: attr(alt); + color: transparent; + -webkit-background-clip: text; + background-clip: text; + position: absolute; + width: 100%; + left: 0; +} +.header-great::after{ + background-image: linear-gradient(0deg, #f00 10%, #fe0 70%); +} +.header-fail::after{ + background-image: linear-gradient(0deg, #00b3df 30%, #6a62f9 90%); + +} +.scoresheet .stroke-sub{ + position:relative; + z-index:1; +} +.scoresheet .stroke-sub::before{ + left:auto; } \ No newline at end of file diff --git a/public/src/js/assets.js b/public/src/js/assets.js index 2fa85d6..6ddc3d0 100644 --- a/public/src/js/assets.js +++ b/public/src/js/assets.js @@ -28,7 +28,8 @@ var assets = { 'muzu_hard.png', 'muzu_oni.png', 'don_anim_normal.png', - 'don_anim_10combo.png' + 'don_anim_10combo.png', + 'balloon.png' ], audioSfx: [ @@ -83,6 +84,7 @@ var assets = { 'note_don.ogg', 'note_ka.ogg', + 'balloon.ogg' ], audioMusic:[ diff --git a/public/src/js/circle.js b/public/src/js/circle.js index 09be407..579755c 100644 --- a/public/src/js/circle.js +++ b/public/src/js/circle.js @@ -1,94 +1,80 @@ -function Circle(id, ms, type, text, speed){ - - var _id=id; - var _ms = ms; - var _type = type; - var _played = false; - var _pos={x:0, y:0}; - var _animating = false; - var _animT = 0; - var _score=0; - var _lastFrame = ms+100; - var _animationEnded = false; - - var played=false; //if cirlce has been played - var _status=-1; //check if circle is playable - - // -1 : Not playable - // 0 : Playable, giving 0 points if played at current time (fail) - // 50 : Playable, giving 50 points if played at current time (pass) - // 100 : Playable, giving 100 points if played at current time (good) - - this.getMS = function(){ - return _ms; - } - - this.getType = function(){ - return _type; - } - - this.getLastFrame = function(){ - return _lastFrame; +class Circle{ + constructor(id, ms, type, text, speed, endTime, requiredHits){ + this.id = id + this.ms = ms + this.type = type + this.text = text + this.speed = speed + this.endTime = endTime ? endTime : ms + 150 + this.isPlayed = false + this.animating = false + this.animT = 0 + this.score = 0 + this.lastFrame = ms + 100 + this.animationEnded = false + this.status = -1 + this.timesHit = 0 + this.requiredHits = requiredHits ? requiredHits : 0 } - - this.incFrame = function(){ - _lastFrame+=20; + getMS(){ + return this.ms } - - this.animate = function(){ - _animating=true; + getEndTime(){ + return this.endTime } - - this.isAnimated = function(){ - return _animating; + getType(){ + return this.type } - - this.getAnimT = function(){ - return _animT; + getLastFrame(){ + return this.lastFrame } - - this.incAnimT = function(){ - _animT+=0.05; + incFrame(){ + this.lastFrame += 20 } - - this.updateStatus = function(status){ - _status=status; - } - - this.getStatus = function(){ - return _status; - } - - this.getPlayed = function(){ - return _played; - } - - this.isAnimationFinished = function(){ - return _animationEnded; + animate(){ + this.animating = true } - - this.endAnimation = function(){ - _animationEnded = true; + isAnimated(){ + return this.animating } - - this.played = function(score){ - _score=score; - _played=true; - } - - this.getScore = function(){ - return _score; + getAnimT(){ + return this.animT + } + incAnimT(){ + this.animT += 0.05 + } + updateStatus(status){ + this.status = status + } + getStatus(){ + return this.status + } + getPlayed(){ + return this.isPlayed + } + isAnimationFinished(){ + return this.animationEnded + } + endAnimation(){ + this.animationEnded = true + } + played(score){ + this.score = score + this.isPlayed = true + } + hit(){ + this.timesHit++ + } + getScore(){ + return this.score + } + getID(){ + return this.id + } + getText(){ + return this.text + } + getSpeed(){ + return this.speed } - - this.getID = function(){ - return _id; - } - - this.getText = function(){ - return text; - } - - this.getSpeed = function(){ - return speed; - } } \ No newline at end of file diff --git a/public/src/js/controller.js b/public/src/js/controller.js index 491ecea..2414dc2 100644 --- a/public/src/js/controller.js +++ b/public/src/js/controller.js @@ -57,6 +57,13 @@ class Controller{ this.mainLoopRunning = true this.mainLoop() } + stopMainLoop(){ + this.mainLoopRunning = false + this.mainAsset.stop() + if(this.syncWith){ + this.syncWith.stopMainLoop() + } + } mainLoop(){ if(this.mainLoopRunning){ if(this.multiplayer != 2){ @@ -88,9 +95,6 @@ class Controller{ this.keyboard.checkMenuKeys() } } - getDistanceForCircle(){ - return this.view.getDistanceForCircle() - } togglePauseMenu(){ this.togglePause() this.view.togglePauseMenu() @@ -98,43 +102,41 @@ class Controller{ displayResults(){ var score = this.getGlobalScore() var vp - if (score.fail == 0) { + if(score.fail == 0){ vp = "fullcombo" this.playSoundMeka("fullcombo", 1.350) - } else if (score.hp >= 50) { + }else if(score.hp >= 50){ vp = "clear" - } else { + }else{ vp = "fail" } assets.sounds["game" + vp].play() setTimeout(() => { - this.mainLoopRunning = false - if(this.multiplayer != 2){ - new Scoresheet(this, this.getGlobalScore()) + if(this.mainLoopRunning){ + this.stopMainLoop() + if(this.multiplayer != 2){ + new Scoresheet(this, this.getGlobalScore(), this.multiplayer) + } } }, 7000) } displayScore(score, notPlayed){ this.view.displayScore(score, notPlayed) } - fadeOutOver(){ - this.game.fadeOutOver() - this.displayResults() - } - getCurrentTimingPoint(){ - return this.game.getCurrentTimingPoint() - } songSelection(){ $("#music-bg").remove() - this.mainLoopRunning = false + this.stopMainLoop() new SongSelect() } restartSong(){ - this.mainAsset.stop() - this.mainLoopRunning = false + this.stopMainLoop() $("#screen").load("/src/views/game.html", () => { - var taikoGame = new Controller(this.selectedSong, this.songData, this.autoPlayEnabled) - taikoGame.run() + if(this.multiplayer){ + new loadSong(this.selectedSong, false, true) + }else{ + var taikoGame = new Controller(this.selectedSong, this.songData, this.autoPlayEnabled) + taikoGame.run() + } }) } playSoundMeka(soundID, time){ @@ -144,27 +146,12 @@ class Controller{ } assets.sounds[soundID + meka].play(time) } - initTiming(){ - this.game.initTiming() - } - setHitcircleSpeed(speed){ - this.view.setHitcircleSpeed(speed) - } - getHitcircleSpeed(){ - return this.game.getHitcircleSpeed() - } - toggleMainMusic(){ - this.game.toggleMainMusic() - } togglePause(){ if(this.syncWith){ this.syncWith.game.togglePause() } this.game.togglePause() } - isPaused(){ - return this.game.isPaused() - } getKeys(){ return this.keyboard.getKeys() } @@ -186,9 +173,6 @@ class Controller{ getCurrentCircle(){ return this.game.getCurrentCircle() } - updateCurrentCircle(){ - this.game.updateCurrentCircle() - } isWaitingForKeyup(key, type){ return this.keyboard.isWaitingForKeyup(key, type) } @@ -198,18 +182,12 @@ class Controller{ getKeyTime(){ return this.keyboard.getKeyTime() } - updateCombo(score){ - this.game.updateCombo(score) - } getCombo(){ return this.game.getCombo() } getGlobalScore(){ return this.game.getGlobalScore() } - updateGlobalScore(score){ - this.game.updateGlobalScore(score) - } autoPlay(circle){ if(this.multiplayer){ p2.play(circle, this.mekadon) diff --git a/public/src/js/game.js b/public/src/js/game.js index fbfe763..7d660dd 100644 --- a/public/src/js/game.js +++ b/public/src/js/game.js @@ -1,446 +1,361 @@ -function Game(controller, selectedSong, songData){ - - var _this = this; - var _selectedSong = selectedSong; - this.elapsedTime = {} //current time in ms from the beginning of the song - var _offsetDate; //date when the chrono is started (before the game begins) - var _startDate; //real start date (when the chrono will be 0) - var _currentDate; // refreshed date - var _songData=songData; - var _currentCircle=0; - var _currentScore=0; - var _combo=0; - var _globalScore={points:0, great:0, good:0, fail:0, maxCombo:0, hp:0, song:selectedSong.title}; - var _HPGain= 100/_songData.circles.length; - var _paused=false; - var _started=false; - var _mainMusicPlaying=false; - var _latestDate; - var _elapsedTimeSincePause=0; - var _musicFadeOut=0; - var _fadeOutStarted=false; - var _currentTimingPoint=0; - var _offsetTime=0; - var _hitcircleSpeed=_songData.difficulty.sliderMultiplier*8; - var _timeForDistanceCircle; - var _mainAsset - assets.songs.forEach(song => { - if(song.id == selectedSong.folder){ - _mainAsset = song.sound - } - }) - - this.run = function(){ - _timeForDistanceCircle=2500 - _this.initTiming(); - } - - this.initTiming = function(){ - _offsetDate = new Date(); - _this.setElapsedTime(-_timeForDistanceCircle |0) - _offsetTime = _timeForDistanceCircle |0 - _startDate = new Date(); - // The real start for the game will start when chrono will reach 0 - _startDate.setMilliseconds(_startDate.getMilliseconds()+_offsetTime); - } - - this.update = function(){ - - // Main operations - _this.updateTime(); - _this.checkTiming(); - _this.updateCirclesStatus(); - _this.checkPlays(); - - // Event operations - _this.whenFadeoutMusic(); - _this.whenLastCirclePlayed(); - - } - - this.getCircles = function(){ - return _songData.circles; - } - - this.updateCirclesStatus = function(){ - - var circles = _songData.circles; - - circles.forEach(function(circle){ - - if(!circle.getPlayed()){ - - var currentTime = _this.getElapsedTime().ms; - var startingTime = circle.getMS()-_timeForDistanceCircle; - // At circle.getMS(), the circle fits the slot - var finishTime = circle.getMS(); - - if( currentTime >= startingTime && currentTime <= finishTime+200){ - - if(currentTime>= finishTime-50 && currentTime < finishTime-30){ - circle.updateStatus(0); - } - else if(currentTime>= finishTime-30 && currentTime < finishTime){ - circle.updateStatus(230); - } - else if(currentTime >= finishTime && currentTime < finishTime+200){ - circle.updateStatus(450); - } - - } - else if(currentTime>finishTime+200 && currentTime<=finishTime+300){ - if(controller.multiplayer != 2){ - circle.updateStatus(-1); - _currentScore=0; - circle.played(_currentScore); - controller.displayScore(_currentScore, true); - _this.updateCurrentCircle(); - _this.updateCombo(_currentScore); - _this.updateGlobalScore(_currentScore); - } - if(controller.multiplayer == 1){ - p2.send("note", { - score: -1 - }) - } - - } - - } - - }); - - } - - this.setHPGain = function(gain){ - _HPGain=gain; - } - - this.checkPlays = function(){ - - var circles = _songData.circles; - var circle = circles[_currentCircle]; - - if(circle){ - if(controller.autoPlayEnabled){ - return controller.autoPlay(circle) - } - var keys = controller.getKeys() - var kbd = controller.getBindings() - if(keys[kbd["don_l"]]){ - _this.checkKey(kbd["don_l"], circle) - } - if(keys[kbd["don_r"]]){ - _this.checkKey(kbd["don_r"], circle) - } - if(keys[kbd["ka_l"]]){ - _this.checkKey(kbd["ka_l"], circle) - } - if(keys[kbd["ka_r"]]){ - _this.checkKey(kbd["ka_r"], circle) - } - } - - } - - this.checkKey = function(keyCode, circle){ - if(!circle.getPlayed() && !controller.isWaitingForKeyup(keyCode, "score") && circle.getStatus()!=-1){ - var score = _this.checkScore(circle); - circle.played(score); - _this.updateCurrentCircle(); - controller.waitForKeyup(keyCode, "score"); - if(controller.multiplayer == 1){ - p2.send("note", { - score: score, - ms: circle.getMS() - _this.getElapsedTime().ms - }) - } - } - } - - this.checkScore = function(circle){ - - var keys = controller.getKeys() - var kbd = controller.getBindings() - - if( - ((keys[kbd["don_l"]] || keys[kbd["don_r"]]) && (circle.getType()=="don" || circle.getType()=="daiDon")) || - ((keys[kbd["ka_l"]] || keys[kbd["ka_r"]]) && (circle.getType()=="ka" || circle.getType()=="daiKa")) - ){ - - switch(circle.getStatus()){ - - case 230: - _currentScore=230; - break; - - case 450: - _currentScore=450; - break; - - } - controller.displayScore(_currentScore); - - } - else{ - _currentScore=0; - controller.displayScore(_currentScore, true); - } - - - _this.updateCombo(_currentScore); - _this.updateGlobalScore(_currentScore); - return _currentScore; - } - - this.whenLastCirclePlayed = function(){ - var circles = _songData.circles; - var lastCircle = circles[_songData.circles.length-1]; - if(!_fadeOutStarted && _this.getElapsedTime().ms>=lastCircle.getMS()+2000){ - _fadeOutStarted=_this.getElapsedTime().ms - } - } - - this.whenFadeoutMusic = function(){ - if(_fadeOutStarted){ - if(_musicFadeOut==0){ - snd.musicGain.fadeOut(1.6) - _musicFadeOut++ - if(controller.multiplayer == 1){ - p2.send("gameend") - } - } - if(_musicFadeOut==1 && _this.getElapsedTime().ms>=_fadeOutStarted+1600){ - controller.fadeOutOver() - _mainAsset.stop() - _musicFadeOut++ - setTimeout(() => { - snd.musicGain.fadeIn() - snd.musicGain.unmute() - }, 1000) - } - } - } - - this.checkTiming = function(){ - - if(_songData.timingPoints[_currentTimingPoint+1]){ - if(_this.getElapsedTime().ms>=_songData.timingPoints[_currentTimingPoint+1].start){ - _currentTimingPoint++; - } - } - } - - this.getCurrentTimingPoint = function(){ - return _songData.timingPoints[_currentTimingPoint]; - } - - this.playMainMusic = function(){ - var ms = _this.getElapsedTime().ms - if(!_mainMusicPlaying && (!_fadeOutStarted || ms<_fadeOutStarted+1600)){ - if(controller.multiplayer != 2){ - _mainAsset.play((ms < 0 ? -ms : 0) / 1000, false, Math.max(0, ms / 1000)); - } - _mainMusicPlaying=true; - } - } - - this.fadeOutOver = function(){ - - } - - this.getHitcircleSpeed = function(){ - return _hitcircleSpeed; - } - - this.togglePause = function(){ - if(!_paused){ - assets.sounds["pause"].play(); - _paused=true; - _latestDate = new Date(); - _mainAsset.stop(); - _mainMusicPlaying=false; - - } - else{ - assets.sounds["cancel"].play(); - _paused=false; - var currentDate = new Date(); - _elapsedTimeSincePause = _elapsedTimeSincePause + currentDate.getTime() - _latestDate.getTime(); - } - } - - this.isPaused = function(){ - return _paused; - } - - this.getElapsedTime = function(){ - return this.elapsedTime; - } - - this.setElapsedTime = function(time){ - this.elapsedTime.ms = time - this.elapsedTime.sec = (this.elapsedTime.ms / 1000 |0) % 60 - this.elapsedTime.min = (this.elapsedTime.ms / 1000 / 60 |0) % 60 - this.elapsedTime.hour = (this.elapsedTime.ms / 1000 / 60 / 60 |0) % 60 - } - - this.updateTime = function(){ - _currentDate = new Date(); - var time = _this.getElapsedTime() - - if(time.ms<0){ - _this.setElapsedTime(_currentDate.getTime() - _startDate.getTime() - _elapsedTimeSincePause) - } - else if(time.ms>=0 && !_started){ - _startDate = new Date(); - _elapsedTimeSincePause = 0; - _this.setElapsedTime(_currentDate.getTime() - _startDate.getTime()) - _started=true; - } - else if(time.ms>=0 && _started){ - _this.setElapsedTime(_currentDate.getTime() - _startDate.getTime() - _elapsedTimeSincePause) - } - } - - this.getCircles = function(){ - return _songData.circles; - } - - this.getSongData = function(){ - return _songData; - } - - this.updateCurrentCircle = function(){ - _currentCircle++; - } - - this.getCurrentCircle = function(){ - return _currentCircle; - } - - this.updateCombo = function(score){ - - (score!=0) ? _combo++ : _combo=0; - - if(_combo>_globalScore.maxCombo) _globalScore.maxCombo = _combo; - - switch(_combo){ - case 50: - controller.playSoundMeka("combo-50"); - break; - case 100: - controller.playSoundMeka("combo-100"); - break; - case 200: - controller.playSoundMeka("combo-200"); - break; - case 300: - controller.playSoundMeka("combo-300"); - break; - case 400: - controller.playSoundMeka("combo-400"); - break; - case 500: - controller.playSoundMeka("combo-500"); - break; - case 600: - controller.playSoundMeka("combo-600"); - break; - case 700: - controller.playSoundMeka("combo-700"); - break; - case 800: - controller.playSoundMeka("combo-800"); - break; - case 900: - controller.playSoundMeka("combo-900"); - break; - case 1000: - controller.playSoundMeka("combo-1000"); - break; - case 1100: - controller.playSoundMeka("combo-1100"); - break; - case 1200: - controller.playSoundMeka("combo-1200"); - break; - case 1300: - controller.playSoundMeka("combo-1300"); - break; - case 1400: - controller.playSoundMeka("combo-1400"); - break; - } - - controller.view.updateCombo(_combo) - } - - this.getCombo = function(){ - return _combo; - } - - this.getGlobalScore = function(){ - return _globalScore; - } - - this.updateGlobalScore = function(score){ - - /* Circle score */ - switch(score){ - case 450: - _globalScore.great++; - break; - case 230: - _globalScore.good++; - break; - case 0: - _globalScore.fail++; - break; - } - - /* HP Update */ - if(score!=0){ - _globalScore.hp+=_HPGain; - } - else{ - if(_globalScore.hp-_HPGain>0) - _globalScore.hp-=_HPGain; - else - _globalScore.hp=0; - } - - /* Points update */ - if(_combo>=11 && _combo<=20){ - score+=100; - } - else if(_combo>=21 && _combo<=30){ - score+=200; - } - else if(_combo>=31 && _combo<=40){ - score+=300; - } - else if(_combo>=41 && _combo<=50){ - score+=400; - } - else if(_combo>=51 && _combo<=60){ - score+=500; - } - else if(_combo>=61 && _combo<=70){ - score+=500; - } - else if(_combo>=71 && _combo<=80){ - score+=600; - } - else if(_combo>=81 && _combo<=90){ - score+=700; - } - else if(_combo>=91 && _combo<=100){ - score+=800; - } - - _globalScore.points+=score; - - } - -} \ No newline at end of file +class Game{ + constructor(controller, selectedSong, songData){ + this.controller = controller + this.selectedSong = selectedSong + this.songData = songData + this.elapsedTime = {} + this.currentCircle = 0 + this.combo = 0 + this.globalScore = { + points: 0, + great: 0, + good: 0, + fail: 0, + maxCombo: 0, + drumroll: 0, + hp: 0, + song: selectedSong.title + } + this.HPGain = 100 / this.songData.circles.filter(circle => { + var type = circle.getType() + return type == "don" || type == "ka" || type == "daiDon" || type == "daiKa" + }).length + this.paused = false + this.started = false + this.mainMusicPlaying = false + this.elapsedTimeSincePause = 0 + this.musicFadeOut = 0 + this.fadeOutStarted = false + this.currentTimingPoint = 0 + this.offsetTime = 0 + assets.songs.forEach(song => { + if(song.id == selectedSong.folder){ + this.mainAsset = song.sound + } + }) + } + run(){ + this.timeForDistanceCircle = 2500 + this.initTiming() + } + initTiming(){ + // Date when the chrono is started (before the game begins) + this.offsetDate = new Date() + this.offsetTime = this.timeForDistanceCircle |0 + this.setElapsedTime(-this.offsetTime) + // The real start for the game will start when chrono will reach 0 + this.startDate = new Date() + this.startDate.setMilliseconds(this.startDate.getMilliseconds() + this.offsetTime) + } + update(){ + // Main operations + this.updateTime() + this.checkTiming() + this.updateCirclesStatus() + this.checkPlays() + // Event operations + this.whenFadeoutMusic() + this.whenLastCirclePlayed() + } + getCircles(){ + return this.songData.circles + } + updateCirclesStatus(){ + var circles = this.songData.circles + circles.forEach(circle => { + if(!circle.getPlayed()){ + var currentTime = this.getElapsedTime().ms + var startingTime = circle.getMS() - this.timeForDistanceCircle + // At circle.getMS(), the circle fits the slot + var hitTime = circle.getMS() + var endTime = circle.getEndTime() + var type = circle.getType() + var normalNotes = type == "don" || type == "daiDon" || type == "ka" || type == "daiKa" + + if(currentTime >= startingTime && currentTime <= endTime){ + + if(currentTime>= hitTime - 50 && currentTime < hitTime - 30){ + circle.updateStatus(0) + }else if(currentTime>= hitTime - 30 && currentTime < hitTime){ + circle.updateStatus(230) + }else if(currentTime >= hitTime && currentTime < endTime){ + circle.updateStatus(450) + } + + }else if(currentTime>endTime){ + if(type == "balloon" || type == "drumroll" || type == "daiDrumroll"){ + circle.updateStatus(-1) + circle.played(0) + this.updateCurrentCircle() + if(this.controller.multiplayer == 1){ + p2.send("drumroll", { + pace: (this.getElapsedTime().ms - circle.getMS()) / circle.timesHit + }) + } + }else{ + if(!this.controller.autoPlayEnabled){ + circle.updateStatus(-1) + var currentScore = 0 + circle.played(currentScore) + this.controller.displayScore(currentScore, true) + this.updateCurrentCircle() + this.updateCombo(currentScore) + this.updateGlobalScore(currentScore) + } + if(this.controller.multiplayer == 1){ + p2.send("note", { + score: -1 + }) + } + } + } + } + }) + } + setHPGain(gain){ + this.HPGain = gain + } + checkPlays(){ + var circles = this.songData.circles + var circle = circles[this.currentCircle] + + if(circle && this.controller.autoPlayEnabled){ + return this.controller.autoPlay(circle) + } + var keys = this.controller.getKeys() + var kbd = this.controller.getBindings() + if(keys[kbd["don_l"]]){ + this.checkKey(kbd["don_l"], circle) + } + if(keys[kbd["don_r"]]){ + this.checkKey(kbd["don_r"], circle) + } + if(keys[kbd["ka_l"]]){ + this.checkKey(kbd["ka_l"], circle) + } + if(keys[kbd["ka_r"]]){ + this.checkKey(kbd["ka_r"], circle) + } + } + checkKey(keyCode, circle){ + if(!this.controller.isWaitingForKeyup(keyCode, "score")){ + if(circle && !circle.getPlayed() && circle.getStatus() != -1){ + this.checkScore(circle) + } + this.controller.waitForKeyup(keyCode, "score") + } + } + checkScore(circle){ + var keys = this.controller.getKeys() + var kbd = this.controller.getBindings() + var keysDon = keys[kbd["don_l"]] || keys[kbd["don_r"]] + var keysKa = keys[kbd["ka_l"]] || keys[kbd["ka_r"]] + + var type = circle.getType() + var typeDon = type == "don" || type == "daiDon" + var typeKa = type == "ka" || type == "daiKa" + + if(typeDon || typeKa){ + var score = 0 + if(keysDon && typeDon || keysKa && typeKa){ + var circleStatus = circle.getStatus() + if(circleStatus == 230 || circleStatus == 450){ + score = circleStatus + } + this.controller.displayScore(score) + }else{ + this.controller.displayScore(score, true) + } + this.updateCombo(score) + this.updateGlobalScore(score) + this.updateCurrentCircle() + circle.played(score) + if(this.controller.multiplayer == 1){ + p2.send("note", { + score: score, + ms: circle.getMS() - this.getElapsedTime().ms + }) + } + }else if(keysDon && type == "balloon"){ + this.checkBalloon(circle) + }else if((keysDon || keysKa) && (type == "drumroll" || type == "daiDrumroll")){ + this.checkDrumroll(circle) + } + } + checkBalloon(circle){ + if(circle.timesHit >= circle.requiredHits - 1){ + var score = 5000 + this.updateCurrentCircle() + circle.hit() + circle.played(score) + if(this.controller.multiplayer == 1){ + p2.send("drumroll", { + pace: (this.getElapsedTime().ms - circle.getMS()) / circle.timesHit + }) + } + }else{ + var score = 300 + circle.hit() + } + this.globalScore.drumroll ++ + this.globalScore.points += score + } + checkDrumroll(circle){ + var score = 100 + circle.hit() + var keyTime = this.controller.getKeyTime() + if(circle.getType() == "drumroll"){ + var sound = keyTime["don"] > keyTime["ka"] ? "don" : "ka" + }else{ + var sound = keyTime["don"] > keyTime["ka"] ? "daiDon" : "daiKa" + } + var circleAnim = new Circle(0, this.getElapsedTime().ms, sound, "", circle.speed) + circleAnim.played(score) + circleAnim.animate() + this.controller.view.drumroll.push(circleAnim) + this.globalScore.drumroll ++ + this.globalScore.points += score + } + whenLastCirclePlayed(){ + var circles = this.songData.circles + var lastCircle = circles[this.songData.circles.length - 1] + if(!this.fadeOutStarted && this.getElapsedTime().ms >= lastCircle.getEndTime() + 1900){ + this.fadeOutStarted=this.getElapsedTime().ms + } + } + whenFadeoutMusic(){ + if(this.fadeOutStarted){ + if(this.musicFadeOut==0){ + snd.musicGain.fadeOut(1.6) + if(this.controller.multiplayer == 1){ + p2.send("gameresults", this.controller.getGlobalScore()) + } + this.musicFadeOut++ + } + if(this.musicFadeOut == 1 && this.getElapsedTime().ms >= this.fadeOutStarted + 1600){ + this.controller.displayResults() + this.mainAsset.stop() + p2.send("gameend") + setTimeout(() => { + snd.musicGain.fadeIn() + snd.musicGain.unmute() + }, 1000) + this.musicFadeOut++ + } + } + } + checkTiming(){ + if(this.songData.timingPoints[this.currentTimingPoint + 1]){ + if(this.getElapsedTime().ms >= this.songData.timingPoints[this.currentTimingPoint + 1].start){ + this.currentTimingPoint++ + } + } + } + playMainMusic(){ + var ms = this.getElapsedTime().ms + if(!this.mainMusicPlaying && (!this.fadeOutStarted || ms= 0 && !this.started){ + this.startDate = new Date() + this.elapsedTimeSincePause = 0 + this.setElapsedTime(this.currentDate.getTime() - this.startDate.getTime()) + this.started = true + }else if(ms < 0 || ms >= 0 && this.started){ + this.setElapsedTime(this.currentDate.getTime() - this.startDate.getTime() - this.elapsedTimeSincePause) + } + } + getCircles(){ + return this.songData.circles + } + getSongData(){ + return this.songData + } + updateCurrentCircle(){ + this.currentCircle++ + } + getCurrentCircle(){ + return this.currentCircle + } + updateCombo(score){ + if(score != 0){ + this.combo++ + }else{ + this.combo = 0 + } + if(this.combo > this.globalScore.maxCombo){ + this.globalScore.maxCombo = this.combo + } + if(this.combo == 50 || this.combo > 0 && this.combo % 100 == 0 && this.combo <= 1400){ + this.controller.playSoundMeka("combo-" + this.combo) + } + this.controller.view.updateCombo(this.combo) + } + getCombo(){ + return this.combo + } + getGlobalScore(){ + return this.globalScore + } + updateGlobalScore(score){ + // Circle score + switch(score){ + case 450: + this.globalScore.great++ + break + case 230: + this.globalScore.good++ + break + case 0: + this.globalScore.fail++ + break + } + // HP Update + if(score != 0){ + this.globalScore.hp += this.HPGain + }else if(this.globalScore.hp - this.HPGain > 0){ + this.globalScore.hp -= this.HPGain + }else{ + this.globalScore.hp = 0 + } + // Points update + score += Math.max(0, Math.floor((Math.min(this.combo, 100) - 1) / 10) * 100) + + this.globalScore.points+=score + } +} diff --git a/public/src/js/keyboard.js b/public/src/js/keyboard.js index efcbc94..ee3ebe2 100644 --- a/public/src/js/keyboard.js +++ b/public/src/js/keyboard.js @@ -91,7 +91,20 @@ function Keyboard(controller){ this.checkKeySound = function(keyCode, sound){ _this.checkKey(keyCode, "sound", function(){ - assets.sounds["note_"+sound].play() + var circles = controller.parsedSongData.circles + var circle = circles[controller.game.getCurrentCircle()] + if( + (keyCode == _kbd["don_l"] || keyCode == _kbd["don_r"]) + && circle + && !circle.getPlayed() + && circle.getStatus() != -1 + && circle.getType() == "balloon" + && circle.requiredHits - circle.timesHit <= 1 + ){ + assets.sounds["balloon"].play() + }else{ + assets.sounds["note_"+sound].play() + } _keyTime[sound] = controller.getElapsedTime().ms }) } diff --git a/public/src/js/mekadon.js b/public/src/js/mekadon.js index ecbd330..c7b2ae5 100644 --- a/public/src/js/mekadon.js +++ b/public/src/js/mekadon.js @@ -1,73 +1,98 @@ class Mekadon{ - constructor(controller, game){ - this.controller = controller - this.game = game - this.lr = false - this.keys = {} - } - play(circle){ - if(circle.getStatus() == 450){ - return this.playNow(circle) - } - } - playAt(circle, ms, score){ - var currentMs = circle.getMS() - this.controller.getElapsedTime().ms - if(ms > currentMs - 10){ - return this.playNow(circle, score) - } - } - miss(circle){ - var currentMs = circle.getMS() - this.controller.getElapsedTime().ms - if(0 > currentMs - 10){ - this.controller.displayScore(0, true) - this.game.updateCurrentCircle() - this.game.updateCombo(0) - this.game.updateGlobalScore(0) - return true - } - } - playNow(circle, score){ - var kbd = this.controller.getBindings() - if(circle.getType() == "don"){ - this.setKey(this.lr ? kbd["don_l"] : kbd["don_r"]) - this.lr = !this.lr - }else if(circle.getType() == "daiDon"){ - this.setKey(kbd["don_l"]) - this.setKey(kbd["don_r"]) - this.lr = false - }else if(circle.getType() == "ka"){ - this.setKey(this.lr ? kbd["ka_l"] : kbd["ka_r"]) - this.lr = !this.lr - }else if(circle.getType() == "daiKa"){ - this.setKey(kbd["ka_l"]) - this.setKey(kbd["ka_r"]) - this.lr = false - } - if(typeof score == "undefined"){ - score = this.game.checkScore(circle) - }else{ - this.controller.displayScore(score) - this.game.updateCombo(score) - this.game.updateGlobalScore(score) - } - circle.updateStatus(score) - circle.played(score) - this.game.updateCurrentCircle() - return true - } - setKey(keyCode){ - var self = this - if(this.keys[keyCode]){ - clearTimeout(this.keys[keyCode]) - self.clearKey(keyCode) - } - this.controller.setKey(keyCode, true) - this.keys[keyCode] = setTimeout(function(){ - self.clearKey(keyCode) - },100) - } - clearKey(keyCode){ - this.controller.setKey(keyCode, false) - delete this.keys[keyCode] - } + constructor(controller, game){ + this.controller = controller + this.game = game + this.lr = false + this.keys = {} + this.lastHit = -Infinity + } + play(circle){ + var type = circle.getType() + if(type == "balloon"){ + this.playDrumrollAt(circle, 0, 30) + }else if(type == "drumroll" || type == "daiDrumroll"){ + this.playDrumrollAt(circle, 0, 60) + }else{ + this.playAt(circle, 0, 450) + } + } + playAt(circle, ms, score){ + var currentMs = circle.getMS() - this.getMS() + if(ms > currentMs - 10){ + return this.playNow(circle, score) + } + } + playDrumrollAt(circle, ms, pace){ + if(pace && this.getMS() >= this.lastHit + pace){ + this.playAt(circle, ms) + } + } + miss(circle){ + var currentMs = circle.getMS() - this.getMS() + if(0 >= currentMs - 10){ + this.controller.displayScore(0, true) + this.game.updateCurrentCircle() + this.game.updateCombo(0) + this.game.updateGlobalScore(0) + return true + } + } + playNow(circle, score){ + var kbd = this.controller.getBindings() + var type = circle.getType() + if(type == "don" || type == "balloon" || type == "drumroll" || type == "daiDrumroll"){ + this.setKey(this.lr ? kbd["don_l"] : kbd["don_r"]) + this.lr = !this.lr + }else if(type == "daiDon"){ + this.setKey(kbd["don_l"]) + this.setKey(kbd["don_r"]) + this.lr = false + }else if(type == "ka"){ + this.setKey(this.lr ? kbd["ka_l"] : kbd["ka_r"]) + this.lr = !this.lr + }else if(type == "daiKa"){ + this.setKey(kbd["ka_l"]) + this.setKey(kbd["ka_r"]) + this.lr = false + } + if(type == "balloon"){ + if(circle.requiredHits == 1){ + assets.sounds["balloon"].play() + } + this.game.checkBalloon(circle) + }else if(type == "drumroll" || type == "daiDrumroll"){ + this.game.checkDrumroll(circle) + }else{ + if(typeof score == "undefined"){ + score = this.game.checkScore(circle) + }else{ + this.controller.displayScore(score) + this.game.updateCombo(score) + this.game.updateGlobalScore(score) + this.game.updateCurrentCircle() + } + circle.updateStatus(score) + circle.played(score) + } + this.lastHit = this.getMS() + return true + } + getMS(){ + return this.controller.getElapsedTime().ms + } + setKey(keyCode){ + var self = this + if(this.keys[keyCode]){ + clearTimeout(this.keys[keyCode]) + self.clearKey(keyCode) + } + this.controller.setKey(keyCode, true) + this.keys[keyCode] = setTimeout(function(){ + self.clearKey(keyCode) + }, 100) + } + clearKey(keyCode){ + this.controller.setKey(keyCode, false) + delete this.keys[keyCode] + } } diff --git a/public/src/js/p2.js b/public/src/js/p2.js index ee346d1..205cb0d 100644 --- a/public/src/js/p2.js +++ b/public/src/js/p2.js @@ -5,18 +5,25 @@ class P2Connection{ this.msgCallbacks = {} this.closeCallbacks = new Set() this.openCallbacks = new Set() - this.notes = [] this.otherConnected = false this.onmessage("gamestart", () => { this.otherConnected = true this.notes = [] + this.drumrollPace = 45 + this.results = false }) this.onmessage("gameend", () => { this.otherConnected = false }) + this.onmessage("gameresults", response => { + this.results = response + }) this.onmessage("note", response => { this.notes.push(response) }) + this.onmessage("drumroll", response => { + this.drumrollPace = response.pace + }) } open(){ this.closed = false @@ -92,7 +99,7 @@ class P2Connection{ this.msgCallbacks[data.type].forEach(obj => { obj.callback(data.value) if(obj.once){ - delete this.msgCallbacks[obj] + this.msgCallbacks[data.type].delete(obj) } }) } @@ -113,7 +120,10 @@ class P2Connection{ } play(circle, mekadon){ if(this.otherConnected || this.notes.length > 0){ - if(this.notes.length == 0){ + var type = circle.getType() + if(type == "balloon"|| type == "drumroll" || type == "daiDrumroll"){ + mekadon.playDrumrollAt(circle, 0, this.drumrollPace) + }else if(this.notes.length == 0){ mekadon.play(circle) }else{ var note = this.notes[0] diff --git a/public/src/js/parsesong.js b/public/src/js/parsesong.js index bbaf5c0..31fce34 100644 --- a/public/src/js/parsesong.js +++ b/public/src/js/parsesong.js @@ -1,279 +1,311 @@ -function ParseSong(fileContent){ - - var _this = this; - var _data = fileContent; - var _generalInfo={audioFilename:"", audioWait:0}; - var _metadata={title:'', artist:''}; - var _difficulty={sliderMultiplier:0, sliderTickRate:0, approachRate:0}; - var _beatInfo={beatInterval:0, bpm:0}; - var _editor={distanceSpacing:0, beatDivisor:0, gridSize:0}; - var _circleID=0; - var _circles=[]; - var _timingPoints=[]; - var _measures=[]; - - this.getStartEndIndexes = function(type){ - - var indexes = {start:0, end:0}; - - while(indexes.start<_data.length){ - if(_data[indexes.start].match(type)) - break; - else - indexes.start++; - } - indexes.start++; - - indexes.end = indexes.start; - while(indexes.end<_data.length){ - if(_data[indexes.end].match(/^\s*$/)) - break; - else - indexes.end++; - } - indexes.end--; - - return indexes; - } - - this.parseDifficulty = function(){ - - var indexes = _this.getStartEndIndexes("Difficulty"); - - for(var i=indexes.start; i<= indexes.end; i++){ - - var splitted = _data[i].split(":"); - var item = splitted[0]; - var key = splitted[1]; - - switch(item){ - - case 'SliderMultiplier': - _difficulty.sliderMultiplier = key; - _difficulty.originalMultiplier = key; - break; - case 'SliderTickRate': - _difficulty.sliderTickRate = key; - break; - case 'ApproachRate': - _difficulty.approachRate = key; - break; - } - } - - } - - this.parseTiming = function(){ - - var indexes = _this.getStartEndIndexes("TimingPoints"); - var lastBeatInterval = parseInt(_data[indexes.start].split(",")[1]); - - for(var i=indexes.start; i<= indexes.end; i++){ - - var values = _data[i].split(","); - - var start=parseInt(values[0]) - var msOrPercent=parseFloat(values[1]) - if(i==indexes.start){ - start=0 - _beatInfo.beatInterval=msOrPercent; - _beatInfo.bpm=parseInt((1000/_beatInfo.beatInterval)*60); - } - if(msOrPercent<0){ - var sliderMultiplier=_difficulty.originalMultiplier*1/Math.abs(msOrPercent/100); - }else{ - var sliderMultiplier=500/msOrPercent; - _difficulty.originalMultiplier=sliderMultiplier - } - - _timingPoints.push({ - start:start, - sliderMultiplier:sliderMultiplier, - measure:parseInt(values[2]), - }); - - } - } - - this.parseMeasures = function(){ - var measureNumber=0; - for(var i=0; i<_timingPoints.length; i++){ - var limit = (_timingPoints[i+1]) ? _timingPoints[i+1].start : _circles[_circles.length-1].getMS(); - for(var j=_timingPoints[i].start; j<=limit; j+=_beatInfo.beatInterval){ - - _measures.push({ - ms:j, - nb:measureNumber, - speed:_timingPoints[i].sliderMultiplier - }); - measureNumber++; - if(measureNumber==_timingPoints[i].measure+1){ - measureNumber=0; - } - - } - } - - } - - this.parseGeneralInfo = function(){ - - var indexes = _this.getStartEndIndexes("General"); - - for(var i=indexes.start; i<= indexes.end; i++){ - - var splitted = _data[i].split(":"); - var item = splitted[0]; - var key = splitted[1]; - - switch(item){ - - case 'SliderMultiple': - _generalInfo.audioFilename = key; - break; - case 'AudioWait': - _generalInfo.audioWait = parseInt(key); - break; - } - } - - } - - this.parseMetadata = function(){ - - var indexes = _this.getStartEndIndexes("Metadata"); - - for(var i=indexes.start; i<= indexes.end; i++){ - - var splitted = _data[i].split(":"); - var item = splitted[0]; - var key = splitted[1]; - - switch(item){ - - case 'TitleUnicode': - _metadata.title = key; - break; - - case 'ArtistUnicode': - _metadata.artist = key; - break; - } - } - } - - this.parseEditor = function(){ - - var indexes = _this.getStartEndIndexes("Editor"); - - for(var i=indexes.start; i<= indexes.end; i++){ - - var splitted = _data[i].split(":"); - var item = splitted[0]; - var key = splitted[1]; - - switch(item){ - - case 'DistanceSpacing': - _editor.distanceSpacing = parseFloat(key); - break; - - case 'BeatDivisor': - _editor.beatDivisor = parseInt(key); - break; - - case 'GridSize': - _editor.gridSize = parseInt(key); - break; - } - } - - } - - this.parseCircles = function(){ - - var indexes = _this.getStartEndIndexes("HitObjects"); - - for(var i=indexes.start; i<= indexes.end; i++){ - - _circleID++; - var values = _data[i].split(","); - - var type; - var txt; - var emptyValue=false; - var start=parseInt(values[2]) - var speed=_difficulty.originalMultiplier - - for(var j=0; j<_timingPoints.length; j++){ - if(_timingPoints[j].start<=start){ - speed=_timingPoints[j].sliderMultiplier - }else{ - break - } - } - - switch(parseInt(values[4])){ - case 0: - type="don"; - txt="ドン"; - break; - case 2: - type="ka"; - txt="カッ"; - break; - case 4: - type="daiDon"; - txt="ドン(大)"; - break; - case 6: - type="daiKa"; - txt="カッ(大)"; - break; - case 8: - type="ka"; - txt="カッ"; - break; - case 10: - type="ka"; - txt="カッ"; - break; - case 12: - type="daiKa"; - txt="カッ(大)"; - break; - case 14: - type="daiKa"; - txt="カッ(大)"; - break; - default: - console.log('[WARNING] Unknown note type found on line ' + i+1 + ': ' + _data[i]); - emptyValue=true; - break; - } - if(!emptyValue) - _circles.push(new Circle(_circleID,start,type,txt,speed)); - } - } - - _this.parseGeneralInfo(); - _this.parseMetadata(); - _this.parseEditor(); - _this.parseDifficulty(); - _this.parseTiming(); - _this.parseCircles(); - _this.parseMeasures(); - - this.getData = function(){ - return { - generalInfo: _generalInfo, - metaData: _metadata, - editor: _editor, - beatInfo: _beatInfo, - difficulty: _difficulty, - timingPoints: _timingPoints, - circles: _circles, - measures: _measures - }; +class ParseSong{ + constructor(fileContent){ + this.data = fileContent + this.osu = { + OFFSET: 0, + MSPERBEAT: 1, + METER: 2, + SAMPLESET: 3, + SAMPLEINDEX: 4, + VOLUME: 5, + INHERITED: 6, + KIAIMODE: 7, + + X: 0, + Y: 1, + TIME: 2, + TYPE: 3, + HITSOUND: 4, + EXTRAS: 5, + ENDTIME: 5, + + CIRCLE: 1, + SLIDER: 2, + NEWCOMBO: 4, + SPINNER: 8, + + NORMAL: 1, + WHISTLE: 2, + FINISH: 4, + CLAP: 8, + + CURVEPOINTS: 0, + REPEAT: 1, + PIXELLENGTH: 2, + EDGEHITSOUNDS: 3, + EDGEADDITIONS: 4 + } + this.beatInfo = { + beatInterval: 0, + bpm: 0 + } + this.generalInfo = this.parseGeneralInfo() + this.metadata = this.parseMetadata() + this.editor = this.parseEditor() + this.difficulty = this.parseDifficulty() + this.timingPoints = this.parseTiming() + this.circles = this.parseCircles() + this.measures = this.parseMeasures() } -} \ No newline at end of file + getStartEndIndexes(type){ + var indexes = { + start: 0, + end: 0 + } + while(indexes.start < this.data.length){ + if(this.data[indexes.start].match(type)){ + break + } + indexes.start++ + } + indexes.start++ + indexes.end = indexes.start + while(indexes.end < this.data.length){ + if(this.data[indexes.end].match(/^\s*$/)){ + break + } + indexes.end++ + } + indexes.end-- + return indexes + } + parseDifficulty(){ + var difficulty = { + sliderMultiplier: 0, + sliderTickRate: 0, + approachRate: 0 + } + var indexes = this.getStartEndIndexes("Difficulty") + for(var i = indexes.start; i <= indexes.end; i++){ + var [item, key] = this.data[i].split(":") + switch(item){ + case "SliderMultiplier": + difficulty.sliderMultiplier = key + difficulty.originalMultiplier = key + break + case "SliderTickRate": + difficulty.sliderTickRate = key + break + case "ApproachRate": + difficulty.approachRate = key + break + case "OverallDifficulty": + difficulty.overallDifficulty = key + break + } + } + return difficulty + } + parseTiming(){ + var timingPoints = [] + var indexes = this.getStartEndIndexes("TimingPoints") + var lastBeatInterval = parseInt(this.data[indexes.start].split(",")[1]) + for(var i = indexes.start; i<= indexes.end; i++){ + var values = this.data[i].split(",") + var start = parseInt(values[this.osu.OFFSET]) + var msOrPercent = parseFloat(values[this.osu.MSPERBEAT]) + if(i == indexes.start){ + start = 0 + this.beatInfo.beatInterval = msOrPercent + this.beatInfo.bpm = Math.floor(1000 / this.beatInfo.beatInterval * 60) + } + if(msOrPercent < 0){ + var sliderMultiplier = this.difficulty.lastMultiplier / Math.abs(msOrPercent / 100) + }else{ + var sliderMultiplier = 500 / msOrPercent + if(i == 0){ + this.difficulty.originalMultiplier = sliderMultiplier + } + this.difficulty.lastMultiplier = sliderMultiplier + } + timingPoints.push({ + start: start, + sliderMultiplier: sliderMultiplier, + measure: parseInt(values[this.osu.METER]) + }) + } + return timingPoints + } + parseMeasures(){ + var measures = [] + var measureNumber = 0 + for(var i = 0; i 5){ + return mid + (max - mid) * (difficulty - 5) / 5 + } + if(difficulty < 5){ + return mid - (mid - min) * (5 - difficulty) / 5 + } + return mid + } + parseCircles(){ + var circles = [] + var circleID = 0 + var indexes = this.getStartEndIndexes("HitObjects") + for(var i = indexes.start; i <= indexes.end; i++){ + circleID++ + var values = this.data[i].split(",") + var emptyValue = false + var start = parseInt(values[this.osu.TIME]) + var speed = this.difficulty.originalMultiplier + var osuType = parseInt(values[this.osu.TYPE]) + var hitSound = parseInt(values[this.osu.HITSOUND]) + + for(var j = 0; j < this.timingPoints.length; j++){ + if(this.timingPoints[j].start > start){ + break + } + speed = this.timingPoints[j].sliderMultiplier + } + + if(osuType & this.osu.SPINNER){ + + var endTime = parseInt(values[this.osu.ENDTIME]) + var hitMultiplier = this.difficultyRange(this.difficulty.overallDifficulty, 3, 5, 7.5) * 1.65 + var requiredHits = Math.floor(Math.max(1, (endTime - start) / 1000 * hitMultiplier)) + circles.push(new Circle(circleID, start, "balloon", "ふうせん", speed, endTime, requiredHits)) + + }else if(osuType & this.osu.SLIDER){ + + var extras = values.slice(this.osu.EXTRAS) + var pixelLength = parseFloat(extras[this.osu.PIXELLENGTH]) + var endTime = start + pixelLength / (this.difficulty.originalMultiplier * 100) * this.beatInfo.beatInterval + if(hitSound & this.osu.FINISH){ + type = "daiDrumroll" + txt = "連打(大)ーっ!!" + }else{ + type = "drumroll" + txt = "連打ーっ!!" + } + circles.push(new Circle(circleID, start, type, txt, speed, endTime)) + + }else if(osuType & this.osu.CIRCLE){ + + var type + var txt + if(hitSound & this.osu.FINISH){ + if(hitSound & this.osu.WHISTLE || hitSound & this.osu.CLAP){ + type = "daiKa" + txt = "カッ(大)" + }else if(hitSound & this.osu.NORMAL || hitSound == this.osu.FINISH){ + type = "daiDon" + txt = "ドン(大)" + }else{ + emptyValue = true + } + }else if(hitSound & this.osu.WHISTLE || hitSound & this.osu.CLAP){ + type = "ka" + txt = "カッ" + }else if(hitSound & this.osu.NORMAL || hitSound == 0){ + type = "don" + txt = "ドン" + }else{ + emptyValue = true + } + if(!emptyValue){ + circles.push(new Circle(circleID, start, type, txt, speed)) + } + + }else{ + emptyValue = true + } + if(emptyValue){ + console.warn("Unknown note type found on line " + (i + 1) + ": " + this.data[i]) + } + } + return circles + } + getData(){ + return { + generalInfo: this.generalInfo, + metaData: this.metadata, + editor: this.editor, + beatInfo: this.beatInfo, + difficulty: this.difficulty, + timingPoints: this.timingPoints, + circles: this.circles, + measures: this.measures + } + } +} diff --git a/public/src/js/scoresheet.js b/public/src/js/scoresheet.js index 0273535..766f2a9 100644 --- a/public/src/js/scoresheet.js +++ b/public/src/js/scoresheet.js @@ -1,104 +1,104 @@ - -function Scoresheet(controller, score){ - - var _this = this; - var _score = score; - var _mark; - - this.setResults = function(){ - - if (_score.fail == 0) { - _mark = 'gold'; - } else if (_score.hp >= 50) { - _mark = 'silver'; - }; - - var imgW = (_score.hp*$("#score-hp-bar-colour").width())/100; - $("#score-hp-bar-colour img").css("clip", "rect(0, "+imgW+"px, "+$("#score-hp-bar-colour").height()+"px, 0)"); - - if (_mark == 'gold') { - $("#score-mark").attr("src", '/assets/img/ranking-X.png'); - } else if (_mark == 'silver') { - $("#score-mark").attr("src", '/assets/img/ranking-S.png'); - } else { - $("#score-mark").remove(); - }; - - $("#score-points").html(_score.points+"点"); - $("#nb-great").html(_score.great); - $("#nb-good").html(_score.good); - $("#nb-fail").html(_score.fail); - $("#max-combo").html(_score.maxCombo); - - $('.result-song').attr('alt', _score.song).html(_score.song); - +class Scoresheet{ + constructor(controller, score, multiplayer){ + this.controller = controller + this.score = score + this.multiplayer = multiplayer + $("#screen").load("/src/views/scoresheet.html", () =>{ + this.run() + }) } - - this.positionning = function(){ + setResults(score, scoreCont){ + this.positionning(scoreCont) + var scoreMark = this.elem("score-mark", scoreCont) + var scoreHpBarColour = this.elem("score-hp-bar-colour", scoreCont) - $("#score-cont").css("top", $("#result-bar").height()/2 - ($("#score-cont").height()/2)); - - var markSize = 0.1*$("#score-cont").width(); - var markX = $("#score-cont").offset().left - markSize - (0.5*markSize); - var markY = $("#score-cont").offset().top; - - $("#score-mark").width(markSize); - $("#score-mark").height(markSize); - $("#score-mark").css("left", markX); - $("#score-mark").css("top", markY); - - var scoreBarW = 0.9*$("#score-cont").width(); - - $("#score-hp-bar-bg").width(scoreBarW); - $("#score-hp-bar-bg").height((51/703)*scoreBarW); - - var bgW = $("#score-hp-bar-bg").width(); - var bgH = $("#score-hp-bar-bg").height(); - var bgX = $("#score-hp-bar-bg").position().left; - var bgY = $("#score-hp-bar-bg").position().top; - - $("#score-hp-bar-colour").css("left", bgX+(0.008*bgW)); - $("#score-hp-bar-colour").css("top", bgY+(0.15*bgH)); - $("#score-hp-bar-colour").width(bgW-(0.08*bgW)); - $("#score-hp-bar-colour").height(bgH-(0.25*bgH)); - - $("#score-details").css("top", bgY+bgH+(bgH)); - - var barY = $("#result-bar").position().top; - var barH = $("#result-bar").height(); - - var bottomY = barY+barH+15; - var bottomH = $(window).height()-bottomY; - - $("#bottom-part").css("top", bottomY); - $("#bottom-part").height(bottomH); + if(score.fail == 0){ + var mark = "gold" + }else if (score.hp >= 50){ + var mark = "silver" + } + scoreHpBarColour.dataset.hp = score.hp + var imgW = score.hp * scoreHpBarColour.offsetWidth / 100 + var imgH = scoreHpBarColour.offsetHeight + scoreHpBarColour.getElementsByTagName("img")[0].style.clip = "rect(0, " + imgW + "px, " + imgH + "px, 0)" + if(mark == "gold"){ + scoreMark.src = "/assets/img/ranking-X.png" + }else if(mark == "silver"){ + scoreMark.src = "/assets/img/ranking-S.png" + }else{ + scoreMark.parentNode.removeChild(scoreMark) + } + this.altText(this.elem("score-points", scoreCont), score.points + "点") + this.altText(this.elem("nb-great", scoreCont), score.great) + this.altText(this.elem("nb-good", scoreCont), score.good) + this.altText(this.elem("nb-fail", scoreCont), score.fail) + this.altText(this.elem("max-combo", scoreCont), score.maxCombo) + this.altText(this.elem("nb-drumroll", scoreCont), score.drumroll) + addEventListener("resize", () => { + this.positionning(scoreCont) + }) } - - this.run = function(){ - _this.positionning(); - _this.setResults(); - - $("#song-select").click(function(){ - assets.sounds["don"].play(); - assets.sounds["bgm_result"].stop(); - controller.songSelection(); - }); - - $("#replay").click(function(){ - assets.sounds["don"].play(); - assets.sounds["bgm_result"].stop(); - controller.restartSong(); - }); - - $(window).resize(_this.positionning); - + elem(className, parent){ + return parent.getElementsByClassName(className)[0] } - - assets.sounds["results"].play() - assets.sounds["bgm_result"].playLoop(0.1, false, 0, 0.847, 17.689) - - $("#screen").load("/src/views/scoresheet.html", _this.run); - -} \ No newline at end of file + text(string){ + return document.createTextNode(string) + } + altText(element, string){ + element.appendChild(this.text(string)) + element.setAttribute("alt", string) + } + positionning(scoreCont){ + var scoreHpBarBg = this.elem("score-hp-bar-bg", scoreCont) + var scoreHpBarColour = this.elem("score-hp-bar-colour", scoreCont) + + var scoreBarW = scoreCont.offsetWidth * 0.9 + var bgW = scoreBarW + var bgH = 51 / 703 * scoreBarW + + scoreHpBarBg.style.width = bgW + "px" + scoreHpBarBg.style.height = bgH + "px" + var bgX = scoreHpBarBg.offsetLeft + var bgY = scoreHpBarBg.offsetTop + + scoreHpBarColour.style.left = (bgW * 0.008) + "px" + scoreHpBarColour.style.top = (bgH * 0.15) + "px" + scoreHpBarColour.style.width = (bgW - bgW * 0.08) + "px" + scoreHpBarColour.style.height = (bgH - bgH * 0.25) + "px" + + var imgW = scoreHpBarColour.dataset.hp * scoreHpBarColour.offsetWidth / 100 + var imgH = scoreHpBarColour.offsetHeight + scoreHpBarColour.getElementsByTagName("img")[0].style.clip = "rect(0, " + imgW + "px, " + imgH + "px, 0)" + } + run(){ + this.scoresheet = document.getElementsByClassName("scoresheet")[0] + var scoreCont = this.elem("score-cont", this.scoresheet) + var scoreContHtml = scoreCont.innerHTML + assets.sounds["results"].play() + assets.sounds["bgm_result"].playLoop(0.1, false, 0, 0.847, 17.689) + + this.setResults(this.score, scoreCont) + this.altText(this.elem("result-song", this.scoresheet), this.score.song) + + this.elem("song-select", this.scoresheet).addEventListener("click", () => { + assets.sounds["don"].play() + assets.sounds["bgm_result"].stop() + this.controller.songSelection() + }) + this.elem("replay", this.scoresheet).addEventListener("click", () => { + assets.sounds["don"].play() + assets.sounds["bgm_result"].stop() + this.controller.restartSong() + }) + + if(this.multiplayer && p2.results){ + var scoreCont2 = document.createElement("div") + scoreCont2.classList.add("score-cont") + scoreCont2.innerHTML = scoreContHtml + scoreCont.parentNode.appendChild(scoreCont2) + this.setResults(p2.results, scoreCont2) + } + } +} diff --git a/public/src/js/view.js b/public/src/js/view.js index b7fc73c..572485c 100644 --- a/public/src/js/view.js +++ b/public/src/js/view.js @@ -40,6 +40,8 @@ class View{ this.songTitle = title this.songDifficulty = this.diff.split(".").slice(0, -1).join(".") + this.drumroll = [] + this.beatInterval = this.controller.getSongData().beatInfo.beatInterval this.assets = [] this.don = this.createAsset(frame => { @@ -69,22 +71,15 @@ class View{ this.don.setAnimation("normal") this.don.setUpdateSpeed(this.beatInterval / 16) } - run(){ this.ctx.font = "normal 14pt TnT" this.setBackground() $(".game-song").attr("alt", this.songTitle).html(this.songTitle) this.refresh() } - setBackground(){ $("#game").css("background-image", "url('" + this.bg + "')") } - - getDistanceForCircle(){ - return this.distanceForCircle - } - positionning(){ this.canvas.rescale() var height = $(window).height() @@ -133,7 +128,6 @@ class View{ this.diffX = this.taikoX * 0.10 this.diffY = this.taikoY * 1.05 + this.taikoH * 0.19 } - refresh(){ this.positionning() this.distanceForCircle = this.winW - this.slotX @@ -147,7 +141,8 @@ class View{ this.drawMeasures() this.drawHPBar() this.drawScore() - this.drawCircles() + this.drawCircles(this.controller.getCircles()) + this.drawCircles(this.drumroll) this.drawTaikoSquare() this.drawDifficulty() this.drawPressedKeys() @@ -156,7 +151,6 @@ class View{ this.updateDonFaces() //this.drawTime() } - updateDonFaces(){ if(this.controller.getElapsedTime().ms >= this.nextBeat){ this.nextBeat += this.beatInterval @@ -170,7 +164,6 @@ class View{ } } } - drawHPBar(){ var z = this.canvas.scale @@ -221,7 +214,6 @@ class View{ hpBar.canvasW, this.HPBarColH ) } - getHP(){ var circles = this.controller.getCircles() var currentCircle = this.controller.getCurrentCircle() @@ -232,7 +224,6 @@ class View{ canvasW: width / 650 * this.HPBarColMaxW } } - drawMeasures(){ var measures = this.controller.getSongData().measures var currentTime = this.controller.getElapsedTime().ms @@ -248,7 +239,6 @@ class View{ } }) } - drawMeasure(measure){ var z = this.canvas.scale var currentTime = this.controller.getElapsedTime().ms @@ -261,7 +251,6 @@ class View{ this.ctx.closePath() this.ctx.stroke() } - drawCombo(){ var comboCount = this.controller.getCombo() if(comboCount >= 10){ @@ -314,14 +303,12 @@ class View{ this.scoreDispCount++ } } - strokeFillText(text, x, y){ this.ctx.strokeText(text, x, y) this.ctx.fillText(text, x, y) } - drawGlobalScore(){ - /* Draw score square */ + // Draw score square this.ctx.fillStyle="#000" this.ctx.beginPath() this.ctx.fillRect(0, this.barY, this.scoreSquareW, this.scoreSquareH - 10) @@ -350,7 +337,6 @@ class View{ ) } } - drawPressedKeys(){ var keys = this.controller.getKeys() var kbd = this.controller.getBindings() @@ -399,14 +385,12 @@ class View{ ) } } - displayScore(score, notPlayed){ this.currentScore = score this.special = notPlayed ? "-b" : "" this.scoreDispCount = 0 this.scoreOpacity = 1 } - drawScore(){ if(this.scoreDispCount >= 0 && this.scoreDispCount <= 20){ this.ctx.globalAlpha = this.scoreOpacity @@ -427,63 +411,59 @@ class View{ } this.ctx.globalAlpha = 1 } - - drawCircles(){ - var circles = this.controller.getCircles() + posToMs(pos, speed){ + return 70 / this.circleSize * pos / speed + } + msToPos(ms, speed){ + return speed / (70 / this.circleSize) * ms + } + drawCircles(circles){ for(var i = circles.length; i--;){ var circle = circles[i] + var ms = this.controller.getElapsedTime().ms + var speed = circle.getSpeed() - var currentTime = this.controller.getElapsedTime().ms - var timeForDistance = 70 / this.circleSize * this.distanceForCircle / circle.getSpeed() + this.bigCircleSize / 2 + var timeForDistance = this.posToMs(this.distanceForCircle + this.bigCircleSize / 2, speed) var startingTime = circle.getMS() - timeForDistance - // At circle.getMS(), the cirlce fits the slot - var finishTime = circle.getMS() + 100 + var finishTime = circle.getEndTime() + this.posToMs(this.slotX - this.taikoSquareW + this.bigCircleSize / 2, speed) - if(!circle.getPlayed() && currentTime >= startingTime && currentTime <= finishTime){ - this.drawCircle(circle) - } - else{ - // Animate circle to the HP bar - - // Animation in ms - var animationDuration = 470 - - if(!circle.isAnimated()){ - if(circle.getScore() != 0){ - // Start animation to HP bar - circle.animate() - } + if(!circle.getPlayed() || circle.getScore() == 0){ + if(ms >= startingTime && ms <= finishTime){ + this.drawCircle(circle) } - if(circle.isAnimated()){ - if(currentTime <= finishTime + animationDuration){ - var curveDistance = this.HPBarX + this.HPBarW - this.slotX - var bezierPoint = this.calcBezierPoint(circle.getAnimT(), [{ - x: this.slotX, - y: this.circleY - }, { - x: this.slotX + curveDistance * 0.15, - y: this.barH * 0.5 - }, { - x: this.slotX + curveDistance * 0.35, - y: 0 - }, { - x: this.slotX + curveDistance, - y: this.HPbarColY - }]) - this.drawCircle(circle, {x: bezierPoint.x, y: bezierPoint.y}) - - // Update animation frame - circle.incAnimT() - circle.incFrame() - } - else{ - circle.endAnimation() - } + }else if(!circle.isAnimated()){ + // Start animation to HP bar + circle.animate() + } + if(circle.isAnimated()){ + var animationDuration = 470 + if(ms <= finishTime + animationDuration){ + var curveDistance = this.HPBarX + this.HPBarW - this.slotX + var bezierPoint = this.calcBezierPoint(circle.getAnimT(), [{ + x: this.slotX + this.circleSize * 0.4, + y: this.circleY - this.circleSize * 0.8 + }, { + x: this.slotX + curveDistance * 0.15, + y: this.barH * 0.5 + }, { + x: this.slotX + curveDistance * 0.35, + y: 0 + }, { + x: this.slotX + curveDistance, + y: this.HPbarColY + }]) + this.drawCircle(circle, {x: bezierPoint.x, y: bezierPoint.y}) + + // Update animation frame + circle.incAnimT() + circle.incFrame() + } + else{ + circle.endAnimation() } } } } - calcBezierPoint(t, data){ var at = 1 - t @@ -498,72 +478,117 @@ class View{ return data[0] } - drawCircle(circle, circlePos){ var z = this.canvas.scale - var fill, size, faceID + var type = circle.getType() + var ms = this.controller.getElapsedTime().ms + var circleMs = circle.getMS() + var endTime = circle.getEndTime() + var animated = circle.isAnimated() + var speed = circle.getSpeed() + if(!circlePos){ - var currentTime = this.controller.getElapsedTime().ms circlePos = { - x: this.slotX + circle.getSpeed() / (70 / this.circleSize) * (circle.getMS() - currentTime), + x: this.slotX + this.msToPos(circleMs - ms, speed), y: this.circleY } } - if(circle.getPlayed()){ - var currentDonFace = 1 + if(animated){ + var currentDonFace = 0 var currentBigDonFace = 1 }else{ var currentDonFace = this.currentDonFace var currentBigDonFace = this.currentBigDonFace } - switch(circle.getType()){ + switch(type){ case "don": - fill = "#f54c25" + fill = "#f34728" size = this.circleSize faceID = "don-" + currentDonFace break case "ka": - fill = "#75cee9" + fill = "#65bdbb" size = this.circleSize faceID = "don-" + currentDonFace break case "daiDon": - fill = "#f54c25" + fill = "#f34728" size = this.bigCircleSize faceID = "big-don-" + currentBigDonFace break case "daiKa": - fill = "#75cee9" + fill = "#65bdbb" size = this.bigCircleSize faceID = "big-don-" + currentBigDonFace break + case "balloon": + if(animated){ + fill = "#f34728" + size = this.bigCircleSize * 0.8 + faceID = "big-don-" + currentBigDonFace + break + } + fill = "#f87700" + size = this.circleSize + faceID = "don-" + currentDonFace + var h = size * 1.8 + if(circleMs < ms && ms <= endTime){ + circlePos.x = this.slotX + }else if(ms > endTime){ + circlePos.x = this.slotX + this.msToPos(endTime - ms, speed) + } + this.ctx.drawImage(assets.image["balloon"], + circlePos.x + size - 3, + circlePos.y - h / 2, + h / 61 * 115, + h + ) + break + case "drumroll": + case "daiDrumroll": + fill = "#f3b500" + if(type == "drumroll"){ + size = this.circleSize + faceID = "don-" + currentDonFace + }else{ + size = this.bigCircleSize + faceID = "big-don-" + currentBigDonFace + } + var endX = this.msToPos(endTime - circleMs, speed) + this.ctx.fillStyle = fill + this.ctx.strokeStyle = "#1f1a17" + this.ctx.lineWidth = this.lyricsSize / 10 + this.ctx.beginPath() + this.ctx.moveTo(circlePos.x, circlePos.y - size) + this.ctx.lineTo(circlePos.x + endX, circlePos.y - size) + this.ctx.arc(circlePos.x + endX, circlePos.y, size, -Math.PI / 2, Math.PI / 2) + this.ctx.lineTo(circlePos.x, circlePos.y + size) + this.ctx.fill() + this.ctx.stroke() + break } - // Main circle this.ctx.fillStyle = fill this.ctx.beginPath() this.ctx.arc(circlePos.x, circlePos.y, size, 0, Math.PI * 2) this.ctx.closePath() this.ctx.fill() - // Face on circle - var face = assets.image[faceID] - this.ctx.drawImage(face, + this.ctx.drawImage(assets.image[faceID], circlePos.x - size - 2, circlePos.y - size - 4, size * 2 + 5, size * 2 + 6 ) - if(!circle.isAnimated()){ // Text this.ctx.font = "normal bold " + this.lyricsSize + "px Kozuka" this.ctx.textAlign = "center" this.ctx.strokeStyle = "#000" - this.ctx.lineWidth = this.lyricsSize / 5 + this.ctx.lineWidth = this.lyricsSize / 5 this.ctx.fillStyle = "#fff" this.strokeFillText(circle.getText(), circlePos.x, @@ -571,7 +596,6 @@ class View{ ) } } - togglePauseMenu(){ if($("#pause-menu").is(":visible")){ $("#pause-menu").hide() @@ -579,7 +603,6 @@ class View{ $("#pause-menu").show() } } - drawDifficulty(){ this.ctx.drawImage(assets.image["muzu_" + this.songDifficulty], this.diffX, this.diffY, @@ -591,7 +614,6 @@ class View{ this.taikoW, this.taikoH ) } - drawTime(){ var z = this.canvas.scale var time = this.controller.getElapsedTime() @@ -614,7 +636,6 @@ class View{ ) this.ctx.fillText(time.ms, this.winW - 10 * z, this.winH - 10 * z) } - drawBar(){ this.ctx.strokeStyle = "#000" this.ctx.fillStyle = "#232323" @@ -641,7 +662,6 @@ class View{ this.ctx.fill() this.ctx.globalAlpha = 1 } - this.ctx.stroke() // Lyrics bar this.ctx.fillStyle = "#888888" @@ -651,7 +671,6 @@ class View{ this.ctx.fill() this.ctx.stroke() } - drawSlot(){ // Main circle this.ctx.fillStyle = "#6f6f6e" @@ -659,7 +678,6 @@ class View{ this.ctx.arc(this.slotX, this.circleY, this.circleSize - 0.2 * this.circleSize, 0, 2 * Math.PI) this.ctx.closePath() this.ctx.fill() - // Big stroke circle this.ctx.strokeStyle = "#9e9f9f" this.ctx.lineWidth = 3 @@ -667,7 +685,6 @@ class View{ this.ctx.arc(this.slotX, this.circleY, this.circleSize, 0, 2 * Math.PI) this.ctx.closePath() this.ctx.stroke() - // Bigger stroke circle this.ctx.strokeStyle = "#6f6f6e" this.ctx.lineWidth = 3 @@ -676,7 +693,6 @@ class View{ this.ctx.closePath() this.ctx.stroke() } - drawTaikoSquare(){ // Taiko square this.ctx.lineWidth = 7 @@ -688,13 +704,11 @@ class View{ this.ctx.closePath() this.ctx.stroke() } - createAsset(image, position){ var asset = new CanvasAsset(this, image, position) this.assets.push(asset) return asset } - drawAssets(){ if(this.controller.multiplayer != 2){ this.assets.forEach(asset => { @@ -702,7 +716,6 @@ class View{ }) } } - updateCombo(combo){ if(combo > 0 && combo % 10 == 0 && this.don.getAnimation() != "10combo"){ this.don.setAnimation("10combo") diff --git a/public/src/views/scoresheet.html b/public/src/views/scoresheet.html index 2b405c5..88e93f7 100644 --- a/public/src/views/scoresheet.html +++ b/public/src/views/scoresheet.html @@ -1,43 +1,39 @@ -
- -
+
+

成績発表

- -
- - - -
-
-
- +
+
+ +
+
+
- -
- +
+
- - + + + - - + + + - + +
最大コンボ数最大コンボ数
連打数
不可不可
- -
-
- - +
+
+ +
- -
\ No newline at end of file +
diff --git a/server.py b/server.py index 740bbf1..de7ed04 100644 --- a/server.py +++ b/server.py @@ -4,9 +4,9 @@ import asyncio import websockets import json -users = [] server_status = { - "waiting": {} + "waiting": {}, + "users": [] } def msgobj(type, value=None): @@ -25,7 +25,7 @@ def status_event(): return msgobj("users", value) async def notify_status(): - ready_users = [user for user in users if "ws" in user and user["action"] == "ready"] + ready_users = [user for user in server_status["users"] if "ws" in user and user["action"] == "ready"] if ready_users: sent_msg = status_event() await asyncio.wait([user["ws"].send(sent_msg) for user in ready_users]) @@ -36,7 +36,7 @@ async def connection(ws, path): "ws": ws, "action": "ready" } - users.append(user) + server_status["users"].append(user) try: # Notify user about other users await ws.send(status_event()) @@ -126,8 +126,8 @@ async def connection(ws, path): elif action == "playing": # Playing with another user if "other_user" in user and "ws" in user["other_user"]: - if type == "note": - await user["other_user"]["ws"].send(msgobj("note", value)) + if type == "note" or type == "drumroll" or type == "gameresults": + await user["other_user"]["ws"].send(msgobj(type, value)) if type == "gameend": # User wants to disconnect user["action"] = "ready" @@ -151,7 +151,7 @@ async def connection(ws, path): finally: # User disconnected del user["ws"] - del users[users.index(user)] + del server_status["users"][server_status["users"].index(user)] if "other_user" in user and "ws" in user["other_user"]: user["other_user"]["action"] = "ready" await asyncio.wait([