var fontDeferred = Q.defer(); WebFontConfig = { google: { families: [ 'Quicksand::latin' ] }, active: function() { fontDeferred.resolve(); } }; (function() { var wf = document.createElement('script'); wf.src = ('https:' == document.location.protocol ? 'https' : 'http') + '://ajax.googleapis.com/ajax/libs/webfont/1/webfont.js'; wf.type = 'text/javascript'; wf.async = 'true'; var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(wf, s); })(); var Game = { canvas: document.getElementById('game'), context: document.getElementById('game').getContext('2d'), keysDown: {}, start: function() { addEventListener('keydown', function(e) { switch(e.keyCode) { case 37: case 38: case 39: case 40: case 32: e.preventDefault(); } Game.keysDown[e.keyCode] = true; }, false); addEventListener('keyup', function(e) { delete Game.keysDown[e.keyCode]; }, false); var resourcePromises = [ fontDeferred.promise.timeout(5000), sfxManager.loadSound('confirm', 'sound/confirm.mp3'), sfxManager.loadSound('back', 'sound/back.mp3'), sfxManager.loadSound('pause', 'sound/pause.mp3'), sfxManager.loadSound('cursor', 'sound/cursor.mp3') ]; Game.sceneManager.push(SplashScreen); Q.allResolved(resourcePromises).done(function() { Game.sceneManager.pop(); Game.sceneManager.push(MainMenu); }); Ticker.start(); Ticker.addListener(function(dt) { Game.sceneManager.update(dt); Game.sceneManager.draw(); }); }, pause: function() { Game.sceneManager.push(PauseScreen, 0); }, sceneManager: { sceneStack: [], currentScene: null, promise: Q(), update: function(delta) { if(this.currentScene) this.currentScene._update(delta); }, draw: function() { if(this.currentScene) this.currentScene._draw(); this.drawFade(); }, push: function(scene, outDuration, inDuration) { outDuration = (outDuration == undefined) ? 0.5 : outDuration; inDuration = (inDuration == undefined) ? outDuration : inDuration; var self = this; var promise = this.promise; if(this.currentScene) { this.currentScene.pause(); promise = this.fadeOut(outDuration); } promise.then(function() { self.sceneStack.push(scene); if(!scene.hasTicker) scene._init(); scene.load(); self.currentScene = scene; return self.fadeIn(inDuration); }); }, pop: function(count, outDuration, inDuration) { outDuration = (outDuration == undefined) ? 0.5 : outDuration; inDuration = (inDuration == undefined) ? outDuration : inDuration; count = count || 1; var scenes = []; for(var i = 0; i < count; ++i) { scenes.push(this.sceneStack.pop()); } var promise = scenes.reduce(function(acc, scene) { return Q.when(acc, scene.unload()); }, Q()); var self = this; Q.all([this.fadeOut(outDuration), promise]).then(function() { if(self.sceneStack.length > 0) { self.currentScene = self.sceneStack[self.sceneStack.length-1]; self.currentScene.resume(); self.fadeIn(inDuration); } else { self.currentScene = null; } }); }, fadeIn: function(duration) { var self = this this.promise = this.promise.then(function() { self.tween = tweenFrom(1).to(0, duration).animate(); return self.tween.promise; }); return this.promise; }, fadeOut: function(duration) { var self = this; this.promise = this.promise.then(function() { self.tween = tweenFrom(0).to(1, duration).animate(); return self.tween.promise; }); return this.promise; }, drawFade: function() { if(this.tween && this.promise.isPending()) { Game.context.globalAlpha = this.tween.value; Game.context.fillStyle = 'black'; Game.context.fillRect(0, 0, Game.canvas.width, Game.canvas.height); Game.context.globalAlpha = 1; } } } }; function Scene() {} Scene.prototype._init = function() { makeObservable(this); }; Scene.prototype._update = function(dt) { this.notify(dt); this.update(dt); }; Scene.prototype._draw = function() { this.draw(); }; Scene.prototype.tween = function(from) { var tween = new DeferredTween(from); tween.ticker = this.ticker; return tween; }; Scene.prototype.update = function() {}; Scene.prototype.draw = function() {}; Scene.prototype.load = function() {}; Scene.prototype.unload = function() {}; Scene.prototype.resume = function() {}; Scene.prototype.pause = function() {}; var SplashScreen = new Scene(); (function() { var ctx = Game.context; var x = Game.canvas.width / 2; var y = Game.canvas.height / 2; var beater = new Beater(); beater.init(x, y, 'white'); SplashScreen.update = function(dt) { beater.update(dt); }; SplashScreen.draw = function() { ctx.fillStyle = 'black'; ctx.fillRect(0, 0, Game.canvas.width, Game.canvas.height); beater.draw(); }; })(); var MainMenu = new Scene(); (function() { var ctx = Game.context; var canvasW = Game.canvas.width; var canvasH = Game.canvas.height; var selected = 0; var alternate = false; var notYetDone = { name: '???', alt: '???', start: function() {} }; var games = [ { name: 'sound safari', alt: 'sound catcher', start: function() { var beats = [ {url: 'sound/b1.mp3', duration: 4000}, {url: 'sound/b2.mp3', duration: 4000}, {url: 'sound/b3.mp3', duration: 4000}, {url: 'sound/b4.mp3', duration: 4000}, {url: 'sound/b5.mp3', duration: 4000} ]; Game.sceneManager.push(new SoundSafari(beats, true)); } }, notYetDone, notYetDone, notYetDone, notYetDone, notYetDone, notYetDone ]; function onKeyUp(e) { switch(e.keyCode) { case 66: alternate = !alternate; document.title = alternate ? 'SoundVoyager' : 'audventure'; break; case 38: sfxManager.play('cursor'); selected = (selected + games.length -1) % games.length; break; case 40: sfxManager.play('cursor'); selected = (selected + 1) % games.length; break; case 32: case 13: sfxManager.play('confirm'); games[selected].start(); } } MainMenu.update = function() {}; MainMenu.draw = function() { ctx.fillStyle = 'black'; ctx.fillRect(0, 0, canvasW, canvasH); ctx.fillStyle = 'white'; ctx.textAlign = 'center'; var canvasWM = canvasW/2; var canvasHM = canvasH/2; ctx.font = font(48); ctx.fillText(alternate ? 'SoundVoyager' : 'audventure', canvasWM, canvasHM - 50); ctx.font = font(16); games.forEach(function(game, index) { var y = canvasHM + 10 + index * 25; var name = alternate ? game.alt : game.name; ctx.fillText(name, canvasWM, y); if(index == selected) { var offset = ctx.measureText(name).width / 2 + 10; drawTriangle(canvasWM - offset, y - 5, 10, 7); drawTriangle(canvasWM + offset, y - 5, 10, -7); } }); }; MainMenu.load = MainMenu.resume = function() { addEventListener('keydown', onKeyUp); }; MainMenu.unload = MainMenu.pause = function() { removeEventListener('keydown', onKeyUp); }; })(); var PauseScreen = new Scene(); (function() { var onKeyUp = function(e) { switch(e.charCode) { case 81: case 113: case 27: Game.sceneManager.pop(2); sfxManager.play('back'); break; case 80: case 112: case 32: Game.sceneManager.pop(1, 0); sfxManager.play('back'); } }; PauseScreen.load = PauseScreen.resume = function() { addEventListener('keypress', onKeyUp); }; PauseScreen.unload = PauseScreen.pause = function() { removeEventListener('keypress', onKeyUp); }; PauseScreen.update = function() {}; PauseScreen.draw = function() { Game.context.fillStyle = 'black'; Game.context.fillRect(0, 0, Game.canvas.width, Game.canvas.height); Game.context.fillStyle = 'white'; Game.context.textAlign = 'center'; Game.context.font = font(16); Game.context.fillText('Paused', Game.canvas.width/2, Game.canvas.height/2 - 30); Game.context.font = font(12); Game.context.fillText('P to unpause', Game.canvas.width/2, Game.canvas.height/2); Game.context.fillText('Q to quit', Game.canvas.width/2, Game.canvas.height/2 + 20); Game.context.textAlign = 'left'; }; })(); Game.start();