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/scalablecanvas.js"></script>
|
||||||
<script src="/src/js/element.js"></script>
|
<script src="/src/js/element.js"></script>
|
||||||
<script src="/src/js/soundbuffer.js"></script>
|
<script src="/src/js/soundbuffer.js"></script>
|
||||||
|
<script src="/src/js/p2.js"></script>
|
||||||
|
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
|
@ -75,6 +75,7 @@ ul li{
|
|||||||
box-shadow: 2px 2px 10px black;
|
box-shadow: 2px 2px 10px black;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
|
position: relative;
|
||||||
}
|
}
|
||||||
|
|
||||||
.opened{
|
.opened{
|
||||||
@ -127,3 +128,12 @@ ul li{
|
|||||||
.difficulty:hover .stars{
|
.difficulty:hover .stars{
|
||||||
color:white;
|
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/" + this.selectedSong.folder + "/bg.png"
|
||||||
var _backgroundURL = "/songs/"+selectedSong.folder+"/bg.png";
|
var songParser = new ParseSong(songData)
|
||||||
|
this.parsedSongData = songParser.getData()
|
||||||
|
|
||||||
var _songParser = new ParseSong(songData); //get file content
|
assets.songs.forEach(song => {
|
||||||
var _songData = _songParser.getData();
|
if(song.id == this.selectedSong.folder){
|
||||||
|
this.mainAsset = song.sound
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
var _game = new Game(this, selectedSong, _songData);
|
this.game = new Game(this, this.selectedSong, this.parsedSongData)
|
||||||
var _view = new View(this, _backgroundURL, selectedSong.title, selectedSong.difficulty);
|
this.view = new View(this, backgroundURL, this.selectedSong.title, this.selectedSong.difficulty)
|
||||||
var _mekadon = new Mekadon(this, _game);
|
this.mekadon = new Mekadon(this, this.game)
|
||||||
var _keyboard = new Keyboard(this);
|
this.keyboard = new Keyboard(this)
|
||||||
var _mainLoop;
|
}
|
||||||
var _pauseMenu = false;
|
run(syncWith){
|
||||||
var _mainAsset
|
this.loadUIEvents()
|
||||||
assets.songs.forEach(song => {
|
this.game.run()
|
||||||
if(song.id == selectedSong.folder){
|
this.view.run()
|
||||||
_mainAsset = song.sound
|
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();
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
loadUIEvents(){
|
||||||
this.startMainLoop = function(){
|
$("#song-selection-butt").click(() => {
|
||||||
|
assets.sounds["don"].play()
|
||||||
var started=false;
|
this.songSelection()
|
||||||
_mainLoop = setInterval(function(){
|
})
|
||||||
|
$("#restart-butt").click(() => {
|
||||||
var ms = _game.getEllapsedTime().ms;
|
assets.sounds["don"].play()
|
||||||
if(ms<0){ //before starting game, offseting the circles
|
this.restartSong()
|
||||||
_game.updateTime();
|
})
|
||||||
_view.refresh();
|
$("#continue-butt").click(() => {
|
||||||
}
|
this.togglePauseMenu()
|
||||||
else if(ms>=0 && !started){ //when music shall starts
|
})
|
||||||
_mainAsset.play(_songData.generalInfo.audioWait)
|
}
|
||||||
started=true;
|
startMainLoop(){
|
||||||
}
|
this.mainLoopStarted = false
|
||||||
|
this.mainLoopRunning = true
|
||||||
if(started){ //Game start here
|
this.mainLoop()
|
||||||
if(!_game.isPaused()){
|
}
|
||||||
_game.update();
|
mainLoop(){
|
||||||
_view.refresh();
|
if(this.mainLoopRunning){
|
||||||
_keyboard.checkGameKeys();
|
if(this.multiplayer != 2){
|
||||||
}
|
requestAnimationFrame(() => {
|
||||||
_keyboard.checkMenuKeys();
|
if(this.syncWith){
|
||||||
}
|
this.syncWith.game.elapsedTime.ms = this.game.elapsedTime.ms
|
||||||
|
}
|
||||||
}, 20);
|
this.mainLoop()
|
||||||
|
if(this.syncWith){
|
||||||
}
|
this.syncWith.mainLoop()
|
||||||
|
}
|
||||||
this.getDistanceForCircle = function(){
|
})
|
||||||
return _view.getDistanceForCircle();
|
}
|
||||||
|
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 _this = this;
|
||||||
var _selectedSong = selectedSong;
|
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 _offsetDate; //date when the chrono is started (before the game begins)
|
||||||
var _startDate; //real start date (when the chrono will be 0)
|
var _startDate; //real start date (when the chrono will be 0)
|
||||||
var _currentDate; // refreshed date
|
var _currentDate; // refreshed date
|
||||||
@ -14,60 +14,53 @@ function Game(controller, selectedSong, songData){
|
|||||||
var _HPGain= 100/_songData.circles.length;
|
var _HPGain= 100/_songData.circles.length;
|
||||||
var _paused=false;
|
var _paused=false;
|
||||||
var _started=false;
|
var _started=false;
|
||||||
var _mainMusicPlaying=true;
|
var _mainMusicPlaying=false;
|
||||||
var _latestDate;
|
var _latestDate;
|
||||||
var _ellapsedTimeSincePause=0;
|
var _elapsedTimeSincePause=0;
|
||||||
var _musicFadeOut=0;
|
var _musicFadeOut=0;
|
||||||
var _fadeOutStarted=false;
|
var _fadeOutStarted=false;
|
||||||
var _currentTimingPoint=0;
|
var _currentTimingPoint=0;
|
||||||
var _offsetTime=0;
|
var _offsetTime=0;
|
||||||
var _hitcircleSpeed=_songData.difficulty.sliderMultiplier*8;
|
var _hitcircleSpeed=_songData.difficulty.sliderMultiplier*8;
|
||||||
var _timeForDistanceCircle;
|
var _timeForDistanceCircle;
|
||||||
var _mainAsset
|
var _mainAsset
|
||||||
assets.songs.forEach(song => {
|
assets.songs.forEach(song => {
|
||||||
if(song.id == selectedSong.folder){
|
if(song.id == selectedSong.folder){
|
||||||
_mainAsset = song.sound
|
_mainAsset = song.sound
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
this.run = function(){
|
this.run = function(){
|
||||||
_timeForDistanceCircle=((20*controller.getDistanceForCircle())/_hitcircleSpeed);
|
_timeForDistanceCircle=2500
|
||||||
_this.initTiming();
|
_this.initTiming();
|
||||||
}
|
}
|
||||||
|
|
||||||
this.initTiming = function(){
|
this.initTiming = function(){
|
||||||
|
|
||||||
_offsetDate = new Date();
|
_offsetDate = new Date();
|
||||||
|
_this.setElapsedTime(-_timeForDistanceCircle |0)
|
||||||
_ellapsedTime = {
|
_offsetTime = _timeForDistanceCircle |0
|
||||||
ms:-parseInt(_timeForDistanceCircle),
|
|
||||||
sec:0,
|
|
||||||
min:0,
|
|
||||||
hour:0
|
|
||||||
}
|
|
||||||
_offsetTime = parseInt(_timeForDistanceCircle);
|
|
||||||
_startDate = new Date();
|
_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(){
|
this.update = function(){
|
||||||
|
|
||||||
/* Main operations */
|
// Main operations
|
||||||
_this.updateTime();
|
_this.updateTime();
|
||||||
_this.checkTiming();
|
_this.checkTiming();
|
||||||
_this.updateCirclesStatus();
|
_this.updateCirclesStatus();
|
||||||
_this.checkPlays();
|
_this.checkPlays();
|
||||||
|
|
||||||
/* Event operations */
|
// Event operations
|
||||||
_this.whenFadeoutMusic();
|
_this.whenFadeoutMusic();
|
||||||
_this.whenLastCirclePlayed();
|
_this.whenLastCirclePlayed();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
this.getCircles = function(){
|
this.getCircles = function(){
|
||||||
return _songData.circles;
|
return _songData.circles;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.updateCirclesStatus = function(){
|
this.updateCirclesStatus = function(){
|
||||||
|
|
||||||
@ -77,13 +70,14 @@ function Game(controller, selectedSong, songData){
|
|||||||
|
|
||||||
if(!circle.getPlayed()){
|
if(!circle.getPlayed()){
|
||||||
|
|
||||||
var currentTime = _ellapsedTime.ms;
|
var currentTime = _this.getElapsedTime().ms;
|
||||||
var startingTime = circle.getMS()-_timeForDistanceCircle;
|
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 >= startingTime && currentTime <= finishTime+200){
|
||||||
|
|
||||||
if(currentTime>= finishTime-50 && currentTime < finishTime-30){
|
if(currentTime>= finishTime-50 && currentTime < finishTime-30){
|
||||||
circle.updateStatus(0);
|
circle.updateStatus(0);
|
||||||
}
|
}
|
||||||
else if(currentTime>= finishTime-30 && currentTime < finishTime){
|
else if(currentTime>= finishTime-30 && currentTime < finishTime){
|
||||||
@ -95,14 +89,20 @@ function Game(controller, selectedSong, songData){
|
|||||||
|
|
||||||
}
|
}
|
||||||
else if(currentTime>finishTime+200 && currentTime<=finishTime+300){
|
else if(currentTime>finishTime+200 && currentTime<=finishTime+300){
|
||||||
|
if(controller.multiplayer != 2){
|
||||||
circle.updateStatus(-1);
|
circle.updateStatus(-1);
|
||||||
_currentScore=0;
|
_currentScore=0;
|
||||||
circle.played(_currentScore);
|
circle.played(_currentScore);
|
||||||
controller.displayScore(_currentScore, true);
|
controller.displayScore(_currentScore, true);
|
||||||
_this.updateCurrentCircle();
|
_this.updateCurrentCircle();
|
||||||
_this.updateCombo(_currentScore);
|
_this.updateCombo(_currentScore);
|
||||||
_this.updateGlobalScore(_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);
|
circle.played(score);
|
||||||
_this.updateCurrentCircle();
|
_this.updateCurrentCircle();
|
||||||
controller.waitForKeyup(keyCode, "score");
|
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;
|
break;
|
||||||
|
|
||||||
}
|
}
|
||||||
controller.displayScore(_currentScore);
|
controller.displayScore(_currentScore);
|
||||||
|
|
||||||
}
|
}
|
||||||
else{
|
else{
|
||||||
_currentScore=0;
|
_currentScore=0;
|
||||||
controller.displayScore(_currentScore, true);
|
controller.displayScore(_currentScore, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
_this.updateCombo(_currentScore);
|
_this.updateCombo(_currentScore);
|
||||||
_this.updateGlobalScore(_currentScore);
|
_this.updateGlobalScore(_currentScore);
|
||||||
return _currentScore;
|
return _currentScore;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.whenLastCirclePlayed = function(){
|
this.whenLastCirclePlayed = function(){
|
||||||
var circles = _songData.circles;
|
var circles = _songData.circles;
|
||||||
var lastCircle = circles[_songData.circles.length-1];
|
var lastCircle = circles[_songData.circles.length-1];
|
||||||
if(!_fadeOutStarted && _ellapsedTime.ms>=lastCircle.getMS()+2000){
|
if(!_fadeOutStarted && _this.getElapsedTime().ms>=lastCircle.getMS()+2000){
|
||||||
_fadeOutStarted=_ellapsedTime.ms
|
_fadeOutStarted=_this.getElapsedTime().ms
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -199,23 +205,27 @@ function Game(controller, selectedSong, songData){
|
|||||||
if(_fadeOutStarted){
|
if(_fadeOutStarted){
|
||||||
if(_musicFadeOut==0){
|
if(_musicFadeOut==0){
|
||||||
snd.musicGain.fadeOut(1.6)
|
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()
|
controller.fadeOutOver()
|
||||||
_mainAsset.stop()
|
_mainAsset.stop()
|
||||||
|
_musicFadeOut++
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
snd.musicGain.fadeIn()
|
snd.musicGain.fadeIn()
|
||||||
snd.musicGain.unmute()
|
snd.musicGain.unmute()
|
||||||
}, 1000)
|
}, 1000)
|
||||||
}
|
}
|
||||||
_musicFadeOut++;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
this.checkTiming = function(){
|
this.checkTiming = function(){
|
||||||
|
|
||||||
if(_songData.timingPoints[_currentTimingPoint+1]){
|
if(_songData.timingPoints[_currentTimingPoint+1]){
|
||||||
if(_this.getEllapsedTime().ms>=_songData.timingPoints[_currentTimingPoint+1].start){
|
if(_this.getElapsedTime().ms>=_songData.timingPoints[_currentTimingPoint+1].start){
|
||||||
_currentTimingPoint++;
|
_currentTimingPoint++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -225,19 +235,18 @@ function Game(controller, selectedSong, songData){
|
|||||||
return _songData.timingPoints[_currentTimingPoint];
|
return _songData.timingPoints[_currentTimingPoint];
|
||||||
}
|
}
|
||||||
|
|
||||||
this.toggleMainMusic = function(){
|
this.playMainMusic = function(){
|
||||||
if(_mainMusicPlaying){
|
var ms = _this.getElapsedTime().ms
|
||||||
_mainAsset.stop();
|
if(!_mainMusicPlaying && (!_fadeOutStarted || ms<_fadeOutStarted+1600)){
|
||||||
_mainMusicPlaying=false;
|
if(controller.multiplayer != 2){
|
||||||
}
|
_mainAsset.play((ms < 0 ? -ms : 0) / 1000, false, Math.max(0, ms / 1000));
|
||||||
else{
|
}
|
||||||
_mainAsset.play(0, false, _this.getEllapsedTime().ms / 1000);
|
|
||||||
_mainMusicPlaying=true;
|
_mainMusicPlaying=true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
this.fadeOutOver = function(){
|
this.fadeOutOver = function(){
|
||||||
_fadeOutStarted=false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
this.getHitcircleSpeed = function(){
|
this.getHitcircleSpeed = function(){
|
||||||
@ -249,15 +258,15 @@ function Game(controller, selectedSong, songData){
|
|||||||
assets.sounds["pause"].play();
|
assets.sounds["pause"].play();
|
||||||
_paused=true;
|
_paused=true;
|
||||||
_latestDate = new Date();
|
_latestDate = new Date();
|
||||||
_this.toggleMainMusic();
|
_mainAsset.stop();
|
||||||
|
_mainMusicPlaying=false;
|
||||||
|
|
||||||
}
|
}
|
||||||
else{
|
else{
|
||||||
assets.sounds["cancel"].play();
|
assets.sounds["cancel"].play();
|
||||||
_paused=false;
|
_paused=false;
|
||||||
var currentDate = new Date();
|
var currentDate = new Date();
|
||||||
_ellapsedTimeSincePause = _ellapsedTimeSincePause + Math.abs(currentDate.getTime() - _latestDate.getTime());
|
_elapsedTimeSincePause = _elapsedTimeSincePause + currentDate.getTime() - _latestDate.getTime();
|
||||||
_this.toggleMainMusic();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -265,30 +274,33 @@ function Game(controller, selectedSong, songData){
|
|||||||
return _paused;
|
return _paused;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.getEllapsedTime = function(){
|
this.getElapsedTime = function(){
|
||||||
return _ellapsedTime;
|
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(){
|
this.updateTime = function(){
|
||||||
|
|
||||||
_currentDate = new Date();
|
_currentDate = new Date();
|
||||||
|
var time = _this.getElapsedTime()
|
||||||
|
|
||||||
if(_ellapsedTime.ms<0){
|
if(time.ms<0){
|
||||||
_ellapsedTime.ms = _currentDate.getTime() - _startDate.getTime();
|
_this.setElapsedTime(_currentDate.getTime() - _startDate.getTime() - _elapsedTimeSincePause)
|
||||||
}
|
}
|
||||||
else if(_ellapsedTime.ms>=0 && !_started){
|
else if(time.ms>=0 && !_started){
|
||||||
_startDate = new Date();
|
_startDate = new Date();
|
||||||
_ellapsedTime.ms = Math.abs(_startDate.getTime() - _currentDate.getTime());
|
_elapsedTimeSincePause = 0;
|
||||||
|
_this.setElapsedTime(_currentDate.getTime() - _startDate.getTime())
|
||||||
_started=true;
|
_started=true;
|
||||||
}
|
}
|
||||||
else if(_ellapsedTime.ms>=0 && _started){
|
else if(time.ms>=0 && _started){
|
||||||
_ellapsedTime.ms = Math.abs(_startDate.getTime() - _currentDate.getTime()) - _ellapsedTimeSincePause;
|
_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(){
|
this.getCircles = function(){
|
||||||
@ -400,32 +412,32 @@ function Game(controller, selectedSong, songData){
|
|||||||
if(_combo>=11 && _combo<=20){
|
if(_combo>=11 && _combo<=20){
|
||||||
score+=100;
|
score+=100;
|
||||||
}
|
}
|
||||||
else if(_combo>=21 && _combo<=30){
|
else if(_combo>=21 && _combo<=30){
|
||||||
score+=200;
|
score+=200;
|
||||||
}
|
}
|
||||||
else if(_combo>=31 && _combo<=40){
|
else if(_combo>=31 && _combo<=40){
|
||||||
score+=300;
|
score+=300;
|
||||||
}
|
}
|
||||||
else if(_combo>=41 && _combo<=50){
|
else if(_combo>=41 && _combo<=50){
|
||||||
score+=400;
|
score+=400;
|
||||||
}
|
}
|
||||||
else if(_combo>=51 && _combo<=60){
|
else if(_combo>=51 && _combo<=60){
|
||||||
score+=500;
|
score+=500;
|
||||||
}
|
}
|
||||||
else if(_combo>=61 && _combo<=70){
|
else if(_combo>=61 && _combo<=70){
|
||||||
score+=500;
|
score+=500;
|
||||||
}
|
}
|
||||||
else if(_combo>=71 && _combo<=80){
|
else if(_combo>=71 && _combo<=80){
|
||||||
score+=600;
|
score+=600;
|
||||||
}
|
}
|
||||||
else if(_combo>=81 && _combo<=90){
|
else if(_combo>=81 && _combo<=90){
|
||||||
score+=700;
|
score+=700;
|
||||||
}
|
}
|
||||||
else if(_combo>=91 && _combo<=100){
|
else if(_combo>=91 && _combo<=100){
|
||||||
score+=800;
|
score+=800;
|
||||||
}
|
}
|
||||||
|
|
||||||
_globalScore.points+=score;
|
_globalScore.points+=score;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -65,14 +65,21 @@ function Keyboard(controller){
|
|||||||
}
|
}
|
||||||
|
|
||||||
this.checkMenuKeys = function(){
|
this.checkMenuKeys = function(){
|
||||||
_gamepad.play(1)
|
if(!controller.multiplayer){
|
||||||
_this.checkKey(_kbd["back"], "menu", function(){
|
_gamepad.play(1)
|
||||||
controller.togglePause();
|
_this.checkKey(_kbd["pause"], "menu", function(){
|
||||||
controller.songSelection();
|
controller.togglePauseMenu();
|
||||||
})
|
})
|
||||||
_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){
|
this.checkKey = function(keyCode, keyup, callback){
|
||||||
@ -85,7 +92,7 @@ function Keyboard(controller){
|
|||||||
this.checkKeySound = function(keyCode, sound){
|
this.checkKeySound = function(keyCode, sound){
|
||||||
_this.checkKey(keyCode, "sound", function(){
|
_this.checkKey(keyCode, "sound", function(){
|
||||||
assets.sounds["note_"+sound].play()
|
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 => {
|
this.promises.push(ajax("/api/songs").then(songs => {
|
||||||
assets.songs = JSON.parse(songs)
|
assets.songs = JSON.parse(songs)
|
||||||
}))
|
}))
|
||||||
@ -100,4 +102,5 @@ function promiseLoad(asset){
|
|||||||
}
|
}
|
||||||
|
|
||||||
var snd = {}
|
var snd = {}
|
||||||
|
var p2
|
||||||
new Loader()
|
new Loader()
|
||||||
|
@ -1,7 +1,9 @@
|
|||||||
class loadSong{
|
class loadSong{
|
||||||
constructor(selectedSong, autoPlayEnabled){
|
constructor(selectedSong, autoPlayEnabled, multiplayer){
|
||||||
this.selectedSong = selectedSong
|
this.selectedSong = selectedSong
|
||||||
|
this.multiplayer = multiplayer
|
||||||
this.autoPlayEnabled = autoPlayEnabled
|
this.autoPlayEnabled = autoPlayEnabled
|
||||||
|
this.diff = this.selectedSong.difficulty.slice(0, -4)
|
||||||
this.songFilePath = "/songs/" + this.selectedSong.folder + "/" + this.selectedSong.difficulty
|
this.songFilePath = "/songs/" + this.selectedSong.folder + "/" + this.selectedSong.difficulty
|
||||||
$("#screen").load("/src/views/loadsong.html", () => {
|
$("#screen").load("/src/views/loadsong.html", () => {
|
||||||
this.run()
|
this.run()
|
||||||
@ -42,11 +44,46 @@ class loadSong{
|
|||||||
|
|
||||||
Promise.all(promises).then(() => {
|
Promise.all(promises).then(() => {
|
||||||
$("#screen").load("/src/views/game.html", () => {
|
$("#screen").load("/src/views/game.html", () => {
|
||||||
var taikoGame = new Controller(this.selectedSong, this.songData, this.autoPlayEnabled)
|
this.setupMultiplayer()
|
||||||
taikoGame.run()
|
|
||||||
})
|
})
|
||||||
}, () => {
|
}, error => {
|
||||||
|
console.error(error)
|
||||||
alert("An error occurred, please refresh")
|
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){
|
play(circle){
|
||||||
if(circle.getStatus() == 450){
|
if(circle.getStatus() == 450){
|
||||||
var kbd = this.controller.getBindings()
|
return this.playNow(circle)
|
||||||
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();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
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){
|
setKey(keyCode){
|
||||||
var self = this
|
var self = this
|
||||||
if(this.keys[keyCode]){
|
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.run = function(){
|
||||||
_this.createCode();
|
_this.createCode();
|
||||||
|
_this.startP2();
|
||||||
|
|
||||||
$("#song-container").show();
|
$("#song-container").show();
|
||||||
|
|
||||||
@ -84,7 +85,7 @@ function SongSelect(){
|
|||||||
_selectedSong.folder = songID;
|
_selectedSong.folder = songID;
|
||||||
|
|
||||||
snd.musicGain.fadeIn()
|
snd.musicGain.fadeIn()
|
||||||
new loadSong(_selectedSong, e.shiftKey);
|
new loadSong(_selectedSong, e.shiftKey, e.ctrlKey);
|
||||||
});
|
});
|
||||||
|
|
||||||
$(".song").hover(function(){
|
$(".song").hover(function(){
|
||||||
@ -236,6 +237,41 @@ function SongSelect(){
|
|||||||
$('.difficulty').hide();
|
$('.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);
|
$("#screen").load("/src/views/songselect.html", _this.run);
|
||||||
|
|
||||||
}
|
}
|
@ -4,7 +4,14 @@ class View{
|
|||||||
this.bg = bg
|
this.bg = bg
|
||||||
this.diff = diff
|
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.winW = this.canvas.scaledWidth
|
||||||
this.winH = this.canvas.scaledHeight
|
this.winH = this.canvas.scaledHeight
|
||||||
this.ctx = this.canvas.ctx
|
this.ctx = this.canvas.ctx
|
||||||
@ -50,9 +57,16 @@ class View{
|
|||||||
|
|
||||||
positionning(){
|
positionning(){
|
||||||
this.canvas.rescale()
|
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.winW = this.canvas.scaledWidth
|
||||||
this.winH = this.canvas.scaledHeight
|
this.winH = this.canvas.scaledHeight
|
||||||
|
if(this.controller.multiplayer == 2){
|
||||||
|
this.winH = this.winH / 2 * 3
|
||||||
|
}
|
||||||
|
|
||||||
this.barY = 0.25 * this.winH
|
this.barY = 0.25 * this.winH
|
||||||
this.barH = 0.23 * this.winH
|
this.barH = 0.23 * this.winH
|
||||||
@ -113,7 +127,7 @@ class View{
|
|||||||
}
|
}
|
||||||
|
|
||||||
updateDonFaces(){
|
updateDonFaces(){
|
||||||
if(this.controller.getEllapsedTime().ms >= this.nextBeat){
|
if(this.controller.getElapsedTime().ms >= this.nextBeat){
|
||||||
this.nextBeat += this.controller.getSongData().beatInfo.beatInterval
|
this.nextBeat += this.controller.getSongData().beatInfo.beatInterval
|
||||||
if(this.controller.getCombo() >= 50){
|
if(this.controller.getCombo() >= 50){
|
||||||
this.currentBigDonFace = (this.currentBigDonFace + 1) % 2
|
this.currentBigDonFace = (this.currentBigDonFace + 1) % 2
|
||||||
@ -190,7 +204,7 @@ class View{
|
|||||||
|
|
||||||
drawMeasures(){
|
drawMeasures(){
|
||||||
var measures = this.controller.getSongData().measures
|
var measures = this.controller.getSongData().measures
|
||||||
var currentTime = this.controller.getEllapsedTime().ms
|
var currentTime = this.controller.getElapsedTime().ms
|
||||||
|
|
||||||
measures.forEach((measure, index)=>{
|
measures.forEach((measure, index)=>{
|
||||||
var timeForDistance = 70 / this.circleSize * this.distanceForCircle / measure.speed
|
var timeForDistance = 70 / this.circleSize * this.distanceForCircle / measure.speed
|
||||||
@ -206,7 +220,7 @@ class View{
|
|||||||
|
|
||||||
drawMeasure(measure){
|
drawMeasure(measure){
|
||||||
var z = this.canvas.scale
|
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)
|
var measureX = this.slotX + measure.speed / (70 / this.circleSize) * (measure.ms - currentTime)
|
||||||
this.ctx.strokeStyle = "#bab8b8"
|
this.ctx.strokeStyle = "#bab8b8"
|
||||||
this.ctx.lineWidth = 2
|
this.ctx.lineWidth = 2
|
||||||
@ -388,7 +402,7 @@ class View{
|
|||||||
for(var i = circles.length; i--;){
|
for(var i = circles.length; i--;){
|
||||||
var circle = circles[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 timeForDistance = 70 / this.circleSize * this.distanceForCircle / circle.getSpeed() + this.bigCircleSize / 2
|
||||||
var startingTime = circle.getMS() - timeForDistance
|
var startingTime = circle.getMS() - timeForDistance
|
||||||
// At circle.getMS(), the cirlce fits the slot
|
// At circle.getMS(), the cirlce fits the slot
|
||||||
@ -459,7 +473,7 @@ class View{
|
|||||||
|
|
||||||
var fill, size, faceID
|
var fill, size, faceID
|
||||||
if(!circlePos){
|
if(!circlePos){
|
||||||
var currentTime = this.controller.getEllapsedTime().ms
|
var currentTime = this.controller.getElapsedTime().ms
|
||||||
circlePos = {
|
circlePos = {
|
||||||
x: this.slotX + circle.getSpeed() / (70 / this.circleSize) * (circle.getMS() - currentTime),
|
x: this.slotX + circle.getSpeed() / (70 / this.circleSize) * (circle.getMS() - currentTime),
|
||||||
y: this.circleY
|
y: this.circleY
|
||||||
@ -549,7 +563,7 @@ class View{
|
|||||||
|
|
||||||
drawTime(){
|
drawTime(){
|
||||||
var z = this.canvas.scale
|
var z = this.canvas.scale
|
||||||
var time = this.controller.getEllapsedTime()
|
var time = this.controller.getElapsedTime()
|
||||||
|
|
||||||
this.ctx.globalAlpha = 0.7
|
this.ctx.globalAlpha = 0.7
|
||||||
this.ctx.fillStyle = "#000"
|
this.ctx.fillStyle = "#000"
|
||||||
@ -579,7 +593,7 @@ class View{
|
|||||||
this.ctx.closePath()
|
this.ctx.closePath()
|
||||||
this.ctx.fill()
|
this.ctx.fill()
|
||||||
|
|
||||||
var currentTime = this.controller.getEllapsedTime().ms
|
var currentTime = this.controller.getElapsedTime().ms
|
||||||
var keyTime = this.controller.getKeyTime()
|
var keyTime = this.controller.getKeyTime()
|
||||||
var sound = keyTime["don"] > keyTime["ka"] ? "don" : "ka"
|
var sound = keyTime["don"] > keyTime["ka"] ? "don" : "ka"
|
||||||
if(keyTime[sound] > currentTime - 200){
|
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