Clean up classes before exiting them

This commit is contained in:
LoveEevee 2018-09-18 01:37:59 +03:00
parent f19fbf5371
commit e8809285e0
25 changed files with 1183 additions and 1172 deletions

View File

@ -22,7 +22,6 @@
<link rel="stylesheet" href="/src/css/scoresheet.css">
<link rel="stylesheet" href="/src/css/loadsong.css">
<link rel="stylesheet" href="/src/css/game.css">
<link rel="stylesheet" href="/src/css/animations.css">
<script src="/src/js/lib/jquery.js"></script>
<script src="/src/js/lib/jquery-ui.js"></script>
@ -47,6 +46,7 @@
<script src="/src/js/soundbuffer.js"></script>
<script src="/src/js/p2.js"></script>
<script src="/src/js/canvasasset.js"></script>
<script src="/src/js/pageevents.js"></script>
</head>
<body>

View File

@ -1,58 +0,0 @@
@keyframes don-normal {
0%{background-position-y:0px}
6.35%{background-position-y:-184px}
7.94%{background-position-y:-368px}
9.52%{background-position-y:-552px}
11.11%{background-position-y:-736px}
12.7%{background-position-y:-920px}
14.29%{background-position-y:-1104px}
15.87%{background-position-y:-1104px}
17.46%{background-position-y:-920px}
19.05%{background-position-y:-736px}
20.63%{background-position-y:-552px}
22.22%{background-position-y:-368px}
23.81%{background-position-y:-184px}
25.4%{background-position-y:0px}
31.75%{background-position-y:-184px}
33.33%{background-position-y:-368px}
34.92%{background-position-y:-552px}
36.51%{background-position-y:-736px}
38.1%{background-position-y:-920px}
39.68%{background-position-y:-1104px}
41.27%{background-position-y:-1104px}
42.86%{background-position-y:-920px}
44.44%{background-position-y:-736px}
46.03%{background-position-y:-552px}
47.62%{background-position-y:-368px}
49.21%{background-position-y:-184px}
50.79%{background-position-y:0px}
57.14%{background-position-y:-184px}
58.73%{background-position-y:-368px}
60.32%{background-position-y:-552px}
61.9%{background-position-y:-736px}
63.49%{background-position-y:-920px}
65.08%{background-position-y:-1104px}
66.67%{background-position-y:-1104px}
68.25%{background-position-y:-920px}
69.84%{background-position-y:-1288px}
71.43%{background-position-y:-1472px}
73.02%{background-position-y:-1656px}
74.6%{background-position-y:-1840px}
76.19%{background-position-y:-2024px}
77.78%{background-position-y:-2024px}
79.37%{background-position-y:-2024px}
80.95%{background-position-y:-2024px}
82.54%{background-position-y:-1840px}
84.13%{background-position-y:-1656px}
85.71%{background-position-y:-1472px}
87.3%{background-position-y:-1288px}
88.89%{background-position-y:-2392px}
90.48%{background-position-y:-2208px}
92.06%{background-position-y:-2208px}
93.65%{background-position-y:-2392px}
95.24%{background-position-y:-2576px}
96.83%{background-position-y:-2760px}
98.41%{background-position-y:-2944px}
100%{background-position-y:-3128px}
}

View File

@ -1,31 +1,31 @@
#load-song{
width: 100%;
height: 100%;
margin:0;
padding: 0%;
}
#loading-song{
width:20%;
height:30%;
position: absolute;
top:35%;
left:40%;
background: rgba(0,0,0,0.75);
top: 0;
right: 0;
bottom: 0;
left: 0;
margin: auto;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
width: 20vw;
height: 15vw;
background: rgba(0, 0, 0, 0.75);
border-radius: 5px;
border:3px solid white;
border: 3px solid white;
color: #fff;
}
#loading-don{
width: 50%;
}
.loading-text{
position: relative;
width:50%;
height:65%;
top: 12%;
left: 30%;
}
#loading-song p{
position: absolute;
left:28%;
font-size: 3vmin;
font-size: 1.5vw;
text-align: center;
z-index: 1;
}

View File

@ -1,35 +1,30 @@
@font-face {
font-family: 'TnT';
src: url('../../assets/fonts/TnT.ttf') format('truetype');
@font-face{
font-family: TnT;
src: url("/assets/fonts/TnT.ttf") format("truetype");
}
@font-face {
font-family: 'Kozuka';
src: url('../../assets/fonts/KozGoPro-Bold.otf') format('truetype');
@font-face{
font-family: Kozuka;
src: url("/assets/fonts/KozGoPro-Bold.otf") format("truetype");
}
html, body{
padding: 0;
html,
body{
margin: 0;
width:100%;
width: 100%;
height: 100%;
background: black;
color:white;
background: #fe7839;
user-select: none;
}
#screen{
width:100%;
height:100%;
margin:0;
padding:0;
background: url('/assets/img/bg-pattern-1.png') top center;
width: 100%;
height: 100%;
margin: 0;
padding: 0;
background: #fe7839 url("/assets/img/bg-pattern-1.png") top center;
font-family: TnT;
}
#assets{
display:none;
display: none;
}
.window{
width: 60vmin;
height: 23vmin;
@ -49,18 +44,16 @@ html, body{
justify-content: space-between;
}
.stroke-main {
.stroke-main{
font-weight: 300;
}
.result-title {
.result-title{
margin-top: 9px !important;
margin-left: 5px !important;
z-index: 1;
}
.result-song, .game-song {
.result-song,
.game-song{
position: absolute;
right: 0;
font-size: 5vmin;
@ -70,74 +63,66 @@ html, body{
z-index: 1;
font-weight: 300;
}
.stroke-main:before {
.stroke-main::before{
content: attr(alt);
left: 0;
z-index: -1;
position: absolute;
-webkit-text-stroke: 0.3em #fb3c0c;
}
.stroke-main:after {
.stroke-main::after{
content: attr(alt);
left: 0;
z-index: -2;
position: absolute;
-webkit-text-stroke: 0.5em #000;
}
.stroke-sub:before {
.stroke-sub::before{
content: attr(alt);
position: absolute;
-webkit-text-stroke: 0.25em #000;
left: 0;
z-index: -1;
}
.songsel-title {
position: absolute;
z-index: 1;
font-size: 7vmin;
margin: 20px;
}
.click-to-continue:before {
width: 100%;
}
.don {
.don{
background-position-y: 0;
position: absolute;
top: 0px;
}
.alpha-title .song-title-char {
.alpha-title .song-title-char{
transform: scale(1.3, 1);
font-size: 80%;
line-height: 22px;
}
.song-title-apos {
.song-title-apos{
padding-left: 4px;
}
.song-title-char[alt="ぁ"],.song-title-char[alt="ぃ"],.song-title-char[alt="ぅ"],.song-title-char[alt="ぇ"],.song-title-char[alt="ぉ"],
.song-title-char[alt="ゃ"],.song-title-char[alt="ゅ"],.song-title-char[alt="ょ"],.song-title-char[alt="っ"],
.song-title-char[alt="ァ"],.song-title-char[alt="ィ"],.song-title-char[alt="ゥ"],.song-title-char[alt="ェ"],.song-title-char[alt="ォ"],
.song-title-char[alt="ャ"],.song-title-char[alt="ュ"],.song-title-char[alt="ョ"],.song-title-char[alt="ッ"]
{
.song-title-char[alt="ぁ"],
.song-title-char[alt="ぃ"],
.song-title-char[alt="ぅ"],
.song-title-char[alt="ぇ"],
.song-title-char[alt="ぉ"],
.song-title-char[alt="ゃ"],
.song-title-char[alt="ゅ"],
.song-title-char[alt="ょ"],
.song-title-char[alt="っ"],
.song-title-char[alt="ァ"],
.song-title-char[alt="ィ"],
.song-title-char[alt="ゥ"],
.song-title-char[alt="ェ"],
.song-title-char[alt="ォ"],
.song-title-char[alt="ャ"],
.song-title-char[alt="ュ"],
.song-title-char[alt="ョ"],
.song-title-char[alt="ッ"]{
margin-top: -6px;
}
.song-title-char[alt="ー"], .song-title-char[alt="-"] {
.song-title-char[alt="ー"],
.song-title-char[alt="-"]{
transform: rotate(95deg);
font-size: 90%;
}
#tutorial-outer {
#tutorial-outer{
display: flex;
justify-content: center;
align-items: center;
@ -146,8 +131,7 @@ html, body{
width: 100%;
height: 100%;
}
#tutorial {
#tutorial{
background: rgb(246, 234, 212);
color: black;
border: 5px black solid;
@ -158,39 +142,31 @@ html, body{
font-size: 16pt;
position: relative;
}
#tutorial-title {
#tutorial-title{
z-index: 1;
position: absolute;
color: white;
top: -25px;
font-size: 26pt;
}
#tutorial-content {
#tutorial-content{
padding: 15px 30px;
}
kbd {
kbd{
font-family: inherit;
padding: 0.1em 0.6em;
border: 1px solid #ccc;
font-size: 13px;
background-color: #f7f7f7;
color: #333;
-moz-box-shadow: 0 1px 0px rgba(0, 0, 0, 0.2),0 0 0 2px #ffffff inset;
-webkit-box-shadow: 0 1px 0px rgba(0, 0, 0, 0.2), 0 0 0 2px #ffffff inset;
box-shadow: 0 1px 0px rgba(0, 0, 0, 0.2), 0 0 0 2px #ffffff inset;
-moz-border-radius: 3px;
-webkit-border-radius: 3px;
border-radius: 3px;
display: inline-block;
text-shadow: 0 1px 0 #fff;
line-height: 1.4;
white-space: nowrap;
}
.taibtn {
.taibtn{
bottom: 15px;
margin: 0 auto;
position: absolute;
@ -200,30 +176,15 @@ kbd {
border: 3px rgba(218, 205, 178, 1) solid;
cursor: pointer;
}
.taibtn:hover {
.taibtn:hover{
z-index: 1;
color: white;
background: rgb(255, 181, 71);
border-color: white;
}
.taibtn:before {
.taibtn::before{
padding: 0 40px;
}
#tutorial-end-button {
#tutorial-end-button{
font-size: 22pt;
}
#songsel-help {
float: right;
background: rgba(255, 255, 255, 0.5);
color: black;
padding: 15px;
margin: 10px;
font-size: 18px;
border: 3px black solid;
border-radius: 50px;
cursor: pointer;
}

View File

@ -1,55 +1,63 @@
@-webkit-keyframes bgscroll {
from {background-position:0 0;}
to {background-position:-200px 0;}
@-webkit-keyframes bgscroll{
from{
background-position: 0 0;
}
to{
background-position: -200px 0;
}
}
@keyframes bgscroll {
from {background-position:0 0;}
to {background-position:-200px 0;}
@keyframes bgscroll{
from{
background-position: 0 0;
}
to{
background-position: -200px 0;
}
}
#song-select{
width: 100%;
height:100%;
background: url('/assets/img/bg-pattern-1.png');
height: 100%;
background: url("/assets/img/bg-pattern-1.png");
animation: bgscroll 3s infinite linear;
-webkit-animation: bgscroll 3s infinite linear;
white-space: nowrap;
}
#song-container{
width:98%;
height:80%;
width: 98%;
height: 80%;
padding: 5% 1% 1% 1%;
text-align: center;
}
ul li{
list-style:none;
list-style: none;
}
.difficulties{
float:left;
display:inline-block;
width:70%;
position: absolute;
left: 0;
display: block;
width: 303px;
height: 100%;
opacity: 0;
transition: opacity 0.1s;
}
.song-title-char {
.song.opened .difficulties{
opacity: 1;
transition: opacity 0.1s 0.2s;
}
.song-title-char{
text-align: center;
width: 45px;
display: block;
}
.song-title-char:before {
.song-title-char::before{
content: attr(alt);
position: absolute;
-webkit-text-stroke: 0.25em #000;
z-index: -1;
}
.song-title{
float: right;
width: 45px;
height: 100%;
padding: 10px 2px;
word-wrap: break-word;
font-size: 22pt;
@ -58,16 +66,14 @@ ul li{
z-index: 1;
line-height: 28px;
}
.song-title-space {
.song-title-space{
line-height: 25px;
}
.song{
font-size: 14pt;
width: 50px;
margin-right:15px;
height:100%;
margin-right: 15px;
height: 100%;
color: black;
display: inline-block;
background: rgba(255, 220, 47, 0.90);
@ -76,64 +82,93 @@ ul li{
overflow: hidden;
cursor: pointer;
position: relative;
transition: width 0.3s;
}
.song:not(.opened):hover{
background: rgba(255, 233, 125, 0.90);
}
.opened{
width:375px;
width: 375px;
}
.difficulty{
display:none;
cursor:pointer;
display: none;
cursor: pointer;
width: 35px;
height: 70%;
border-radius: 5px;
display: inline-block;
margin: 5px;
float: left;
background:white;
border:10px solid #ae7a26;
position:relative;
background: white;
border: 10px solid #ae7a26;
position: relative;
}
.difficulty .diffname{
word-wrap: break-word;
width: 20px;
display: block;
margin: auto;
margin-top:10px;
margin-top: 10px;
font-size: 20pt;
margin-left: 6px;
white-space: normal;
}
.difficulty .stars{
position:absolute;
position: absolute;
color: #f12b69;
margin-left: -17px;
width:100%;
bottom:10px;
width: 100%;
bottom: 10px;
}
.difficulty:hover{
border-color:#fa5d3a;
color:white;
background:#0c6577;
border-color: #fa5d3a;
color: white;
background: #0c6577;
}
.difficulty:hover .diffname{
-webkit-text-stroke-width: 1px;
-webkit-text-stroke-color: black;
}
.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%;
content: "P2";
display: block;
position: absolute;
bottom: 0;
width: 100%;
}
#songsel-help{
float: right;
background: rgba(255, 255, 255, 0.5);
color: black;
padding: 15px;
margin: 10px;
font-size: 18px;
border: 3px black solid;
border-radius: 50px;
cursor: pointer;
}
.songsel-title-song,
.songsel-title-difficulty{
position: absolute;
left: -300px;
opacity: 0;
margin: 20px;
color: #fff;
font-size: 7vmin;
z-index: 1;
transition: left 0s 0.2s, opacity 0.2s;
}
#song-select.difficulty-select .songsel-title-difficulty{
left: 0;
opacity: 1;
transition: left 0.4s 0.2s, opacity 0.4s 0.2s;
}
#song-select:not(.difficulty-select) .songsel-title-song{
left: 0;
opacity: 1;
transition: left 0.4s 0.2s, opacity 0.4s 0.2s;
}

View File

@ -1,51 +1,39 @@
@keyframes toggleFade {
0%{
opacity:1;
@keyframes toggleFade{
40%{
opacity: 1;
}
50% {
opacity: 0;
70%{
opacity: 0.2;
}
}
#title-screen{
position:absolute;
top:0;
left:0;
width:100%;
height:100%;
display: none;
margin:0px;
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 0;
display: flex;
justify-content: center;
align-items: center;
background: #1389f0 url("/assets/img/title-screen.png") no-repeat center;
background-size: cover;
cursor: pointer;
background: url('/assets/img/title-screen.png');
-webkit-background-size: cover; /* pour Chrome et Safari */
-moz-background-size: cover; /* pour Firefox */
-o-background-size: cover; /* pour Opera */
background-size: cover; /* version standardis<69>e */
}
#logo-big-cont{
position:absolute;
max-width: 654px;
max-height: 300px;
.logo-big{
width: 90vmin;
height: auto;
}
#logo-big-cont img{
width:100%;
height:100%;
}
.click-to-continue{
display:block;
font-size: 8vmin;
color:white;
text-align: center;
position:absolute;
bottom:2%;
width:100%;
animation: toggleFade 1s infinite ease-out;
bottom: 10%;
color: #fff;
font-size: 8vmin;
text-align: center;
z-index: 1;
animation: toggleFade 2s infinite ease-in-out;
}
.click-to-continue::before{
-webkit-text-stroke: 0.25em #f00;
filter: blur(0.3vmin);
left: auto;
}

View File

@ -1,106 +1,109 @@
var assets = {
"img": [
"background.png",
"title-screen.png",
"logo-big.png",
"don-0.png",
"don-1.png",
"big-don-0.png",
"big-don-1.png",
"taiko.png",
"taiko-key-blue.png",
"taiko-key-red.png",
"hp-bar-bg.png",
"hp-bar-colour.png",
"score-0.png",
"score-0-b.png",
"score-230.png",
"score-450.png",
"dancing-don.gif",
"scoresheet.jpg",
"bg-pattern-1.png",
"bg-pattern-2.png",
"ranking-S.png",
"ranking-X.png",
"muzu_easy.png",
"muzu_normal.png",
"muzu_hard.png",
"muzu_oni.png",
"don_anim_normal.png",
"don_anim_10combo.png",
"balloon.png"
],
"audioSfx": [
"start.wav",
"don.wav",
"ka.wav",
img: [
'background.png',
'title-screen.png',
'logo-big.png',
'don-0.png',
'don-1.png',
'big-don-0.png',
'big-don-1.png',
'taiko.png',
'taiko-key-blue.png',
'taiko-key-red.png',
'hp-bar-bg.png',
'hp-bar-colour.png',
'score-0.png',
'score-0-b.png',
'score-230.png',
'score-450.png',
'dancing-don.gif',
'scoresheet.jpg',
'bg-pattern-1.png',
'bg-pattern-2.png',
'ranking-S.png',
'ranking-X.png',
'muzu_easy.png',
'muzu_normal.png',
'muzu_hard.png',
'muzu_oni.png',
'don_anim_normal.png',
'don_anim_10combo.png',
'balloon.png'
"combo-50.wav",
"combo-100.wav",
"combo-200.wav",
"combo-300.wav",
"combo-400.wav",
"combo-500.wav",
"combo-600.wav",
"combo-700.wav",
"combo-800.wav",
"combo-900.wav",
"combo-1000.wav",
"combo-1100.wav",
"combo-1200.wav",
"combo-1300.wav",
"combo-1400.wav",
"fullcombo.wav",
"combo-50-meka.wav",
"combo-100-meka.wav",
"combo-200-meka.wav",
"combo-300-meka.wav",
"combo-400-meka.wav",
"combo-500-meka.wav",
"combo-600-meka.wav",
"combo-700-meka.wav",
"combo-800-meka.wav",
"combo-900-meka.wav",
"combo-1000-meka.wav",
"combo-1100-meka.wav",
"combo-1200-meka.wav",
"combo-1300-meka.wav",
"combo-1400-meka.wav",
"fullcombo-meka.wav",
"song-select.wav",
"title.ogg",
"pause.wav",
"cancel.wav",
"results.wav",
"diffsel.wav",
"gamefullcombo.wav",
"gameclear.wav",
"gamefail.wav",
"note_don.ogg",
"note_ka.ogg",
"balloon.ogg"
],
"audioMusic": [
"bgm_songsel.ogg",
"bgm_result.ogg",
"bgm_setsume.ogg"
],
"fonts": [
"Kozuka",
"TnT"
],
"views": [
"game.html",
"loadsong.html",
"scoresheet.html",
"songselect.html",
"titlescreen.html",
"tutorial.html"
],
audioSfx: [
'start.wav',
'don.wav',
'ka.wav',
'combo-50.wav',
'combo-100.wav',
'combo-200.wav',
'combo-300.wav',
'combo-400.wav',
'combo-500.wav',
'combo-600.wav',
'combo-700.wav',
'combo-800.wav',
'combo-900.wav',
'combo-1000.wav',
'combo-1100.wav',
'combo-1200.wav',
'combo-1300.wav',
'combo-1400.wav',
'fullcombo.wav',
'combo-50-meka.wav',
'combo-100-meka.wav',
'combo-200-meka.wav',
'combo-300-meka.wav',
'combo-400-meka.wav',
'combo-500-meka.wav',
'combo-600-meka.wav',
'combo-700-meka.wav',
'combo-800-meka.wav',
'combo-900-meka.wav',
'combo-1000-meka.wav',
'combo-1100-meka.wav',
'combo-1200-meka.wav',
'combo-1300-meka.wav',
'combo-1400-meka.wav',
'fullcombo-meka.wav',
'song-select.wav',
'title.ogg',
'pause.wav',
'cancel.wav',
'results.wav',
'diffsel.wav',
'gamefullcombo.wav',
'gameclear.wav',
'gamefail.wav',
'note_don.ogg',
'note_ka.ogg',
'balloon.ogg'
],
audioMusic:[
'bgm_songsel.ogg',
'bgm_result.ogg',
'bgm_setsume.ogg'
],
songs: [],
fonts: [
'Kozuka',
'TnT'
],
sounds: {},
image: {}
};
"songs": [],
"sounds": {},
"image": {},
"pages": {}
}

View File

@ -4,7 +4,6 @@ class Controller{
this.songData = songData
this.autoPlayEnabled = autoPlayEnabled
this.multiplayer = multiplayer
this.pauseMenu = false
var backgroundURL = "/songs/" + this.selectedSong.folder + "/bg.png"
var songParser = new ParseSong(songData)
@ -40,16 +39,19 @@ class Controller{
}
}
loadUIEvents(){
$("#song-selection-butt").click(() => {
assets.sounds["don"].play()
this.songSelection()
this.continueBtn = document.getElementById("song-selection-butt")
this.restartBtn = document.getElementById("song-selection-butt")
this.songSelBtn = document.getElementById("song-selection-butt")
pageEvents.add(this.continueBtn, "click", () => {
this.togglePauseMenu()
})
$("#restart-butt").click(() => {
pageEvents.add(this.restartBtn, "click", () => {
assets.sounds["don"].play()
this.restartSong()
})
$("#continue-butt").click(() => {
this.togglePauseMenu()
pageEvents.add(this.songSelBtn, "click", () => {
assets.sounds["don"].play()
this.songSelection()
})
}
startMainLoop(){
@ -66,7 +68,7 @@ class Controller{
}
mainLoop(){
if(this.mainLoopRunning){
if(this.multiplayer != 2){
if(this.multiplayer !== 2){
requestAnimationFrame(() => {
if(this.syncWith){
this.syncWith.game.elapsedTime.ms = this.game.elapsedTime.ms
@ -87,6 +89,9 @@ class Controller{
}
if(this.mainLoopStarted){
this.game.update()
if(!this.mainLoopRunning){
return
}
this.game.playMainMusic()
}
this.view.refresh()
@ -99,10 +104,10 @@ class Controller{
this.togglePause()
this.view.togglePauseMenu()
}
displayResults(){
gameEnded(){
var score = this.getGlobalScore()
var vp
if(score.fail == 0){
if(score.fail === 0){
vp = "fullcombo"
this.playSoundMeka("fullcombo", 1.350)
}else if(score.hp >= 50){
@ -111,33 +116,29 @@ class Controller{
vp = "fail"
}
assets.sounds["game" + vp].play()
setTimeout(() => {
if(this.mainLoopRunning){
this.stopMainLoop()
if(this.multiplayer != 2){
}
displayResults(){
this.clean()
if(this.multiplayer !== 2){
new Scoresheet(this, this.getGlobalScore(), this.multiplayer)
}
}
}, 7000)
}
displayScore(score, notPlayed){
this.view.displayScore(score, notPlayed)
}
songSelection(){
$("#music-bg").remove()
this.stopMainLoop()
this.clean()
new SongSelect()
}
restartSong(){
this.stopMainLoop()
$("#screen").load("/src/views/game.html", () => {
this.clean()
if(this.multiplayer){
new loadSong(this.selectedSong, false, true)
}else{
loader.changePage("game")
var taikoGame = new Controller(this.selectedSong, this.songData, this.autoPlayEnabled)
taikoGame.run()
}
})
}
playSoundMeka(soundID, time){
var meka = ""
@ -195,4 +196,16 @@ class Controller{
this.mekadon.play(circle)
}
}
clean(){
this.stopMainLoop()
this.keyboard.clean()
this.view.clean()
pageEvents.remove(this.continueBtn, "click")
delete this.continueBtn
pageEvents.remove(this.restartBtn, "click")
delete this.restartBtn
pageEvents.remove(this.songSelBtn, "click")
delete this.songSelBtn
}
}

View File

@ -219,27 +219,32 @@ class Game{
whenLastCirclePlayed(){
var circles = this.songData.circles
var lastCircle = circles[this.songData.circles.length - 1]
if(!this.fadeOutStarted && this.getElapsedTime().ms >= lastCircle.getEndTime() + 1900){
this.fadeOutStarted=this.getElapsedTime().ms
var ms = this.getElapsedTime().ms
if(!this.fadeOutStarted && ms >= lastCircle.getEndTime() + 1900){
this.fadeOutStarted = ms
}
}
whenFadeoutMusic(){
if(this.fadeOutStarted){
if(this.musicFadeOut==0){
var started = this.fadeOutStarted
if(started){
var ms = this.getElapsedTime().ms
if(this.musicFadeOut === 0){
snd.musicGain.fadeOut(1.6)
if(this.controller.multiplayer == 1){
if(this.controller.multiplayer === 1){
p2.send("gameresults", this.controller.getGlobalScore())
}
this.musicFadeOut++
}
if(this.musicFadeOut == 1 && this.getElapsedTime().ms >= this.fadeOutStarted + 1600){
this.controller.displayResults()
}else if(this.musicFadeOut === 1 && ms >= started + 1600){
this.controller.gameEnded()
this.mainAsset.stop()
p2.send("gameend")
setTimeout(() => {
this.musicFadeOut++
}else if(this.musicFadeOut === 2 && ms >= started + 2600){
snd.musicGain.fadeIn()
snd.musicGain.unmute()
}, 1000)
this.musicFadeOut++
}else if(this.musicFadeOut === 3 && ms >= started + 8600){
this.controller.displayResults()
this.musicFadeOut++
}
}

View File

@ -1,6 +1,7 @@
function Keyboard(controller){
var _kbd = {
class Keyboard{
constructor(controller){
this.controller = controller
this.kbd = {
"don_l": 86, // V
"don_r": 66, // B
"ka_l": 67, // C
@ -8,138 +9,126 @@ function Keyboard(controller){
"pause": 81, // Q
"back": 8 // Backspace
}
var _this = this;
var _keys = {};
var _waitKeyupScore = {};
var _waitKeyupSound = {};
var _waitKeyupMenu = {};
var _keyTime = {
this.keys = {}
this.waitKeyupScore = {}
this.waitKeyupSound = {}
this.waitKeyupMenu = {}
this.keyTime = {
"don": -Infinity,
"ka": -Infinity
}
this.getBindings = function(){
return _kbd
}
var _gamepad = new Gamepad(this)
$(document).keydown(function(e){
if (e.which === 8 && !$(e.target).is("input, textarea"))
this.gamepad = new Gamepad(this)
pageEvents.keyAdd(this, "all", "both", event => {
if (event.keyCode === 8){
// Disable back navigation when pressing backspace
e.preventDefault();
if(_this.buttonEnabled(e.which)){
_this.setKey(e.which, true);
event.preventDefault()
}
});
$(document).keyup(function(e){
if(_this.buttonEnabled(e.which)){
_this.setKey(e.which, false);
if(this.buttonEnabled(event.keyCode)){
this.setKey(event.keyCode, event.type === "keydown")
}
});
this.buttonEnabled = function(keyCode){
if(controller.autoPlayEnabled){
})
}
getBindings(){
return this.kbd
}
buttonEnabled(keyCode){
if(this.controller.autoPlayEnabled){
switch(keyCode){
case _kbd["don_l"]:
case _kbd["don_r"]:
case _kbd["ka_l"]:
case _kbd["ka_r"]:
case this.kbd["don_l"]:
case this.kbd["don_r"]:
case this.kbd["ka_l"]:
case this.kbd["ka_r"]:
return false
}
}
return true
}
this.checkGameKeys = function(){
if(!controller.autoPlayEnabled){
_gamepad.play()
checkGameKeys(){
if(!this.controller.autoPlayEnabled){
this.gamepad.play()
}
_this.checkKeySound(_kbd["don_l"], "don")
_this.checkKeySound(_kbd["don_r"], "don")
_this.checkKeySound(_kbd["ka_l"], "ka")
_this.checkKeySound(_kbd["ka_r"], "ka")
this.checkKeySound(this.kbd["don_l"], "don")
this.checkKeySound(this.kbd["don_r"], "don")
this.checkKeySound(this.kbd["ka_l"], "ka")
this.checkKeySound(this.kbd["ka_r"], "ka")
}
this.checkMenuKeys = function(){
if(!controller.multiplayer){
_gamepad.play(1)
_this.checkKey(_kbd["pause"], "menu", function(){
controller.togglePauseMenu();
checkMenuKeys(){
if(!this.controller.multiplayer){
this.gamepad.play(true)
this.checkKey(this.kbd["pause"], "menu", () => {
this.controller.togglePauseMenu()
})
}
if(controller.multiplayer != 2){
_this.checkKey(_kbd["back"], "menu", function(){
if(controller.multiplayer == 1){
if(this.controller.multiplayer !== 2){
this.checkKey(this.kbd["back"], "menu", () => {
if(this.controller.multiplayer === 1){
p2.send("gameend")
}
controller.togglePause();
controller.songSelection();
this.controller.togglePause()
this.controller.songSelection()
})
}
}
this.checkKey = function(keyCode, keyup, callback){
if(_keys[keyCode] && !_this.isWaitingForKeyup(keyCode, keyup)){
_this.waitForKeyup(keyCode, keyup);
checkKey(keyCode, keyup, callback){
if(this.keys[keyCode] && !this.isWaitingForKeyup(keyCode, keyup)){
this.waitForKeyup(keyCode, keyup)
callback()
}
}
this.checkKeySound = function(keyCode, sound){
_this.checkKey(keyCode, "sound", function(){
var circles = controller.parsedSongData.circles
var circle = circles[controller.game.getCurrentCircle()]
checkKeySound(keyCode, sound){
this.checkKey(keyCode, "sound", () => {
var circles = this.controller.parsedSongData.circles
var circle = circles[this.controller.game.getCurrentCircle()]
if(
(keyCode == _kbd["don_l"] || keyCode == _kbd["don_r"])
(keyCode === this.kbd["don_l"] || keyCode === this.kbd["don_r"])
&& circle
&& !circle.getPlayed()
&& circle.getStatus() != -1
&& circle.getType() == "balloon"
&& circle.getStatus() !== -1
&& circle.getType() === "balloon"
&& circle.requiredHits - circle.timesHit <= 1
){
assets.sounds["balloon"].play()
}else{
assets.sounds["note_"+sound].play()
assets.sounds["note_" + sound].play()
}
_keyTime[sound] = controller.getElapsedTime().ms
this.keyTime[sound] = this.controller.getElapsedTime().ms
})
}
this.getKeys = function(){
return _keys;
getKeys(){
return this.keys
}
this.setKey=function(keyCode, down){
setKey(keyCode, down){
if(down){
_keys[keyCode]=true;
this.keys[keyCode] = true
}else{
delete _keys[keyCode];
delete _waitKeyupScore[keyCode];
delete _waitKeyupSound[keyCode];
delete _waitKeyupMenu[keyCode];
delete this.keys[keyCode]
delete this.waitKeyupScore[keyCode]
delete this.waitKeyupSound[keyCode]
delete this.waitKeyupMenu[keyCode]
}
}
this.isWaitingForKeyup = function(key, type){
var isWaiting;
if(type == "score") isWaiting = _waitKeyupScore[key];
else if(type == "sound") isWaiting = _waitKeyupSound[key];
else if(type == "menu") isWaiting = _waitKeyupMenu[key];
return isWaiting;
isWaitingForKeyup(key, type){
if(type === "score"){
return this.waitKeyupScore[key]
}else if(type === "sound"){
return this.waitKeyupSound[key]
}else if(type === "menu"){
return this.waitKeyupMenu[key]
}
this.waitForKeyup = function(key, type){
if(type == "score") _waitKeyupScore[key] = true;
else if(type == "sound") _waitKeyupSound[key] = true;
else if(type == "menu") _waitKeyupMenu[key] = true;
}
this.getKeyTime = function(){
return _keyTime;
waitForKeyup(key, type){
if(type === "score"){
this.waitKeyupScore[key] = true
}else if(type === "sound"){
this.waitKeyupSound[key] = true
}else if(type === "menu"){
this.waitKeyupMenu[key] = true
}
}
getKeyTime(){
return this.keyTime
}
clean(){
pageEvents.keyRemove(this, "all")
}
}

View File

@ -1,15 +1,15 @@
class Loader{
constructor(){
this.loadedAssets = 0
this.errorCount = 0
this.assetsDiv = document.getElementById("assets")
this.promises = []
$("#screen").load("/src/views/loader.html", () => {
this.run()
})
this.ajax("src/views/loader.html").then(this.run.bind(this))
}
run(){
run(page){
this.promises = []
this.screen = document.getElementById("screen")
this.screen.innerHTML = page
this.loaderPercentage = document.querySelector("#loader .percentage")
this.loaderProgress = document.querySelector("#loader .progress")
assets.fonts.forEach(name => {
var font = document.createElement("h1")
@ -20,11 +20,13 @@ class Loader{
FontDetect.onFontLoaded(name, resolve, reject, {msTimeout: 90000})
}))
})
var fontDetectDiv = document.getElementById("fontdetectHelper")
fontDetectDiv.parentNode.removeChild(fontDetectDiv)
assets.img.forEach(name => {
var id = name.substr(0, name.length - 4)
var id = this.getFilename(name)
var image = document.createElement("img")
this.promises.push(promiseLoad(image))
this.promises.push(pageEvents.load(image))
image.id = name
image.src = "/assets/img/" + name
this.assetsDiv.appendChild(image)
@ -39,68 +41,82 @@ class Loader{
snd.previewGain.setVolume(0.5)
assets.audioSfx.forEach(name => {
var id = name.substr(0, name.length-4)
this.promises.push(snd.sfxGain.load("/assets/audio/" + name).then(sound => {
assets.sounds[id] = sound
}))
this.promises.push(this.loadSound(name, snd.sfxGain))
})
assets.audioMusic.forEach(name => {
var id = name.substr(0, name.length-4)
this.promises.push(snd.musicGain.load("/assets/audio/" + name).then(sound => {
assets.sounds[id] = sound
}))
this.promises.push(this.loadSound(name, snd.musicGain))
})
p2 = new P2Connection()
this.promises.push(ajax("/api/songs").then(songs => {
this.promises.push(this.ajax("/api/songs").then(songs => {
assets.songs = JSON.parse(songs)
}))
this.promises.forEach(promise => {
promise.then(() => {
this.assetLoaded()
}, () => {
this.errorMsg()
assets.views.forEach(name => {
var id = this.getFilename(name)
this.promises.push(this.ajax("src/views/" + name).then(page => {
assets.pages[id] = page
}))
})
this.promises.forEach(promise => {
promise.then(this.assetLoaded.bind(this))
})
Promise.all(this.promises).then(() => {
this.clean()
new Titlescreen()
}, this.errorMsg.bind(this))
}
loadSound(name, gain){
var id = this.getFilename(name)
return gain.load("/assets/audio/" + name).then(sound => {
assets.sounds[id] = sound
})
}
getFilename(name){
return name.slice(0, name.lastIndexOf("."))
}
errorMsg(){
if(this.errorCount == 0){
this.error = true
this.loaderPercentage.appendChild(document.createElement("br"))
this.loaderPercentage.appendChild(document.createTextNode("An error occurred, please refresh"))
}
this.errorCount++
this.clean()
}
assetLoaded(){
if(!this.error){
this.loadedAssets++
var percentage = parseInt(this.loadedAssets * 100 / this.promises.length)
document.querySelector("#loader .progress").style.width = percentage + "%"
var percentage = Math.floor(this.loadedAssets * 100 / this.promises.length)
this.loaderProgress.style.width = percentage + "%"
this.loaderPercentage.firstChild.data = percentage + "%"
}
}
function ajax(url){
}
changePage(name){
document.getElementById("screen").innerHTML = assets.pages[name]
}
ajax(url, customRequest){
return new Promise((resolve, reject) => {
var request = new XMLHttpRequest()
request.open("GET", url)
promiseLoad(request).then(() => {
pageEvents.load(request).then(() => {
resolve(request.response)
}, reject)
if(customRequest){
customRequest(request)
}
request.send()
})
}
function promiseLoad(asset){
return new Promise((resolve, reject) => {
asset.addEventListener("load", resolve)
asset.addEventListener("error", reject)
asset.addEventListener("abort", reject)
})
}
clean(){
delete this.assetsDiv
delete this.loaderPercentage
delete this.loaderProgress
delete this.promises
}
}
var pageEvents = new PageEvents()
var loader = new Loader()
var snd = {}
var p2
new Loader()

View File

@ -5,9 +5,8 @@ class loadSong{
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", () => {
loader.changePage("loadsong")
this.run()
})
}
run(){
var id = this.selectedSong.folder
@ -15,7 +14,7 @@ class loadSong{
assets.sounds["start"].play()
var img = document.createElement("img")
promises.push(promiseLoad(img))
promises.push(pageEvents.load(img))
img.id = "music-bg"
img.src = "/songs/" + id + "/bg.png"
document.getElementById("assets").appendChild(img)
@ -37,15 +36,11 @@ class loadSong{
}, reject)
}
}))
promises.push(ajax(this.songFilePath).then(data => {
promises.push(loader.ajax(this.songFilePath).then(data => {
this.songData = data.replace(/\0/g, "").split("\n")
}))
Promise.all(promises).then(() => {
$("#screen").load("/src/views/game.html", () => {
this.setupMultiplayer()
})
}, error => {
console.error(error)
alert("An error occurred, please refresh")
@ -53,37 +48,50 @@ class loadSong{
}
setupMultiplayer(){
if(this.multiplayer){
var loadingText = document.getElementsByClassName("loading-text")[0]
var waitingText = "Waiting for Another Player..."
loadingText.firstChild.data = waitingText
loadingText.setAttribute("alt", waitingText)
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){
pageEvents.add(p2, "message", event => {
if(event.type === "gameload"){
if(event.value === this.diff){
p2.send("gamestart")
}else{
this.selectedSong2 = {
title: this.selectedSong.title,
folder: this.selectedSong.folder,
difficulty: response + ".osu"
difficulty: event.value + ".osu"
}
ajax("/songs/" + this.selectedSong2.folder + "/" + this.selectedSong2.difficulty).then(data => {
loader.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)
}else if(event.type === "gamestart"){
this.clean()
loader.changePage("game")
var taikoGame1 = new Controller(this.selectedSong, this.songData, false, 1)
var taikoGame2 = new Controller(this.selectedSong2, this.song2Data, true, 2)
taikoGame1.run(taikoGame2)
}
})
p2.send("join", {
id: this.selectedSong.folder,
diff: this.diff
})
}else{
this.clean()
loader.changePage("game")
var taikoGame = new Controller(this.selectedSong, this.songData, this.autoPlayEnabled)
taikoGame.run()
}
}
clean(){
pageEvents.remove(p2, "message")
}
}

View File

@ -2,128 +2,119 @@ class P2Connection{
constructor(){
this.closed = true
this.lastMessages = {}
this.msgCallbacks = {}
this.closeCallbacks = new Set()
this.openCallbacks = new Set()
this.otherConnected = false
this.onmessage("gamestart", () => {
this.otherConnected = true
this.notes = []
this.drumrollPace = 45
this.results = false
})
this.onmessage("gameend", () => {
this.otherConnected = false
})
this.onmessage("gameresults", response => {
this.results = response
})
this.onmessage("note", response => {
this.notes.push(response)
})
this.onmessage("drumroll", response => {
this.drumrollPace = response.pace
})
this.allEvents = new Map()
this.addEventListener("message", this.message.bind(this))
}
addEventListener(type, callback){
var addedType = this.allEvents.get(type)
if(!addedType){
addedType = new Set()
this.allEvents.set(type, addedType)
}
return addedType.add(callback)
}
removeEventListener(type, callback){
var addedType = this.allEvents.get(type)
if(addedType){
return addedType.delete(callback)
}
}
open(){
this.closed = false
var wsProtocol = location.protocol == "https:" ? "wss:" : "ws:"
this.socket = new WebSocket(wsProtocol + "//" + location.host + "/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)
pageEvents.race(this.socket, "open", "close", listener =>{
if(listener === "open"){
return this.openEvent()
}
return this.closeEvent()
})
pageEvents.add(this.socket, "message", this.messageEvent.bind(this))
}
openEvent(){
var addedType = this.allEvents.get("open")
if(addedType){
addedType.forEach(callback => callback())
}
onopen(callback, once){
this.openCallbacks.add({
callback: callback,
once: once
})
}
close(){
this.closed = true
this.socket.close()
}
closeEvent(event){
closeEvent(){
this.removeEventListener(onmessage)
this.otherConnected = false
if(!this.closed){
setTimeout(() => {
if(this.socket.readyState != this.socket.OPEN){
if(this.socket.readyState !== this.socket.OPEN){
this.open()
}
}, 500)
}
this.closeCallbacks.forEach(obj => {
obj.callback()
if(obj.once){
this.closeCallbacks.delete(obj)
var addedType = this.allEvents.get("close")
if(addedType){
addedType.forEach(callback => callback())
}
})
}
onclose(callback, once){
this.closeCallbacks.add({
callback: callback,
once: once
})
}
send(type, value){
if(this.socket.readyState == this.socket.OPEN){
if(typeof value == "undefined"){
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(() => {
pageEvents.once(this, "open").then(() => {
this.send(type, value)
}, true)
})
}
}
messageEvent(event){
try{
var data = JSON.parse(event.data)
var response = JSON.parse(event.data)
}catch(e){
var data = {}
var response = {}
}
this.lastMessages[data.type] = data.value
if(this.msgCallbacks[data.type]){
this.msgCallbacks[data.type].forEach(obj => {
obj.callback(data.value)
if(obj.once){
this.msgCallbacks[data.type].delete(obj)
this.lastMessages[response.type] = response.value
var addedType = this.allEvents.get("message")
if(addedType){
addedType.forEach(callback => callback(response))
}
})
}
}
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])
return this.lastMessages[type]
}
}
message(response){
switch(response.type){
case "gamestart":
this.otherConnected = true
this.notes = []
this.drumrollPace = 45
this.results = false
break
case "gameend":
this.otherConnected = false
break
case "gameresults":
this.results = response.value
break
case "note":
this.notes.push(response.value)
break
case "drumroll":
this.drumrollPace = response.value.pace
break
}
}
play(circle, mekadon){
if(this.otherConnected || this.notes.length > 0){
var type = circle.getType()
if(type == "balloon"|| type == "drumroll" || type == "daiDrumroll"){
if(type === "balloon"|| type === "drumroll" || type === "daiDrumroll"){
mekadon.playDrumrollAt(circle, 0, this.drumrollPace)
}else if(this.notes.length == 0){
}else if(this.notes.length === 0){
mekadon.play(circle)
}else{
var note = this.notes[0]

115
public/src/js/pageevents.js Normal file
View File

@ -0,0 +1,115 @@
class PageEvents{
constructor(){
this.allEvents = new Map()
this.keyListeners = new Map()
this.add(window, "keydown", this.keyEvent.bind(this))
this.add(window, "keyup", this.keyEvent.bind(this))
}
add(target, type, callback){
this.remove(target, type)
var addedEvent = this.allEvents.get(target)
if(!addedEvent){
addedEvent = new Map()
this.allEvents.set(target, addedEvent)
}
addedEvent.set(type, callback)
return target.addEventListener(type, callback)
}
remove(target, type){
var addedEvent = this.allEvents.get(target)
if(addedEvent){
var callback = addedEvent.get(type)
if(callback){
target.removeEventListener(type, callback)
addedEvent.delete(type)
if(addedEvent.size == 0){
return this.allEvents.delete(target)
}
}
}
}
once(target, type){
return new Promise(resolve => {
this.add(target, type, event => {
this.remove(target, type)
return resolve(event)
})
})
}
race(){
var target = arguments[0]
return new Promise(resolve => {
for(var i = 1;i < arguments.length; i++){
let type = arguments[i]
this.add(target, type, event => {
resolve({
type: type,
event: event
})
})
}
}).then(response => {
for(var i = 1;i < arguments.length; i++){
this.remove(target, arguments[i])
}
return response
})
}
load(target){
return new Promise((resolve, reject) => {
this.race(target, "load", "error", "abort").then(response => {
if(response.type === "load"){
return resolve(response.event)
}
return reject()
})
})
}
keyEvent(event){
this.keyListeners.forEach(addedKeyCode => {
this.checkListener(addedKeyCode.get("all"), event)
this.checkListener(addedKeyCode.get(event.keyCode), event)
})
}
checkListener(keyObj, event){
if(keyObj && (
keyObj.type === "both"
|| keyObj.type === "down" && event.type === "keydown"
|| keyObj.type === "up" && event.type === "up"
)){
keyObj.callback(event)
}
}
keyAdd(target, keyCode, type, callback){
// keyCode="all", type="both"
var addedKeyCode = this.keyListeners.get(target)
if(!addedKeyCode){
addedKeyCode = new Map()
this.keyListeners.set(target, addedKeyCode)
}
addedKeyCode.set(keyCode, {
type: type,
callback: callback
})
}
keyRemove(target, keyCode){
var addedKeyCode = this.keyListeners.get(target)
if(addedKeyCode){
var keyObj = addedKeyCode.get(keyCode)
if(keyObj){
addedKeyCode.delete(keyCode)
if(addedKeyCode.size == 0){
return this.keyListeners.delete(target)
}
}
}
}
keyOnce(target, keyCode, type){
return new Promise(resolve => {
this.keyAdd(target, keyCode, type, event => {
this.keyRemove(target, keyCode)
return resolve(event)
})
})
}
}

View File

@ -3,9 +3,8 @@ class Scoresheet{
this.controller = controller
this.score = score
this.multiplayer = multiplayer
$("#screen").load("/src/views/scoresheet.html", () =>{
loader.changePage("scoresheet")
this.run()
})
}
setResults(score, scoreCont){
this.positionning(scoreCont)
@ -36,7 +35,7 @@ class Scoresheet{
this.altText(this.elem("max-combo", scoreCont), score.maxCombo)
this.altText(this.elem("nb-drumroll", scoreCont), score.drumroll)
addEventListener("resize", () => {
pageEvents.add(window, "resize", () => {
this.positionning(scoreCont)
})
}
@ -82,17 +81,16 @@ class Scoresheet{
this.setResults(this.score, scoreCont)
this.altText(this.elem("result-song", this.scoresheet), this.score.song)
this.elem("song-select", this.scoresheet).addEventListener("click", () => {
pageEvents.once(this.elem("song-select", this.scoresheet), "click").then(() => {
this.clean()
assets.sounds["don"].play()
assets.sounds["bgm_result"].stop()
this.controller.songSelection()
})
this.elem("replay", this.scoresheet).addEventListener("click", () => {
pageEvents.once(this.elem("replay", this.scoresheet), "click").then(() => {
this.clean()
assets.sounds["don"].play()
assets.sounds["bgm_result"].stop()
this.controller.restartSong()
})
if(this.multiplayer && p2.results){
var scoreCont2 = document.createElement("div")
scoreCont2.classList.add("score-cont")
@ -101,4 +99,8 @@ class Scoresheet{
this.setResults(p2.results, scoreCont2)
}
}
clean(){
assets.sounds["bgm_result"].stop()
pageEvents.remove(window, "resize")
}
}

View File

@ -1,202 +1,153 @@
function SongSelect(){
var _this=this;
var _songs;
var _selectedSong = {title:'', folder:'', difficulty:''};
var _preview;
var _preview_id = 0
var _diffNames={
easy:"かんたん",
normal:"ふつう",
hard:"むずかしい",
oni:"おに"
class SongSelect{
constructor(){
this.songs
this.selectedSong = {
"title": "",
"folder": "",
"difficulty": ""
}
this.startPreview = function(id, prvtime, first_open=true) {
_this.endPreview();
this.previewId = 0
this.diffNames={
"easy": "かんたん",
"normal": "ふつう",
"hard": "むずかしい",
"oni": "おに"
}
loader.changePage("songselect")
this.run()
}
startPreview(id, prvtime, switchedTo){
this.endPreview()
var startLoad = +new Date
var current_id = _preview_id
if(first_open){
var currentId = this.previewId
if(!switchedTo){
snd.musicGain.fadeOut(0.4)
}
var songObj
assets.songs.forEach(song => {
if(song.id == id){
songObj = song
}
})
var songObj = assets.songs.find(song => song.id == id)
if(songObj.sound){
_preview = songObj.sound
_preview.gain = snd.previewGain
this.previewLoaded(startLoad, prvtime, first_open)
this.preview = songObj.sound
this.preview.gain = snd.previewGain
this.previewLoaded(startLoad, prvtime, switchedTo)
}else{
snd.previewGain.load("/songs/" + id + "/main.mp3").then(sound => {
if(current_id == _preview_id){
if(currentId == this.previewId){
songObj.sound = sound
_preview = sound
this.previewLoaded(startLoad, prvtime, first_open)
this.preview = sound
this.previewLoaded(startLoad, prvtime, switchedTo)
}
})
}
};
this.previewLoaded = function(startLoad, prvtime, first_open){
}
previewLoaded(startLoad, prvtime, switchedTo){
var endLoad = +new Date
var difference = endLoad - startLoad
var minDelay = first_open ? 1000 : 300
var minDelay = switchedTo ? 300 : 1000
var delay = minDelay - Math.min(minDelay, difference)
_preview.playLoop(delay / 1000, false, prvtime / 1000)
this.preview.playLoop(delay / 1000, false, prvtime / 1000)
}
endPreview() {
this.previewId++
if(this.preview){
this.preview.stop()
}
}
run(){
this.createCode()
this.startP2()
this.endPreview = function() {
_preview_id++
if (_preview) {
_preview.stop();
};
};
this.songselHelp = document.getElementById("songsel-help")
pageEvents.once(this.songselHelp, "click").then(() => {
this.clean()
assets.sounds["don"].play()
new Tutorial()
})
this.diffElements = document.getElementsByClassName("difficulty")
for(let difficulty of this.diffElements){
pageEvents.once(difficulty, "click").then(this.onDifficulty.bind(this))
}
this.songElements = document.getElementsByClassName("song")
for(let song of this.songElements){
pageEvents.add(song, "click", this.onSong.bind(this))
}
this.songSelect = document.getElementById("song-select")
}
onDifficulty(event){
this.clean()
var target = event.currentTarget
var song = target.parentNode.parentNode
assets.sounds["don"].play()
this.run = function(){
_this.createCode();
_this.startP2();
this.selectedSong.difficulty = target.classList[1] + ".osu"
this.selectedSong.title = song.dataset.title
this.selectedSong.folder = song.dataset.songId
$("#song-container").show();
$('#songsel-help').click(function(){
assets.sounds["bgm_songsel"].stop()
new loadSong(this.selectedSong, event.shiftKey, event.ctrlKey)
}
onSong(event){
var target = event.currentTarget
var opened = document.getElementsByClassName("opened")[0]
if(!opened){
this.startPreview(target.dataset.songId, target.dataset.preview)
assets.sounds["don"].play()
assets.sounds["song-select"].stop()
assets.sounds["diffsel"].stop()
assets.sounds["don"].play()
snd.musicGain.fadeIn()
_this.endPreview();
new Tutorial();
});
$(".difficulty").click(function(e){
_this.endPreview();
assets.sounds["bgm_songsel"].stop()
assets.sounds["diffsel"].stop()
assets.sounds["don"].play()
var difficultyElement = (e.target.className=="stars" || e.target.className=="diffname") ? e.target.parentElement : e.target;
_selectedSong.difficulty = difficultyElement.classList[1]+'.osu';
var parentID = $(this).parent().closest(".song").attr("id");
var songID = parseInt(parentID.substr(5, parentID.length-1));
_selectedSong.title = $(this).parent().closest('.song').data('title');
_selectedSong.folder = songID;
snd.musicGain.fadeIn()
new loadSong(_selectedSong, e.shiftKey, e.ctrlKey);
});
$(".song").hover(function(){
if(!$(this).hasClass("opened"))
$(this).css("background", "rgba(255, 233, 125, 0.90)");
},
function(){
if(!$(this).hasClass("opened"))
$(this).css("background", "rgba(255, 220, 47, 0.90)");
});
$(".song").click(function(e){
if (!$(e.target).parents('.difficulties').length) {
if ($(".opened").length && $(".opened").attr('id') == $(this).attr('id')) {
_this.endPreview();
assets.sounds["diffsel"].play(0.3)
target.classList.add("opened")
this.songSelect.classList.add("difficulty-select")
}else if(opened == target){
this.endPreview()
snd.musicGain.fadeIn(0.4)
assets.sounds["diffsel"].stop()
assets.sounds["cancel"].play()
assets.sounds["song-select"].play(0.3)
$(".difficulty").hide();
$(".opened").removeClass("opened", 300);
$('.songsel-title').fadeOut(200, function(){
$('.songsel-title').attr('alt', '曲をえらぶ').html('曲をえらぶ').css('left', -300);
$('.songsel-title').animate({left:0, opacity:"show"}, 400);
});
return;
opened.classList.remove("opened")
this.songSelect.classList.remove("difficulty-select")
}else{
this.startPreview(target.dataset.songId, target.dataset.preview, true)
assets.sounds["ka"].play()
opened.classList.remove("opened")
target.classList.add("opened")
}
if(!$('.opened').length) {
_this.startPreview($(this).data('song-id'), $(this).data('preview'));
assets.sounds["don"].play()
assets.sounds["song-select"].stop()
assets.sounds["diffsel"].play(0.3)
$('.songsel-title').fadeOut(200, function(){
$('.songsel-title').attr('alt', 'むずかしさをえらぶ').html('むずかしさをえらぶ').css('left', -300);
$('.songsel-title').animate({left:0, opacity:"show"}, 400);
});
} else {
_this.startPreview($(this).data('song-id'), $(this).data('preview'), false);
assets.sounds["ka"].play();
}
};
$(".difficulty").hide();
$(".opened").removeClass("opened", 300);
$(this).addClass("opened", 300, "linear", function(){
$(this).find(".difficulty").show();
$(this).css("background", "rgba(255, 220, 47, 0.90)");
});
});
}
this.createCode = function(){
createCode(){
assets.sounds["bgm_songsel"].playLoop(0.1, false, 0, 1.442, 3.506)
assets.sounds["song-select"].play(0.2);
assets.sounds["song-select"].play(0.2)
var songElements = [0]
for(var i=0; i<assets.songs.length; i++){
var song = assets.songs[i];
var songTitle = song.title;
var skipChars = [];
assets.songs.forEach(song => {
var songTitle = song.title
var charElements = [0]
var diffElements = [0]
for (var c=0; c<songTitle.length; c++) {
if (skipChars.indexOf(c) > -1) {
continue;
};
var ch = songTitle.charAt(c) == " " ? "\xa0" : songTitle.charAt(c);
var isApos = false;
if (songTitle.charAt(c+1) == "'") {
ch = ch + "'";
skipChars.push(c+1);
isApos = true;
};
var cl = ch == "\xa0" ? "song-title-char song-title-space" : "song-title-char";
cl = isApos ? cl + " song-title-apos" : cl;
for(var charIndex = 0; charIndex < songTitle.length; charIndex++){
var ch = songTitle.charAt(charIndex)
var cl = "song-title-char"
if(ch == " "){
ch = "\xa0"
cl += " song-title-space"
}else if(songTitle.charAt(charIndex + 1) == "'"){
ch = ch + "'"
cl += " song-title-apos"
charIndex++
}
charElements.push(
["span", {
class: cl,
alt: ch
}, ch]
)
};
for(var diff in _diffNames){
var diffName = diff;
var diffLevel = song.stars[diff];
if (!diffLevel) {
continue;
}
for(var diff in this.diffNames){
var diffName = diff
var diffLevel = song.stars[diff]
if (!diffLevel) {
continue
}
var starsDisplay = [0]
for(var x=1; x<=diffLevel; x++){
for(var star = 1; star <= diffLevel; star++){
starsDisplay.push("\u2605")
starsDisplay.push(["br"])
}
var diffTxt=_diffNames[diffName]
var diffTxt = this.diffNames[diffName]
diffElements.push(
["li", {
class: "difficulty " + diffName
@ -209,9 +160,7 @@ function SongSelect(){
}, starsDisplay]
]
)
}
songElements.push(
["div", {
id: "song-" + song.id,
@ -228,25 +177,22 @@ function SongSelect(){
}, diffElements]
]
)
}
})
element(
document.getElementById("song-container"),
songElements
)
$('.difficulty').hide();
}
this.onusers = function(response){
onusers(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 id = idDiff.id |0
var diff = idDiff.diff
if(diff in this.diffNames){
var idElement = document.getElementById("song-" + id)
if(idElement){
idElement.classList.add("p2")
@ -259,19 +205,34 @@ function SongSelect(){
})
}
}
this.startP2 = function(){
p2.getMessage("users", response =>{
this.onusers(response)
})
p2.onmessage("users", response => {
this.onusers(response)
startP2(){
this.onusers(p2.getMessage("users"))
pageEvents.add(p2, "message", response => {
if(response.type == "users"){
this.onusers(response.value)
}
})
if(p2.closed){
p2.open()
}
}
$("#screen").load("/src/views/songselect.html", _this.run);
clean(){
assets.sounds["bgm_songsel"].stop()
assets.sounds["song-select"].stop()
assets.sounds["diffsel"].stop()
this.endPreview()
snd.musicGain.fadeIn()
pageEvents.remove(p2, "message")
for(let difficulty of this.diffElements){
pageEvents.remove(difficulty, "click")
}
delete this.diffElements
for(let song of this.songElements){
pageEvents.remove(song, "click")
}
delete this.songElements
pageEvents.remove(this.songselHelp, "click")
delete this.songselHelp
delete this.songSelect
}
}

View File

@ -1,27 +1,19 @@
class SoundBuffer{
constructor(){
this.context = new AudioContext()
var resume = () => {
pageEvents.once(window, "click").then(() => {
if(this.context.state == "suspended"){
this.context.resume()
}
removeEventListener("click", resume)
}
addEventListener("click", resume)
})
}
load(url, gain){
return new Promise((resolve, reject) => {
var request = new XMLHttpRequest()
request.open("GET", url)
return loader.ajax(url, request => {
request.responseType = "arraybuffer"
request.addEventListener("load", () => {
this.context.decodeAudioData(request.response, buffer => {
resolve(new Sound(gain || {soundBuffer: this}, buffer))
}, reject)
})
request.addEventListener("error", reject)
request.addEventListener("abort", reject)
request.send()
}).then(response => {
return this.context.decodeAudioData(response)
}).then(buffer => {
return new Sound(gain || {soundBuffer: this}, buffer)
})
}
createGain(){

View File

@ -1,53 +1,24 @@
function Titlescreen(){
var _this = this;
$("body").css("font-family", "TnT");
this.positionning = function(){
var width = 0.70*$(window).width();
var logoW = (width>=654) ? 654 : width;
var logoH = logoW/2.18;
$("#logo-big-cont").width(logoW);
$("#logo-big-cont").height(logoH);
$("#logo-big-cont").css("left", $(window).width()/2-($("#logo-big-cont").width()/2));
$("#logo-big-cont").css("top", $(window).height()/2-($("#logo-big-cont").height()/2));
class Titlescreen{
constructor(){
loader.changePage("titlescreen")
this.titleScreen = document.getElementById("title-screen")
pageEvents.keyOnce(this, 13, "down").then(this.goNext.bind(this))
pageEvents.once(this.titleScreen, "click").then(this.goNext.bind(this))
assets.sounds["title"].play()
}
this.run = function(){
$(document).keypress(function(e){
if(e.keyCode==13 && $("#screen").find("#title-screen").html())
_this.goNext();
});
$("#screen").find("#title-screen").click(function(){
_this.goNext();
});
_this.positionning();
$("#screen").find("#title-screen").show();
$(window).resize(_this.positionning);
assets.sounds["title"].play();
}
this.goNext = function(){
assets.sounds["title"].pause();
assets.sounds["title"].currentTime = 0;
assets.sounds["don"].play();
if (localStorage.getItem('tutorial') !== 'true') {
new Tutorial();
goNext(){
this.clean()
assets.sounds["don"].play()
if(localStorage.getItem("tutorial") !== "true"){
new Tutorial()
} else {
new SongSelect();
};
new SongSelect()
}
}
clean(){
assets.sounds["title"].stop()
pageEvents.keyRemove(this, 13)
pageEvents.remove(this.titleScreen, "click")
delete this.titleScreen
}
$("#screen").load("/src/views/titlescreen.html", _this.run);
}

View File

@ -1,17 +1,19 @@
function Tutorial() {
var _this = this;
this.run = function() {
class Tutorial{
constructor(){
loader.changePage("tutorial")
assets.sounds["bgm_setsume"].playLoop(0.1, false, 0, 1.054, 16.054)
$('#tutorial-end-button').click(function(){
assets.sounds["bgm_setsume"].stop();
assets.sounds["don"].play();
localStorage.setItem('tutorial', 'true');
new SongSelect();
});
};
$('#screen').load('/src/views/tutorial.html', _this.run);
};
this.endButton = document.getElementById("tutorial-end-button")
pageEvents.once(this.endButton, "click").then(this.onEnd.bind(this))
}
onEnd(){
this.clean()
assets.sounds["don"].play()
localStorage.setItem("tutorial", "true")
new SongSelect()
}
clean(){
assets.sounds["bgm_setsume"].stop()
pageEvents.remove(this.endButton, "click")
delete this.endButton
}
}

View File

@ -4,17 +4,21 @@ 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.pauseMenu = document.getElementById("pause-menu")
var docW = document.body.offsetWidth
var docH = document.body.offsetHeight
if(this.controller.multiplayer === 2){
this.canvas = new ScalableCanvas("canvas-p2", docW, docH / 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.canvas = new ScalableCanvas("canvas", docW, docH)
}
this.winW = this.canvas.scaledWidth
this.winH = this.canvas.scaledHeight
if(this.controller.multiplayer == 2){
if(this.controller.multiplayer === 2){
this.winH = this.winH / 2 * 3
}
this.ctx = this.canvas.ctx
@ -74,19 +78,22 @@ class View{
run(){
this.ctx.font = "normal 14pt TnT"
this.setBackground()
$(".game-song").attr("alt", this.songTitle).html(this.songTitle)
var gameSong = document.getElementsByClassName("game-song")[0]
gameSong.appendChild(document.createTextNode(this.songTitle))
gameSong.setAttribute("alt", this.songTitle)
this.refresh()
}
setBackground(){
$("#game").css("background-image", "url('" + this.bg + "')")
document.getElementById("game").style.backgroundImage = "url('" + this.bg + "')"
}
positionning(){
var docW = document.body.offsetWidth
var docH = document.body.offsetHeight
this.canvas.rescale()
var height = $(window).height()
if(this.controller.multiplayer == 2){
height = height / 3 * 2
docH = docH / 3 * 2
}
this.canvas.resize($(window).width(), height)
this.canvas.resize(docW, docH)
this.winW = this.canvas.scaledWidth
this.winH = this.canvas.scaledHeight
if(this.controller.multiplayer == 2){
@ -597,10 +604,10 @@ class View{
}
}
togglePauseMenu(){
if($("#pause-menu").is(":visible")){
$("#pause-menu").hide()
if(this.controller.game.isPaused()){
this.pauseMenu.style.display = "block"
}else{
$("#pause-menu").show()
this.pauseMenu.style.display = ""
}
}
drawDifficulty(){
@ -728,4 +735,10 @@ class View{
})
}
}
clean(){
delete this.pauseMenu
delete this.canvas
delete this.ctx
}
}

View File

@ -1,4 +1,4 @@
<div id="loader">
<div class='progress'></div>
<span class='percentage'>0%</span>
<div class="progress"></div>
<span class="percentage">0%</span>
</div>

View File

@ -1,6 +1,6 @@
<div id='load-song'>
<div id='loading-song'>
<img id='loading-don' src="/assets/img/dancing-don.gif" />
<p>Loading...</p>
<div id="load-song">
<div id="loading-song">
<img id="loading-don" src="/assets/img/dancing-don.gif">
<div class="loading-text stroke-sub" alt="Loading...">Loading...</div>
</div>
</div>

View File

@ -1,5 +1,6 @@
<div id="song-select">
<h2 alt="曲をえらぶ" class="stroke-main songsel-title">曲をえらぶ</h2>
<h2 alt="曲をえらぶ" class="stroke-main songsel-title-song">曲をえらぶ</h2>
<h2 alt="むずかしさをえらぶ" class="stroke-main songsel-title-difficulty">むずかしさをえらぶ</h2>
<div id="songsel-help">?</div>
<div id='song-container'></div>
<div id="song-container"></div>
</div>

View File

@ -1,4 +1,4 @@
<div id='title-screen'>
<div id='logo-big-cont'><img src="/assets/img/logo-big.png" alt="太鼓の達人ウェブ" /></div>
<h2 class='click-to-continue stroke-sub' alt="Click or press enter">Click or press enter</h2>
<div id="title-screen">
<img class="logo-big" src="/assets/img/logo-big.png" alt="太鼓の達人ウェブ">
<div class="click-to-continue stroke-sub" alt="Click or Press Enter!">Click or Press Enter!</h2>
</div>

View File

@ -51,6 +51,9 @@ async def connection(ws, path):
except asyncio.TimeoutError:
# Disconnect
break
except websockets.exceptions.ConnectionClosed:
# Connection closed
break
else:
# Message received
try: