mirror of
https://github.com/jiojciojsioe3/a3cjroijsiojiorj.git
synced 2024-11-15 07:21:50 +08:00
Add 2-player mode
This commit is contained in:
parent
7744fdac45
commit
8e99da6aa2
@ -45,6 +45,7 @@
|
||||
<script src="/src/js/scalablecanvas.js"></script>
|
||||
<script src="/src/js/element.js"></script>
|
||||
<script src="/src/js/soundbuffer.js"></script>
|
||||
<script src="/src/js/p2.js"></script>
|
||||
|
||||
</head>
|
||||
<body>
|
||||
|
@ -75,6 +75,7 @@ ul li{
|
||||
box-shadow: 2px 2px 10px black;
|
||||
overflow: hidden;
|
||||
cursor: pointer;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.opened{
|
||||
@ -127,3 +128,12 @@ ul li{
|
||||
.difficulty:hover .stars{
|
||||
color:white;
|
||||
}
|
||||
|
||||
.song.p2:not(.opened)::after,
|
||||
.difficulty.p2::after{
|
||||
content:"P2";
|
||||
display:block;
|
||||
position:absolute;
|
||||
bottom:0;
|
||||
width:100%;
|
||||
}
|
||||
|
@ -1,226 +1,220 @@
|
||||
function Controller(selectedSong, songData, autoPlayEnabled){
|
||||
class Controller{
|
||||
constructor(selectedSong, songData, autoPlayEnabled, multiplayer){
|
||||
this.selectedSong = selectedSong
|
||||
this.songData = songData
|
||||
this.autoPlayEnabled = autoPlayEnabled
|
||||
this.multiplayer = multiplayer
|
||||
this.pauseMenu = false
|
||||
|
||||
var _this = this;
|
||||
var _backgroundURL = "/songs/"+selectedSong.folder+"/bg.png";
|
||||
var backgroundURL = "/songs/" + this.selectedSong.folder + "/bg.png"
|
||||
var songParser = new ParseSong(songData)
|
||||
this.parsedSongData = songParser.getData()
|
||||
|
||||
var _songParser = new ParseSong(songData); //get file content
|
||||
var _songData = _songParser.getData();
|
||||
assets.songs.forEach(song => {
|
||||
if(song.id == this.selectedSong.folder){
|
||||
this.mainAsset = song.sound
|
||||
}
|
||||
})
|
||||
|
||||
var _game = new Game(this, selectedSong, _songData);
|
||||
var _view = new View(this, _backgroundURL, selectedSong.title, selectedSong.difficulty);
|
||||
var _mekadon = new Mekadon(this, _game);
|
||||
var _keyboard = new Keyboard(this);
|
||||
var _mainLoop;
|
||||
var _pauseMenu = false;
|
||||
var _mainAsset
|
||||
assets.songs.forEach(song => {
|
||||
if(song.id == selectedSong.folder){
|
||||
_mainAsset = song.sound
|
||||
this.game = new Game(this, this.selectedSong, this.parsedSongData)
|
||||
this.view = new View(this, backgroundURL, this.selectedSong.title, this.selectedSong.difficulty)
|
||||
this.mekadon = new Mekadon(this, this.game)
|
||||
this.keyboard = new Keyboard(this)
|
||||
}
|
||||
run(syncWith){
|
||||
this.loadUIEvents()
|
||||
this.game.run()
|
||||
this.view.run()
|
||||
this.startMainLoop()
|
||||
if(syncWith){
|
||||
syncWith.game.getElapsedTime = () => {
|
||||
return this.game.elapsedTime
|
||||
}
|
||||
this.game.setElapsedTime =
|
||||
syncWith.game.setElapsedTime = time => {
|
||||
this.game.elapsedTime.ms = time
|
||||
syncWith.game.elapsedTime.ms = time
|
||||
}
|
||||
syncWith.run()
|
||||
this.syncWith = syncWith
|
||||
}
|
||||
})
|
||||
|
||||
this.autoPlayEnabled = autoPlayEnabled
|
||||
|
||||
this.run = function(){
|
||||
|
||||
_this.loadUIEvents();
|
||||
_game.run();
|
||||
_view.run();
|
||||
_this.startMainLoop();
|
||||
}
|
||||
|
||||
this.loadUIEvents = function(){
|
||||
$("#song-selection-butt").click(function(){
|
||||
assets.sounds["don"].play();
|
||||
_this.songSelection();
|
||||
});
|
||||
$("#restart-butt").click(function(){
|
||||
assets.sounds["don"].play();
|
||||
_this.restartSong();
|
||||
});
|
||||
$("#continue-butt").click(function(){
|
||||
_this.togglePauseMenu();
|
||||
});
|
||||
}
|
||||
|
||||
this.startMainLoop = function(){
|
||||
|
||||
var started=false;
|
||||
_mainLoop = setInterval(function(){
|
||||
|
||||
var ms = _game.getEllapsedTime().ms;
|
||||
if(ms<0){ //before starting game, offseting the circles
|
||||
_game.updateTime();
|
||||
_view.refresh();
|
||||
}
|
||||
else if(ms>=0 && !started){ //when music shall starts
|
||||
_mainAsset.play(_songData.generalInfo.audioWait)
|
||||
started=true;
|
||||
}
|
||||
|
||||
if(started){ //Game start here
|
||||
if(!_game.isPaused()){
|
||||
_game.update();
|
||||
_view.refresh();
|
||||
_keyboard.checkGameKeys();
|
||||
}
|
||||
_keyboard.checkMenuKeys();
|
||||
}
|
||||
|
||||
}, 20);
|
||||
|
||||
}
|
||||
|
||||
this.getDistanceForCircle = function(){
|
||||
return _view.getDistanceForCircle();
|
||||
loadUIEvents(){
|
||||
$("#song-selection-butt").click(() => {
|
||||
assets.sounds["don"].play()
|
||||
this.songSelection()
|
||||
})
|
||||
$("#restart-butt").click(() => {
|
||||
assets.sounds["don"].play()
|
||||
this.restartSong()
|
||||
})
|
||||
$("#continue-butt").click(() => {
|
||||
this.togglePauseMenu()
|
||||
})
|
||||
}
|
||||
startMainLoop(){
|
||||
this.mainLoopStarted = false
|
||||
this.mainLoopRunning = true
|
||||
this.mainLoop()
|
||||
}
|
||||
mainLoop(){
|
||||
if(this.mainLoopRunning){
|
||||
if(this.multiplayer != 2){
|
||||
requestAnimationFrame(() => {
|
||||
if(this.syncWith){
|
||||
this.syncWith.game.elapsedTime.ms = this.game.elapsedTime.ms
|
||||
}
|
||||
this.mainLoop()
|
||||
if(this.syncWith){
|
||||
this.syncWith.mainLoop()
|
||||
}
|
||||
})
|
||||
}
|
||||
var ms = this.game.getElapsedTime().ms
|
||||
if(!this.game.isPaused()){
|
||||
if(ms >= 0 && !this.mainLoopStarted){
|
||||
this.mainLoopStarted = true
|
||||
}
|
||||
if(ms < 0){
|
||||
this.game.updateTime()
|
||||
}
|
||||
if(this.mainLoopStarted){
|
||||
this.game.update()
|
||||
this.game.playMainMusic()
|
||||
}
|
||||
this.view.refresh()
|
||||
this.keyboard.checkGameKeys()
|
||||
}
|
||||
this.keyboard.checkMenuKeys()
|
||||
}
|
||||
}
|
||||
getDistanceForCircle(){
|
||||
return this.view.getDistanceForCircle()
|
||||
}
|
||||
togglePauseMenu(){
|
||||
this.togglePause()
|
||||
this.view.togglePauseMenu()
|
||||
}
|
||||
displayResults(){
|
||||
var score = this.getGlobalScore()
|
||||
var vp
|
||||
if (score.fail == 0) {
|
||||
vp = "fullcombo"
|
||||
this.playSoundMeka("fullcombo", 1.350)
|
||||
} else if (score.hp >= 50) {
|
||||
vp = "clear"
|
||||
} else {
|
||||
vp = "fail"
|
||||
}
|
||||
assets.sounds["game" + vp].play()
|
||||
setTimeout(() => {
|
||||
this.mainLoopRunning = false
|
||||
if(this.multiplayer != 2){
|
||||
new Scoresheet(this, this.getGlobalScore())
|
||||
}
|
||||
}, 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
|
||||
new SongSelect()
|
||||
}
|
||||
restartSong(){
|
||||
this.mainAsset.stop()
|
||||
this.mainLoopRunning = false
|
||||
$("#screen").load("/src/views/game.html", () => {
|
||||
var taikoGame = new Controller(this.selectedSong, this.songData, this.autoPlayEnabled)
|
||||
taikoGame.run()
|
||||
})
|
||||
}
|
||||
playSoundMeka(soundID, time){
|
||||
var meka = ""
|
||||
if(this.autoPlayEnabled && !this.multiplayer){
|
||||
meka = "-meka"
|
||||
}
|
||||
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()
|
||||
}
|
||||
setKey(keyCode, down){
|
||||
return this.keyboard.setKey(keyCode, down)
|
||||
}
|
||||
getBindings(){
|
||||
return this.keyboard.getBindings()
|
||||
}
|
||||
getSongData(){
|
||||
return this.game.getSongData()
|
||||
}
|
||||
getElapsedTime(){
|
||||
return this.game.getElapsedTime()
|
||||
}
|
||||
getCircles(){
|
||||
return this.game.getCircles()
|
||||
}
|
||||
getCurrentCircle(){
|
||||
return this.game.getCurrentCircle()
|
||||
}
|
||||
updateCurrentCircle(){
|
||||
this.game.updateCurrentCircle()
|
||||
}
|
||||
isWaitingForKeyup(key, type){
|
||||
return this.keyboard.isWaitingForKeyup(key, type)
|
||||
}
|
||||
waitForKeyup(key, type){
|
||||
this.keyboard.waitForKeyup(key, type)
|
||||
}
|
||||
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)
|
||||
}else{
|
||||
this.mekadon.play(circle)
|
||||
}
|
||||
}
|
||||
|
||||
this.togglePauseMenu = function(){
|
||||
_this.togglePause();
|
||||
_view.togglePauseMenu();
|
||||
}
|
||||
|
||||
this.displayResults = function(){
|
||||
clearInterval(_mainLoop);
|
||||
|
||||
|
||||
var score = _this.getGlobalScore();
|
||||
|
||||
if (score.fail == 0) {
|
||||
vp = 'fullcombo';
|
||||
_this.playSoundMeka('fullcombo', 1.350);
|
||||
} else if (score.hp >= 50) {
|
||||
vp = 'clear';
|
||||
} else {
|
||||
vp = 'fail';
|
||||
}
|
||||
|
||||
assets.sounds['game' + vp].play();
|
||||
|
||||
setTimeout(function(){
|
||||
new Scoresheet(_this, _this.getGlobalScore());
|
||||
}, 7000);
|
||||
}
|
||||
|
||||
this.displayScore = function(score, notPlayed){
|
||||
_view.displayScore(score, notPlayed);
|
||||
}
|
||||
|
||||
this.fadeOutOver = function(){
|
||||
_game.fadeOutOver();
|
||||
_this.displayResults();
|
||||
}
|
||||
|
||||
this.getCurrentTimingPoint = function(){
|
||||
return _game.getCurrentTimingPoint();
|
||||
}
|
||||
|
||||
this.songSelection = function(){
|
||||
$("#main-music").remove();
|
||||
$("#music-bg").remove();
|
||||
clearInterval(_mainLoop);
|
||||
new SongSelect();
|
||||
}
|
||||
|
||||
this.restartSong = function(){
|
||||
_mainAsset.stop()
|
||||
clearInterval(_mainLoop);
|
||||
$("#screen").load("/src/views/game.html", function(){
|
||||
var taikoGame = new Controller(selectedSong, songData, autoPlayEnabled);
|
||||
taikoGame.run();
|
||||
});
|
||||
}
|
||||
|
||||
this.playSoundMeka = function(soundID, time){
|
||||
assets.sounds[soundID + (autoPlayEnabled ? '-meka' : '')].play(time)
|
||||
}
|
||||
|
||||
this.initTiming = function(){
|
||||
_game.initTiming();
|
||||
}
|
||||
|
||||
this.setHitcircleSpeed = function(speed){
|
||||
_view.setHitcircleSpeed(speed);
|
||||
}
|
||||
|
||||
this.getHitcircleSpeed = function(){
|
||||
return _game.getHitcircleSpeed();
|
||||
}
|
||||
|
||||
this.toggleMainMusic = function(){
|
||||
_game.toggleMainMusic();
|
||||
}
|
||||
|
||||
this.togglePause = function(){
|
||||
_game.togglePause();
|
||||
}
|
||||
|
||||
this.isPaused = function(){
|
||||
return _game.isPaused();
|
||||
}
|
||||
|
||||
this.getKeys = function(){
|
||||
return _keyboard.getKeys();
|
||||
}
|
||||
|
||||
this.setKey = function(keyCode, down){
|
||||
return _keyboard.setKey(keyCode, down);
|
||||
}
|
||||
|
||||
this.getBindings = function(){
|
||||
return _keyboard.getBindings();
|
||||
}
|
||||
|
||||
this.getSongData = function(){
|
||||
return _game.getSongData();
|
||||
}
|
||||
|
||||
this.getEllapsedTime = function(){
|
||||
return _game.getEllapsedTime();
|
||||
}
|
||||
|
||||
this.getCircles = function(){
|
||||
return _game.getCircles();
|
||||
}
|
||||
|
||||
this.getCurrentCircle = function(){
|
||||
return _game.getCurrentCircle();
|
||||
}
|
||||
|
||||
this.updateCurrentCircle = function(){
|
||||
_game.updateCurrentCircle();
|
||||
}
|
||||
|
||||
this.isWaitingForKeyup = function(key, type){
|
||||
return _keyboard.isWaitingForKeyup(key, type);
|
||||
}
|
||||
|
||||
this.waitForKeyup = function(key, type){
|
||||
_keyboard.waitForKeyup(key, type);
|
||||
}
|
||||
|
||||
this.getKeyTime = function(){
|
||||
return _keyboard.getKeyTime();
|
||||
}
|
||||
|
||||
this.updateCombo = function(score){
|
||||
_game.updateCombo(score);
|
||||
}
|
||||
|
||||
this.getCombo = function(){
|
||||
return _game.getCombo();
|
||||
}
|
||||
|
||||
this.getGlobalScore = function(){
|
||||
return _game.getGlobalScore();
|
||||
}
|
||||
|
||||
this.updateGlobalScore = function(score){
|
||||
_game.updateGlobalScore(score);
|
||||
}
|
||||
|
||||
this.autoPlay = function(circle){
|
||||
_mekadon.play(circle)
|
||||
}
|
||||
|
||||
}
|
@ -2,7 +2,7 @@ function Game(controller, selectedSong, songData){
|
||||
|
||||
var _this = this;
|
||||
var _selectedSong = selectedSong;
|
||||
var _ellapsedTime; //current time in ms from the beginning of the song
|
||||
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
|
||||
@ -14,60 +14,53 @@ function Game(controller, selectedSong, songData){
|
||||
var _HPGain= 100/_songData.circles.length;
|
||||
var _paused=false;
|
||||
var _started=false;
|
||||
var _mainMusicPlaying=true;
|
||||
var _mainMusicPlaying=false;
|
||||
var _latestDate;
|
||||
var _ellapsedTimeSincePause=0;
|
||||
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
|
||||
}
|
||||
})
|
||||
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=((20*controller.getDistanceForCircle())/_hitcircleSpeed);
|
||||
_this.initTiming();
|
||||
_timeForDistanceCircle=2500
|
||||
_this.initTiming();
|
||||
}
|
||||
|
||||
this.initTiming = function(){
|
||||
|
||||
_offsetDate = new Date();
|
||||
|
||||
_ellapsedTime = {
|
||||
ms:-parseInt(_timeForDistanceCircle),
|
||||
sec:0,
|
||||
min:0,
|
||||
hour:0
|
||||
}
|
||||
_offsetTime = parseInt(_timeForDistanceCircle);
|
||||
_this.setElapsedTime(-_timeForDistanceCircle |0)
|
||||
_offsetTime = _timeForDistanceCircle |0
|
||||
_startDate = new Date();
|
||||
_startDate.setMilliseconds(_startDate.getMilliseconds()+_offsetTime); //The real start for the game will start when chrono will reach 0
|
||||
|
||||
// The real start for the game will start when chrono will reach 0
|
||||
_startDate.setMilliseconds(_startDate.getMilliseconds()+_offsetTime);
|
||||
}
|
||||
|
||||
this.update = function(){
|
||||
|
||||
/* Main operations */
|
||||
// Main operations
|
||||
_this.updateTime();
|
||||
_this.checkTiming();
|
||||
_this.updateCirclesStatus();
|
||||
_this.checkPlays();
|
||||
|
||||
/* Event operations */
|
||||
// Event operations
|
||||
_this.whenFadeoutMusic();
|
||||
_this.whenLastCirclePlayed();
|
||||
|
||||
}
|
||||
|
||||
this.getCircles = function(){
|
||||
return _songData.circles;
|
||||
}
|
||||
this.getCircles = function(){
|
||||
return _songData.circles;
|
||||
}
|
||||
|
||||
this.updateCirclesStatus = function(){
|
||||
|
||||
@ -77,13 +70,14 @@ function Game(controller, selectedSong, songData){
|
||||
|
||||
if(!circle.getPlayed()){
|
||||
|
||||
var currentTime = _ellapsedTime.ms;
|
||||
var currentTime = _this.getElapsedTime().ms;
|
||||
var startingTime = circle.getMS()-_timeForDistanceCircle;
|
||||
var finishTime = circle.getMS(); //at circle.getMS(), the cirlce fits the slot
|
||||
// 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){
|
||||
if(currentTime>= finishTime-50 && currentTime < finishTime-30){
|
||||
circle.updateStatus(0);
|
||||
}
|
||||
else if(currentTime>= finishTime-30 && currentTime < finishTime){
|
||||
@ -95,14 +89,20 @@ function Game(controller, selectedSong, songData){
|
||||
|
||||
}
|
||||
else if(currentTime>finishTime+200 && currentTime<=finishTime+300){
|
||||
|
||||
circle.updateStatus(-1);
|
||||
_currentScore=0;
|
||||
circle.played(_currentScore);
|
||||
controller.displayScore(_currentScore, true);
|
||||
_this.updateCurrentCircle();
|
||||
_this.updateCombo(_currentScore);
|
||||
_this.updateGlobalScore(_currentScore);
|
||||
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
|
||||
})
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -149,6 +149,12 @@ function Game(controller, selectedSong, songData){
|
||||
circle.played(score);
|
||||
_this.updateCurrentCircle();
|
||||
controller.waitForKeyup(keyCode, "score");
|
||||
if(controller.multiplayer == 1){
|
||||
p2.send("note", {
|
||||
score: score,
|
||||
ms: circle.getMS() - _this.getElapsedTime().ms
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -173,25 +179,25 @@ function Game(controller, selectedSong, songData){
|
||||
break;
|
||||
|
||||
}
|
||||
controller.displayScore(_currentScore);
|
||||
controller.displayScore(_currentScore);
|
||||
|
||||
}
|
||||
else{
|
||||
_currentScore=0;
|
||||
controller.displayScore(_currentScore, true);
|
||||
controller.displayScore(_currentScore, true);
|
||||
}
|
||||
|
||||
|
||||
_this.updateCombo(_currentScore);
|
||||
_this.updateGlobalScore(_currentScore);
|
||||
return _currentScore;
|
||||
return _currentScore;
|
||||
}
|
||||
|
||||
this.whenLastCirclePlayed = function(){
|
||||
var circles = _songData.circles;
|
||||
var lastCircle = circles[_songData.circles.length-1];
|
||||
if(!_fadeOutStarted && _ellapsedTime.ms>=lastCircle.getMS()+2000){
|
||||
_fadeOutStarted=_ellapsedTime.ms
|
||||
if(!_fadeOutStarted && _this.getElapsedTime().ms>=lastCircle.getMS()+2000){
|
||||
_fadeOutStarted=_this.getElapsedTime().ms
|
||||
}
|
||||
}
|
||||
|
||||
@ -199,23 +205,27 @@ function Game(controller, selectedSong, songData){
|
||||
if(_fadeOutStarted){
|
||||
if(_musicFadeOut==0){
|
||||
snd.musicGain.fadeOut(1.6)
|
||||
_musicFadeOut++
|
||||
if(controller.multiplayer == 1){
|
||||
p2.send("gameend")
|
||||
}
|
||||
}
|
||||
if(_ellapsedTime.ms>=_fadeOutStarted+1600){
|
||||
if(_musicFadeOut==1 && _this.getElapsedTime().ms>=_fadeOutStarted+1600){
|
||||
controller.fadeOutOver()
|
||||
_mainAsset.stop()
|
||||
_musicFadeOut++
|
||||
setTimeout(() => {
|
||||
snd.musicGain.fadeIn()
|
||||
snd.musicGain.unmute()
|
||||
}, 1000)
|
||||
}
|
||||
_musicFadeOut++;
|
||||
}
|
||||
}
|
||||
|
||||
this.checkTiming = function(){
|
||||
|
||||
if(_songData.timingPoints[_currentTimingPoint+1]){
|
||||
if(_this.getEllapsedTime().ms>=_songData.timingPoints[_currentTimingPoint+1].start){
|
||||
if(_this.getElapsedTime().ms>=_songData.timingPoints[_currentTimingPoint+1].start){
|
||||
_currentTimingPoint++;
|
||||
}
|
||||
}
|
||||
@ -225,19 +235,18 @@ function Game(controller, selectedSong, songData){
|
||||
return _songData.timingPoints[_currentTimingPoint];
|
||||
}
|
||||
|
||||
this.toggleMainMusic = function(){
|
||||
if(_mainMusicPlaying){
|
||||
_mainAsset.stop();
|
||||
_mainMusicPlaying=false;
|
||||
}
|
||||
else{
|
||||
_mainAsset.play(0, false, _this.getEllapsedTime().ms / 1000);
|
||||
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(){
|
||||
_fadeOutStarted=false;
|
||||
|
||||
}
|
||||
|
||||
this.getHitcircleSpeed = function(){
|
||||
@ -249,15 +258,15 @@ function Game(controller, selectedSong, songData){
|
||||
assets.sounds["pause"].play();
|
||||
_paused=true;
|
||||
_latestDate = new Date();
|
||||
_this.toggleMainMusic();
|
||||
_mainAsset.stop();
|
||||
_mainMusicPlaying=false;
|
||||
|
||||
}
|
||||
else{
|
||||
assets.sounds["cancel"].play();
|
||||
_paused=false;
|
||||
_paused=false;
|
||||
var currentDate = new Date();
|
||||
_ellapsedTimeSincePause = _ellapsedTimeSincePause + Math.abs(currentDate.getTime() - _latestDate.getTime());
|
||||
_this.toggleMainMusic();
|
||||
_elapsedTimeSincePause = _elapsedTimeSincePause + currentDate.getTime() - _latestDate.getTime();
|
||||
}
|
||||
}
|
||||
|
||||
@ -265,30 +274,33 @@ function Game(controller, selectedSong, songData){
|
||||
return _paused;
|
||||
}
|
||||
|
||||
this.getEllapsedTime = function(){
|
||||
return _ellapsedTime;
|
||||
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(_ellapsedTime.ms<0){
|
||||
_ellapsedTime.ms = _currentDate.getTime() - _startDate.getTime();
|
||||
if(time.ms<0){
|
||||
_this.setElapsedTime(_currentDate.getTime() - _startDate.getTime() - _elapsedTimeSincePause)
|
||||
}
|
||||
else if(_ellapsedTime.ms>=0 && !_started){
|
||||
else if(time.ms>=0 && !_started){
|
||||
_startDate = new Date();
|
||||
_ellapsedTime.ms = Math.abs(_startDate.getTime() - _currentDate.getTime());
|
||||
_elapsedTimeSincePause = 0;
|
||||
_this.setElapsedTime(_currentDate.getTime() - _startDate.getTime())
|
||||
_started=true;
|
||||
}
|
||||
else if(_ellapsedTime.ms>=0 && _started){
|
||||
_ellapsedTime.ms = Math.abs(_startDate.getTime() - _currentDate.getTime()) - _ellapsedTimeSincePause;
|
||||
else if(time.ms>=0 && _started){
|
||||
_this.setElapsedTime(_currentDate.getTime() - _startDate.getTime() - _elapsedTimeSincePause)
|
||||
}
|
||||
|
||||
_ellapsedTime.sec = parseInt(_ellapsedTime.ms / 1000) % 60;
|
||||
_ellapsedTime.min = parseInt(_ellapsedTime.ms / (1000 * 60)) % 60;
|
||||
_ellapsedTime.hour = parseInt(_ellapsedTime.ms / (1000 * 60 * 60)) % 60;
|
||||
|
||||
}
|
||||
|
||||
this.getCircles = function(){
|
||||
@ -400,32 +412,32 @@ function Game(controller, selectedSong, songData){
|
||||
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;
|
||||
}
|
||||
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;
|
||||
_globalScore.points+=score;
|
||||
|
||||
}
|
||||
|
||||
|
@ -65,14 +65,21 @@ function Keyboard(controller){
|
||||
}
|
||||
|
||||
this.checkMenuKeys = function(){
|
||||
_gamepad.play(1)
|
||||
_this.checkKey(_kbd["back"], "menu", function(){
|
||||
controller.togglePause();
|
||||
controller.songSelection();
|
||||
})
|
||||
_this.checkKey(_kbd["pause"], "menu", function(){
|
||||
controller.togglePauseMenu();
|
||||
})
|
||||
if(!controller.multiplayer){
|
||||
_gamepad.play(1)
|
||||
_this.checkKey(_kbd["pause"], "menu", function(){
|
||||
controller.togglePauseMenu();
|
||||
})
|
||||
}
|
||||
if(controller.multiplayer != 2){
|
||||
_this.checkKey(_kbd["back"], "menu", function(){
|
||||
if(controller.multiplayer == 1){
|
||||
p2.send("gameend")
|
||||
}
|
||||
controller.togglePause();
|
||||
controller.songSelection();
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
this.checkKey = function(keyCode, keyup, callback){
|
||||
@ -85,7 +92,7 @@ function Keyboard(controller){
|
||||
this.checkKeySound = function(keyCode, sound){
|
||||
_this.checkKey(keyCode, "sound", function(){
|
||||
assets.sounds["note_"+sound].play()
|
||||
_keyTime[sound] = controller.getEllapsedTime().ms
|
||||
_keyTime[sound] = controller.getElapsedTime().ms
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -51,6 +51,8 @@ class Loader{
|
||||
}))
|
||||
})
|
||||
|
||||
p2 = new P2Connection()
|
||||
|
||||
this.promises.push(ajax("/api/songs").then(songs => {
|
||||
assets.songs = JSON.parse(songs)
|
||||
}))
|
||||
@ -100,4 +102,5 @@ function promiseLoad(asset){
|
||||
}
|
||||
|
||||
var snd = {}
|
||||
var p2
|
||||
new Loader()
|
||||
|
@ -1,7 +1,9 @@
|
||||
class loadSong{
|
||||
constructor(selectedSong, autoPlayEnabled){
|
||||
constructor(selectedSong, autoPlayEnabled, multiplayer){
|
||||
this.selectedSong = selectedSong
|
||||
this.multiplayer = multiplayer
|
||||
this.autoPlayEnabled = autoPlayEnabled
|
||||
this.diff = this.selectedSong.difficulty.slice(0, -4)
|
||||
this.songFilePath = "/songs/" + this.selectedSong.folder + "/" + this.selectedSong.difficulty
|
||||
$("#screen").load("/src/views/loadsong.html", () => {
|
||||
this.run()
|
||||
@ -42,11 +44,46 @@ class loadSong{
|
||||
|
||||
Promise.all(promises).then(() => {
|
||||
$("#screen").load("/src/views/game.html", () => {
|
||||
var taikoGame = new Controller(this.selectedSong, this.songData, this.autoPlayEnabled)
|
||||
taikoGame.run()
|
||||
this.setupMultiplayer()
|
||||
})
|
||||
}, () => {
|
||||
}, error => {
|
||||
console.error(error)
|
||||
alert("An error occurred, please refresh")
|
||||
})
|
||||
}
|
||||
}
|
||||
setupMultiplayer(){
|
||||
if(this.multiplayer){
|
||||
this.song2Data = this.songData
|
||||
this.selectedSong2 = this.selectedSong
|
||||
p2.onmessage("gamestart", () => {
|
||||
var taikoGame1 = new Controller(this.selectedSong, this.songData, false, 1)
|
||||
var taikoGame2 = new Controller(this.selectedSong2, this.song2Data, true, 2)
|
||||
taikoGame1.run(taikoGame2)
|
||||
}, true)
|
||||
p2.onmessage("gameload", response => {
|
||||
if(response == this.diff){
|
||||
p2.send("gamestart")
|
||||
}else{
|
||||
this.selectedSong2 = {
|
||||
title: this.selectedSong.title,
|
||||
folder: this.selectedSong.folder,
|
||||
difficulty: response + ".osu"
|
||||
}
|
||||
ajax("/songs/" + this.selectedSong2.folder + "/" + this.selectedSong2.difficulty).then(data => {
|
||||
this.song2Data = data.replace(/\0/g, "").split("\n")
|
||||
p2.send("gamestart")
|
||||
}, () => {
|
||||
p2.send("gamestart")
|
||||
})
|
||||
}
|
||||
}, true)
|
||||
p2.send("join", {
|
||||
id: this.selectedSong.folder,
|
||||
diff: this.diff
|
||||
})
|
||||
}else{
|
||||
var taikoGame = new Controller(this.selectedSong, this.songData, this.autoPlayEnabled)
|
||||
taikoGame.run()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -7,27 +7,56 @@ class Mekadon{
|
||||
}
|
||||
play(circle){
|
||||
if(circle.getStatus() == 450){
|
||||
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
|
||||
}
|
||||
var score = this.game.checkScore(circle);
|
||||
circle.played(score);
|
||||
this.game.updateCurrentCircle();
|
||||
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){
|
||||
circle.updateStatus(-1)
|
||||
circle.played(0)
|
||||
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]){
|
||||
|
132
public/src/js/p2.js
Normal file
132
public/src/js/p2.js
Normal file
@ -0,0 +1,132 @@
|
||||
class P2Connection{
|
||||
constructor(){
|
||||
this.closed = true
|
||||
this.lastMessages = {}
|
||||
this.msgCallbacks = {}
|
||||
this.closeCallbacks = new Set()
|
||||
this.openCallbacks = new Set()
|
||||
this.notes = []
|
||||
this.otherConnected = false
|
||||
this.onmessage("gamestart", () => {
|
||||
this.otherConnected = true
|
||||
this.notes = []
|
||||
})
|
||||
this.onmessage("gameend", () => {
|
||||
this.otherConnected = false
|
||||
})
|
||||
this.onmessage("note", response => {
|
||||
this.notes.push(response)
|
||||
})
|
||||
}
|
||||
open(){
|
||||
this.closed = false
|
||||
var wsProtocol = location.protocol == "https:" ? "wss:" : "ws:"
|
||||
this.socket = new WebSocket(wsProtocol + "//" + window.location.hostname + "/p2")
|
||||
var events = ["open", "close", "message"]
|
||||
events.forEach(eventName => {
|
||||
this.socket.addEventListener(eventName, event => {
|
||||
this[eventName + "Event"](event)
|
||||
})
|
||||
})
|
||||
}
|
||||
openEvent(event){
|
||||
this.openCallbacks.forEach(obj => {
|
||||
obj.callback()
|
||||
if(obj.once){
|
||||
this.openCallbacks.delete(obj)
|
||||
}
|
||||
})
|
||||
}
|
||||
onopen(callback, once){
|
||||
this.openCallbacks.add({
|
||||
callback: callback,
|
||||
once: once
|
||||
})
|
||||
}
|
||||
close(){
|
||||
this.closed = true
|
||||
this.socket.close()
|
||||
}
|
||||
closeEvent(event){
|
||||
if(!this.closed){
|
||||
setTimeout(() => {
|
||||
if(this.socket.readyState != this.socket.OPEN){
|
||||
this.open()
|
||||
}
|
||||
}, 500)
|
||||
}
|
||||
this.closeCallbacks.forEach(obj => {
|
||||
obj.callback()
|
||||
if(obj.once){
|
||||
this.closeCallbacks.delete(obj)
|
||||
}
|
||||
})
|
||||
}
|
||||
onclose(callback, once){
|
||||
this.closeCallbacks.add({
|
||||
callback: callback,
|
||||
once: once
|
||||
})
|
||||
}
|
||||
send(type, value){
|
||||
if(this.socket.readyState == this.socket.OPEN){
|
||||
if(typeof value == "undefined"){
|
||||
this.socket.send(JSON.stringify({type: type}))
|
||||
}else{
|
||||
this.socket.send(JSON.stringify({type: type, value: value}))
|
||||
}
|
||||
}else{
|
||||
this.onopen(() => {
|
||||
this.send(type, value)
|
||||
}, true)
|
||||
}
|
||||
}
|
||||
messageEvent(event){
|
||||
try{
|
||||
var data = JSON.parse(event.data)
|
||||
}catch(e){
|
||||
var data = {}
|
||||
}
|
||||
this.lastMessages[data.type] = data.value
|
||||
if(this.msgCallbacks[data.type]){
|
||||
this.msgCallbacks[data.type].forEach(obj => {
|
||||
obj.callback(data.value)
|
||||
if(obj.once){
|
||||
delete this.msgCallbacks[obj]
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
onmessage(type, callback, once){
|
||||
if(!(type in this.msgCallbacks)){
|
||||
this.msgCallbacks[type] = new Set()
|
||||
}
|
||||
this.msgCallbacks[type].add({
|
||||
callback: callback,
|
||||
once: once
|
||||
})
|
||||
}
|
||||
getMessage(type, callback){
|
||||
if(type in this.lastMessages){
|
||||
callback(this.lastMessages[type])
|
||||
}
|
||||
}
|
||||
play(circle, mekadon){
|
||||
if(this.otherConnected){
|
||||
if(this.notes.length == 0){
|
||||
mekadon.play(circle)
|
||||
}else{
|
||||
var note = this.notes[0]
|
||||
if(note.score >= 0){
|
||||
if(mekadon.playAt(circle, note.ms, note.score)){
|
||||
this.notes.shift()
|
||||
}
|
||||
}else{
|
||||
if(mekadon.miss(circle)){
|
||||
this.notes.shift()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -56,6 +56,7 @@ function SongSelect(){
|
||||
|
||||
this.run = function(){
|
||||
_this.createCode();
|
||||
_this.startP2();
|
||||
|
||||
$("#song-container").show();
|
||||
|
||||
@ -84,7 +85,7 @@ function SongSelect(){
|
||||
_selectedSong.folder = songID;
|
||||
|
||||
snd.musicGain.fadeIn()
|
||||
new loadSong(_selectedSong, e.shiftKey);
|
||||
new loadSong(_selectedSong, e.shiftKey, e.ctrlKey);
|
||||
});
|
||||
|
||||
$(".song").hover(function(){
|
||||
@ -236,6 +237,41 @@ function SongSelect(){
|
||||
$('.difficulty').hide();
|
||||
}
|
||||
|
||||
this.onusers = function(response){
|
||||
var oldP2Elements = document.getElementsByClassName("p2")
|
||||
for(var i = oldP2Elements.length; i--;){
|
||||
oldP2Elements[i].classList.remove("p2")
|
||||
}
|
||||
if(response){
|
||||
response.forEach(idDiff => {
|
||||
id = idDiff.id |0
|
||||
diff = idDiff.diff
|
||||
if(diff in _diffNames){
|
||||
var idElement = document.getElementById("song-" + id)
|
||||
if(idElement){
|
||||
idElement.classList.add("p2")
|
||||
var diffElement = idElement.getElementsByClassName("difficulty " + diff)[0]
|
||||
if(diffElement){
|
||||
diffElement.classList.add("p2")
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
this.startP2 = function(){
|
||||
p2.getMessage("users", response =>{
|
||||
this.onusers(response)
|
||||
})
|
||||
p2.onmessage("users", response => {
|
||||
this.onusers(response)
|
||||
})
|
||||
if(p2.closed){
|
||||
p2.open()
|
||||
}
|
||||
}
|
||||
|
||||
$("#screen").load("/src/views/songselect.html", _this.run);
|
||||
|
||||
}
|
@ -4,7 +4,14 @@ class View{
|
||||
this.bg = bg
|
||||
this.diff = diff
|
||||
|
||||
this.canvas = new ScalableCanvas("canvas", $(window).width(), $(window).height())
|
||||
if(this.controller.multiplayer == 2){
|
||||
this.canvas = new ScalableCanvas("canvas-p2", $(window).width(), $(window).height() / 3 * 2)
|
||||
this.canvas.canvas.style.position = "absolute"
|
||||
this.canvas.canvas.style.top = "33%"
|
||||
document.getElementById("game").appendChild(this.canvas.canvas)
|
||||
}else{
|
||||
this.canvas = new ScalableCanvas("canvas", $(window).width(), $(window).height())
|
||||
}
|
||||
this.winW = this.canvas.scaledWidth
|
||||
this.winH = this.canvas.scaledHeight
|
||||
this.ctx = this.canvas.ctx
|
||||
@ -50,9 +57,16 @@ class View{
|
||||
|
||||
positionning(){
|
||||
this.canvas.rescale()
|
||||
this.canvas.resize($(window).width(), $(window).height())
|
||||
var height = $(window).height()
|
||||
if(this.controller.multiplayer == 2){
|
||||
height = height / 3 * 2
|
||||
}
|
||||
this.canvas.resize($(window).width(), height)
|
||||
this.winW = this.canvas.scaledWidth
|
||||
this.winH = this.canvas.scaledHeight
|
||||
if(this.controller.multiplayer == 2){
|
||||
this.winH = this.winH / 2 * 3
|
||||
}
|
||||
|
||||
this.barY = 0.25 * this.winH
|
||||
this.barH = 0.23 * this.winH
|
||||
@ -113,7 +127,7 @@ class View{
|
||||
}
|
||||
|
||||
updateDonFaces(){
|
||||
if(this.controller.getEllapsedTime().ms >= this.nextBeat){
|
||||
if(this.controller.getElapsedTime().ms >= this.nextBeat){
|
||||
this.nextBeat += this.controller.getSongData().beatInfo.beatInterval
|
||||
if(this.controller.getCombo() >= 50){
|
||||
this.currentBigDonFace = (this.currentBigDonFace + 1) % 2
|
||||
@ -190,7 +204,7 @@ class View{
|
||||
|
||||
drawMeasures(){
|
||||
var measures = this.controller.getSongData().measures
|
||||
var currentTime = this.controller.getEllapsedTime().ms
|
||||
var currentTime = this.controller.getElapsedTime().ms
|
||||
|
||||
measures.forEach((measure, index)=>{
|
||||
var timeForDistance = 70 / this.circleSize * this.distanceForCircle / measure.speed
|
||||
@ -206,7 +220,7 @@ class View{
|
||||
|
||||
drawMeasure(measure){
|
||||
var z = this.canvas.scale
|
||||
var currentTime = this.controller.getEllapsedTime().ms
|
||||
var currentTime = this.controller.getElapsedTime().ms
|
||||
var measureX = this.slotX + measure.speed / (70 / this.circleSize) * (measure.ms - currentTime)
|
||||
this.ctx.strokeStyle = "#bab8b8"
|
||||
this.ctx.lineWidth = 2
|
||||
@ -388,7 +402,7 @@ class View{
|
||||
for(var i = circles.length; i--;){
|
||||
var circle = circles[i]
|
||||
|
||||
var currentTime = this.controller.getEllapsedTime().ms
|
||||
var currentTime = this.controller.getElapsedTime().ms
|
||||
var timeForDistance = 70 / this.circleSize * this.distanceForCircle / circle.getSpeed() + this.bigCircleSize / 2
|
||||
var startingTime = circle.getMS() - timeForDistance
|
||||
// At circle.getMS(), the cirlce fits the slot
|
||||
@ -459,7 +473,7 @@ class View{
|
||||
|
||||
var fill, size, faceID
|
||||
if(!circlePos){
|
||||
var currentTime = this.controller.getEllapsedTime().ms
|
||||
var currentTime = this.controller.getElapsedTime().ms
|
||||
circlePos = {
|
||||
x: this.slotX + circle.getSpeed() / (70 / this.circleSize) * (circle.getMS() - currentTime),
|
||||
y: this.circleY
|
||||
@ -549,7 +563,7 @@ class View{
|
||||
|
||||
drawTime(){
|
||||
var z = this.canvas.scale
|
||||
var time = this.controller.getEllapsedTime()
|
||||
var time = this.controller.getElapsedTime()
|
||||
|
||||
this.ctx.globalAlpha = 0.7
|
||||
this.ctx.fillStyle = "#000"
|
||||
@ -579,7 +593,7 @@ class View{
|
||||
this.ctx.closePath()
|
||||
this.ctx.fill()
|
||||
|
||||
var currentTime = this.controller.getEllapsedTime().ms
|
||||
var currentTime = this.controller.getElapsedTime().ms
|
||||
var keyTime = this.controller.getKeyTime()
|
||||
var sound = keyTime["don"] > keyTime["ka"] ? "don" : "ka"
|
||||
if(keyTime[sound] > currentTime - 200){
|
||||
|
168
server.py
Normal file
168
server.py
Normal file
@ -0,0 +1,168 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
import asyncio
|
||||
import websockets
|
||||
import json
|
||||
|
||||
users = []
|
||||
server_status = {
|
||||
"waiting": {}
|
||||
}
|
||||
|
||||
def msgobj(type, value=None):
|
||||
if value == None:
|
||||
return json.dumps({"type": type})
|
||||
else:
|
||||
return json.dumps({"type": type, "value": value})
|
||||
|
||||
def status_event():
|
||||
value = []
|
||||
for id, userDiff in server_status["waiting"].items():
|
||||
value.append({
|
||||
"id": id,
|
||||
"diff": userDiff["diff"]
|
||||
})
|
||||
return msgobj("users", value)
|
||||
|
||||
async def notify_status():
|
||||
ready_users = [user for user in 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])
|
||||
|
||||
async def connection(ws, path):
|
||||
# User connected
|
||||
user = {
|
||||
"ws": ws,
|
||||
"action": "ready"
|
||||
}
|
||||
users.append(user)
|
||||
try:
|
||||
# Notify user about other users
|
||||
await ws.send(status_event())
|
||||
while True:
|
||||
try:
|
||||
message = await asyncio.wait_for(ws.recv(), timeout=5)
|
||||
except asyncio.TimeoutError:
|
||||
# Keep user connected
|
||||
pong_waiter = await ws.ping()
|
||||
try:
|
||||
await asyncio.wait_for(pong_waiter, timeout=5)
|
||||
except asyncio.TimeoutError:
|
||||
# Disconnect
|
||||
break
|
||||
else:
|
||||
# Message received
|
||||
try:
|
||||
data = json.loads(message)
|
||||
except json.decoder.JSONDecodeError:
|
||||
data = {}
|
||||
action = user["action"]
|
||||
type = data["type"] if "type" in data else None
|
||||
value = data["value"] if "value" in data else None
|
||||
if action == "ready":
|
||||
# Not playing or waiting
|
||||
if type == "join":
|
||||
waiting = server_status["waiting"]
|
||||
id = value["id"] if "id" in value else None
|
||||
diff = value["diff"] if "diff" in value else None
|
||||
if not id or not diff:
|
||||
continue
|
||||
if id not in waiting:
|
||||
# Wait for another user
|
||||
user["action"] = "waiting"
|
||||
user["gameid"] = id
|
||||
waiting[id] = {
|
||||
"user": user,
|
||||
"diff": diff
|
||||
}
|
||||
await ws.send(msgobj("waiting"))
|
||||
else:
|
||||
# Join the other user and start game
|
||||
user["other_user"] = waiting[id]["user"]
|
||||
waiting_diff = waiting[id]["diff"]
|
||||
del waiting[id]
|
||||
if "ws" in user["other_user"]:
|
||||
user["action"] = "loading"
|
||||
user["other_user"]["action"] = "loading"
|
||||
user["other_user"]["other_user"] = user
|
||||
await asyncio.wait([
|
||||
ws.send(msgobj("gameload", waiting_diff)),
|
||||
user["other_user"]["ws"].send(msgobj("gameload", diff))
|
||||
])
|
||||
else:
|
||||
# Wait for another user
|
||||
user["action"] = "waiting"
|
||||
user["gameid"] = id
|
||||
waiting[id] = {
|
||||
"user": user,
|
||||
"diff": diff
|
||||
}
|
||||
await ws.send(msgobj("waiting"))
|
||||
# Update others on waiting players
|
||||
await notify_status()
|
||||
elif action == "waiting" or action == "loading" or action == "loaded":
|
||||
# Waiting for another user
|
||||
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 action == "loading":
|
||||
if type == "gamestart":
|
||||
user["action"] = "loaded"
|
||||
if user["other_user"]["action"] == "loaded":
|
||||
user["action"] = "playing"
|
||||
user["other_user"]["action"] = "playing"
|
||||
sent_msg = msgobj("gamestart")
|
||||
await asyncio.wait([
|
||||
ws.send(sent_msg),
|
||||
user["other_user"]["ws"].send(sent_msg)
|
||||
])
|
||||
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 == "gameend":
|
||||
# User wants to disconnect
|
||||
user["action"] = "ready"
|
||||
user["other_user"]["action"] = "ready"
|
||||
sent_msg1 = msgobj("gameend")
|
||||
sent_msg2 = status_event()
|
||||
await asyncio.wait([
|
||||
ws.send(sent_msg1),
|
||||
ws.send(sent_msg2),
|
||||
user["other_user"]["ws"].send(sent_msg1),
|
||||
user["other_user"]["ws"].send(sent_msg2)
|
||||
])
|
||||
del user["other_user"]
|
||||
else:
|
||||
# Other user disconnected
|
||||
user["action"] = "ready"
|
||||
await asyncio.wait([
|
||||
ws.send(msgobj("gameend")),
|
||||
ws.send(status_event())
|
||||
])
|
||||
finally:
|
||||
# User disconnected
|
||||
del user["ws"]
|
||||
del users[users.index(user)]
|
||||
if "other_user" in user and "ws" in user["other_user"]:
|
||||
user["other_user"]["action"] = "ready"
|
||||
await asyncio.wait([
|
||||
user["other_user"]["ws"].send(msgobj("gameend")),
|
||||
user["other_user"]["ws"].send(status_event())
|
||||
])
|
||||
if user["action"] == "waiting":
|
||||
del server_status["waiting"][user["gameid"]]
|
||||
await notify_status()
|
||||
|
||||
asyncio.get_event_loop().run_until_complete(
|
||||
websockets.serve(connection, "localhost", 34802)
|
||||
)
|
||||
asyncio.get_event_loop().run_forever()
|
Loading…
Reference in New Issue
Block a user