Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Initial commit of HTML5 Emberwind to github from internal repo.

  • Loading branch information...
commit 60a26405c9928cbaacc2c6742d63903b807accbe 0 parents
@emoller emoller authored
Showing with 138,039 additions and 0 deletions.
  1. BIN  icon_114x114.png
  2. BIN  icon_57x57.png
  3. BIN  icon_72x72.png
  4. +122 −0 index.html
  5. BIN  resources/atlas/backgrounds/cave0.png
  6. BIN  resources/atlas/backgrounds/cave0_scale1.png
  7. BIN  resources/atlas/backgrounds/cave1.png
  8. BIN  resources/atlas/backgrounds/cave1_scale1.png
  9. BIN  resources/atlas/backgrounds/cave2.png
  10. BIN  resources/atlas/backgrounds/cave2_scale1.png
  11. BIN  resources/atlas/backgrounds/outer0.png
  12. BIN  resources/atlas/backgrounds/outer0_scale1.png
  13. BIN  resources/atlas/backgrounds/outer1.png
  14. BIN  resources/atlas/backgrounds/outer1_scale1.png
  15. BIN  resources/atlas/backgrounds/outer2.png
  16. BIN  resources/atlas/backgrounds/outer2_scale1.png
  17. BIN  resources/atlas/backgrounds/windmill.png
  18. BIN  resources/atlas/backgrounds/windmill_scale1.png
  19. BIN  resources/atlas/foes/bandit.png
  20. BIN  resources/atlas/foes/banditburnt.png
  21. BIN  resources/atlas/foes/bouncer.png
  22. BIN  resources/atlas/foes/bouncerburnt.png
  23. BIN  resources/atlas/foes/guard.png
  24. BIN  resources/atlas/foes/guardburnt.png
  25. BIN  resources/atlas/foes/scout.png
  26. BIN  resources/atlas/foes/scoutburnt.png
  27. BIN  resources/atlas/foes/soup.png
  28. BIN  resources/atlas/foes/soupburnt.png
  29. BIN  resources/atlas/foes/warrior.png
  30. BIN  resources/atlas/foes/warriorburnt.png
  31. BIN  resources/atlas/friends/wick.png
  32. BIN  resources/atlas/game/battle_text.png
  33. BIN  resources/atlas/game/block_effect.png
  34. BIN  resources/atlas/game/brownie_houses.png
  35. BIN  resources/atlas/game/bubble.png
  36. BIN  resources/atlas/game/bullrush.png
  37. BIN  resources/atlas/game/cave_entrances.png
  38. BIN  resources/atlas/game/chest_pieces.png
  39. BIN  resources/atlas/game/coins.png
  40. BIN  resources/atlas/game/entrance_boarded.png
  41. BIN  resources/atlas/game/entrance_bricks.png
  42. BIN  resources/atlas/game/entrance_rocks.png
  43. BIN  resources/atlas/game/fairystone.png
  44. BIN  resources/atlas/game/flame.png
  45. BIN  resources/atlas/game/force_dash_right.png
  46. BIN  resources/atlas/game/gremlinbasket.png
  47. BIN  resources/atlas/game/gremship.png
  48. BIN  resources/atlas/game/hiteffect.png
  49. BIN  resources/atlas/game/knife.png
  50. BIN  resources/atlas/game/lamp_post.png
  51. BIN  resources/atlas/game/laze_sparkle.png
  52. BIN  resources/atlas/game/lightshapes.png
  53. BIN  resources/atlas/game/magic_acorn.png
  54. BIN  resources/atlas/game/pickup_effects.png
  55. BIN  resources/atlas/game/pickups.png
  56. BIN  resources/atlas/game/stalactites.png
  57. BIN  resources/atlas/game/statues.png
  58. BIN  resources/atlas/game/timetrap.png
  59. BIN  resources/atlas/game/tornado.png
  60. BIN  resources/atlas/game/trees.png
  61. BIN  resources/atlas/game/water.png
  62. BIN  resources/atlas/game/water_splash.png
  63. BIN  resources/atlas/game/weepingwillow.png
  64. BIN  resources/atlas/game/windmill_vane.p16
  65. BIN  resources/atlas/game/windmill_vane.png
  66. BIN  resources/atlas/gui/btn_canvas.png
  67. BIN  resources/atlas/gui/btn_canvas_disabled.png
  68. BIN  resources/atlas/gui/btn_webgl.png
  69. BIN  resources/atlas/gui/button.png
  70. BIN  resources/atlas/gui/character_icons.png
  71. BIN  resources/atlas/gui/controls_iphone.png
  72. BIN  resources/atlas/gui/controls_iphone_button_escape.png
  73. BIN  resources/atlas/gui/controls_xbox.png
  74. BIN  resources/atlas/gui/controls_xbox_large.png
  75. BIN  resources/atlas/gui/crystal.png
  76. BIN  resources/atlas/gui/devheads.png
  77. BIN  resources/atlas/gui/floating_points.png
  78. BIN  resources/atlas/gui/frame.png
  79. BIN  resources/atlas/gui/generic_background.png
  80. BIN  resources/atlas/gui/healthbar.png
  81. BIN  resources/atlas/gui/house_display.png
  82. BIN  resources/atlas/gui/idols_brownie.png
  83. BIN  resources/atlas/gui/kindle_icons.png
  84. BIN  resources/atlas/gui/opera_logo.png
  85. BIN  resources/atlas/gui/score_tally_items.png
  86. BIN  resources/atlas/gui/stage_banner.png
  87. BIN  resources/atlas/gui/textbubble.png
  88. BIN  resources/atlas/gui/titlescreen0.png
  89. BIN  resources/atlas/gui/titlescreen2.png
  90. BIN  resources/atlas/gui/titlescreen_kindle_eyes.png
  91. BIN  resources/atlas/gui/titlescreen_wick_eyes.png
  92. BIN  resources/atlas/gui/titletext_html5.png
  93. BIN  resources/atlas/hero/kindle.png
  94. BIN  resources/atlas/hero/kindle_barrel.png
  95. BIN  resources/atlas/hero/kindle_flurry.png
  96. BIN  resources/atlas/hero/kindle_jumpattack.png
  97. BIN  resources/atlas/hero/kindle_sprint.png
  98. BIN  resources/atlas/hero/kindle_swing.png
  99. BIN  resources/atlas/no_c_red/attackeffect.png
  100. BIN  resources/atlas/no_c_red/kindle_tally.png
  101. BIN  resources/atlas/no_c_red/kindle_tally_upgrade.png
  102. BIN  resources/atlas/no_c_red/lamp_post_lit.png
  103. BIN  resources/atlas/no_c_red/mushrooms.png
  104. BIN  resources/atlas/no_c_red/particles.png
  105. BIN  resources/atlas/no_c_red/storyboardintro.png
  106. BIN  resources/atlas/no_c_red/titlescreen1.png
  107. BIN  resources/atlas/no_c_red/titlescreen3.png
  108. BIN  resources/atlas/no_c_red/titlescreen4.png
  109. BIN  resources/atlas/no_c_red/titletext.png
  110. BIN  resources/atlas/storyboards/storyboard1.png
  111. BIN  resources/atlas/storyboards/storyboard2.png
  112. BIN  resources/atlas/storyboards/storyboard3.png
  113. BIN  resources/atlas/storyboards/storyboard4.png
  114. BIN  resources/atlas/tilesets/GremShipBackground.png
  115. BIN  resources/atlas/tilesets/castle.png
  116. BIN  resources/atlas/tilesets/cleanup.png
  117. BIN  resources/atlas/tilesets/indoors.png
  118. BIN  resources/atlas/tilesets/outer.png
  119. BIN  resources/atlas/tilesets/urban.png
  120. BIN  resources/atlas/tilesets/water.png
  121. BIN  resources/audio/music.m4a
  122. BIN  resources/audio/music.mp3
  123. BIN  resources/audio/music.ogg
  124. BIN  resources/audio/music.wav
  125. BIN  resources/audio/sfx.m4a
  126. BIN  resources/audio/sfx.mp3
  127. BIN  resources/audio/sfx.ogg
  128. BIN  resources/audio/sfx.wav
  129. +116,008 −0 resources/emberwind.json
  130. BIN  resources/localized/english/Copyright.png
  131. BIN  resources/localized/english/ObjectiveArrows.png
  132. +260 −0 src/Animation.js
  133. +533 −0 src/App.js
  134. +869 −0 src/AppStates.js
  135. +448 −0 src/Audio.js
  136. +592 −0 src/CaveEntrance.js
  137. +504 −0 src/Collision.js
  138. +296 −0 src/Common.js
  139. +281 −0 src/FSM.js
  140. +503 −0 src/GUIButtons.js
  141. +1,226 −0 src/GUIHeadsUp.js
  142. +719 −0 src/Game.js
  143. +619 −0 src/GameObjects.js
  144. +1,144 −0 src/Gremlin.js
  145. +740 −0 src/GremlinStates.js
  146. +612 −0 src/HittableObject.js
  147. +341 −0 src/House.js
  148. +523 −0 src/Input.js
  149. +928 −0 src/Movement.js
  150. +945 −0 src/PCStates.js
  151. +110 −0 src/ParticleSystem.js
  152. +81 −0 src/Perlin.js
  153. +564 −0 src/Pickup.js
  154. +787 −0 src/PlayerCharacter.js
  155. +173 −0 src/ResourceClasses.js
  156. +392 −0 src/ResourceDepot.js
  157. +357 −0 src/Stage.js
  158. +550 −0 src/StageClasses.js
  159. +1,046 −0 src/Trigger.js
  160. +420 −0 src/Wick.js
  161. +816 −0 src/render/Render.js
  162. +486 −0 src/render/RenderCanvas.js
  163. +1,678 −0 src/render/RenderWebGL.js
  164. +116 −0 src/render/Utils.js
  165. +1,834 −0 src/render/glMatrix.js
  166. +241 −0 src/render/shaders.xml
  167. +175 −0 src/render/webgl-utils.js
BIN  icon_114x114.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
BIN  icon_57x57.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
BIN  icon_72x72.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
122 index.html
@@ -0,0 +1,122 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <title>Emberwind</title>
+ <meta name="viewport" content="width=device-width, height=device-height, initial-scale=1.0, maximum-scale=1.0"/>
+ <meta name="apple-mobile-web-app-capable" content="yes" />
+ <meta name="apple-mobile-web-app-status-bar-style" content="black-translucent" />
+ <link rel="apple-touch-icon-precomposed" href="icon_57x57.png" />
+ <link rel="apple-touch-icon-precomposed" sizes="72x72" href="icon_72x72.png" />
+ <link rel="apple-touch-icon-precomposed" sizes="114x114" href="icon_114x114.png" />
+
+ <link href='http://fonts.googleapis.com/css?family=Lobster&subset=latin&v2' rel='stylesheet' type='text/css'/>
+ <link href='http://fonts.googleapis.com/css?family=Allan:700&v2' rel='stylesheet' type='text/css'/>
+ <link href='http://fonts.googleapis.com/css?family=Meddon&v2' rel='stylesheet' type='text/css'/>
+
+ <script type="text/javascript" src="src/Common.js"></script>
+ <script type="text/javascript" src="src/Perlin.js"></script>
+
+ <script type="text/javascript" src="src/render/Render.js"></script>
+ <script type="text/javascript" src="src/render/RenderCanvas.js"></script>
+ <script type="text/javascript" src="src/render/RenderWebGL.js"></script>
+ <script type="text/javascript" src="src/render/Utils.js"></script>
+ <script type="text/javascript" src="src/render/glMatrix.js"></script>
+ <script type="text/javascript" src="src/render/webgl-utils.js"></script>
+
+ <script type="text/javascript" src="src/Audio.js"></script>
+ <script type="text/javascript" src="src/Animation.js"></script>
+ <script type="text/javascript" src="src/Collision.js"></script>
+ <script type="text/javascript" src="src/Movement.js"></script>
+ <script type="text/javascript" src="src/Trigger.js"></script>
+ <script type="text/javascript" src="src/ParticleSystem.js"></script>
+ <script type="text/javascript" src="src/GameObjects.js"></script>
+ <script type="text/javascript" src="src/HittableObject.js"></script>
+
+ <script type="text/javascript" src="src/PlayerCharacter.js"></script>
+ <script type="text/javascript" src="src/Gremlin.js"></script>
+ <script type="text/javascript" src="src/CaveEntrance.js"></script>
+ <script type="text/javascript" src="src/House.js"></script>
+ <script type="text/javascript" src="src/Pickup.js"></script>
+
+ <script type="text/javascript" src="src/ResourceClasses.js"></script>
+ <script type="text/javascript" src="src/ResourceDepot.js"></script>
+ <script type="text/javascript" src="src/Stage.js"></script>
+ <script type="text/javascript" src="src/StageClasses.js"></script>
+
+ <script type="text/javascript" src="src/GUIButtons.js"></script>
+ <script type="text/javascript" src="src/GUIHeadsUp.js"></script>
+ <script type="text/javascript" src="src/FSM.js"></script>
+ <script type="text/javascript" src="src/Game.js"></script>
+ <script type="text/javascript" src="src/Input.js"></script>
+ <script type="text/javascript" src="src/AppStates.js"></script>
+ <script type="text/javascript" src="src/App.js"></script>
+ <script type="text/javascript" src="src/GremlinStates.js"></script>
+ <script type="text/javascript" src="src/PCStates.js"></script>
+ <script type="text/javascript" src="src/Wick.js"></script>
+
+ <script type="text/javascript">
+ var app = null;
+
+ window.onload = function() {
+ utils.loadShaderXml("src/render/shaders.xml", null, function(shaders) {
+ if (shaders instanceof Exception) {
+ app = shaders;
+ } else {
+ try {
+ app = new App('canvas', shaders, null);
+ } catch (e) {
+ app = e;
+ }
+ }
+ });
+ };
+
+ function application() {
+ if (app == null) {
+ alert("Application is absent");
+ throw "no application";
+ } else if (app instanceof Exception) {
+ alert("An exception occured while creating the application:\n" + app.message);
+ throw app;
+ } else {
+ return app;
+ }
+ }
+ </script>
+
+ <style type="text/css">
+ body{
+ margin: 0px; padding: 0px; overflow: hidden;
+ background: #000;
+ }
+ #canvas-holder.active {
+ position: absolute;
+ padding: 0px;
+ left: 50%;
+ top: 50%;
+ }
+
+ #canvas-holder.inactive {
+ position: absolute;
+ top:50%;
+ width: 100%;
+ text-align: center;
+ }
+
+ #canvas {
+ padding: 0px;
+ width: 100%;
+ height: 100%;
+ color: #fff;
+ }
+ </style>
+</head>
+<body>
+<div id="canvas-holder" class="inactive">
+ <div id="canvas">Emberwind is loading...</div>
+</div>
+<div style="font-family: Lobster; visibility: hidden">one</div>
+<div style="font-family: Allan; visibility: hidden">two</div>
+<div style="font-family: Meddon; visibility: hidden">three</div>
+</body>
+</html>
BIN  resources/atlas/backgrounds/cave0.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
BIN  resources/atlas/backgrounds/cave0_scale1.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
BIN  resources/atlas/backgrounds/cave1.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
BIN  resources/atlas/backgrounds/cave1_scale1.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
BIN  resources/atlas/backgrounds/cave2.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
BIN  resources/atlas/backgrounds/cave2_scale1.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
BIN  resources/atlas/backgrounds/outer0.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
BIN  resources/atlas/backgrounds/outer0_scale1.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
BIN  resources/atlas/backgrounds/outer1.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
BIN  resources/atlas/backgrounds/outer1_scale1.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
BIN  resources/atlas/backgrounds/outer2.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
BIN  resources/atlas/backgrounds/outer2_scale1.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
BIN  resources/atlas/backgrounds/windmill.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
BIN  resources/atlas/backgrounds/windmill_scale1.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
BIN  resources/atlas/foes/bandit.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
BIN  resources/atlas/foes/banditburnt.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
BIN  resources/atlas/foes/bouncer.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
BIN  resources/atlas/foes/bouncerburnt.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
BIN  resources/atlas/foes/guard.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
BIN  resources/atlas/foes/guardburnt.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
BIN  resources/atlas/foes/scout.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
BIN  resources/atlas/foes/scoutburnt.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
BIN  resources/atlas/foes/soup.png
Diff not rendered
BIN  resources/atlas/foes/soupburnt.png
Diff not rendered
BIN  resources/atlas/foes/warrior.png
Diff not rendered
BIN  resources/atlas/foes/warriorburnt.png
Diff not rendered
BIN  resources/atlas/friends/wick.png
Diff not rendered
BIN  resources/atlas/game/battle_text.png
Diff not rendered
BIN  resources/atlas/game/block_effect.png
Diff not rendered
BIN  resources/atlas/game/brownie_houses.png
Diff not rendered
BIN  resources/atlas/game/bubble.png
Diff not rendered
BIN  resources/atlas/game/bullrush.png
Diff not rendered
BIN  resources/atlas/game/cave_entrances.png
Diff not rendered
BIN  resources/atlas/game/chest_pieces.png
Diff not rendered
BIN  resources/atlas/game/coins.png
Diff not rendered
BIN  resources/atlas/game/entrance_boarded.png
Diff not rendered
BIN  resources/atlas/game/entrance_bricks.png
Diff not rendered
BIN  resources/atlas/game/entrance_rocks.png
Diff not rendered
BIN  resources/atlas/game/fairystone.png
Diff not rendered
BIN  resources/atlas/game/flame.png
Diff not rendered
BIN  resources/atlas/game/force_dash_right.png
Diff not rendered
BIN  resources/atlas/game/gremlinbasket.png
Diff not rendered
BIN  resources/atlas/game/gremship.png
Diff not rendered
BIN  resources/atlas/game/hiteffect.png
Diff not rendered
BIN  resources/atlas/game/knife.png
Diff not rendered
BIN  resources/atlas/game/lamp_post.png
Diff not rendered
BIN  resources/atlas/game/laze_sparkle.png
Diff not rendered
BIN  resources/atlas/game/lightshapes.png
Diff not rendered
BIN  resources/atlas/game/magic_acorn.png
Diff not rendered
BIN  resources/atlas/game/pickup_effects.png
Diff not rendered
BIN  resources/atlas/game/pickups.png
Diff not rendered
BIN  resources/atlas/game/stalactites.png
Diff not rendered
BIN  resources/atlas/game/statues.png
Diff not rendered
BIN  resources/atlas/game/timetrap.png
Diff not rendered
BIN  resources/atlas/game/tornado.png
Diff not rendered
BIN  resources/atlas/game/trees.png
Diff not rendered
BIN  resources/atlas/game/water.png
Diff not rendered
BIN  resources/atlas/game/water_splash.png
Diff not rendered
BIN  resources/atlas/game/weepingwillow.png
Diff not rendered
BIN  resources/atlas/game/windmill_vane.p16
Binary file not shown
BIN  resources/atlas/game/windmill_vane.png
Diff not rendered
BIN  resources/atlas/gui/btn_canvas.png
Diff not rendered
BIN  resources/atlas/gui/btn_canvas_disabled.png
Diff not rendered
BIN  resources/atlas/gui/btn_webgl.png
Diff not rendered
BIN  resources/atlas/gui/button.png
Diff not rendered
BIN  resources/atlas/gui/character_icons.png
Diff not rendered
BIN  resources/atlas/gui/controls_iphone.png
Diff not rendered
BIN  resources/atlas/gui/controls_iphone_button_escape.png
Diff not rendered
BIN  resources/atlas/gui/controls_xbox.png
Diff not rendered
BIN  resources/atlas/gui/controls_xbox_large.png
Diff not rendered
BIN  resources/atlas/gui/crystal.png
Diff not rendered
BIN  resources/atlas/gui/devheads.png
Diff not rendered
BIN  resources/atlas/gui/floating_points.png
Diff not rendered
BIN  resources/atlas/gui/frame.png
Diff not rendered
BIN  resources/atlas/gui/generic_background.png
Diff not rendered
BIN  resources/atlas/gui/healthbar.png
Diff not rendered
BIN  resources/atlas/gui/house_display.png
Diff not rendered
BIN  resources/atlas/gui/idols_brownie.png
Diff not rendered
BIN  resources/atlas/gui/kindle_icons.png
Diff not rendered
BIN  resources/atlas/gui/opera_logo.png
Diff not rendered
BIN  resources/atlas/gui/score_tally_items.png
Diff not rendered
BIN  resources/atlas/gui/stage_banner.png
Diff not rendered
BIN  resources/atlas/gui/textbubble.png
Diff not rendered
BIN  resources/atlas/gui/titlescreen0.png
Diff not rendered
BIN  resources/atlas/gui/titlescreen2.png
Diff not rendered
BIN  resources/atlas/gui/titlescreen_kindle_eyes.png
Diff not rendered
BIN  resources/atlas/gui/titlescreen_wick_eyes.png
Diff not rendered
BIN  resources/atlas/gui/titletext_html5.png
Diff not rendered
BIN  resources/atlas/hero/kindle.png
Diff not rendered
BIN  resources/atlas/hero/kindle_barrel.png
Diff not rendered
BIN  resources/atlas/hero/kindle_flurry.png
Diff not rendered
BIN  resources/atlas/hero/kindle_jumpattack.png
Diff not rendered
BIN  resources/atlas/hero/kindle_sprint.png
Diff not rendered
BIN  resources/atlas/hero/kindle_swing.png
Diff not rendered
BIN  resources/atlas/no_c_red/attackeffect.png
Diff not rendered
BIN  resources/atlas/no_c_red/kindle_tally.png
Diff not rendered
BIN  resources/atlas/no_c_red/kindle_tally_upgrade.png
Diff not rendered
BIN  resources/atlas/no_c_red/lamp_post_lit.png
Diff not rendered
BIN  resources/atlas/no_c_red/mushrooms.png
Diff not rendered
BIN  resources/atlas/no_c_red/particles.png
Diff not rendered
BIN  resources/atlas/no_c_red/storyboardintro.png
Diff not rendered
BIN  resources/atlas/no_c_red/titlescreen1.png
Diff not rendered
BIN  resources/atlas/no_c_red/titlescreen3.png
Diff not rendered
BIN  resources/atlas/no_c_red/titlescreen4.png
Diff not rendered
BIN  resources/atlas/no_c_red/titletext.png
Diff not rendered
BIN  resources/atlas/storyboards/storyboard1.png
Diff not rendered
BIN  resources/atlas/storyboards/storyboard2.png
Diff not rendered
BIN  resources/atlas/storyboards/storyboard3.png
Diff not rendered
BIN  resources/atlas/storyboards/storyboard4.png
Diff not rendered
BIN  resources/atlas/tilesets/GremShipBackground.png
Diff not rendered
BIN  resources/atlas/tilesets/castle.png
Diff not rendered
BIN  resources/atlas/tilesets/cleanup.png
Diff not rendered
BIN  resources/atlas/tilesets/indoors.png
Diff not rendered
BIN  resources/atlas/tilesets/outer.png
Diff not rendered
BIN  resources/atlas/tilesets/urban.png
Diff not rendered
BIN  resources/atlas/tilesets/water.png
Diff not rendered
BIN  resources/audio/music.m4a
Binary file not shown
BIN  resources/audio/music.mp3
Binary file not shown
BIN  resources/audio/music.ogg
Binary file not shown
BIN  resources/audio/music.wav
Binary file not shown
BIN  resources/audio/sfx.m4a
Binary file not shown
BIN  resources/audio/sfx.mp3
Binary file not shown
BIN  resources/audio/sfx.ogg
Binary file not shown
BIN  resources/audio/sfx.wav
Binary file not shown
116,008 resources/emberwind.json
116,008 additions, 0 deletions not shown
BIN  resources/localized/english/Copyright.png
Diff not rendered
BIN  resources/localized/english/ObjectiveArrows.png
Diff not rendered
260 src/Animation.js
@@ -0,0 +1,260 @@
+function AnimationHandle(animation, callback, mirrored){
+ if(animation instanceof AnimationHandle){
+ animation = animation.animation;
+ }
+ this.animation = animation;
+ this.callback = callback === undefined ? null : callback;
+
+ this.currentFrame = 0;
+ this.time = 0;
+
+ if(mirrored === undefined) mirrored = false;
+ this.renderMirrored = mirrored;
+
+ this.speed = 1;
+ this.start = 0;
+ this.end = 1;
+
+ this.playTo = -1;
+
+ this.loop = true;
+ this.playing = false;
+}
+
+AnimationHandle.constructor = AnimationHandle;
+
+AnimationHandle.prototype.clone = function() {
+ var clone = new AnimationHandle(this.animation, this.callback, this.renderMirrored);
+ clone.start = this.start;
+ clone.end = this.end;
+ clone.time = this.time;
+ return clone;
+};
+
+AnimationHandle.prototype.update = function(dt) {
+ if(!this.playing) return;
+
+ var oldTime = this.time;
+ this.time += this.speed * dt;
+ var halfFrame = 0.5 / this.animation.framerate;
+
+ var animationLength = this.animation.animationLength;
+
+ if (this.loop) {
+ if (this.speed > 0) {
+ this.time = this.time >= animationLength * this.end ? this.start * animationLength : this.time;
+ } else {
+ this.time = this.time <= animationLength * this.start ? this.end * animationLength - halfFrame : this.time;
+ }
+ } else {
+ var tempPlayTo;
+ if (this.speed > 0) {
+ tempPlayTo = this.playTo >= 0 ? this.playTo : this.end;
+ if (this.time >= animationLength * tempPlayTo) {
+ this.time = animationLength * tempPlayTo - halfFrame;
+ this.playing = false;
+ }
+ } else {
+ tempPlayTo = this.playTo >= 0 ? this.playTo : this.start;
+ if (this.time <= animationLength * tempPlayTo) {
+ this.time = animationLength * tempPlayTo + halfFrame;
+ this.playing = false;
+ }
+ }
+ }
+
+ this.time = Math.max(0, this.time);
+
+ this.currentFrame = Math.floor(this.time * this.animation.framerate) % this.animation.nbrOfFrames;
+
+ if(this.callback !== null){
+ var timeToCheck = this.playing ? this.time : (this.speed > 0 ? animationLength * this.end : this.animation.animationLength * this.start);
+ var evts;
+ if(oldTime < timeToCheck)
+ evts = this.animation.getEvents(oldTime, timeToCheck);
+ else
+ evts = this.animation.getEventsSlow(oldTime, timeToCheck, animationLength * this.start, animationLength * this.end, dt);
+
+ if(evts.length >= 2){
+ this.time = this.animation.getTimeForNextEvent(oldTime, timeToCheck);
+ evts = [evts[0]];
+ }
+
+ for (var e = 0; e < evts.length; e++) {
+ this.callback(evts[e], this);
+ }
+
+ if (!this.playing) {
+ this.callback("stopped", this);
+ }
+ }
+};
+
+AnimationHandle.prototype.draw = function(render, x, y, angle, alpha, tint) {
+ var image = this.animation.frames[this.currentFrame];
+
+ var baseX = this.renderMirrored ? x - (image.textureWidth - this.animation.pivotx) : x - this.animation.pivotx;
+ render.drawImage(image, baseX, y - this.animation.pivoty, angle, false, alpha, tint, this.renderMirrored);
+};
+
+AnimationHandle.prototype.mirror = function() {
+ this.renderMirrored = !this.renderMirrored;
+};
+
+AnimationHandle.prototype.play = function(loop) {
+ this.playTo = -1;
+ if(loop === undefined) loop = true;
+ this.loop = loop;
+ this.playing = true;
+};
+
+AnimationHandle.prototype.playToTime = function(t) {
+ this.playTo = t;
+ this.playing = true;
+};
+
+AnimationHandle.prototype.playToEvent = function(name) {
+ for (var i = 0; i < this.animation.events.length; i++) {
+ var e = this.animation.events[i];
+ if(e.name == name){
+ this.playToTime(e.time / this.animation.animationLength);
+ break;
+ }
+ }
+};
+
+AnimationHandle.prototype.stop = function() {
+ this.playing = false;
+};
+
+AnimationHandle.prototype.rewind = function() {
+ this.time = this.start * this.animation.animationLength;
+};
+
+AnimationHandle.prototype.gotoTime = function(time) {
+ this.time = time * this.animation.animationLength;
+};
+
+AnimationHandle.prototype.gotoEvent = function(evt) {
+ for (var i = 0; i < this.animation.events.length; i++) {
+ var e = this.animation.events[i];
+ if(e.name == evt) {
+ this.time = e.time;
+ break;
+ }
+ }
+};
+
+AnimationHandle.prototype.gotoEnd = function() {
+ var halfFrame = 0.5 / this.animation.framerate;
+ this.time = (this.end - halfFrame) * this.animation.animationLength;
+};
+
+AnimationHandle.prototype.setRange = function(s, e) {
+ this.start = s;
+ this.end = e;
+
+ var length = this.animation.animationLength;
+
+ if(this.time < s * length) this.time = s * length;
+ if(this.time > e * length) this.time = e * length;
+};
+
+AnimationHandle.prototype.setSpeed = function(speed) {
+ this.speed = speed;
+};
+
+AnimationHandle.prototype.playToTime = function(time) {
+ this.end = time;
+ this.loop = false;
+};
+
+AnimationHandle.prototype.playToEvent = function(name) {
+ for (var i = 0; i < this.animation.events.length; i++) {
+ var e = this.animation.events[i];
+ if(e.name == name){
+ this.playToTime(e.time / this.animation.animationLength);
+ break;
+ }
+ }
+};
+
+AnimationHandle.prototype.getLength = function() {
+ return this.animation.animationLength * (this.end - this.start);
+};
+
+AnimationHandle.prototype.getCurrentPosition = function() {
+ return this.time;
+};
+
+AnimationHandle.prototype.isStopped = function() {
+ return !this.playing;
+};
+
+AnimationHandle.prototype.setCallback = function(callback) {
+ this.callback = callback;
+};
+
+function Animation(anim, frames){
+ copy(anim, this);
+
+ /**
+ * The frames in the animation.
+ */
+ this.frames = frames;
+ /**
+ * How long the animation is in seconds.
+ */
+ this.animationLength = frames.length / anim.framerate;
+}
+
+Animation.prototype.constructor = Animation;
+
+/**
+ * Return all events between the different points in time
+ *
+ * @returns [String]
+ */
+Animation.prototype.getEvents = function (from, to) {
+ var events = [];
+ for (var e = 0; e < this.events.length; e++) {
+ var evt = this.events[e];
+ if (evt.time >= from && evt.time < to) {
+ events.push(evt.name);
+ }
+ }
+
+ return events;
+};
+
+Animation.prototype.getTimeForNextEvent = function(from, to){
+ var first = -1;
+ for (var e = 0; e < this.events.length; e++) {
+ var evt = this.events[e];
+ if (evt.time > from && evt.time < to) {
+ if(first != -1) return evt.time;
+ first = evt.time;
+ }
+ }
+ return first;
+};
+
+Animation.prototype.getEventsSlow = function (from, to, start, end, dt) {
+ var events = [];
+ var e, evt;
+ for (e = 0; e < this.events.length; e++) {
+ evt = this.events[e];
+ if (evt.time >= from && evt.time < end) {
+ events.push(evt.name);
+ }
+ }
+
+ for (e = 0; e < this.events.length; e++) {
+ evt = this.events[e];
+ if (evt.time >= start && evt.time < to) {
+ events.push(evt.name);
+ }
+ }
+
+ return events;
+};
533 src/App.js
@@ -0,0 +1,533 @@
+/**
+ * Class that manages the application. Changes between states.
+ *
+ * @param canvasId canvasId the id of the canvas element (or place holder).
+ * @param initCallback a callback that will be called once all resources are
+ * loaded.
+ * @returns {App}
+ */
+function App(canvasId, shaders, initCallback) {
+ this.canvasId = canvasId;
+ this.canvas = null;
+ this.shaders = shaders;
+ this.initCallback = initCallback;
+
+ this.useGL = true;
+ this.webGLFailed = false;
+ this.skipToStage = null;
+ this.useTouch = false;
+ this.frontToBack = false;
+
+ this.debug = false;
+ this.debugKeyboardTimeout = 0;
+ this.debugAudio = false;
+ this.debugMovementTrigger = false;
+ this.showFPS = false;
+ this.freezeFrame = false;
+
+ this.resources = new ResourceDepot();
+ this.resources.setCallback(createCallback(this.resourceCallback, this));
+ ResourceDepot.instance = this.resources;
+
+ var statesList = [ appStates.kStateIntro, IntroState,
+ appStates.kStateDeveloperSplash, DeveloperSplashState,
+ appStates.kStateMainMenu, MainMenuState,
+ appStates.kStateLoadingStage, LoadingStageState,
+ appStates.kStateInGame, InGameState ];
+ this.fsm = new AppFSM(this, statesList);
+ this.newState = -1;
+ this.newMessage = null;
+ this.stateModes = {
+ kStateActive : 0,
+ kTransitionOut : 1,
+ kTransitionIn : 2
+ };
+ this.stateMode = this.stateModes.kStateActive;
+
+ this.screenTransition = null;
+ this.screenTransitions = [
+ {
+ from : appStates.kStateIntro,
+ to : appStates.kStateDeveloperSplash,
+ out : true,
+ transition : new ScreenTransitionFade(0.25, new Pixel32(255, 255, 255, 0), new Pixel32(255, 255, 255, 255))
+ },
+ {
+ from : appStates.kStateIntro,
+ to : appStates.kStateDeveloperSplash,
+ out : false,
+ transition : new ScreenTransitionFade(0.25, new Pixel32(255, 255, 255, 255), new Pixel32(255, 255, 255, 0))
+ },
+ {
+ from : appStates.kStateDeveloperSplash,
+ to : appStates.kStateMainMenu,
+ out : true,
+ transition : new ScreenTransitionFade(0.25, new Pixel32(255, 255, 255, 0), new Pixel32(255, 255, 255, 255))
+ },
+ {
+ from : appStates.kStateDeveloperSplash,
+ to : appStates.kStateMainMenu,
+ out : false,
+ transition : new ScreenTransitionFade(0.5, new Pixel32(255, 255, 255, 255), new Pixel32(255, 255, 255, 0))
+ }
+ ];
+ this.screenTransitionsDefaultIn = new ScreenTransitionFade(0.25, new Pixel32(0, 0, 0, 255), new Pixel32(0, 0, 0, 0));
+ this.screenTransitionsDefaultOut = new ScreenTransitionFade(0.25, new Pixel32(0, 0, 0, 0),
+ new Pixel32(0, 0, 0, 255));
+
+ this.audioTransition = new AudioTransition(0.25);
+
+ this.game = new Game(this.resources);
+
+ this.audio = new Audio(this);
+
+ this.render = null;
+ this.fillScreen = true;
+ this.aspectRatio = 4 / 3;
+ this.maxHeight = 600;
+ this.maxWidth = 800;
+
+ this.getURLOptions();
+
+ this.createRender(this.useGL);
+
+ this.initialized = false;
+
+ this.appLoop = null;
+
+ App.instance = this;
+
+ window.addEventListener('resize', createCallback(this.resize, this), false);
+ window.addEventListener('orientationchange', createCallback(this.resize, this), false);
+
+ this.frameCount = 0;
+ this.frameDate = null;
+ this.frameText = null;
+ this.frameFont = null;
+
+ this.resources.init();
+
+ return this;
+}
+
+/**
+ * The applications states.
+ */
+var appStates = {
+ kStateIntro : 0,
+ kStateDeveloperSplash : 1,
+ kStateMainMenu : 2,
+ kStateLoadingStage : 3,
+ kStateInGame : 4
+};
+
+App.instance = null;
+
+App.getInstance = function() {
+ if (App.instance === null) {
+ throw "App class has not been created";
+ }
+
+ return App.instance;
+};
+
+App.prototype = {};
+App.constructor = App;
+
+/**
+ * This is called when all resources have been loaded.
+ */
+App.prototype.resourceCallback = function() {
+ if (this.initialized) return;
+ this.initialized = true;
+ this.game.init();
+
+ this.frameFont = ResourceDepot.getInstance().getFont("StartTextFont");
+
+ if (this.initCallback != null) {
+ this.initCallback();
+ }
+
+ if (this.skipToStage != null) {
+ this.fsm.setState(appStates.kStateLoadingStage, this.skipToStage);
+ } else {
+ this.fsm.setState(appStates.kStateIntro);
+ }
+
+ this.appLoop = new AppLoop(this.looper, this);
+};
+
+App.prototype.looper = function(dt) {
+ this.update(dt);
+ this.draw();
+};
+
+App.prototype.tryChangeState = function(condition, toState, msg, reEnter, suspendedCurrent) {
+ if (reEnter === undefined) reEnter = true;
+ if (suspendedCurrent === undefined) suspendedCurrent = false;
+ if (toState == fsmStates.kNextState) toState = this.fsm.currentState + 1;
+
+ if (condition && (toState != this.fsm.currentState || reEnter)) {
+ this.setState(toState, msg, suspendedCurrent);
+ return true;
+ }
+ return false;
+};
+
+App.prototype.setState = function(state, msg, suspendCurrent) {
+ this.newState = state;
+ this.newMessage = msg;
+ if (suspendCurrent || state == -1 || this.fsm.isSuspended(state)) {
+ this.fsm.setState(state, msg, suspendCurrent);
+ } else {
+ var st = this.findScreenTransition(this.fsm.currentState, state, true);
+
+ if (st == null) st = this.findScreenTransition(this.fsm.currentState, -1, true);
+ if (st == null) st = this.screenTransitionsDefaultOut;
+
+ st.reset();
+ this.audioTransition.reset();
+
+ this.stateMode = this.stateModes.kTransitionOut;
+ this.screenTransition = st;
+ }
+};
+
+/**
+ * Finds a screen transition that for fills the conditions.
+ *
+ * @param from the state that it should go from.
+ * @param to the state that it should go to.
+ * @param out True if the transition should be in or out from the from state.
+ * @returns A screen transition if found else null.
+ */
+App.prototype.findScreenTransition = function(from, to, out) {
+ for (var i = 0; i < this.screenTransitions.length; i++) {
+ var stt = this.screenTransitions[i];
+ if (stt.from == from && stt.to == to && stt.out == out) {
+ return stt.transition;
+ }
+ }
+ return null;
+};
+
+App.prototype.update = function(dt) {
+ if (InputHandler.instance !== null) {
+ InputHandler.instance.update(dt);
+ GameInput.instance.update(dt);
+ if(this.debug) this.updateDebug(dt);
+ }
+
+ if(this.freezeFrame) dt = 0;
+
+ if (this.stateMode == this.stateModes.kStateActive) {
+ this.fsm.update(dt);
+ // TODO: add control conditions.
+ } else {
+ this.screenTransition.update(dt);
+ this.audioTransition.update(dt, this.stateMode == this.stateModes.kTransitionOut);
+ if (this.screenTransition.isDone) {
+ if (this.stateMode == this.stateModes.kTransitionOut) {
+ var st = this.findScreenTransition(this.fsm.currentState, this.newState, false);
+ if (st == null) st = this.findScreenTransition(-1, this.newState, false);
+ if (st == null) st = this.screenTransitionsDefaultIn;
+
+ st.reset();
+ this.audioTransition.reset();
+
+ this.screenTransition = st;
+ this.stateMode = this.stateModes.kTransitionIn;
+
+ this.fsm.setState(this.newState, this.newMessage);
+ } else {
+ this.screenTransition = null;
+ this.stateMode = this.stateModes.kStateActive;
+ this.audioTransition.end();
+ }
+ }
+ }
+};
+
+App.prototype.updateDebug = function(dt) {
+ if (this.debugKeyboardTimeout > 0) {
+ this.debugKeyboardTimeout -= dt;
+ return;
+ }
+
+ var change = false;
+ if (InputHandler.instance.keyboard.keys[49].down) { // 1
+ this.debugAudio = !this.debugAudio;
+ change = true;
+ } else if (InputHandler.instance.keyboard.keys[50].down) { // 2
+ this.debugMovementTrigger = !this.debugMovementTrigger;
+ change = true;
+ } else if (InputHandler.instance.keyboard.keys[51].down) { // 3
+ this.showFPS = !this.showFPS;
+ change = true;
+ } else if (InputHandler.instance.keyboard.keys[52].down) { // 4
+ this.freezeFrame = !this.freezeFrame;
+ this.render.maxCalls = this.freezeFrame ? 0 : 1000;
+ change = true;
+ } else if (InputHandler.instance.keyboard.keys[53].down) { // 5
+ this.frontToBack = !this.frontToBack;
+ this.createRender();
+ change = true;
+ } else if (InputHandler.instance.keyboard.keys[74].down) {// J
+ this.render.maxCalls++;
+ change = true;
+ } else if (InputHandler.instance.keyboard.keys[75].down) { // K
+ this.render.maxCalls--;
+ change = true;
+ }
+
+ if (change) this.debugKeyboardTimeout = 0.2;
+};
+
+App.prototype.draw = function() {
+ if (this.render.frontToBack) {
+ this.render.clear();
+ if (this.screenTransition) this.screenTransition.draw(this.render);
+ if (this.showFPS) this.drawFPS();
+ if (this.debug && GameInput.instance) this.drawDebug();
+ this.fsm.draw(this.render);
+ } else {
+ this.render.clear();
+ this.fsm.draw(this.render);
+ if (this.debug && GameInput.instance) this.drawDebug();
+ if (this.showFPS) this.drawFPS();
+ if (this.screenTransition) this.screenTransition.draw(this.render);
+ }
+
+ this.render.flush();
+};
+
+App.prototype.drawDebug = function(){
+ var inp = GameInput.instance;
+ var str = "";
+ for (var b in inp.buttons) {
+ if (inp.buttons[b].down) {
+ str += " " + inp.buttons[b].name;
+ }
+ }
+
+ inp = InputHandler.instance;
+ if(!this.useTouch) str = "mouse: " + inp.mouse.x + " " + inp.mouse.y + " " + str;
+ this.render.drawSystemText(str, 10, 10, this.render.white);
+
+ if(this.frontToBack) this.render.drawSystemText("Front to back", 730, 10, this.render.white);
+
+ if(this.debugAudio) this.audio.draw(this.render);
+};
+
+App.prototype.drawFPS = function(){
+ this.frameCount++;
+ if (this.frameCount == 10) {
+ var date = new Date().getTime();
+ if (this.frameDate != null) {
+ var frameRate = Math.round(100000 / (date - this.frameDate)) / 10;
+ this.frameText = this.frameFont.generateCanvas("FPS: " + frameRate + " : " +
+ (this.freezeFrame ? this.render.maxCalls + " / " : "") + this.render.calls);
+ }
+ this.frameDate = date;
+ this.frameCount = 0;
+ }
+ if (this.frameText != null) this.render.drawText(this.frameText, 630, 15, 1, true);
+};
+
+/**
+ * Creates a new render.
+ *
+ * @param {Boolean} useGL True if WebGL should be used, false for canvas.
+ */
+App.prototype.createRender = function(useGL) {
+ if(this.render !== null) this.render.evict();
+ var oldRender = this.render;
+ var oldCanvas = document.getElementById(this.canvasId);
+ var canvasParent = oldCanvas.parentNode;
+ canvasParent.className = "active";
+
+ var canvas = document.createElement("canvas");
+ canvas.height = 600;
+ canvas.width = 800;
+ canvas.id = this.canvasId;
+ // Prevent selection of text while interacting with the canvas.
+ canvas.onselectstart = function () {
+ return false;
+ };
+
+ if (useGL) {
+ try {
+ this.render = utils.createWebGLRender(canvas, this.shaders);
+ this.render.frontToBack = this.frontToBack;
+ } catch (e) {
+ this.createRender(false);
+ this.webGLFailed = true;
+ return;
+ }
+ } else {
+ this.render = new RenderCanvas(canvas, 1, this.frontToBack);
+ }
+
+ if(this.freezeFrame) this.render.maxCalls = oldRender.maxCalls;
+
+ canvasParent.replaceChild(canvas, oldCanvas);
+
+ this.game.render = this.render;
+ this.canvas = canvas;
+
+ // Temporary
+ if (this.input !== undefined) {
+ this.input.updateCanvas(canvas);
+ }
+
+ this.resize();
+};
+
+App.prototype.resize = function() {
+ var canvas = document.getElementById(this.canvasId);
+ var canvasParent = canvas.parentNode;
+
+ var newWidth = window.innerWidth;
+ var newHeight = window.innerHeight;
+ var windowRatio = newWidth / newHeight;
+
+ if (!this.fillScreen && (newHeight > this.maxHeight && newWidth > this.maxWidth)) {
+ newHeight = this.maxHeight;
+ newWidth = this.maxWidth;
+ } else if (windowRatio > this.aspectRatio) {
+ newWidth = newHeight * this.aspectRatio;
+ } else {
+ newHeight = newWidth / this.aspectRatio;
+ }
+
+ newHeight = Math.floor(newHeight);
+ newWidth = Math.floor(newWidth);
+
+ canvasParent.style.height = newHeight + 'px';
+ canvasParent.style.width = newWidth + 'px';
+ canvasParent.style.marginTop = (-Math.floor(newHeight / 2)) + 'px';
+ canvasParent.style.marginLeft = (-Math.floor(newWidth / 2)) + 'px';
+
+ var canvasHeight = Math.min(this.maxHeight, newHeight);
+ var canvasWidth = Math.min(this.maxWidth, newWidth);
+ canvas.height = canvasHeight;
+ canvas.width = canvasWidth;
+
+ var scale = newWidth / this.maxWidth;
+
+ if (this.render != null) {
+ this.render.setScaleFactor(Math.min(1, scale));
+ }
+
+ if (InputHandler.instance != null) {
+ var offset = new Point2(window.innerWidth - newWidth, window.innerHeight - newHeight).div(2);
+ InputHandler.instance.setSize(scale, offset);
+ //InputHandler.instance.updateSize(canvas);
+ }
+};
+
+/**
+ * determines whether current render is the WebGL render
+ *
+ * @returns {Boolean}
+ */
+App.prototype.isWebGLRender = function() {
+ return this.render instanceof RenderWebGL;
+};
+
+/**
+ * Sets different application options from the url string
+ */
+App.prototype.getURLOptions = function () {
+ var url;
+
+ if (document.location) {
+ url = document.location.href;
+ } else if (document.URL) {
+ // Firefox doesn't have the location field
+ url = document.URL;
+ }
+
+ if (url.search("[\\?&]canvas") !== -1) {
+ this.useGL = false;
+ }
+
+ if (url.search("[\\?&]fps") !== -1) {
+ this.showFPS = true;
+ }
+
+ if (url.search("[\\?&]debug") !== -1) {
+ this.debug = true;
+ }
+
+ if (url.search("[\\?&]nomusic") !== -1) {
+ this.audio.musicVolume = 0;
+ }
+
+ if (url.search("[\\?&]nofillscreen") !== -1) {
+ this.fillScreen = false;
+ }
+
+ if (url.search("[\\?&]stage=") !== -1) {
+ var r = /[\\?&]stage=([^&]*)/;
+ this.skipToStage = r.exec(url)[1];
+
+ // Skips the splash screen and menu, which sets the input system,
+ // defaults to keyboard
+ this.createRender(this.useGL);
+ this.input = new InputHandler(this.canvas, false);
+ }
+
+ if (url.search("[\\?&]touch") !== -1) {
+ this.input = new InputHandler(this.canvas, true);
+ this.useTouch = true;
+ }
+};
+
+/**
+ * Enables debugging.
+ */
+App.prototype.enableDebugging = function () {
+ this.debug = true;
+ if (this.game.currentStage != null) {
+ this.game.currentStage.gameObjects.depth = -10;
+ this.game.currentStage.sortLayers();
+ }
+};
+
+/**
+ * A application loop. When created the callback will be called until stop is
+ * called.
+ *
+ * @param {Function} callback the function that should be called by the loop.
+ * @param {Object} that changes "this" to the specified when callback is called.
+ * @returns {AppLoop}
+ */
+function AppLoop(callback, that) {
+ var keepUpdating = true;
+ var lastLoopTime = new Date();
+
+ function loop() {
+ if (!keepUpdating) return;
+ requestAnimFrame(loop);
+ var time = new Date();
+ callback.call(that, (time - lastLoopTime) / 1000);
+ lastLoopTime = time;
+ }
+
+ this.stop = function() {
+ keepUpdating = false;
+ };
+
+ this.resume = function() {
+ keepUpdating = true;
+ lastLoopTime = new Date();
+ loop();
+ };
+
+ loop();
+ return this;
+}
+
+AppLoop.prototype = {};
+AppLoop.prototype.constructor = AppLoop;
869 src/AppStates.js
@@ -0,0 +1,869 @@
+/**
+ * Fades the screen from one color to another.
+ *
+ * @param {Number} maxT the maximum time that the transition should take.
+ * @param {Pixel32} from starting color.
+ * @param {Pixel32} to ending color.
+ * @returns {ScreenTransitionFade}
+ */
+function ScreenTransitionFade(maxT, from, to) {
+ this.maxT = maxT;
+ this.from = from;
+ this.to = to;
+
+ this.time = 0;
+ this.isDone = false;
+}
+
+ScreenTransitionFade.prototype = {};
+ScreenTransitionFade.constructor = ScreenTransitionFade;
+
+ScreenTransitionFade.prototype.update = function(dt) {
+ this.t = Math.min(this.t + dt, this.maxT);
+};
+
+ScreenTransitionFade.prototype.draw = function(render) {
+ this.isDone = this.t == this.maxT;
+
+ var color = new Pixel32(lerp(this.from.r, this.to.r, this.t / this.maxT),
+ lerp(this.from.g, this.to.g, this.t / this.maxT),
+ lerp(this.from.b, this.to.b, this.t / this.maxT),
+ lerp(this.from.a, this.to.a, this.t / this.maxT));
+ if (color.a > 0) {
+ render.drawFillScreen(color);
+ }
+};
+
+ScreenTransitionFade.prototype.reset = function() {
+ this.t = 0;
+ this.isDone = false;
+};
+
+// ---------------------------------------------------------------------------
+
+/**
+ * Fades the music from 0 to 100% user set volume.
+ */
+function AudioTransition(length){
+ this.length = length;
+ this.t = 0;
+}
+
+AudioTransition.prototype.reset = function() {
+ this.t = 0;
+};
+
+AudioTransition.prototype.end = function() {
+ app.audio.setMusicVolume(1);
+};
+
+AudioTransition.prototype.update = function(dt, out) {
+ this.t += dt;
+ var value = out ? Math.max(0, (this.length - this.t) / this.length) : Math.min(1, this.t / this.length);
+ app.audio.setMusicVolume(value);
+};
+
+// ---------------------------------------------------------------------------
+
+/**
+ * State that shows the developer splash screen.
+ *
+ * @returns {DeveloperSplashState}
+ */
+function DeveloperSplashState() {
+ this.skip = false;
+
+ BaseState.apply(this, arguments);
+}
+
+DeveloperSplashState.prototype = new BaseState();
+DeveloperSplashState.constructor = DeveloperSplashState;
+
+DeveloperSplashState.prototype.enter = function(msg, fromState) {
+ this.host.canvas.onmousedown = createCallback(function(e){
+ this.skip = true;
+ this.host.input = new InputHandler(this.host.canvas, false);
+ }, this);
+ window.onkeydown = this.host.canvas.onmousedown;
+
+ this.host.canvas.ontouchstart = createCallback(function(e){
+ this.skip = true;
+ this.host.input = new InputHandler(this.host.canvas, true);
+ // Some units seem to send both touch and mousedown events, prevent
+ // the input system to be overwritten..
+ this.host.canvas.onmousedown = undefined;
+ }, this);
+
+
+ var res = ResourceDepot.getInstance();
+ this.animation = res.getAnimation("TimeTrap");
+ this.splashSound = res.getSFX("timetrap_sound");
+
+ this.timeInState = 0;
+
+ // this.host.preload();
+};
+
+DeveloperSplashState.prototype.update = function(dt) {
+ dt = Math.min(dt, 1/15);
+ this.animation.update(dt);
+ if (this.timeInState < 0.5 && this.timeInState + dt > 0.5) {
+ this.animation.play(false);
+ this.soundID = this.host.audio.playFX(this.splashSound);
+ }
+ this.timeInState += dt;
+
+};
+
+DeveloperSplashState.prototype.leave = function () {
+ this.host.audio.stopSound(this.soundID);
+};
+
+DeveloperSplashState.prototype.transition = function() {
+ return this.host.tryChangeState(this.timeInState > 5 || this.skip, fsmStates.kNextState, "stage0");
+};
+
+DeveloperSplashState.prototype.draw = function(render) {
+ render.clear(render.white);
+ if (this.timeInState > 0.5) {
+ this.animation.draw(render, render.getWidth() / 2, render.getHeight() / 2, 0, 1, null);
+ }
+};
+
+// ---------------------------------------------------------------------------
+
+/**
+ * State when a stage is loading.
+ */
+function LoadingStageState() {
+ this.t = 0;
+ this.delayAfter = 1;
+ this.delayBefore = 0.1;
+ this.doneT = null;
+ this.progress = 0;
+
+ this.font = null;
+ this.progressText = null;
+ this.lastProgress = -1;
+
+ BaseState.apply(this, arguments);
+}
+
+LoadingStageState.prototype = new BaseState();
+LoadingStageState.constructor = LoadingStageState;
+
+LoadingStageState.prototype.enter = function(msg, fromState) {
+ this.doneT = null;
+ this.t = 0;
+ this.progress = 0;
+
+ this.stage = msg;
+
+ this.font = ResourceDepot.getInstance().getFont("BannerFont");
+
+ this.host.game.loadStage(msg, createCallback(this.progressCallback, this));
+};
+
+LoadingStageState.prototype.progressCallback = function(status) {
+ this.progress = status;
+
+ if(status >= 1){
+ if(this.t <= this.delayBefore){
+ this.doneT = 0;
+ }else{
+ this.doneT = this.t + this.delayAfter;
+ }
+ }
+};
+
+LoadingStageState.prototype.update = function(dt) {
+ this.t += dt;
+};
+
+LoadingStageState.prototype.transition = function() {
+ return this.host.tryChangeState(this.doneT != null && this.t >= this.doneT, appStates.kStateInGame);
+};
+
+LoadingStageState.prototype.draw = function(render) {
+ render.clear(render.black);
+
+ if(this.lastProgress != this.progress){
+ this.progressText = this.font.generateCanvas(Math.ceil(this.progress * 100) + " %");
+ this.lastProgress = this.progress;
+ }
+
+ var alpha = Math.min(1, Math.max(0, this.t * 2 - this.delayBefore));
+
+ render.drawText(this.progressText, (render.getWidth() - this.progressText.width) / 2,
+ render.getHeight()/2 - this.progressText.height/2, alpha);
+};
+
+// ---------------------------------------------------------------------------
+
+/**
+ * In game state, when the player is playing a stage.
+ *
+ * @returns {InGameState}
+ */
+function InGameState() {
+ this.restartDelay = 0;
+ this.stageDisplayDelay = 0;
+
+ this.stageNameDisplayAnim = null;
+ this.stageDisplayBannerR = null;
+ this.stageDisplayBannerC = null;
+ this.bannerSound = null;
+
+ this.stageNameDisplayXPos = 0;
+
+ this.areaNameText = "";
+ this.stageNameText = "";
+
+ this.backReleased = false;
+ this.playBannerSound = false;
+ this.playInGameTrack = false;
+
+ this.controlImage = null;
+ this.canvasImage = null;
+ this.canvasDisabledImage = null;
+ this.webglImage = null;
+
+ this.controlPressedTint = new Pixel32(0,0,0,128);
+ this.dpadImage = null;
+ this.dpadStickImage = null;
+ this.deadZoneDpad = 20;
+ this.dpadRect = null;
+ this.dpadRectInner = null;
+ this.dpadDistance = 128;
+ this.dpadInnerDistance = 10;
+
+ this.interactImage = null;
+
+ BaseState.apply(this, arguments);
+}
+
+InGameState.prototype = new BaseState();
+InGameState.constructor = InGameState;
+
+InGameState.prototype.enter = function(msg, fromState) {
+ this.timeSinceRenderSwap = 0;
+ this.dimTimeLeft = 0;
+ this.playBannerSound = false;
+ this.playInGameTrack = false;
+
+ this.gremlinFont = ResourceDepot.getInstance().getFont("StartTextFont");
+
+ this.restartDelay = 0;
+ this.stageDisplayDelay = 0;
+ this.stageDisplayBannerR = null;
+ this.stageDisplayBannerC = null;
+
+ this.controlImage = ResourceDepot.getInstance().getImage("ControlsiPhoneEscape", "default");
+ this.canvasImage = ResourceDepot.getInstance().getImage("btn_canvas", "btn_canvas");
+ this.canvasDisabledImage = ResourceDepot.getInstance().getImage("btn_canvas_disabled", "btn_canvas_disabled");
+ this.webglImage = ResourceDepot.getInstance().getImage("btn_webgl", "btn_webgl");
+
+ // Todo: Add the extra states checks.
+
+ if (fromState == appStates.kStateLoadingStage && this.host.skipToStage === null) {
+ this.stageDisplayDelay = 4.25;
+ this.stageNameDisplayXPos = -50.0;
+ this.bannerSound = ResourceDepot.getInstance().getSFX("stage_banner");
+ this.stageNameDisplayAnim = ResourceDepot.getInstance().getAnimation("WickFlyRight");
+ this.stageNameDisplayAnim.play();
+
+ this.stageDisplayBannerR = ResourceDepot.getInstance().getImage("StageBanner", "RightPiece");
+ this.stageDisplayBannerC = ResourceDepot.getInstance().getImage("StageBanner", "CentrePiece");
+
+ var font = ResourceDepot.getInstance().getFont("BannerFont");
+
+ //Todo: temporary below
+ var stagename = app.game.currentStage.name;
+
+ this.areaNameText = font.generateCanvas( stagename != "stage0" ? "Outer Grendale" : "The Elderwood");
+ var text = "Stage " + (parseInt(stagename[5])+1);
+ if(stagename =="stage0") text = "Boulderhood Lake";
+ else if(stagename =="stage1") text = "Emerald Shores";
+ else if(stagename=="stage2") text = "Glenbrook";
+ this.stageNameText = font.generateCanvas(text);
+
+ this.playBannerSound = true;
+ }
+
+ this.playInGameTrack = true;
+
+ if (this.host.useTouch) {
+ this.dpadImage = ResourceDepot.getInstance().getImage("ControlsiPhoneDpad", "default");
+ this.dpadStickImage = ResourceDepot.getInstance().getImage("ControlsiPhoneStick", "default");
+
+ this.attackImage = ResourceDepot.getInstance().getImage("ControlsiPhoneButtonA", "default");
+ this.jumpImage = ResourceDepot.getInstance().getImage("ControlsiPhoneButtonY", "default");
+ this.interactImage = ResourceDepot.getInstance().getImage("ControlsiPhoneButtonX", "default");
+
+ var screenW = this.host.render.getWidth();
+ var screenH = this.host.render.getHeight();
+
+
+ var x = 18 + 64;
+ var y = screenH / 2;
+
+ GameInput.instance.addGUIIsoscelesTriangle(x, y, this.dpadInnerDistance, this.dpadDistance, 100, 0, Buttons.down);
+ GameInput.instance.addGUIIsoscelesTriangle(x, y, this.dpadInnerDistance, this.dpadDistance, 100, 180, Buttons.up);
+ GameInput.instance.addGUIIsoscelesTriangle(x, y, this.dpadInnerDistance, this.dpadDistance, 100, 90, Buttons.left);
+ GameInput.instance.addGUIIsoscelesTriangle(x, y, this.dpadInnerDistance, this.dpadDistance, 100, 270, Buttons.right);
+
+ this.dpadRect = new Rectf(x - this.dpadDistance, y - this.dpadDistance, x + this.dpadDistance, y + this.dpadDistance);
+ this.dpadRectInner = new Rectf(x - this.dpadInnerDistance, y - this.dpadInnerDistance, x + this.dpadInnerDistance, y + this.dpadInnerDistance);
+
+ GameInput.instance.addGUICircle(screenW - 50, screenH / 2, 32, Buttons.attack);
+ GameInput.instance.addGUICircle(screenW - 50, screenH / 2 + 74, 32, Buttons.jump);
+ GameInput.instance.addGUICircle(screenW - 50, screenH / 2 - 74, 32, Buttons.enter);
+ }
+
+ this.host.game.updateCamera(0.01);
+};
+
+InGameState.prototype.leave = function() {
+ this.areaNameText = null;
+ this.stageNameText = null;
+};
+
+InGameState.prototype.update = function(dt) {
+ if (this.playBannerSound) {
+ this.playBannerSound = false;
+ app.audio.playFX(this.bannerSound);
+ }
+
+ if (this.playInGameTrack) {
+ this.playInGameTrack = false;
+ this.startInGameTrack();
+ }
+
+ var game = this.host.game;
+
+ if (this.stageDisplayDelay > 0) {
+ this.stageDisplayDelay -= dt;
+ this.stageNameDisplayAnim.update(dt);
+ this.stageNameDisplayXPos += dt * 800;
+ game.updateCamera(dt);
+ //Todo: add update background?
+ } else {
+ game.update(dt);
+
+ // Todo: Add focus object stuff
+ }
+
+ var inp = InputHandler.instance;
+ if(GameInput.instance.held(Buttons.esc) || (inp.clickInCircle(50, 50, 32)) && app.useTouch) {
+ this.host.setState(appStates.kStateMainMenu);
+ }
+ if(!this.host.webGLFailed && (GameInput.instance.pressed(Buttons.render) || inp.clickInCircle((this.host.useTouch ? 50 + 74 : 50), 50, 32)) && this.timeSinceRenderSwap > 1) {
+ this.host.createRender(this.host.render instanceof RenderCanvas);
+ this.timeSinceRenderSwap = 0;
+ }
+ this.timeSinceRenderSwap += dt;
+};
+
+InGameState.prototype.draw = function(render) {
+ if(!render.frontToBack) this.host.game.draw(render);
+
+ if (this.stageDisplayDelay > 0) {
+ this.bannerAlpha = 1;
+ this.textAlpha = 1;
+
+ if (this.stageDisplayDelay < 1) {
+ this.bannerAlpha = Math.max(0, this.stageDisplayDelay);
+ this.textAlpha = Math.max(0, this.stageDisplayDelay);
+ } else if (this.stageDisplayDelay < 3) {
+
+ } else if (this.stageDisplayDelay < 3.5) {
+ this.textAlpha = (3.5 - this.stageDisplayDelay) * 2;
+ } else {
+ this.textAlpha = 0;
+ }
+
+ var tmpPos = Math.min(render.getWidth(), Math.floor(this.stageNameDisplayXPos) - this.stageDisplayBannerR.textureWidth);
+ render.drawImage(this.stageDisplayBannerR, tmpPos, 200, 0, false, this.bannerAlpha, null, false);
+
+ while (tmpPos > 0) {
+ tmpPos -= this.stageDisplayBannerC.textureWidth;
+ render.drawImage(this.stageDisplayBannerC, tmpPos, 200, 0, false, this.bannerAlpha, null, false);
+ }
+
+ if (this.textAlpha) {
+ render.drawText(this.areaNameText, (render.getWidth() - this.areaNameText.width) / 2, 220, this.textAlpha);
+ render.drawText(this.stageNameText, (render.getWidth() - this.stageNameText.width) / 2, 270, this.textAlpha);
+ }
+
+ this.stageNameDisplayAnim.draw(render, this.stageNameDisplayXPos - 25, 255);
+ }
+
+ var controlsAlpha = 1;
+ if (this.stageDisplayDelay > 0)
+ controlsAlpha = Math.max(0, 1 - this.stageDisplayDelay);
+
+ if (this.host.useTouch) {
+ render.drawImage(this.controlImage, 50, 50, 0, true, controlsAlpha, null, false);
+
+ var input = InputHandler.instance;
+
+ var screenW = render.getWidth();
+ var screenH = render.getHeight();
+ var x = 18 + 64;
+ var y = screenH / 2;
+ render.drawImage(this.dpadImage, x, y, 0, true, controlsAlpha, null, false);
+ var noTouch = true;
+ for (var k in input.touches) {
+ if (input.touches.hasOwnProperty(k)) {
+ var touch = input.touches[k];
+ if (this.dpadRect.contains(touch.x, touch.y) && !this.dpadRectInner.contains(touch.x, touch.y)) {
+ if (Math.pow(x - touch.x, 2) + Math.pow(y - touch.y, 2) < Math.pow(64, 2)) {
+ render.drawImage(this.dpadStickImage, touch.x, touch.y, 0, true, controlsAlpha, null, false);
+ } else {
+ var angle = Math.atan2(touch.y - y, touch.x - x);
+ render.drawImage(this.dpadStickImage, Math.cos(angle) * 64 + x, Math.sin(angle) * 64 + y, 0, true, controlsAlpha, null, false);
+ }
+ noTouch = false;
+ break;
+ }
+ }
+ }
+ if (noTouch) {
+ render.drawImage(this.dpadStickImage, x, y, 0, true, controlsAlpha, null, false);
+ }
+
+ render.drawImage(this.attackImage, screenW - 50, screenH / 2, 0, true, controlsAlpha, null, false);
+ render.drawImage(this.jumpImage, screenW - 50, screenH / 2 + 74, 0, true, controlsAlpha, null, false);
+ if (this.host.game.focus.hasInteractTarget())
+ render.drawImage(this.interactImage, screenW - 50, screenH / 2 - 74, 0, true, controlsAlpha, null, false);
+ }
+
+ var renderImage;
+ if (this.host.webGLFailed) {
+ renderImage = this.canvasDisabledImage;
+ } else {
+ renderImage = render instanceof RenderCanvas ? this.canvasImage : this.webglImage;
+ }
+ render.drawImage(renderImage, (this.host.useTouch ? 50 + 74 : 50), 50, 0, true, controlsAlpha, null, false);
+
+ if(render.frontToBack) this.host.game.draw(render);
+};
+
+InGameState.prototype.startInGameTrack = function () {
+ if (this.host.game.currentStage.type === "siege") {
+ var sName = this.host.game.currentStage.name;
+ if (sName == "stage0" || sName == "stage1" || sName == "stage2" || sName == "stage3") {
+ this.host.audio.playMusic(ResourceDepot.getInstance().getMusic("outer_grendale"));
+ }
+ // Should be more stuff here I guess, but since we only include the
+ // first stages, there's no point in going any further..
+ else {
+ this.host.audio.playMusic(ResourceDepot.getInstance().getMusic("outer_grendale"));
+ }
+ }
+};
+
+// ---------------------------------------------------------------------------
+
+function MainMenuState() {
+ this.timeInactive = null;
+ this.titleImgs = [];
+ this.titleLeftImgs = [];
+ this.titleRightImgs = [];
+ this.wickEyes = [];
+ this.kindleEyes = [];
+ this.copyright = null;
+
+ // todo: buttons
+
+ this.guiBox = null;
+
+ this.buttonPressed = -1;
+ this.cloudXPos = 0;
+ this.fogXPos = 0;
+
+ this.acceptSound = null; // todo
+ this.declineSound = null; // todo
+ this.refuseSound = null; // todo
+ this.selectSound = null; // todo
+ this.enterSound = null; // todo
+
+ this.nextWickBlink = 0;
+ this.wickBlinkLeft = 0;
+ this.nextWickLook = 0;
+ this.wickLookLeft = 0;
+ this.wickLookType = 0;
+ this.nextKindleBlink = 0;
+ this.kindleBlinkLeft = 0;
+ this.lastMusicPos = null;
+
+ this.doStartScreen = true; // temp
+ this.timeIntoStartScreen = 0;
+ this.titleParam = 0;
+ this.pressStartText = null;
+ this.pressStartFlash = 0;
+ this.timeInSinceStartScreen = 0;
+
+ BaseState.apply(this, arguments);
+}
+
+MainMenuState.prototype = new BaseState();
+MainMenuState.constructor = MainMenuState;
+
+MainMenuState.prototype.enter = function(msg, fromState) {
+ if(this.doStartScreen){
+ this.host.canvas.onmousedown = createCallback(function(e){
+ this.timeInactive = 0;
+ this.doStartScreen = true;
+ this.timeIntoStartScreen = 0.01;
+ this.host.useTouch = false;
+ this.host.input = new InputHandler(this.host.canvas, false);
+ this.host.canvas.ontouchstart = undefined;
+ }, this);
+ window.onkeydown = this.host.canvas.onmousedown;
+
+ this.host.canvas.ontouchstart = createCallback(function(e){
+ this.timeInactive = 0;
+ this.doStartScreen = true;
+ this.timeIntoStartScreen = 0.01;
+ this.host.useTouch = true;
+ this.host.input = new InputHandler(this.host.canvas, true);
+ // Some units seem to send both touch and mousedown events, prevent
+ // the input system to be overwritten..
+ this.host.canvas.onmousedown = undefined;
+ }, this);
+ }
+
+ this.timeInSinceStartScreen = 999;
+ this.timeInactive = 0;
+ this.lastMusicPos = 0;
+
+ this.buttonPressed = -1;
+ this.titleImgs[0] = ResourceDepot.getInstance().getImage("Titlescreen0", "default");
+ this.titleImgs[1] = ResourceDepot.getInstance().getImage("Titlescreen1", "default");
+ this.titleImgs[2] = ResourceDepot.getInstance().getImage("Titlescreen2", "default");
+ this.titleImgs[3] = ResourceDepot.getInstance().getImage("Titlescreen3", "default");
+ this.titleImgs[4] = ResourceDepot.getInstance().getImage("Titlescreen4", "default");
+ this.titleImgs[5] = ResourceDepot.getInstance().getImage("TitlescreenLogo", "default");
+
+ this.wickEyes[0] = ResourceDepot.getInstance().getImage("TitlescreenWickEyes", "eyes0");
+ this.wickEyes[1] = ResourceDepot.getInstance().getImage("TitlescreenWickEyes", "eyes1");
+ this.wickEyes[2] = ResourceDepot.getInstance().getImage("TitlescreenWickEyes", "eyes2");
+ this.wickEyes[3] = ResourceDepot.getInstance().getImage("TitlescreenWickEyes", "eyes3");
+
+ this.kindleEyes = ResourceDepot.getInstance().getImage("TitlescreenKindleEyes", "default");
+
+ this.copyright = ResourceDepot.getInstance().getImage("copyright", "copyright", true);
+
+ this.wickBlinkLeft = 0;
+ this.nextWickBlink = randomRange(4, 6);
+ this.wickLookLeft = 0;
+ this.nextWickLook = randomRange(4, 6);
+ this.wickLookType = 1;
+
+ this.nextKindleBlink = randomRange(4, 6);
+ this.kindleBlinkLeft = 0;
+
+ this.cloudXPos = 0;
+ this.fogXPos = 0;
+
+ var startStage = function(event, num) {
+ if (GUIButton.eventTypes.onButtonPressed == event) {
+ app.setState(appStates.kStateLoadingStage, "stage" + num);
+ }
+ };
+
+ var stage1 = GUITextButton.getStandardButton(null, null, "Boulderhood Lake", "MenuButtonFont",function(a){startStage(a, 0);});
+ var stage2 = GUITextButton.getStandardButton(null, null, "Emerald Shores", "MenuButtonFont",function(a){startStage(a, 1);});
+ var stage3 = GUITextButton.getStandardButton(null, null, "Glenbrook", "MenuButtonFont",function(a){startStage(a, 2);});
+
+ this.guiBox = new GUIBox();
+ this.guiBox.addButton(stage1);
+ this.guiBox.addButton(stage2);
+ this.guiBox.addButton(stage3);
+
+ // todo: init buttons and stuff
+
+ this.font = ResourceDepot.getInstance().getFont("StartTextFont");
+ this.pressStartText = this.font.generateCanvas("Click or touch the screen");
+
+ this.backgroundMusic = ResourceDepot.getInstance().getMusic("main_theme");
+ this.musicID = this.host.audio.playMusic(this.backgroundMusic, true);
+
+};
+
+MainMenuState.prototype.leave = function() {
+ this.host.audio.stopSound(this.musicID);
+};
+
+MainMenuState.prototype.draw = function(render) {
+ if (this.doStartScreen)
+ this.drawStartScreenBackground(render);
+ else
+ {
+ this.drawBackground(render);
+ this.guiBox.draw(render);
+ }
+};
+
+MainMenuState.prototype.drawStartScreenBackground = function(render) {
+ var center = new Vec2(render.getWidth() / 2, render.getHeight() / 2);
+
+ render.clear();
+ render.drawImage(this.titleImgs[0], center.x, center.y, 0, true, 1, null, false);
+
+
+ for (var i = 0; i < 3; i++)
+ render.drawParticle(this.titleImgs[1], this.cloudXPos + this.titleImgs[1].textureWidth * 2 * i, this.titleImgs[1].textureHeight - 150, 0, 2, 2, 1, new Pixel32(255, 255, 255), false);
+
+
+ var castleScale = 1.25;
+ if (this.timeIntoStartScreen > 0.5)
+ castleScale = 1.25 - 0.25 * Clamp(0, (this.timeIntoStartScreen - 0.5) / 2, 1);
+
+
+ render.drawParticle(this.titleImgs[2], center.x, center.y, 0, castleScale, castleScale, 1, new Pixel32(0xff, 0xff, 0xff, 0x0), false);
+
+ var fgScale = 5;
+ if (this.timeIntoStartScreen > 0.5)
+ fgScale = 5 - 4 * Clamp(0, (this.timeIntoStartScreen - 0.5) / 2, 1);
+
+ render.drawParticle(this.titleImgs[4], center.x, center.y, 0, fgScale, fgScale, 1, new Pixel32(0xff, 0xff, 0xff, 0x0), false);
+
+
+ var titlePos = center.y;
+ if (this.timeIntoStartScreen > 2.5)
+ titlePos = -(this.titleImgs[5].textureHeight / 2) + this.titleImgs[5].textureHeight * Clamp(0, (this.timeIntoStartScreen - 2.5) * 2, 1);
+ else{
+ var tp = Clamp(0, this.timeIntoStartScreen * 4, 1) * Math.PI/2;
+ titlePos = center.y - Math.sin(tp) * render.getHeight() * 2/3;
+ }
+
+
+ var offsetX = perlin.noise1(this.titleParam / 2) * 5;
+ var offsetY = perlin.noise1(this.titleParam / 2 + 100) * 5;
+
+ offsetY += 10; // Maybe
+
+ render.drawParticle(this.titleImgs[5], center.x + offsetX, titlePos + offsetY, 0, 1, 1, 1, new Pixel32(0xff, 0xff, 0xff, 0xff), false);
+
+ render.drawImage(this.copyright, center.x, render.getHeight() - this.copyright.textureHeight / 2 - 5, 0, true, 1, null, false);
+
+ if (this.timeIntoStartScreen == 0){
+ var alpha = 0.5 + (1 + Math.sin(this.pressStartFlash)) / 4;
+ render.drawText(this.pressStartText, center.x - this.pressStartText.width / 2, render.getHeight() * 2/3, alpha);
+ }
+};
+
+MainMenuState.prototype.drawBackground = function(render) {
+ var center = new Vec2(render.getWidth() / 2, render.getHeight() / 2);
+
+ render.drawImage(this.titleImgs[0], center.x, center.y, 0, true, 1, null, false);
+
+ for (var i = 0; i < 3; ++i)
+ render.drawParticle(this.titleImgs[1], this.cloudXPos + this.titleImgs[1].textureWidth * 2 * i, this.titleImgs[1].textureHeight - 150, 0, 2, 2, 1, new Pixel32(255, 255, 255), false);
+
+ render.drawImage(this.titleImgs[2], center.x, center.y, 0, true, 1, null, false);
+
+ render.drawParticle(this.titleImgs[3], this.fogXPos + this.titleImgs[3].textureWidth * 5, 620, 0, 10, 10, Math.min(1, this.timeInSinceStartScreen), new Pixel32(255, 255, 255), false);
+
+
+ if (this.titleImgs[3].textureWidth * 10 + this.fogXPos < render.getWidth())
+ render.drawParticle(this.titleImgs[3], this.titleImgs[3].textureWidth * 15 + this.fogXPos, 620, 0, 10, 10, Math.min(1, this.timeInSinceStartScreen), new Pixel32(255, 255, 255), false);
+
+ render.drawImage(this.titleImgs[4], center.x, center.y, 0, true, 1, null, false);
+
+ var offsetX = perlin.noise1(this.titleParam / 2) * 5;
+ var offsetY = perlin.noise1(this.titleParam / 2 + 100) * 5;
+
+
+ offsetY += 10;
+
+ render.drawParticle(this.titleImgs[5], center.x + offsetX, this.titleImgs[5].textureHeight / 2 + offsetY, 0, 1, 1, 1, new Pixel32(0xff, 0xff, 0xff, 0xff), false);
+
+ render.drawImage(this.copyright, center.x, render.getHeight() - this.copyright.textureHeight / 2 - 5, 0, true, 1, null, false);
+
+ var wx = center.x + 214;
+ var wy = center.y - 49;
+ if (this.wickBlinkLeft > 0)
+ render.drawImage(this.wickEyes[0], wx, wy);
+ else if (this.wickLookLeft > 0)
+ render.drawImage(this.wickEyes[Math.floor(this.wickLookType)], wx, wy);