world_game.js 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402
  1. /* describes the game */
  2. class WorldGame extends World {
  3. assets() {
  4. return [
  5. "images/crystal.png",
  6. "images/darek_run_0.png",
  7. "images/darek_run_1.png",
  8. "images/darek_run_2.png",
  9. "images/darek_run_3.png",
  10. "images/darek_run_4.png",
  11. "images/darek_run_5.png",
  12. "images/darek_run_6.png",
  13. "images/darek_run_7.png",
  14. "images/darek_stand.png",
  15. "images/game_bg.png",
  16. "images/button_shop.png",
  17. "images/button_spawn_speed.png",
  18. "images/button_spawn_value.png",
  19. "images/button_collector_quantity.png",
  20. "images/button_collector_speed.png",
  21. "images/button_spawn_limit.png",
  22. "images/button_options.png",
  23. "images/button_quit.png",
  24. ];
  25. }
  26. /* initialize game */
  27. start() {
  28. /* interface data */
  29. let PADDING = 10;
  30. /* game data */
  31. this.shop = new Shop();
  32. this.pickups = 0;
  33. this.paused = false;
  34. /* background, tile image */
  35. let bg = new PIXI.extras.TilingSprite(
  36. loader.resources["images/game_bg.png"].texture,
  37. width, height
  38. );
  39. app.stage.addChild(bg);
  40. /* container of everything that "stands" on the ground
  41. * everything in this container should be sorted based on the
  42. * bottom side of its sprite, to emulate objects that are behind
  43. * other objects
  44. */
  45. this.ground_container = new PIXI.Container();
  46. app.stage.addChild(this.ground_container);
  47. /* spawner of crystals */
  48. this.spawner = new PickupSpawner(this.ground_container,
  49. this.shop.get_data(this.shop.SPAWN_SPEED),
  50. this.shop.get_data(this.shop.SPAWN_LIMIT));
  51. /* collectors */
  52. this.collector_array = [];
  53. Collector.new_timer = this.shop.get_data(this.shop.COLLECTOR_SPEED);
  54. /* text to display pickups */
  55. this.style = new PIXI.TextStyle(
  56. {
  57. fill: 0x6699ff,
  58. dropShadow: true,
  59. dropShadowColor: 0x000000,
  60. dropShadowBlur: 2,
  61. dropShadowDistance: 2,
  62. });
  63. this.text = new PIXI.Text("hello world", this.style);
  64. this.text.x = PADDING;
  65. this.text.y = PADDING;
  66. app.stage.addChild(this.text);
  67. /* open-close shop button and its animation
  68. * used to animate shop buttons
  69. */
  70. this.button_open_shop = new PIXI.Sprite( loader.resources["images/button_shop.png"].texture );
  71. this.button_open_shop.position.set( PADDING, height -this.button_open_shop.height -PADDING );
  72. app.stage.addChild(this.button_open_shop);
  73. this.anim_open_shop = new Animation(15);
  74. /* shop buttons */
  75. this.shop_buttons = [
  76. new PIXI.Sprite( loader.resources["images/button_spawn_speed.png"].texture ),
  77. new PIXI.Sprite( loader.resources["images/button_spawn_value.png"].texture ),
  78. new PIXI.Sprite( loader.resources["images/button_collector_quantity.png"].texture ),
  79. new PIXI.Sprite( loader.resources["images/button_collector_speed.png"].texture ),
  80. new PIXI.Sprite( loader.resources["images/button_spawn_limit.png"].texture )
  81. ];
  82. /* text for shop prices */
  83. this.txt_shop = [
  84. new PIXI.Text("", this.style),
  85. new PIXI.Text("", this.style),
  86. new PIXI.Text("", this.style),
  87. new PIXI.Text("", this.style),
  88. new PIXI.Text("", this.style),
  89. ];
  90. this.update_text();
  91. /* place buttons horizontally, equal distance from each other
  92. * and below the screen (they show when they are animated)
  93. */
  94. for (let i = 0; i < this.shop_buttons.length; i++) {
  95. this.shop_buttons[i].x = width /(this.shop_buttons.length+1) *(i+1)
  96. -this.shop_buttons[i].width/2;
  97. this.shop_buttons[i].y = height;
  98. app.stage.addChild(this.shop_buttons[i]);
  99. /* texts */
  100. this.txt_shop[i].anchor = {x:0.5, y:1};
  101. this.txt_shop[i].position.set( this.shop_buttons[i].x +this.shop_buttons[i].width/2,
  102. this.shop_buttons[i].y -this.shop_buttons[i].height);
  103. this.txt_shop[i].visible = false;
  104. app.stage.addChild(this.txt_shop[i]);
  105. }
  106. /* options button */
  107. this.button_options = new PIXI.Sprite(
  108. loader.resources["images/button_options.png"].texture
  109. );
  110. this.button_options.x = width -this.button_options.width -PADDING;
  111. this.button_options.y = PADDING;
  112. app.stage.addChild(this.button_options);
  113. /* quit button */
  114. this.button_quit = new PIXI.Sprite(
  115. loader.resources["images/button_quit.png"].texture
  116. );
  117. this.button_quit.x = width;
  118. this.button_quit.y = this.button_options.y +this.button_options.height
  119. +PADDING;
  120. app.stage.addChild(this.button_quit);
  121. /* quit button animation */
  122. this.anim_quit = new Animation(15);
  123. /* paused text */
  124. this.txt_paused = new PIXI.Text("Paused", this.style);
  125. this.txt_paused.anchor = {x:0.5, y:0.5};
  126. this.txt_paused.position.set(width/2, height/2);
  127. this.txt_paused.visible = false;
  128. app.stage.addChild(this.txt_paused);
  129. /* button sound */
  130. this.button_sound = new Audio("audio/button_click.mp3");
  131. /* theme music */
  132. this.theme = new Audio("audio/collector_game.mp3");
  133. this.theme.addEventListener('ended', function() {
  134. this.currentTime = 0;
  135. this.play();
  136. }, false);
  137. if (!muted) {
  138. this.theme.play();
  139. }
  140. /* fade in animation */
  141. this.fade_in = new PIXI.Graphics();
  142. this.fade_in.beginFill(0x000000);
  143. this.fade_in.drawRect(0, 0, width, height);
  144. this.fade_in.endFill();
  145. this.fade_in.alpha = 1;
  146. app.stage.addChild(this.fade_in);
  147. this.anim_open = new Animation(15);
  148. this.anim_open.start();
  149. } /* start */
  150. /* runs once each frame */
  151. update() {
  152. /* opening animation */
  153. if (this.anim_open.update()) {
  154. /* when animation ends, remove rectangle */
  155. if (!this.anim_open.is_running()) {
  156. this.fade_in.visible = false;
  157. /* animation is back in the beginning
  158. * a new world is opening
  159. */
  160. if (this.anim_open.timer == 0) {
  161. this.theme.pause();
  162. return 0;
  163. }
  164. }
  165. /* animate rectangle alpha to fade in */
  166. this.fade_in.alpha = 1 -this.anim_open.interpolate(1);
  167. this.theme.volume = this.anim_open.interpolate(1);
  168. /* ignore input and update during animation */
  169. return;
  170. } /* opening animation */
  171. /* handle input */
  172. for (let e = 0; e < input.length; e++) {
  173. /* mouse left click */
  174. if (input[e].which == 1) {
  175. /* save clicking point */
  176. let p = new PIXI.Point(input[e].offsetX, input[e].offsetY);
  177. /* clicked on options button */
  178. if (this.button_options.containsPoint(p)) {
  179. if (!muted) this.button_sound.play();
  180. this.paused = !this.paused;
  181. this.txt_paused.visible = this.paused;
  182. this.anim_quit.flip();
  183. }
  184. /* clicked on quit button */
  185. if (this.button_quit.containsPoint(p)) {
  186. if (!muted) this.button_sound.play();
  187. this.anim_open.start();
  188. this.fade_in.visible = true;
  189. }
  190. /* clicked on open-close shop button */
  191. if (this.button_open_shop.containsPoint(p)) {
  192. /* play sound */
  193. if (!muted) this.button_sound.play();
  194. /* animate buttons */
  195. this.anim_open_shop.flip();
  196. /* make prices invisible */
  197. for (let i = 0; i < this.txt_shop.length; i++) {
  198. this.txt_shop[i].visible = false;
  199. }
  200. /* touch only one button per input */
  201. break;
  202. } /* button open-close shop */
  203. /* clicked on a crystal, only if game is not paused */
  204. if (!this.paused) {
  205. let i;
  206. if ((i = this.spawner.collect(p)) > -1) {
  207. this.pickup(i);
  208. }
  209. } /* clicked on pickup */
  210. /* clicked on shop button */
  211. for (let i = 0; i < this.shop_buttons.length; i++) {
  212. /* find which button it was */
  213. if (this.shop_buttons[i].containsPoint(p)) {
  214. /* user attempted to buy something */
  215. this.buy_something(i);
  216. /* one touch per input */
  217. break;
  218. } /* which shop button */
  219. } /* shop buttons */
  220. } /* left click */
  221. } /* handle input */
  222. /* quit button is animating */
  223. if (this.anim_quit.update()) {
  224. this.button_quit.x = width -this.anim_quit.interpolate(
  225. this.button_quit.width +10);
  226. }
  227. /* game is paused, do not update anything
  228. * except animation for quit button
  229. */
  230. if (this.paused) {
  231. return;
  232. }
  233. /* shop buttons animation */
  234. if (this.anim_open_shop.update()) {
  235. /* make all buttons move from below the screen
  236. * to the bottom part of the screen
  237. */
  238. for (let i = 0; i < this.shop_buttons.length; i++) {
  239. this.shop_buttons[i].y =
  240. height -this.anim_open_shop.interpolate(this.shop_buttons[0].height +10);
  241. }
  242. /* animation stopped */
  243. if (!this.anim_open_shop.is_running()) {
  244. if (this.anim_open_shop.timer == this.anim_open_shop.max) {
  245. for (let i = 0; i < this.txt_shop.length; i++) {
  246. this.txt_shop[i].visible = true;
  247. }
  248. }
  249. }
  250. } /* shop buttons animation */
  251. /* update spawner (to make more pickups) */
  252. this.spawner.update();
  253. /* update collectors */
  254. for (let i = 0; i < this.collector_array.length; i++) {
  255. this.collector_array[i].update();
  256. }
  257. } /* update */
  258. /* show how many pickups have been picked up on the screen
  259. * and shop prices
  260. */
  261. update_text() {
  262. this.text.text = "pickups: " +this.pickups;
  263. for (let i = 0; i < this.txt_shop.length; i++) {
  264. this.txt_shop[i].text = this.shop.cost(i);
  265. }
  266. }
  267. /* user attempted to buy something,
  268. * handle everything here (TO DO)
  269. */
  270. buy_something(i) {
  271. /* play sound */
  272. if (!muted) {
  273. this.button_sound.play();
  274. }
  275. /* user has enough crystals */
  276. let cost = this.shop.cost(i);
  277. if (this.pickups >= cost) {
  278. /* pay price */
  279. this.pickups -= cost;
  280. /* buy shop level */
  281. let data = this.shop.increase_data(i);
  282. this.update_text();
  283. if ( this.shop.get_counter(i) == 8 ) {
  284. this.shop_buttons[i].visible = false;
  285. }
  286. /* change game data depending on what changed */
  287. switch (i) {
  288. case 0:
  289. this.spawner.set_speed(this.shop.get_data(this.shop.SPAWN_SPEED));
  290. console.log("new spawn speed: " +this.spawner.anim_spawn.max);
  291. break;
  292. case 1:
  293. console.log("new spawn value: " +this.shop.get_data(this.shop.SPAWN_VALUE));
  294. break;
  295. case 2:
  296. for (let i = 0; i < data; i++) {
  297. this.collector_array.push( new Collector(this) );
  298. }
  299. console.log("total number of collectors: " +this.collector_array.length);
  300. break;
  301. case 3:
  302. Collector.new_timer = this.shop.get_data(
  303. this.shop.COLLECTOR_SPEED);
  304. console.log("collector speed: ", Collector.new_timer);
  305. break;
  306. case 4:
  307. this.spawner.limit = this.shop.get_data(this.shop.SPAWN_LIMIT);
  308. console.log("pickup limit: " +this.spawner.limit);
  309. break;
  310. } /* switch data type */
  311. } /* user can pay cost */
  312. } /* buy something */
  313. /* picked up crystal with index i */
  314. pickup(i) {
  315. /* show current pickups on screen */
  316. this.pickups += this.shop.get_data(this.shop.SPAWN_VALUE);
  317. this.update_text();
  318. /* remove crystal from ground container and spawner */
  319. this.ground_container.removeChild(this.spawner.array[i]);
  320. this.spawner.array.splice(i, 1);
  321. /* notify all collectors that crystal was picked up */
  322. for (let j = 0; j < this.collector_array.length; j++) {
  323. this.collector_array[j].notify_collected(i);
  324. }
  325. } /* pickup */
  326. } /* game world */