Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Sign in / Register
Toggle navigation
T
Taiko Web
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Locked Files
Issues
0
Issues
0
List
Boards
Labels
Service Desk
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Security & Compliance
Security & Compliance
Dependency List
License Compliance
Packages
Packages
List
Container Registry
Analytics
Analytics
CI / CD
Code Review
Insights
Issues
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
nanahira
Taiko Web
Commits
8e99da6a
Commit
8e99da6a
authored
Sep 12, 2018
by
LoveEevee
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Add 2-player mode
parent
7744fdac
Changes
12
Expand all
Show whitespace changes
Inline
Side-by-side
Showing
12 changed files
with
815 additions
and
372 deletions
+815
-372
public/index.html
public/index.html
+1
-0
public/src/css/songselect.css
public/src/css/songselect.css
+10
-0
public/src/js/controller.js
public/src/js/controller.js
+219
-225
public/src/js/game.js
public/src/js/game.js
+116
-104
public/src/js/keyboard.js
public/src/js/keyboard.js
+16
-9
public/src/js/loader.js
public/src/js/loader.js
+3
-0
public/src/js/loadsong.js
public/src/js/loadsong.js
+42
-5
public/src/js/mekadon.js
public/src/js/mekadon.js
+48
-19
public/src/js/p2.js
public/src/js/p2.js
+132
-0
public/src/js/songselect.js
public/src/js/songselect.js
+37
-1
public/src/js/view.js
public/src/js/view.js
+23
-9
server.py
server.py
+168
-0
No files found.
public/index.html
View file @
8e99da6a
...
...
@@ -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>
...
...
public/src/css/songselect.css
View file @
8e99da6a
...
...
@@ -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%
;
}
public/src/js/controller.js
View file @
8e99da6a
This diff is collapsed.
Click to expand it.
public/src/js/game.js
View file @
8e99da6a
...
...
@@ -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,9 +14,9 @@ function Game(controller, selectedSong, songData){
var
_HPGain
=
100
/
_songData
.
circles
.
length
;
var
_paused
=
false
;
var
_started
=
false
;
var
_mainMusicPlaying
=
tru
e
;
var
_mainMusicPlaying
=
fals
e
;
var
_latestDate
;
var
_el
l
apsedTimeSincePause
=
0
;
var
_elapsedTimeSincePause
=
0
;
var
_musicFadeOut
=
0
;
var
_fadeOutStarted
=
false
;
var
_currentTimingPoint
=
0
;
...
...
@@ -31,35 +31,28 @@ function Game(controller, selectedSong, songData){
})
this
.
run
=
function
(){
_timeForDistanceCircle
=
((
20
*
controller
.
getDistanceForCircle
())
/
_hitcircleSpeed
);
_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
();
...
...
@@ -77,9 +70,10 @@ 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
){
...
...
@@ -95,7 +89,7 @@ function Game(controller, selectedSong, songData){
}
else
if
(
currentTime
>
finishTime
+
200
&&
currentTime
<=
finishTime
+
300
){
if
(
controller
.
multiplayer
!=
2
){
circle
.
updateStatus
(
-
1
);
_currentScore
=
0
;
circle
.
played
(
_currentScore
);
...
...
@@ -103,6 +97,12 @@ function Game(controller, selectedSong, songData){
_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
})
}
}
}
...
...
@@ -190,8 +196,8 @@ function Game(controller, selectedSong, songData){
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
.
getEl
l
apsedTime
().
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
;
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
));
}
else
{
_mainAsset
.
play
(
0
,
false
,
_this
.
getEllapsedTime
().
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
;
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
.
getEl
l
apsedTime
=
function
(){
return
_el
lapsedTime
;
this
.
getElapsedTime
=
function
(){
return
this
.
e
lapsedTime
;
}
this
.
updateTime
=
function
(){
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
(
_ellapsedT
ime
.
ms
<
0
){
_
ellapsedTime
.
ms
=
_currentDate
.
getTime
()
-
_startDate
.
getTime
();
if
(
t
ime
.
ms
<
0
){
_
this
.
setElapsedTime
(
_currentDate
.
getTime
()
-
_startDate
.
getTime
()
-
_elapsedTimeSincePause
)
}
else
if
(
_ellapsedT
ime
.
ms
>=
0
&&
!
_started
){
else
if
(
t
ime
.
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
(
_ellapsedT
ime
.
ms
>=
0
&&
_started
){
_
ellapsedTime
.
ms
=
Math
.
abs
(
_startDate
.
getTime
()
-
_currentDate
.
getTime
())
-
_ellapsedTimeSincePause
;
else
if
(
t
ime
.
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
(){
...
...
public/src/js/keyboard.js
View file @
8e99da6a
...
...
@@ -65,14 +65,21 @@ function Keyboard(controller){
}
this
.
checkMenuKeys
=
function
(){
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
(
_kbd
[
"
pause
"
],
"
menu
"
,
function
(){
controller
.
togglePauseMenu
();
})
}
}
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
.
getEl
l
apsedTime
().
ms
_keyTime
[
sound
]
=
controller
.
getElapsedTime
().
ms
})
}
...
...
public/src/js/loader.js
View file @
8e99da6a
...
...
@@ -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
()
public/src/js/loadsong.js
View file @
8e99da6a
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
()
}
}
}
public/src/js/mekadon.js
View file @
8e99da6a
...
...
@@ -7,6 +7,28 @@ class Mekadon{
}
play
(
circle
){
if
(
circle
.
getStatus
()
==
450
){
return
this
.
playNow
(
circle
)
}
}
playAt
(
circle
,
ms
,
score
){
var
currentMs
=
circle
.
getMS
()
-
this
.
controller
.
getElapsedTime
().
ms
if
(
ms
>
currentMs
-
10
){
return
this
.
playNow
(
circle
,
score
)
}
}
miss
(
circle
){
var
currentMs
=
circle
.
getMS
()
-
this
.
controller
.
getElapsedTime
().
ms
if
(
0
>
currentMs
-
10
){
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
"
])
...
...
@@ -23,10 +45,17 @@ class Mekadon{
this
.
setKey
(
kbd
[
"
ka_r
"
])
this
.
lr
=
false
}
var
score
=
this
.
game
.
checkScore
(
circle
);
circle
.
played
(
score
);
this
.
game
.
updateCurrentCircle
();
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
...
...
public/src/js/p2.js
0 → 100644
View file @
8e99da6a
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
()
}
}
}
}
}
}
public/src/js/songselect.js
View file @
8e99da6a
...
...
@@ -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
);
}
\ No newline at end of file
public/src/js/view.js
View file @
8e99da6a
...
...
@@ -4,7 +4,14 @@ class View{
this
.
bg
=
bg
this
.
diff
=
diff
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
.
getEl
l
apsedTime
().
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
.
getEl
l
apsedTime
().
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
.
getEl
l
apsedTime
().
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
.
getEl
l
apsedTime
().
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
.
getEl
l
apsedTime
().
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
.
getEl
l
apsedTime
()
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
.
getEl
l
apsedTime
().
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
){
...
...
server.py
0 → 100644
View file @
8e99da6a
#!/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
()
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment