game.js 8.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327
  1. var fontDeferred = Q.defer();
  2. WebFontConfig = {
  3. google: { families: [ 'Quicksand::latin' ] },
  4. active: function() {
  5. fontDeferred.resolve();
  6. }
  7. };
  8. (function() {
  9. var wf = document.createElement('script');
  10. wf.src = ('https:' == document.location.protocol ? 'https' : 'http') +
  11. '://ajax.googleapis.com/ajax/libs/webfont/1/webfont.js';
  12. wf.type = 'text/javascript';
  13. wf.async = 'true';
  14. var s = document.getElementsByTagName('script')[0];
  15. s.parentNode.insertBefore(wf, s);
  16. })();
  17. var soundDeferred = Q.defer();
  18. soundManager.setup({
  19. url: 'swf/',
  20. flashVersion: 9,
  21. onready: function() {
  22. soundDeferred.resolve(this);
  23. }
  24. });
  25. var Game = {
  26. canvas: document.getElementById('game'),
  27. context: document.getElementById('game').getContext('2d'),
  28. keysDown: {},
  29. start: function() {
  30. addEventListener('keydown', function(e) {
  31. switch(e.keyCode) {
  32. case 37:
  33. case 38:
  34. case 39:
  35. case 40:
  36. case 32:
  37. e.preventDefault();
  38. }
  39. Game.keysDown[e.keyCode] = true;
  40. }, false);
  41. addEventListener('keyup', function(e) {
  42. delete Game.keysDown[e.keyCode];
  43. }, false);
  44. var fontPromise = fontDeferred.promise.timeout(5000);
  45. var soundPromise = soundDeferred.promise.then(function() {
  46. return [
  47. createSound('confirm', 'sound/confirm.mp3'),
  48. createSound('back', 'sound/back.mp3'),
  49. createSound('pause', 'sound/pause.mp3'),
  50. createSound('cursor', 'sound/cursor.mp3')
  51. ]
  52. });
  53. Game.sceneManager.push(SplashScreen);
  54. Q.allResolved([fontPromise, soundPromise]).done(function() {
  55. Game.sceneManager.pop();
  56. Game.sceneManager.push(MainMenu);
  57. });
  58. Ticker.start();
  59. Ticker.addListener(function(dt) {
  60. Game.sceneManager.update(dt);
  61. Game.sceneManager.draw();
  62. });
  63. },
  64. pause: function() {
  65. Game.sceneManager.push(PauseScreen, 0);
  66. },
  67. sceneManager: {
  68. sceneStack: [],
  69. currentScene: null,
  70. promise: Q(),
  71. update: function(delta) {
  72. if(this.currentScene) this.currentScene._update(delta);
  73. },
  74. draw: function() {
  75. if(this.currentScene) this.currentScene._draw();
  76. this.drawFade();
  77. },
  78. push: function(scene, outDuration, inDuration) {
  79. outDuration = (outDuration == undefined) ? 0.5 : outDuration;
  80. inDuration = (inDuration == undefined) ? outDuration : inDuration;
  81. var self = this;
  82. var promise = this.promise;
  83. if(this.currentScene) {
  84. this.currentScene.pause();
  85. promise = this.fadeOut(outDuration);
  86. }
  87. promise.then(function() {
  88. self.sceneStack.push(scene);
  89. if(!scene.hasTicker) scene._init();
  90. scene.load();
  91. self.currentScene = scene;
  92. return self.fadeIn(inDuration);
  93. });
  94. },
  95. pop: function(count, outDuration, inDuration) {
  96. outDuration = (outDuration == undefined) ? 0.5 : outDuration;
  97. inDuration = (inDuration == undefined) ? outDuration : inDuration;
  98. count = count || 1;
  99. var scenes = [];
  100. for(var i = 0; i < count; ++i) {
  101. scenes.push(this.sceneStack.pop());
  102. }
  103. var promise = scenes.reduce(function(acc, scene) {
  104. return Q.when(acc, scene.unload());
  105. }, Q());
  106. var self = this;
  107. Q.all([this.fadeOut(outDuration), promise]).then(function() {
  108. if(self.sceneStack.length > 0) {
  109. self.currentScene = self.sceneStack[self.sceneStack.length-1];
  110. self.currentScene.resume();
  111. self.fadeIn(inDuration);
  112. }
  113. else {
  114. self.currentScene = null;
  115. }
  116. });
  117. },
  118. fadeIn: function(duration) {
  119. var self = this
  120. this.promise = this.promise.then(function() {
  121. self.tween = tweenFrom(1).to(0, duration).animate();
  122. return self.tween.promise;
  123. });
  124. return this.promise;
  125. },
  126. fadeOut: function(duration) {
  127. var self = this;
  128. this.promise = this.promise.then(function() {
  129. self.tween = tweenFrom(0).to(1, duration).animate();
  130. return self.tween.promise;
  131. });
  132. return this.promise;
  133. },
  134. drawFade: function() {
  135. if(this.tween && this.promise.isPending()) {
  136. Game.context.globalAlpha = this.tween.value;
  137. Game.context.fillStyle = 'black';
  138. Game.context.fillRect(0, 0, Game.canvas.width, Game.canvas.height);
  139. Game.context.globalAlpha = 1;
  140. }
  141. }
  142. }
  143. };
  144. function Scene() {}
  145. Scene.prototype._init = function() {
  146. makeObservable(this);
  147. };
  148. Scene.prototype._update = function(dt) {
  149. this.notify(dt);
  150. this.update(dt);
  151. };
  152. Scene.prototype._draw = function() {
  153. this.draw();
  154. };
  155. Scene.prototype.tween = function(from) {
  156. var tween = new DeferredTween(from);
  157. tween.ticker = this.ticker;
  158. return tween;
  159. };
  160. Scene.prototype.update = function() {};
  161. Scene.prototype.draw = function() {};
  162. Scene.prototype.load = function() {};
  163. Scene.prototype.unload = function() {};
  164. Scene.prototype.resume = function() {};
  165. Scene.prototype.pause = function() {};
  166. var SplashScreen = new Scene();
  167. (function() {
  168. var ctx = Game.context;
  169. var x = Game.canvas.width / 2;
  170. var y = Game.canvas.height / 2;
  171. var beater = new Beater();
  172. beater.init(x, y, 'white');
  173. SplashScreen.update = function(dt) {
  174. beater.update(dt);
  175. };
  176. SplashScreen.draw = function() {
  177. ctx.fillStyle = 'black';
  178. ctx.fillRect(0, 0, Game.canvas.width, Game.canvas.height);
  179. beater.draw();
  180. };
  181. })();
  182. var MainMenu = new Scene();
  183. (function() {
  184. var ctx = Game.context;
  185. var canvasW = Game.canvas.width;
  186. var canvasH = Game.canvas.height;
  187. var selected = 0;
  188. var alternate = false;
  189. var notYetDone = {
  190. name: '???',
  191. alt: '???',
  192. start: function() {}
  193. };
  194. var games = [
  195. {
  196. name: 'sound safari',
  197. alt: 'sound catcher',
  198. start: function() {
  199. var beats = [
  200. {url: 'sound/b1.mp3', duration: 4000},
  201. {url: 'sound/b2.mp3', duration: 4000},
  202. {url: 'sound/b3.mp3', duration: 4000},
  203. {url: 'sound/b4.mp3', duration: 4000},
  204. {url: 'sound/b5.mp3', duration: 4000}
  205. ];
  206. Game.sceneManager.push(new SoundSafari(beats, true));
  207. }
  208. },
  209. notYetDone,
  210. notYetDone,
  211. notYetDone,
  212. notYetDone,
  213. notYetDone,
  214. notYetDone
  215. ];
  216. function onKeyUp(e) {
  217. switch(e.keyCode) {
  218. case 66:
  219. alternate = !alternate;
  220. document.title = alternate ? 'SoundVoyager' : 'audventure';
  221. break;
  222. case 38:
  223. soundManager.play('cursor');
  224. selected = (selected + games.length -1) % games.length;
  225. break;
  226. case 40:
  227. soundManager.play('cursor');
  228. selected = (selected + 1) % games.length;
  229. break;
  230. case 32:
  231. case 13:
  232. soundManager.play('confirm');
  233. games[selected].start();
  234. }
  235. }
  236. MainMenu.update = function() {};
  237. MainMenu.draw = function() {
  238. ctx.fillStyle = 'black';
  239. ctx.fillRect(0, 0, canvasW, canvasH);
  240. ctx.fillStyle = 'white';
  241. ctx.textAlign = 'center';
  242. var canvasWM = canvasW/2;
  243. var canvasHM = canvasH/2;
  244. ctx.font = font(48);
  245. ctx.fillText(alternate ? 'SoundVoyager' : 'audventure', canvasWM, canvasHM - 50);
  246. ctx.font = font(16);
  247. games.forEach(function(game, index) {
  248. var y = canvasHM + 10 + index * 25;
  249. var name = alternate ? game.alt : game.name;
  250. ctx.fillText(name, canvasWM, y);
  251. if(index == selected) {
  252. var offset = ctx.measureText(name).width / 2 + 10;
  253. drawTriangle(canvasWM - offset, y - 5, 10, 7);
  254. drawTriangle(canvasWM + offset, y - 5, 10, -7);
  255. }
  256. });
  257. };
  258. MainMenu.load = MainMenu.resume = function() {
  259. addEventListener('keydown', onKeyUp);
  260. };
  261. MainMenu.unload = MainMenu.pause = function() {
  262. removeEventListener('keydown', onKeyUp);
  263. };
  264. })();
  265. var PauseScreen = new Scene();
  266. (function() {
  267. var onKeyUp = function(e) {
  268. switch(e.charCode) {
  269. case 81:
  270. case 113:
  271. case 27:
  272. Game.sceneManager.pop(2);
  273. soundManager.play('back');
  274. break;
  275. case 80:
  276. case 112:
  277. case 32:
  278. Game.sceneManager.pop(1, 0);
  279. soundManager.play('back');
  280. }
  281. };
  282. PauseScreen.load = PauseScreen.resume = function() {
  283. addEventListener('keypress', onKeyUp);
  284. };
  285. PauseScreen.unload = PauseScreen.pause = function() {
  286. removeEventListener('keypress', onKeyUp);
  287. };
  288. PauseScreen.update = function() {};
  289. PauseScreen.draw = function() {
  290. Game.context.fillStyle = 'black';
  291. Game.context.fillRect(0, 0, Game.canvas.width, Game.canvas.height);
  292. Game.context.fillStyle = 'white';
  293. Game.context.textAlign = 'center';
  294. Game.context.font = font(16);
  295. Game.context.fillText('Paused', Game.canvas.width/2, Game.canvas.height/2 - 30);
  296. Game.context.font = font(12);
  297. Game.context.fillText('P to unpause', Game.canvas.width/2, Game.canvas.height/2);
  298. Game.context.fillText('Q to quit', Game.canvas.width/2, Game.canvas.height/2 + 20);
  299. Game.context.textAlign = 'left';
  300. };
  301. })();
  302. Game.start();