game.js 8.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308
  1. var Mobile = require('./mobile');
  2. var Item = require('./item');
  3. var NonPlayerCharacter = require('./nonplayercharacter');
  4. var PlayerCharacter = require('./playercharacter');
  5. var OnionNpc = require('./npcs/onionnpc');
  6. var GrugNpc = require('./npcs/grugnpc');
  7. var GlendaNpc = require('./npcs/glendanpc');
  8. function Game() {
  9. var lastTime = 0;
  10. var socketConnections = [];
  11. var mobileIdCount = 1;
  12. var itemIdCount = 1;
  13. this.mobiles = [];
  14. this.nonplayer = [];
  15. this.items = [];
  16. this.init = function() {
  17. lastTime = new Date().getTime();
  18. setInterval(function() {
  19. var currentTime = new Date().getTime();
  20. var delta = (currentTime - lastTime) / (1000 / 60);
  21. game.tick(delta);
  22. lastTime = currentTime;
  23. }, 100);
  24. this.mobiles = [];
  25. mobileIdCount = 1;
  26. this.items = [];
  27. itemIdCount = 1;
  28. this.spawnOnion();
  29. this.spawnGrug();
  30. this.spawnGlenda();
  31. }
  32. this.getConnections = function() {
  33. return socketConnections;
  34. }
  35. this.addConnection = function(key, connection) {
  36. socketConnections[key] = connection;
  37. };
  38. this.removeConnection = function(key) {
  39. delete socketConnections[key];
  40. };
  41. this.shutdown = function() {
  42. for(var index in this.getConnections()) {
  43. socketConnections[index].close();
  44. }
  45. socketConnections = [];
  46. };
  47. this.tick = function(delta) {
  48. for(var index in this.mobiles) {
  49. var mobile = this.mobiles[index];
  50. mobile.update(delta, this);
  51. }
  52. for(var index in this.mobiles) {
  53. var mobile = this.mobiles[index].mobile;
  54. this.pickUp(this.mobiles[index]);
  55. mobile.angleRadians = this.angleTo(mobile.position, mobile.targetPosition);
  56. if(mobile.targetPosition.x != mobile.position.x) {
  57. if(Math.abs(mobile.position.x - mobile.targetPosition.x) < mobile.maxSpeed * (1000/120)) {
  58. mobile.position.x = mobile.targetPosition.x;
  59. mobile.targetAngle = mobile.angleRadians;
  60. } else {
  61. mobile.targetAngle = mobile.angleRadians;
  62. mobile.position.x += mobile.maxSpeed * Math.cos(mobile.angleRadians) * delta;
  63. }
  64. }
  65. if(mobile.targetPosition.y != mobile.position.y) {
  66. if(Math.abs(mobile.position.y - mobile.targetPosition.y) < mobile.maxSpeed * (1000/120)) {
  67. mobile.position.y = mobile.targetPosition.y;
  68. mobile.targetAngle = mobile.angleRadians;
  69. } else {
  70. mobile.targetAngle = mobile.angleRadians;
  71. mobile.position.y += (mobile.maxSpeed) * Math.sin(mobile.angleRadians) * delta;
  72. }
  73. }
  74. }
  75. for(var index in this.items) {
  76. var item = this.items[index];
  77. if(item == null) {
  78. this.items.splice(this.items.indexOf(item), 1);
  79. index--;
  80. }
  81. }
  82. if(this.items.length < 5) {
  83. this.spawnItem("Food " + itemIdCount);
  84. }
  85. }
  86. this.addPlayer = function(playerData, socketKey) {
  87. var newPlayer = new PlayerCharacter(this);
  88. var mobile = newPlayer.init(mobileIdCount++, socketKey, playerData);
  89. this.mobiles.push(newPlayer);
  90. console.log("Player " + newPlayer.id + " joined");
  91. return newPlayer;
  92. };
  93. this.takeOverNpc = function(playerData, socketKey) {
  94. var maxNpc = 3;
  95. var mobilecopy = this.mobiles.slice(0, this.mobiles.length-1);
  96. for(var index = mobilecopy.length-1; index >= 0; index--) {
  97. }
  98. var newPlayer = new PlayerCharacter(this);
  99. newPlayer.init(mobileIdCount++, socketKey, playerData);
  100. this.mobiles.push(newPlayer);
  101. console.log("Player " + newPlayer.id + " joined");
  102. return newPlayer;
  103. };
  104. this.removePlayer = function(socketKey) {
  105. for(var index in this.mobiles) {
  106. var player = this.mobiles[index];
  107. if(player.mobile.socketKey == socketKey) {
  108. console.log("Player " + player.mobile.id + " disconnected");
  109. this.mobiles.splice(this.mobiles.indexOf(player), 1);
  110. return;
  111. }
  112. }
  113. console.log("Player with key " + socketKey + " not found");
  114. }
  115. this.takeOverPlayer = function(socketKey) {
  116. for(var index in this.mobiles) {
  117. var player = this.mobiles[index];
  118. if(player.mobile.socketKey == socketKey) {
  119. console.log("Player " + player.mobile.id + " disconnected");
  120. //this.mobiles.splice(this.mobiles.indexOf(player), 1);
  121. var replacementNpc = new NonPlayerCharacter(this);
  122. replacementNpc.takeOver(player);
  123. this.mobiles[index] = replacementNpc;
  124. return;
  125. }
  126. }
  127. console.log("Player with key " + socketKey + " not found");
  128. }
  129. this.movePlayer = function(playerId, movementData) {
  130. for(var index in this.mobiles) {
  131. var player = this.mobiles[index].mobile;
  132. if(player.id == playerId) {
  133. player.targetPosition = movementData.targetPosition;
  134. return;
  135. }
  136. }
  137. };
  138. this.updatePlayer = function(playerId, playerInfo) {
  139. for(var index in this.mobiles) {
  140. var player = this.mobiles[index].mobile;
  141. if(player.id == playerId) {
  142. for(var key in player) {
  143. if(playerInfo.hasOwnProperty(key)) {
  144. player[key] = playerInfo[key];
  145. }
  146. }
  147. return;
  148. }
  149. }
  150. }
  151. this.sendToAll = function(data) {
  152. for(var socketIndex in this.getConnections()) {
  153. socketConnections[socketIndex].send(data);
  154. }
  155. }
  156. this.sendToOthers = function(key, data) {
  157. for(var socketIndex in this.getConnections()) {
  158. if(socketIndex == key) { continue; }
  159. socketConnections[socketIndex].send(data);
  160. }
  161. }
  162. this.getUpdate = function() {
  163. var allMobiles = [];
  164. for(var index in this.mobiles) {
  165. allMobiles.push(this.mobiles[index].mobile);
  166. }
  167. return {mobiles: allMobiles, items: this.items};
  168. }
  169. this.formatFloat = function(val) {
  170. if (Number.isNaN(parseFloat(val))) {
  171. return 0;
  172. }
  173. return parseFloat(val.toFixed(6));
  174. };
  175. this.distanceTo = function(source, target) {
  176. return this.formatFloat(Math.sqrt(Math.pow(target.x - source.x, 2) + Math.pow(target.y - source.y, 2)));
  177. }
  178. this.angleTo = function(source, target) {
  179. return this.formatFloat(Math.atan2(target.y - source.y , target.x - source.x));
  180. }
  181. this.getRandomPosition = function(origin, range) {
  182. if(origin == null) {
  183. origin = {x: 0, y: 0};
  184. }
  185. if(range == null) {
  186. range = {min: -250, max: 500};
  187. }
  188. var position = {x: 0, y: 0};
  189. position.x = parseInt(range.max * Math.random() + range.min) + origin.x;
  190. position.y = parseInt(range.max * Math.random() + range.min) + origin.y;
  191. return position;
  192. }
  193. this.spawnNpc = function(npcData) {
  194. var newNpc = new NonPlayerCharacter(this);
  195. newNpc.init(mobileIdCount++, npcData);
  196. this.mobiles.push(newNpc);
  197. };
  198. this.spawnOnion = function(){
  199. var newNpc = new OnionNpc(this);
  200. newNpc.init(mobileIdCount++, {});
  201. this.mobiles.push(newNpc);
  202. }
  203. this.spawnGrug = function(){
  204. var newNpc = new GrugNpc(this);
  205. newNpc.init(mobileIdCount++, {});
  206. this.mobiles.push(newNpc);
  207. }
  208. this.spawnGlenda = function(){
  209. var newNpc = new GlendaNpc(this);
  210. newNpc.init(mobileIdCount++, {});
  211. this.mobiles.push(newNpc);
  212. }
  213. this.spawnItem = function(name) {
  214. var newItem = new Item();
  215. newItem.id = itemIdCount++;
  216. newItem.color = "green";
  217. newItem.name = name;
  218. newItem.position = this.getRandomPosition();
  219. this.items.push(newItem);
  220. };
  221. this.pickUp = function(mobile) {
  222. if(mobile.inventory.length >= mobile.maxInventory) {
  223. return;
  224. }
  225. for(var itemIndex in this.items) {
  226. var item = this.items[itemIndex];
  227. if(item != null && this.inBounds(mobile.mobile, item)) {
  228. mobile.inventory.push(item);
  229. console.log(mobile.mobile.name + "("+mobile.mobile.id+") picked up " + item.name + "("+item.id+") at ", item.position);
  230. this.items[itemIndex] = null;
  231. continue;
  232. }
  233. }
  234. }
  235. this.inBounds = function(mobile, item) {
  236. var halfMobileWidth = mobile.width / 2;
  237. var halfMobileHeight = mobile.height / 2;
  238. var halfItemWidth = item.width / 2;
  239. var halfItemHeight = item.height / 2;
  240. if(mobile.position.x + halfMobileWidth > item.position.x - halfItemWidth &&
  241. mobile.position.x - halfMobileWidth < item.position.x + halfItemWidth &&
  242. mobile.position.y + halfMobileHeight > item.position.y - halfItemHeight &&
  243. mobile.position.y - halfMobileHeight < item.position.y + halfItemHeight) {
  244. return true;
  245. }
  246. return false;
  247. }
  248. this.sendChat = function(mobile, message) {
  249. var mobileName = mobile.name;
  250. message = mobileName + ": " + message;
  251. var chatData = {action: "chat", data:{mobileid:mobile.id, message:message}};
  252. console.log("chat:", message);
  253. game.sendToAll(JSON.stringify(chatData));
  254. }
  255. this.handleChat = function(chatData) {
  256. for(var index in this.mobiles) {
  257. var mobile = this.mobiles[index];
  258. if(mobile.id == chatData.data.mobileid) {
  259. this.sendChat(mobile.mobile, chatData.data.message);
  260. break;
  261. }
  262. }
  263. }
  264. };
  265. module.exports = new Game();