PageRenderTime 48ms CodeModel.GetById 23ms RepoModel.GetById 1ms app.codeStats 0ms

/game.js

https://github.com/muralivvn/MojoJojo
JavaScript | 150 lines | 130 code | 8 blank | 12 comment | 19 complexity | 27e08e69c3c26cdbd8c90cd36d4e571d MD5 | raw file
  1. (function() {
  2. //private methods
  3. function gameLoop(game) {
  4. game.fire("gameLoopBegin");
  5. game.fire("gameLoopEnd");
  6. }
  7. jojo.Game = Class.create(jojo.event.EventPublisher, {
  8. frameDelay: 30,
  9. initialize: function($super, options) {
  10. //basic validation: require a canvas element to be passed in
  11. if (!options || !options.canvas) {
  12. throw new Error("The MojoJojo.Game class requires a canvas element to be passed into the constructor");
  13. }
  14. //base class construction
  15. $super(options);
  16. //entity management objects
  17. this.entityCollection = []; //flat array of all entities that can be used for sorting algorithms
  18. this.entityCache = {}; //indexed associative array for fast retrieval
  19. this.entityKeys = []; //array of keys used to index entities in the cache object
  20. //setup options
  21. this.frameDelay = options.frameDelay || this.frameDelay;
  22. this.canvas = options.canvas; //the canvas element to use to draw the game scenes to and listen to events
  23. this.config = options.config;
  24. if (options.configPath) {
  25. this.loadConfig(options.configPath);
  26. }
  27. //pause game on explicit errors
  28. this.on("error", this.pauseGame.bind(this));
  29. },
  30. loadConfig: function(path) {
  31. var me = this;
  32. this.configPath = path;
  33. var request = new Ajax.Request(path, {
  34. method: 'get',
  35. evalJSON: 'force',
  36. onSuccess: function(args) {
  37. me.config = args.responseJSON;
  38. me.fire("configLoaded");
  39. },
  40. onFailure: function(args) {
  41. me.fire("error", {
  42. source: "loadConfig",
  43. message: "Failure loading config file",
  44. data: args
  45. });
  46. }
  47. });
  48. },
  49. startGame: function(options) {
  50. if (options) {
  51. Object.extend(this, options);
  52. }
  53. var me = this;
  54. if (!this.wired) { //only want to wire the Mojo listeners once per instance
  55. this.ctx = this.canvas.getContext('2d');
  56. Mojo.Event.listen(this.canvas, 'mousedown', this.handleTouch.bind(this));
  57. Mojo.Event.listen(this.canvas, 'mouseup', this.handleMouseUp.bind(this));
  58. Mojo.Event.listen(this.canvas, 'mousemove' , this.handleMouseMove.bind(this));
  59. this.wired = true;
  60. }
  61. this.fire("beforeGameStart");
  62. if (!this.preventGameStart) {
  63. this.gameInterval = setInterval(function(){
  64. try {
  65. gameLoop(me);
  66. }
  67. catch (error) {
  68. me.fire("error", {
  69. source: "gameLoop",
  70. message: "Failure in gameLoop: " + error.message
  71. });
  72. }
  73. }, this.frameDelay);
  74. this.gameRunning = true;
  75. this.fire("gameStarted");
  76. }
  77. },
  78. pauseGame: function() {
  79. if (this.gameRunning && this.gameInterval) {
  80. this.fire("beforeGamePause");
  81. if (!this.preventGamePause) {
  82. clearInterval(this.gameInterval);
  83. delete this.gameInterval;
  84. this.gameRunning = false;
  85. this.fire("gamePaused");
  86. }
  87. }
  88. },
  89. handleTouch: function(event) {
  90. this.fire("touch", {event: event});
  91. //handle entity touch events
  92. var touchedEntities = findTouchedEntities();//pseudo-code
  93. if (touchedEntities) {
  94. for (var i = 0, _e = touchedEntities; i < touchedEntities.length; i++) {
  95. _e[i].fire("touch", {game: this, event: event});
  96. }
  97. }
  98. },
  99. handleMouseUp: function(event) {
  100. this.fire("mouseUp", {event: event});
  101. //handle entity click events
  102. var clickedEntities = findClickedEntities(event);//pseudo-code
  103. if (clickedEntities) {
  104. for (var i = 0, _e = clickedEntities; i < clickedEntities.length; i++) {
  105. _e[i].fire("click", {game: this, event: event});
  106. }
  107. }
  108. },
  109. handleMouseMove: function(event) {
  110. this.fire("mouseMove", {event: event});
  111. //handle entity "untouch" events (entities where the previous x/y/z was in touchzone but new x/y/z is not)
  112. var untouchedEntities = findUntouchedEntities(event);//pseudo-code
  113. if (untouchedEntities) {
  114. for (var i = 0, _e = untouchedEntities; i < untouchedEntities.length; i++) {
  115. _e[i].fire("untouch", {game: this, event: event});
  116. }
  117. }
  118. //handle new entity touch events
  119. var newTouchedEntities = findNewTouchedEntities(event);//pseudo-code
  120. if (newTouchedEntities) {
  121. for (var i = 0, _e = newTouchedEntities; i < newTouchedEntities.length; i++) {
  122. _e[i].fire("touch", {game: this, event: event});
  123. }
  124. }
  125. },
  126. addEntity: function(entity) {
  127. if (!entity.addedToCollection) {
  128. this.fire("beforeAddEntity", {entity: entity});
  129. this.entityCollection.push(entity);
  130. //allow custom indexing function on entity classes (recommended)
  131. var key = entity.getIndexKey ? entity.getIndexKey() : entity.id;
  132. this.entityCache[key] = entity;
  133. this.entityKeys.push(key);
  134. entity.addedToCollection = true;
  135. entity.game = this;
  136. //allow entity classes to define logic upon being added to the scene (for example, for initial pathfinding calculations or other setup)
  137. entity.fire("added");
  138. this.fire("entityAdded", {entity: entity});
  139. }
  140. }
  141. });
  142. })();