Buffer every sound asset

This commit is contained in:
LoveEevee 2018-09-11 01:17:13 +03:00
parent 66b0924252
commit 0feb31227a
17 changed files with 510 additions and 506 deletions

View File

@ -12,8 +12,9 @@
<html> <html>
<meta charset="UTF-8"> <meta charset="UTF-8">
<head> <head>
<title>太鼓の達人ウェブ - Taiko no Tatsujin Web</title> <title>太鼓の達人ウェブ - Taiko no Tatsujin Web</title>
<link rel="icon" href="/assets/img/favicon.png" type="image/png">
<link rel="stylesheet" href="/src/css/main.css"/> <link rel="stylesheet" href="/src/css/main.css"/>
<link rel="stylesheet" href="/src/css/loader.css"> <link rel="stylesheet" href="/src/css/loader.css">
<link rel="stylesheet" href="/src/css/titlescreen.css"> <link rel="stylesheet" href="/src/css/titlescreen.css">
@ -23,37 +24,32 @@
<link rel="stylesheet" href="/src/css/game.css"> <link rel="stylesheet" href="/src/css/game.css">
<link rel="stylesheet" href="/src/css/animations.css"> <link rel="stylesheet" href="/src/css/animations.css">
<link rel="icon" href="/assets/img/favicon.png" type="image/png"> <script src="/src/js/lib/jquery.js"></script>
<link rel="shortcut icon" href="/assets/img/favicon.png" type="image/png"> <script src="/src/js/lib/jquery-ui.js"></script>
<script src="/src/js/lib/fontdetect.min.js"></script>
<script type='application/javascript' src='/src/js/lib/jquery.js'></script> <script src="/src/js/assets.js"></script>
<script type='application/javascript' src='/src/js/lib/jquery-ui.js'></script> <script src="/src/js/loadsong.js"></script>
<script type='application/javascript' src='/src/js/lib/fontdetect.min.js'></script> <script src="/src/js/parsesong.js"></script>
<script src="/src/js/titlescreen.js"></script>
<script type='application/javascript' src='/src/js/assets.js'></script> <script src="/src/js/scoresheet.js"></script>
<script type='application/javascript' src='/src/js/loader.js'></script> <script src="/src/js/songselect.js"></script>
<script type='application/javascript' src='/src/js/loadsong.js'></script> <script src="/src/js/keyboard.js"></script>
<script type='application/javascript' src='/src/js/parsesong.js'></script> <script src="/src/js/game.js"></script>
<script type='application/javascript' src='/src/js/titlescreen.js'></script> <script src="/src/js/controller.js"></script>
<script type='application/javascript' src='/src/js/scoresheet.js'></script> <script src="/src/js/circle.js"></script>
<script type='application/javascript' src='/src/js/songselect.js'></script> <script src="/src/js/view.js"></script>
<script type='application/javascript' src='/src/js/soundsystem.js'></script> <script src="/src/js/mekadon.js"></script>
<script type='application/javascript' src='/src/js/keyboard.js'></script> <script src="/src/js/gamepad.js"></script>
<script type='application/javascript' src='/src/js/game.js'></script> <script src="/src/js/tutorial.js"></script>
<script type='application/javascript' src='/src/js/controller.js'></script> <script src="/src/js/scalablecanvas.js"></script>
<script type='application/javascript' src='/src/js/circle.js'></script> <script src="/src/js/element.js"></script>
<script type='application/javascript' src='/src/js/main.js'></script> <script src="/src/js/soundbuffer.js"></script>
<script type='application/javascript' src='/src/js/view.js'></script>
<script type='application/javascript' src='/src/js/bufferedloop.js'></script>
<script type='application/javascript' src='/src/js/mekadon.js'></script>
<script type='application/javascript' src='/src/js/gamepad.js'></script>
<script type='application/javascript' src='/src/js/tutorial.js'></script>
<script type='application/javascript' src='/src/js/scalablecanvas.js'></script>
<script type='application/javascript' src='/src/js/element.js'></script>
</head> </head>
<body> <body>
<div id="assets"></div> <div id="assets"></div>
<div id="screen"></div> <div id="screen"></div>
<script src="/src/js/loader.js"></script>
</body> </body>
</html> </html>

View File

@ -23,7 +23,7 @@ html, body{
height:100%; height:100%;
margin:0; margin:0;
padding:0; padding:0;
background: url('/assets/img/bg-pattern-1.png'); background: url('/assets/img/bg-pattern-1.png') top center;
} }
#assets{ #assets{

View File

@ -1,6 +1,6 @@
var assets = { var assets = {
img: new Array( img: [
'background.png', 'background.png',
'title-screen.png', 'title-screen.png',
'logo-big.png', 'logo-big.png',
@ -28,9 +28,9 @@ var assets = {
'muzu_hard.png', 'muzu_hard.png',
'muzu_oni.png', 'muzu_oni.png',
'don_anim_normal.png' 'don_anim_normal.png'
), ],
audio: new Array( audioSfx: [
'start.wav', 'start.wav',
'don.wav', 'don.wav',
'ka.wav', 'ka.wav',
@ -82,21 +82,20 @@ var assets = {
'note_don.ogg', 'note_don.ogg',
'note_ka.ogg', 'note_ka.ogg',
],
audioMusic:[
'bgm_songsel.ogg', 'bgm_songsel.ogg',
'bgm_songsel_loop.ogg',
'bgm_result.ogg', 'bgm_result.ogg',
'bgm_result_loop.ogg', 'bgm_setsume.ogg'
'bgm_setsume.ogg', ],
'bgm_setsume_loop.ogg'
),
songs: new Array(), songs: [],
fonts: new Array( fonts: [
'Kozuka', 'Kozuka',
'TnT' 'TnT'
), ],
sounds: {}, sounds: {},
image: {} image: {}

View File

@ -1,92 +0,0 @@
// thx to @LoveEevee for this - https://github.com/LoveEevee
class BufferedLoop{
constructor(bgm1,bgm2){
this.context=new AudioContext()
this.buffers=[]
this.sources=new Set()
this.loadCallback=[]
this.bufferedTime=0
this.bgm1=bgm1
this.bgm2=bgm2
this.loadSound(bgm1.url,0)
this.loadSound(bgm2.url,1)
}
loadSound(url,number){
var self=this
var request=new XMLHttpRequest()
request.open("GET",url)
request.responseType="arraybuffer"
request.onload=function(){
self.context.decodeAudioData(request.response,function(buffer){
self.buffers[number]=buffer
self.setLoaded()
})
}
request.send()
}
setLoaded(){
if(this.buffers[0]&&this.buffers[1]){
this.loaded=true
for(var i in this.loadCallback){
this.loadCallback[i]()
}
}
}
onLoad(callback){
this.loadCallback.push(callback)
}
playSound(buffer,time,duration){
var self=this
var source=this.context.createBufferSource()
source.buffer=buffer
source.connect(this.context.destination)
source.start(time)
this.bufferedTime=time+duration
var sourceObject={
source:source,
timeout:setTimeout(function(){
self.sources.delete(sourceObject)
},duration*1000)
}
this.sources.add(sourceObject)
}
addLoop(){
if(this.context.currentTime>this.bufferedTime-1){
this.playSound(
this.buffers[1],
this.start+this.bgm1.duration+this.bgm2.duration*this.iteration,
this.bgm2.duration
)
this.iteration++
}
}
play(){
var self=this
if(!this.loaded){
return this.onLoad(function(){
self.play()
})
}
this.start=this.context.currentTime+0.1
this.iteration=0
this.playSound(
this.buffers[0],
this.start,
this.bgm1.duration
)
self.addLoop()
self.interval=setInterval(function(){
self.addLoop()
},100)
}
pause(){
var self=this
clearInterval(this.interval)
this.sources.forEach(function(sourceObject){
sourceObject.source.stop(0)
clearTimeout(sourceObject.timeout)
self.sources.delete(sourceObject)
})
}
}

View File

@ -12,6 +12,12 @@ function Controller(selectedSong, songData, autoPlayEnabled){
var _keyboard = new Keyboard(this); var _keyboard = new Keyboard(this);
var _mainLoop; var _mainLoop;
var _pauseMenu = false; var _pauseMenu = false;
var _mainAsset
assets.songs.forEach(song => {
if(song.id == selectedSong.folder){
_mainAsset = song.sound
}
})
this.autoPlayEnabled = autoPlayEnabled this.autoPlayEnabled = autoPlayEnabled
@ -25,11 +31,11 @@ function Controller(selectedSong, songData, autoPlayEnabled){
this.loadUIEvents = function(){ this.loadUIEvents = function(){
$("#song-selection-butt").click(function(){ $("#song-selection-butt").click(function(){
assets.sounds["don"].playAsset(); assets.sounds["don"].play();
_this.songSelection(); _this.songSelection();
}); });
$("#restart-butt").click(function(){ $("#restart-butt").click(function(){
assets.sounds["don"].playAsset(); assets.sounds["don"].play();
_this.restartSong(); _this.restartSong();
}); });
$("#continue-butt").click(function(){ $("#continue-butt").click(function(){
@ -48,10 +54,7 @@ function Controller(selectedSong, songData, autoPlayEnabled){
_view.refresh(); _view.refresh();
} }
else if(ms>=0 && !started){ //when music shall starts else if(ms>=0 && !started){ //when music shall starts
setTimeout(function(){ _mainAsset.play(_songData.generalInfo.audioWait)
assets.sounds["main-music"].volume = 0.7;
assets.sounds["main-music"].playAsset();
}, _songData.generalInfo.audioWait);
started=true; started=true;
} }
@ -85,20 +88,17 @@ function Controller(selectedSong, songData, autoPlayEnabled){
if (score.fail == 0) { if (score.fail == 0) {
vp = 'fullcombo'; vp = 'fullcombo';
setTimeout(function(){ _this.playSoundMeka('fullcombo', 1350);
_this.playSoundMeka('fullcombo');
}, 1350);
} else if (score.hp >= 50) { } else if (score.hp >= 50) {
vp = 'clear'; vp = 'clear';
} else { } else {
vp = 'fail'; vp = 'fail';
} }
assets.sounds['game' + vp].playAsset(); assets.sounds['game' + vp].play();
setTimeout(function(){ setTimeout(function(){
var scoresheet = new Scoresheet(_this, _this.getGlobalScore()); new Scoresheet(_this, _this.getGlobalScore());
scoresheet.run();
}, 7000); }, 7000);
} }
@ -123,8 +123,7 @@ function Controller(selectedSong, songData, autoPlayEnabled){
} }
this.restartSong = function(){ this.restartSong = function(){
assets.sounds["main-music"].pause(); _mainAsset.stop()
assets.sounds["main-music"].currentTime=0;
clearInterval(_mainLoop); clearInterval(_mainLoop);
$("#screen").load("/src/views/game.html", function(){ $("#screen").load("/src/views/game.html", function(){
var taikoGame = new Controller(selectedSong, songData, autoPlayEnabled); var taikoGame = new Controller(selectedSong, songData, autoPlayEnabled);
@ -132,16 +131,8 @@ function Controller(selectedSong, songData, autoPlayEnabled){
}); });
} }
this.playSound = function(soundID){ this.playSoundMeka = function(soundID, time){
_game.playSound(soundID); assets.sounds[soundID + (autoPlayEnabled ? '-meka' : '')].play(time)
}
this.playSoundMeka = function(soundID){
_game.playSound(soundID + (autoPlayEnabled ? '-meka' : ''));
}
this.pauseSound = function(soundID, stop){
_game.pauseSound(soundID, stop);
} }
this.initTiming = function(){ this.initTiming = function(){

View File

@ -6,7 +6,6 @@ function Game(controller, selectedSong, songData){
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
var _soundSystem = new soundSystem(controller);
var _songData=songData; var _songData=songData;
var _currentCircle=0; var _currentCircle=0;
var _currentScore=0; var _currentScore=0;
@ -24,6 +23,12 @@ function Game(controller, selectedSong, songData){
var _offsetTime=0; var _offsetTime=0;
var _hitcircleSpeed=_songData.difficulty.sliderMultiplier*8; var _hitcircleSpeed=_songData.difficulty.sliderMultiplier*8;
var _timeForDistanceCircle; var _timeForDistanceCircle;
var _mainAsset
assets.songs.forEach(song => {
if(song.id == selectedSong.folder){
_mainAsset = song.sound
}
})
this.run = function(){ this.run = function(){
_timeForDistanceCircle=((20*controller.getDistanceForCircle())/_hitcircleSpeed); _timeForDistanceCircle=((20*controller.getDistanceForCircle())/_hitcircleSpeed);
@ -185,20 +190,22 @@ function Game(controller, selectedSong, songData){
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(_ellapsedTime.ms>=lastCircle.getMS()+2000){ if(!_fadeOutStarted && _ellapsedTime.ms>=lastCircle.getMS()+2000){
_fadeOutStarted=true; _fadeOutStarted=_ellapsedTime.ms
} }
} }
this.whenFadeoutMusic = function(){ this.whenFadeoutMusic = function(){
if(_fadeOutStarted){ if(_fadeOutStarted){
if(_musicFadeOut%8==0){ if(_musicFadeOut==0){
_soundSystem.fadeOutMusic(); snd.musicGain.fadeOut(1.6)
_musicFadeOut++; _mainAsset.stop(1.6)
snd.musicGain.fadeIn(0, 1.7)
} }
else{ if(_ellapsedTime.ms>=_fadeOutStarted+1600){
_musicFadeOut++; controller.fadeOutOver()
} }
_musicFadeOut++;
} }
} }
@ -217,11 +224,11 @@ function Game(controller, selectedSong, songData){
this.toggleMainMusic = function(){ this.toggleMainMusic = function(){
if(_mainMusicPlaying){ if(_mainMusicPlaying){
assets.sounds["main-music"].pause(); _mainAsset.pause();
_mainMusicPlaying=false; _mainMusicPlaying=false;
} }
else{ else{
assets.sounds["main-music"].playAsset(); _mainAsset.play(0, false, _this.getEllapsedTime().ms / 1000);
_mainMusicPlaying=true; _mainMusicPlaying=true;
} }
} }
@ -230,10 +237,6 @@ function Game(controller, selectedSong, songData){
_fadeOutStarted=false; _fadeOutStarted=false;
} }
this.playSound = function(soundID){
_soundSystem.playSound(soundID);
}
this.pauseSound = function(soundID, stop){ this.pauseSound = function(soundID, stop){
_soundSystem.pauseSound(soundID, stop); _soundSystem.pauseSound(soundID, stop);
} }
@ -244,14 +247,14 @@ function Game(controller, selectedSong, songData){
this.togglePause = function(){ this.togglePause = function(){
if(!_paused){ if(!_paused){
assets.sounds["pause"].playAsset(); assets.sounds["pause"].play();
_paused=true; _paused=true;
_latestDate = new Date(); _latestDate = new Date();
_this.toggleMainMusic(); _this.toggleMainMusic();
} }
else{ else{
assets.sounds["cancel"].playAsset(); assets.sounds["cancel"].play();
_paused=false; _paused=false;
var currentDate = new Date(); var currentDate = new Date();
_ellapsedTimeSincePause = _ellapsedTimeSincePause + Math.abs(currentDate.getTime() - _latestDate.getTime()); _ellapsedTimeSincePause = _ellapsedTimeSincePause + Math.abs(currentDate.getTime() - _latestDate.getTime());

View File

@ -67,7 +67,7 @@ function Keyboard(controller){
this.checkMenuKeys = function(){ this.checkMenuKeys = function(){
_gamepad.play(1) _gamepad.play(1)
_this.checkKey(_kbd["back"], "menu", function(){ _this.checkKey(_kbd["back"], "menu", function(){
controller.pauseSound("main-music", true); controller.togglePause();
controller.songSelection(); controller.songSelection();
}) })
_this.checkKey(_kbd["pause"], "menu", function(){ _this.checkKey(_kbd["pause"], "menu", function(){
@ -84,7 +84,7 @@ function Keyboard(controller){
this.checkKeySound = function(keyCode, sound){ this.checkKeySound = function(keyCode, sound){
_this.checkKey(keyCode, "sound", function(){ _this.checkKey(keyCode, "sound", function(){
controller.playSound("note_"+sound); assets.sounds["note_"+sound].play()
_keyTime[sound] = controller.getEllapsedTime().ms _keyTime[sound] = controller.getEllapsedTime().ms
}) })
} }

View File

@ -1,92 +1,103 @@
function Loader(){ class Loader{
constructor(){
this.loadedAssets = 0
this.errorCount = 0
this.assetsDiv = document.getElementById("assets")
this.promises = []
$("#screen").load("/src/views/loader.html", () => {
this.run()
})
}
run(){
this.loaderPercentage = document.querySelector("#loader .percentage")
var _this=this; assets.fonts.forEach(name => {
var _loadedAssets=0;
var _percentage=0;
var _nbAssets=assets.audio.length+assets.img.length+assets.fonts.length+1; //+1 for song structures
var _assetsDiv=document.getElementById("assets")
var _loaderPercentage
var _errorCount=0
this.run = function(){
_loaderPercentage = document.querySelector("#loader .percentage")
assets.fonts.forEach(function(name){
var font = document.createElement("h1") var font = document.createElement("h1")
font.style.fontFamily = name font.style.fontFamily = name
font.appendChild(document.createTextNode("I am a font")) font.appendChild(document.createTextNode("I am a font"))
_assetsDiv.appendChild(font) this.assetsDiv.appendChild(font)
FontDetect.onFontLoaded (name, _this.assetLoaded, _this.errorMsg, {msTimeout: 90000}); this.promises.push(new Promise((resolve, reject) => {
}); FontDetect.onFontLoaded(name, resolve, reject, {msTimeout: 90000})
}))
assets.img.forEach(function(name){
var id = name.substr(0, name.length-4);
var image = document.createElement("img")
image.addEventListener("load", event=>{
_this.assetLoaded();
}) })
assets.img.forEach(name => {
var id = name.substr(0, name.length - 4)
var image = document.createElement("img")
this.promises.push(promiseLoad(image))
image.id = name image.id = name
image.src = "/assets/img/" + name image.src = "/assets/img/" + name
_assetsDiv.appendChild(image) this.assetsDiv.appendChild(image)
assets.image[id] = image assets.image[id] = image
}); })
assets.audio.forEach(function(name){ snd.buffer = new SoundBuffer()
var id = name.substr(0, name.length-4); snd.musicGain = snd.buffer.createGain()
assets.sounds[id] = new Audio(); snd.sfxGain = snd.buffer.createGain()
assets.sounds[id].muted = true; snd.buffer.setCrossfade(snd.musicGain, snd.sfxGain, 0.5)
assets.sounds[id].playAsset = function(){ snd.previewGain = snd.buffer.createGain()
try{ snd.previewGain.setVolume(0.5)
assets.sounds[id].muted = false;
assets.sounds[id].play()
}catch(e){
console.warn(e)
}
}
assets.sounds[id].onloadeddata = function(){
_this.assetLoaded();
};
assets.sounds[id].src = '/assets/audio/'+name;
assets.sounds[id].load();
});
$.ajax({ assets.audioSfx.forEach(name => {
url: "/api/songs", var id = name.substr(0, name.length-4)
mimeType: "application/json", this.promises.push(snd.sfxGain.load("/assets/audio/" + name).then(sound => {
success: function(songs){ assets.sounds[id] = sound
assets.songs = songs; }))
_this.assetLoaded(); })
}, assets.audioMusic.forEach(name => {
error: _this.errorMsg 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(ajax("/api/songs").then(songs => {
assets.songs = JSON.parse(songs)
}))
this.errorMsg = function(){ this.promises.forEach(promise => {
if(_errorCount == 0){ promise.then(() => {
_loaderPercentage.appendChild(document.createElement("br")) this.assetLoaded()
_loaderPercentage.appendChild(document.createTextNode("An error occured, please refresh")) }, () => {
} this.errorMsg()
_errorCount++ })
} })
this.assetLoaded = function(){ Promise.all(this.promises).then(() => {
_loadedAssets++; new Titlescreen()
_percentage=parseInt((_loadedAssets*100)/_nbAssets); })
$("#loader .progress").css("width", _percentage+"%");
_loaderPercentage.firstChild.data=_percentage+"%"
_this.checkIfEverythingLoaded();
} }
errorMsg(){
this.checkIfEverythingLoaded = function(){ if(this.errorCount == 0){
if(_percentage==100){ this.loaderPercentage.appendChild(document.createElement("br"))
new Titlescreen(); this.loaderPercentage.appendChild(document.createTextNode("An error occurred, please refresh"))
//var globalScore={points:1000, great:100, good:60, fail:10, maxCombo:50, hp:90};
//new Scoresheet(null, globalScore);
} }
this.errorCount++
}
assetLoaded(){
this.loadedAssets++
var percentage = parseInt(this.loadedAssets * 100 / this.promises.length)
document.querySelector("#loader .progress").style.width = percentage + "%"
this.loaderPercentage.firstChild.data = percentage + "%"
} }
$("#screen").load("/src/views/loader.html", _this.run);
} }
function ajax(url){
return new Promise((resolve, reject) => {
var request = new XMLHttpRequest()
request.open("GET", url)
promiseLoad(request).then(() => {
resolve(request.response)
}, reject)
request.send()
})
}
function promiseLoad(asset){
return new Promise((resolve, reject) => {
asset.addEventListener("load", resolve)
asset.addEventListener("error", reject)
asset.addEventListener("abort", reject)
})
}
var snd = {}
new Loader()

View File

@ -1,66 +1,52 @@
function loadSong(selectedSong, autoPlayEnabled){ class loadSong{
constructor(selectedSong, autoPlayEnabled){
this.selectedSong = selectedSong
this.autoPlayEnabled = autoPlayEnabled
this.songFilePath = "/songs/" + this.selectedSong.folder + "/" + this.selectedSong.difficulty
$("#screen").load("/src/views/loadsong.html", () => {
this.run()
})
}
run(){
var id = this.selectedSong.folder
var promises = []
assets.sounds["start"].play()
var _this = this; var img = document.createElement("img")
var _selectedSong=selectedSong; promises.push(promiseLoad(img))
var _bgLoaded=false; img.id = "music-bg"
var _musicLoaded=false; img.src = "/songs/" + id + "/bg.png"
var _songDataLoaded=false; document.getElementById("assets").appendChild(img)
var _songFilePath = '/songs/'+_selectedSong.folder+'/'+_selectedSong.difficulty;
var _songData;
this.run = function(){ promises.push(new Promise((resolve, reject) => {
var songObj
assets.songs.forEach(song => {
if(song.id == id){
songObj = song
}
})
if(songObj.sound){
songObj.sound.gain = snd.musicGain
resolve()
}else{
snd.musicGain.load("/songs/" + id + "/main.mp3").then(sound => {
songObj.sound = sound
resolve()
}, reject)
}
}))
assets.sounds["bgm_songsel"].pause(); promises.push(ajax(this.songFilePath).then(data => {
assets.sounds["bgm_songsel"].currentTime = 0; this.songData = data.replace(/\0/g, "").split("\n")
}))
assets.sounds["start"].playAsset(); Promise.all(promises).then(() => {
$("#assets").append("<img id='music-bg' src='/songs/"+_selectedSong.folder+"/bg.png' />"); $("#screen").load("/src/views/game.html", () => {
var taikoGame = new Controller(this.selectedSong, this.songData, this.autoPlayEnabled)
var audio = new Audio(); taikoGame.run()
audio.muted = true; })
audio.src = '/songs/'+_selectedSong.folder+'/main.mp3'; }, () => {
audio.load(); alert("An error occurred, please refresh")
})
$("#music-bg").load(function(){
_bgLoaded=true;
_this.checkIfEverythingLoaded();
});
audio.playAsset = function(){
try{
audio.muted = false;
audio.play()
}catch(e){
console.warn(e)
} }
} }
audio.onloadeddata = function(){
_musicLoaded=true;
assets.sounds["main-music"]=audio;
_this.checkIfEverythingLoaded();
};
$.ajax({
url : _songFilePath,
dataType: "text",
success : function (data) {
_songData = data.split("\n");
_songDataLoaded=true;
_this.checkIfEverythingLoaded();
}
});
}
this.checkIfEverythingLoaded = function(){
if(_musicLoaded && _songDataLoaded && _bgLoaded){
$("#screen").load("/src/views/game.html", function(){
var taikoGame = new Controller(_selectedSong, _songData, autoPlayEnabled);
taikoGame.run();
});
}
}
$("#screen").load("/src/views/loadsong.html", _this.run);
}

View File

@ -1,7 +0,0 @@
$(document).ready(function(){
new Loader();
});

View File

@ -81,14 +81,14 @@ function Scoresheet(controller, score){
_this.setResults(); _this.setResults();
$("#song-select").click(function(){ $("#song-select").click(function(){
assets.sounds["don"].playAsset(); assets.sounds["don"].play();
bgm.pause(); assets.sounds["bgm_result"].stop();
controller.songSelection(); controller.songSelection();
}); });
$("#replay").click(function(){ $("#replay").click(function(){
assets.sounds["don"].playAsset(); assets.sounds["don"].play();
bgm.pause(); assets.sounds["bgm_result"].stop();
controller.restartSong(); controller.restartSong();
}); });
@ -96,15 +96,8 @@ function Scoresheet(controller, score){
} }
assets.sounds["results"].playAsset(); assets.sounds["results"].play()
assets.sounds["bgm_result"].playLoop(0, false, 0, 0.846625)
bgm = new BufferedLoop(
{url: '/assets/audio/bgm_result.ogg', duration: 0.847},
{url: '/assets/audio/bgm_result_loop.ogg', duration: 16.842}
);
bgm.play();
$("#screen").load("/src/views/scoresheet.html", _this.run); $("#screen").load("/src/views/scoresheet.html", _this.run);

View File

@ -1,10 +1,10 @@
function SongSelect(){ function SongSelect(){
var _this=this; var _this=this;
var _songs; var _songs;
var _selectedSong = {title:'', folder:'', difficulty:''}; var _selectedSong = {title:'', folder:'', difficulty:''};
var _preview; var _preview;
var _preview_to; var _preview_ended
var _preview_startLoad
var _diffNames={ var _diffNames={
easy:"かんたん", easy:"かんたん",
normal:"ふつう", normal:"ふつう",
@ -13,62 +13,68 @@ function SongSelect(){
} }
this.startPreview = function(id, prvtime, first_open=true) { this.startPreview = function(id, prvtime, first_open=true) {
var start = Date.now(); _this.endPreview();
setTimeout(function(){ _preview_startLoad = +new Date
bgm.pause(); _preview_ended = false
}, 400); if(first_open){
snd.musicGain.fadeOut(0.4)
_preview = new Audio('/songs/' + id + '/main.mp3'); }
_preview.onloadeddata = function() { var songObj
var end = Date.now(); assets.songs.forEach(song => {
var delay = end - start; if(song.id == id){
var no_delay = first_open ? 0 : 300; songObj = song
}
_preview.currentTime = prvtime/1000; })
_preview.volume = 0.5; if(songObj.sound){
_preview = songObj.sound
_preview.addEventListener('ended', function(){ _preview.gain = snd.previewGain
this.currentTime = prvtime/1000; this.previewLoaded(prvtime)
this.play(); }else{
}, false); snd.previewGain.load("/songs/" + id + "/main.mp3").then(sound => {
if(!_preview_ended){
_preview_to = setTimeout(function(){ songObj.sound = sound
_preview.play(); _preview = sound
}, delay <= 1000 && first_open ? 1000 : no_delay); this.previewLoaded(prvtime)
}
})
} }
}; };
this.previewLoaded = function(prvtime){
var endLoad = +new Date
var delay = Math.max(1000 - Math.min(1000, endLoad - _preview_startLoad), 300)
_preview.playLoop(delay / 1000, false, prvtime / 1000)
}
this.endPreview = function() { this.endPreview = function() {
clearTimeout(_preview_to); _preview_ended = true
if (_preview) { if (_preview) {
_preview.pause(); _preview.stop();
}; };
}; };
this.run = function(){ this.run = function(){
_this.createCode(); _this.createCode();
_this.display();
$(window).resize(_this.display);
var menuLoop = setInterval(_this.refresh, 20);
$("#song-container").show(); $("#song-container").show();
$('#songsel-help').click(function(){ $('#songsel-help').click(function(){
bgm.pause(); assets.sounds["bgm_songsel"].stop()
assets.sounds["song-select"].stop()
assets.sounds["diffsel"].stop()
assets.sounds["don"].play()
snd.musicGain.fadeIn()
_this.endPreview(); _this.endPreview();
assets.sounds['don'].playAsset();
new Tutorial(); new Tutorial();
}); });
$(".difficulty").click(function(e){ $(".difficulty").click(function(e){
_this.endPreview(); _this.endPreview();
assets.sounds["diffsel"].pause(); assets.sounds["bgm_songsel"].stop()
assets.sounds["diffsel"].currentTime = 0; assets.sounds["diffsel"].stop()
assets.sounds["don"].playAsset(); assets.sounds["don"].play()
clearInterval(menuLoop);
var difficultyElement = (e.target.className=="stars" || e.target.className=="diffname") ? e.target.parentElement : e.target; var difficultyElement = (e.target.className=="stars" || e.target.className=="diffname") ? e.target.parentElement : e.target;
_selectedSong.difficulty = difficultyElement.classList[1]+'.osu'; _selectedSong.difficulty = difficultyElement.classList[1]+'.osu';
var parentID = $(this).parent().closest(".song").attr("id"); var parentID = $(this).parent().closest(".song").attr("id");
@ -76,7 +82,7 @@ function SongSelect(){
_selectedSong.title = $(this).parent().closest('.song').data('title'); _selectedSong.title = $(this).parent().closest('.song').data('title');
_selectedSong.folder = songID; _selectedSong.folder = songID;
bgm.pause(); snd.musicGain.fadeIn()
new loadSong(_selectedSong, e.shiftKey); new loadSong(_selectedSong, e.shiftKey);
}); });
@ -93,17 +99,14 @@ function SongSelect(){
if (!$(e.target).parents('.difficulties').length) { if (!$(e.target).parents('.difficulties').length) {
if ($(".opened").length && $(".opened").attr('id') == $(this).attr('id')) { if ($(".opened").length && $(".opened").attr('id') == $(this).attr('id')) {
_this.endPreview(); _this.endPreview();
bgm.play(); snd.musicGain.fadeIn(0.4)
assets.sounds["cancel"].playAsset(); assets.sounds["diffsel"].stop()
assets.sounds["cancel"].play()
assets.sounds["song-select"].play(0.3)
$(".difficulty").hide(); $(".difficulty").hide();
$(".opened").removeClass("opened", 300); $(".opened").removeClass("opened", 300);
assets.sounds["diffsel"].pause();
assets.sounds["diffsel"].currentTime = 0;
setTimeout(function(){
assets.sounds["song-select"].playAsset();
}, 300);
$('.songsel-title').fadeOut(200, function(){ $('.songsel-title').fadeOut(200, function(){
$('.songsel-title').attr('alt', '曲をえらぶ').html('曲をえらぶ').css('left', -300); $('.songsel-title').attr('alt', '曲をえらぶ').html('曲をえらぶ').css('left', -300);
$('.songsel-title').animate({left:0, opacity:"show"}, 400); $('.songsel-title').animate({left:0, opacity:"show"}, 400);
@ -112,24 +115,19 @@ function SongSelect(){
return; return;
} }
if(!$('.opened').length) { if(!$('.opened').length) {
_this.startPreview($(this).data('song-id'), $(this).data('preview')); _this.startPreview($(this).data('song-id'), $(this).data('preview'));
assets.sounds["don"].playAsset(); assets.sounds["don"].play()
assets.sounds["song-select"].pause(); assets.sounds["song-select"].stop()
assets.sounds["song-select"].currentTime = 0; assets.sounds["diffsel"].play(0.3)
setTimeout(function(){
assets.sounds["diffsel"].playAsset();
}, 300);
$('.songsel-title').fadeOut(200, function(){ $('.songsel-title').fadeOut(200, function(){
$('.songsel-title').attr('alt', 'むずかしさをえらぶ').html('むずかしさをえらぶ').css('left', -300); $('.songsel-title').attr('alt', 'むずかしさをえらぶ').html('むずかしさをえらぶ').css('left', -300);
$('.songsel-title').animate({left:0, opacity:"show"}, 400); $('.songsel-title').animate({left:0, opacity:"show"}, 400);
}); });
} else { } else {
_preview.pause();
_this.startPreview($(this).data('song-id'), $(this).data('preview'), false); _this.startPreview($(this).data('song-id'), $(this).data('preview'), false);
assets.sounds["ka"].playAsset(); assets.sounds["ka"].play();
} }
}; };
@ -144,15 +142,8 @@ function SongSelect(){
} }
this.createCode = function(){ this.createCode = function(){
bgm = new BufferedLoop( assets.sounds["bgm_songsel"].playLoop(0, false, 0, 1.4423958333333333)
{url: '/assets/audio/bgm_songsel.ogg', duration: 1.442}, assets.sounds["song-select"].play(0.2);
{url: '/assets/audio/bgm_songsel_loop.ogg', duration: 2.064}
);
bgm.play();
setTimeout(function(){
assets.sounds["song-select"].playAsset();
}, 200);
var songElements = [0] var songElements = [0]
@ -244,13 +235,6 @@ function SongSelect(){
$('.difficulty').hide(); $('.difficulty').hide();
} }
this.display = function(){
}
this.refresh = function(){
}
$("#screen").load("/src/views/songselect.html", _this.run); $("#screen").load("/src/views/songselect.html", _this.run);
} }

View File

@ -0,0 +1,193 @@
class SoundBuffer{
constructor(){
this.context = new AudioContext()
var resume = () => {
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)
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()
})
}
createGain(){
return new SoundGain(this)
}
setCrossfade(gain1, gain2, median){
gain1.setCrossfade(1 - median)
gain2.setCrossfade(median)
}
getTime(){
return this.context.currentTime
}
convertTime(time, absolute){
time = (time || 0)
if(time < 0){
time = 0
}
return time + (absolute ? 0 : this.getTime())
}
createSource(sound){
var source = this.context.createBufferSource()
source.buffer = sound.buffer
source.connect(sound.gain.gainNode || this.context.destination)
return source
}
}
class SoundGain{
constructor(soundBuffer){
this.soundBuffer = soundBuffer
this.gainNode = soundBuffer.context.createGain()
this.gainNode.connect(soundBuffer.context.destination)
this.setVolume(1)
}
load(url){
return this.soundBuffer.load(url, this)
}
convertTime(time, absolute){
return this.soundBuffer.convertTime(time, absolute)
}
setVolume(amount){
this.gainNode.gain.value = amount * amount
this.volume = amount
}
setCrossfade(amount){
this.setVolume(Math.pow(Math.sin(Math.PI / 2 * amount), 1 / 4))
}
fadeIn(duration, time, absolute){
this.fadeVolume(0, this.volume * this.volume, duration, time, absolute)
}
fadeOut(duration, time, absolute){
this.fadeVolume(this.volume * this.volume, 0, duration, time, absolute)
}
fadeVolume(vol1, vol2, duration, time, absolute){
time = this.convertTime(time, absolute)
this.gainNode.gain.linearRampToValueAtTime(vol1, time)
this.gainNode.gain.linearRampToValueAtTime(vol2, time + (duration || 0))
}
mute(){
this.gainNode.gain.value = 0
}
unmute(){
this.setVolume(this.volume)
}
}
class Sound{
constructor(gain, buffer){
this.gain = gain
this.buffer = buffer
this.soundBuffer = gain.soundBuffer
this.duration = buffer.duration
this.timeouts = new Set()
this.sources = new Set()
}
getTime(){
return this.soundBuffer.getTime()
}
convertTime(time, absolute){
return this.soundBuffer.convertTime(time, absolute)
}
setTimeouts(time){
return new Promise(resolve => {
var relTime = time - this.getTime()
if(relTime > 0){
var timeout = setTimeout(() => {
this.timeouts.delete(timeout)
resolve()
}, relTime * 1000)
this.timeouts.add(timeout)
}else{
resolve()
}
})
}
clearTimeouts(){
this.timeouts.forEach(timeout => {
clearTimeout(timeout)
this.timeouts.delete(timeout)
})
}
playLoop(time, absolute, seek1, seek2, until){
time = this.convertTime(time, absolute)
seek1 = seek1 || 0
seek2 = seek2 || seek1
until = until || this.duration
this.loop = {
started: time + until - seek1,
seek: seek2,
until: until
}
this.play(time, true, seek1, until)
this.addLoop()
this.loop.interval = setInterval(() => {
this.addLoop()
}, 100)
}
addLoop(){
if(this.getTime() > this.loop.started - 1){
this.play(this.loop.started, true, this.loop.seek, this.loop.until)
this.loop.started += this.loop.until - this.loop.seek
}
}
play(time, absolute, seek, until){
time = this.convertTime(time, absolute)
var source = this.soundBuffer.createSource(this)
seek = seek || 0
until = until || this.duration
this.setTimeouts(time).then(() => {
this.cfg = {
started: time,
seek: seek,
until: until
}
})
source.start(time, Math.max(0, seek || 0), Math.max(0, until - seek))
source.startTime = time
this.sources.add(source)
source.onended = () => {
this.sources.delete(source)
}
}
stop(time, absolute){
time = this.convertTime(time, absolute)
this.sources.forEach(source => {
source.stop(Math.max(source.startTime, time))
})
this.setTimeouts(time).then(() => {
if(this.loop){
clearInterval(this.loop.interval)
}
this.clearTimeouts()
})
}
pause(time, absolute){
if(this.cfg){
time = this.convertTime(time, absolute)
this.stop(time, true)
this.cfg.pauseSeek = time - this.cfg.started + this.cfg.seek
}
}
resume(time, absolute){
if(this.cfg){
if(this.loop){
this.playLoop(time, absolute, this.cfg.pauseSeek, this.loop.seek, this.loop.until)
}else{
this.play(time, absolute, this.cfg.pauseSeek, this.cfg.until)
}
}
}
}

View File

@ -1,48 +0,0 @@
function soundSystem(controller){
var _this = this;
var _speed=0;
var _circles = [];
var _circleID = -1;
var _measures = [];
var _sounds = assets.sounds;
var _channels=[];
var _channelMAX=20;
for (var i=0;i<_channelMAX;i++) {// prepare the channels
_channels[i] = {};
_channels[i]["end"] = -1;
_channels[i]["audio"] = new Audio();
}
this.playSound = function(soundID){
for(var i=0;i<_channelMAX;i++){ //play in different sounds in different channels
var now = new Date();
if (_channels[i]["end"] < now.getTime()) {// is this channel finished?
_channels[i]["end"] = now.getTime() + _sounds[soundID].duration*1000;
_channels[i]["audio"].src = _sounds[soundID].src;
_channels[i]["audio"].load();
_channels[i]["audio"].play();
break;
}
}
}
this.pauseSound = function(){
_sounds["main-music"].pause();
}
this.fadeOutMusic = function(){
if(_sounds["main-music"].volume.toFixed(1)!=0.0){
_sounds["main-music"].volume-=0.1;
}
else{
_sounds["main-music"].pause();
controller.fadeOutOver();
}
}
}

View File

@ -32,7 +32,7 @@ function Titlescreen(){
$("#screen").find("#title-screen").show(); $("#screen").find("#title-screen").show();
$(window).resize(_this.positionning); $(window).resize(_this.positionning);
assets.sounds["title"].playAsset(); assets.sounds["title"].play();
} }
@ -40,7 +40,7 @@ function Titlescreen(){
assets.sounds["title"].pause(); assets.sounds["title"].pause();
assets.sounds["title"].currentTime = 0; assets.sounds["title"].currentTime = 0;
assets.sounds["don"].playAsset(); assets.sounds["don"].play();
if (localStorage.getItem('tutorial') !== 'true') { if (localStorage.getItem('tutorial') !== 'true') {
new Tutorial(); new Tutorial();
} else { } else {

View File

@ -2,15 +2,11 @@ function Tutorial() {
var _this = this; var _this = this;
this.run = function() { this.run = function() {
bgm = new BufferedLoop( assets.sounds["bgm_setsume"].playLoop(0, false, 0, 1.0540416666666668)
{url: '/assets/audio/bgm_setsume.ogg', duration: 1.054},
{url: '/assets/audio/bgm_setsume_loop.ogg', duration: 15}
);
bgm.play();
$('#tutorial-end-button').click(function(){ $('#tutorial-end-button').click(function(){
bgm.pause(); assets.sounds["bgm_setsume"].stop();
assets.sounds['don'].playAsset(); assets.sounds["don"].play();
localStorage.setItem('tutorial', 'true'); localStorage.setItem('tutorial', 'true');
new SongSelect(); new SongSelect();

View File

@ -4,10 +4,9 @@ class View{
this.bg = bg this.bg = bg
this.diff = diff this.diff = diff
this.winW = $(window).width() this.canvas = new ScalableCanvas("canvas", $(window).width(), $(window).height())
this.winH = $(window).height() this.winW = this.canvas.scaledWidth
this.winH = this.canvas.scaledHeight
this.canvas = new ScalableCanvas("canvas", this.winW, this.winH)
this.ctx = this.canvas.ctx this.ctx = this.canvas.ctx
this.taikoSquareW = this.winW / 4 this.taikoSquareW = this.winW / 4