globals_control.js 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659
  1. /**************************************************************
  2. * LInE - Free Education, Private Data - http://www.usp.br/line
  3. *
  4. * This file holds all global elements to the game.
  5. *
  6. * Generating game levels in menu:
  7. * .....................................................
  8. * ...............square....................circle...... } = gameShape
  9. * .........../...........\....................|........ } = gameName (game)
  10. * ........One.............Two................One....... }
  11. * ......./...\.........../...\............./....\......
  12. * ......a.....b.........a.....b...........a......b..... = gameMode (game mode)
  13. * .(floor)..(stack)..(top)..(bottom)..(floor)..(stack).
  14. * .......\./.............\./................\./........
  15. * ........|...............|..................|.........
  16. * ......./.\..............|................/.|.\.......
  17. * ...plus...minus.......minus........plus.minus.mixed. = gameOperation (game math operation)
  18. * .......\./..............|................\.|./.......
  19. * ........|...............|..................|.........
  20. * ......1,2,3.........1,2,3,4,5............1,2,3,...... = gameDifficulty (difficulty level)
  21. * .....................................................
  22. *
  23. * About levels in map:
  24. *
  25. * ..................(game.levels)......................
  26. * ......................__|__..........................
  27. * .....................|.|.|.|.........................
  28. * ...................0,1,2,3,4,5....................... = curMapPosition (map positions)
  29. * ...................|.........|.......................
  30. * ................(start)....(end).....................
  31. **************************************************************/
  32. /** FOR MOODLE <br>
  33. *
  34. * iFractions can run on a server or inside moodle through iAssign. <br>
  35. * Detected automatically: true if iAssign passes iLM_PARAM_SendAnswer in the URL.
  36. */
  37. const moodle = new URLSearchParams(window.location.search).has('iLM_PARAM_SendAnswer');
  38. let moodleVar = {
  39. hits: [0, 0, 0, 0],
  40. errors: [0, 0, 0, 0],
  41. time: [0, 0, 0, 0],
  42. };
  43. /**
  44. * Index of the current game in gameList array
  45. *
  46. * @type {number}
  47. */
  48. let gameId;
  49. /**
  50. * Selected game name.<br>
  51. * Can be: 'squareOne', 'squareTwo' or 'circleOne'.
  52. *
  53. * @type {string}
  54. */
  55. let gameName;
  56. /**
  57. * Used for text and game information.<br>
  58. * Shape that makes the name of the game - e.g in 'squareOne' it is 'square'.<br>
  59. * Can be: 'circle' or 'square'.
  60. *
  61. * @type {string}
  62. */
  63. let gameShape;
  64. /**
  65. * Holds selected game mode.<br>
  66. * In squareOne/circleOne can be: 'a' (click on the floor) or 'b' (click on the amount to go/stacked figures).<br>
  67. * In squareTwo can be: 'a' (more subdivisions on top) or 'b' (more subdivisions on bottom).
  68. *
  69. * @type {string}
  70. */
  71. let gameMode;
  72. /**
  73. * Holds game math operation.<br>
  74. * In squareOne can be: 'plus' (green tractor goes right) or 'minus' (red tractor goes left).<br>
  75. * In circleOne can be: 'plus' (green tractor goes right), 'minus' (red tractor goes left) or 'mixed' (green tractor goes both sides).<br>
  76. * In squareTwo can be: 'minus' (compares two rectangle subdivisions).
  77. *
  78. * @type {string}
  79. */
  80. let gameOperation;
  81. /**
  82. * Holds game overall difficulty. 1 (easier) -> n (harder).<br>
  83. * In squareOne can be: 1..3.<br>
  84. * In circleOne/squareTwo can be: 1..5.
  85. *
  86. * @type {number}
  87. */
  88. let gameDifficulty;
  89. /**
  90. * Turns displaying the fraction labels on levels ON/OFF
  91. * @type {boolean}
  92. */
  93. let showFractions = true;
  94. /**
  95. * When true, the character can move to next position in the map
  96. * @type {boolean}
  97. */
  98. let canGoToNextMapPosition;
  99. /**
  100. * Character position on the map, aka game levels (1..4: valid; 5: end)
  101. * @type {number}
  102. */
  103. let curMapPosition;
  104. /**
  105. * Number of finished levels in the map
  106. * @type {number}
  107. */
  108. let completedLevels;
  109. /**
  110. * Turns game audio ON/OFF
  111. * @type {boolean}
  112. */
  113. let audioStatus = false;
  114. /**
  115. * Player's name
  116. * @type {string}
  117. */
  118. let playerName;
  119. /**
  120. * String that contains the selected language.<br>
  121. * It is the name of the language file.
  122. * @type {string}
  123. */
  124. let langString;
  125. /**
  126. * Holds the current state.<br>
  127. * Is used as if it was a 'this' inside state functions.
  128. * @type {object}
  129. */
  130. let self;
  131. /**
  132. * Information for all the games
  133. * @type {Array}
  134. */
  135. const gameList = [
  136. {
  137. gameName: 'squareOne',
  138. gameMode: ['a', 'b'],
  139. gameOperation: ['plus', 'minus'],
  140. gameDifficulty: 3,
  141. gameShape: 'square',
  142. assets: {
  143. menu: {
  144. gameNameBtn: 'game_0',
  145. infoBox: () => ({
  146. title: `<strong>${game.lang.game}:</strong> ${game.lang.square} I`,
  147. body: `<ul>${game.lang.infoBox_squareOne}</ul>`,
  148. img: `<img class="ifr-infoBox__menu__img" src="${game.image['s1-A'].src}">`,
  149. }),
  150. },
  151. customMenu: {
  152. gameModeBtn: ['mode_0', 'mode_1'],
  153. gameOperationBtn: ['operation_plus', 'operation_minus'],
  154. gameModeDescription: ['s1_a_description', 's1_b_description'],
  155. gameOperationDescription: [
  156. 'op_plus_description',
  157. 'op_minus_description',
  158. ],
  159. gameDifficultyDescription: [
  160. 'diff_1_description',
  161. 'diff_2_description',
  162. 'diff_3_description',
  163. ],
  164. gameLabelDescription: 'label_description',
  165. auxiliarTitle: (x, y, offsetW, offsetH) => {
  166. game.add.text(
  167. x + 5 * offsetW,
  168. y + offsetH + 50,
  169. game.lang.show + '\n' + game.lang.title,
  170. textStyles.h4_
  171. );
  172. },
  173. infoBox: () => ({
  174. gameMode: {
  175. title: game.lang.game_modes,
  176. body: `<p>${game.lang.infoBox_mode}</p>`,
  177. img: `<table>
  178. <tr>
  179. <td><b>${game.lang.mode}: A</b> - ${game.lang.infoBox_mode_s1_A}</td>
  180. <td><b>${game.lang.mode}: B</b> - ${game.lang.infoBox_mode_s1_B}</td>
  181. </tr>
  182. <tr>
  183. <td><img width=100% src="${game.image['s1-A-h'].src}"></td>
  184. <td><img width=100% src="${game.image['s1-B-h'].src}"></td>
  185. </tr>
  186. <table>`,
  187. },
  188. gameDifficulty: {
  189. title: game.lang.difficulties,
  190. body: `<p>${game.lang.infoBox_diff}</p><p>${game.lang.infoBox_diff_obs}</p>`,
  191. img: `<table>
  192. <tr>
  193. <td><b>${game.lang.difficulty}:</b> 1</td>
  194. <td><b>${game.lang.difficulty}:</b> 3</td>
  195. </tr>
  196. <tr>
  197. <td><img width=100% src="${game.image['s1-diff-1'].src}"></td>
  198. <td style="border-left: 4px solid white"><img width=100% src="${game.image['s1-diff-3'].src}"></td>
  199. </tr>
  200. </table>
  201. <br>
  202. ${game.lang.infoBox_diff_aux}
  203. <div><img width=50% src="${game.image['map-s1'].src}"></div>`,
  204. },
  205. gameMisc: {
  206. title: `${game.lang.show} ${self.auxText}`,
  207. body: game.lang.infoBox_misc_label,
  208. img: `<img class="mx-auto" width=80% src="${game.image['s1-label'].src}">`,
  209. },
  210. }),
  211. },
  212. map: {
  213. characterAnimation: (operation) => {
  214. return operation === 'plus'
  215. ? ['move', [0, 1, 2, 3, 4], 3]
  216. : ['move', [10, 11, 12, 13, 14], 3];
  217. },
  218. character: (operation) => {
  219. let char;
  220. if (operation == 'plus') {
  221. char = game.add.sprite(
  222. self.scene.roadPoints.x[curMapPosition],
  223. self.scene.roadPoints.y[curMapPosition],
  224. 'tractor',
  225. 0,
  226. 0.75
  227. );
  228. }
  229. if (operation === 'minus') {
  230. char = game.add.sprite(
  231. self.scene.roadPoints.x[curMapPosition],
  232. self.scene.roadPoints.y[curMapPosition],
  233. 'tractor',
  234. 10,
  235. 0.75
  236. );
  237. }
  238. char.rotate = -30; // 25 counterclockwise
  239. char.anchor(0.25, 0.5);
  240. return char;
  241. },
  242. startBuilding: () => {
  243. return game.add.image(
  244. self.scene.roadPoints.x[0] - 60,
  245. self.scene.roadPoints.y[0] - 155,
  246. 'garage',
  247. 0.6
  248. );
  249. },
  250. endBuilding: () => {
  251. return game.add.image(
  252. self.scene.roadPoints.x[5] - 10,
  253. self.scene.roadPoints.y[5] - 215,
  254. 'farm',
  255. 0.9
  256. );
  257. },
  258. },
  259. end: {
  260. characterAnimation: () =>
  261. gameOperation === 'plus'
  262. ? ['move', [0, 1, 2, 3, 4], 3]
  263. : ['move', [10, 11, 12, 13, 14], 3],
  264. character: () => {
  265. const char = game.add.sprite(
  266. 0,
  267. context.canvas.height - 170 - 80,
  268. 'tractor',
  269. 0,
  270. 1.05
  271. );
  272. char.anchor(0.5, 0.5);
  273. if (gameOperation === 'minus') char.curFrame = 10;
  274. return char;
  275. },
  276. building: () =>
  277. game.add
  278. .image(
  279. context.canvas.width - 420,
  280. context.canvas.height - 100,
  281. 'farm',
  282. 1.7
  283. )
  284. .anchor(0, 1),
  285. },
  286. },
  287. },
  288. {
  289. gameName: 'circleOne',
  290. gameMode: ['a', 'b'],
  291. gameOperation: ['plus', 'minus', 'mixed'],
  292. gameDifficulty: 3,
  293. // info
  294. gameShape: 'circle',
  295. assets: {
  296. menu: {
  297. gameNameBtn: 'game_1',
  298. infoBox: () => ({
  299. title: `<strong>${game.lang.game}:</strong> ${game.lang.circle} I`,
  300. body: `<ul>${game.lang.infoBox_circleOne}</ul>`,
  301. img: `<img class="mx-auto" width=60% src="${game.image['c1-A'].src}">`,
  302. }),
  303. },
  304. customMenu: {
  305. gameModeBtn: ['mode_2', 'mode_3'],
  306. gameModeDescription: ['c1_a_description', 'c1_b_description'],
  307. gameOperationDescription: [
  308. 'op_plus_description',
  309. 'op_minus_description',
  310. 'op_mixed_description',
  311. ],
  312. gameDifficultyDescription: [
  313. 'diff_1_description',
  314. 'diff_2_description',
  315. 'diff_3_description',
  316. ],
  317. gameLabelDescription: 'label_description',
  318. gameOperationBtn: [
  319. 'operation_plus',
  320. 'operation_minus',
  321. 'operation_mixed',
  322. ],
  323. auxiliarTitle: (x, y, offsetW, offsetH) => {
  324. game.add.text(
  325. x + 5 * offsetW,
  326. y + offsetH + 50,
  327. game.lang.show + '\n' + game.lang.title,
  328. textStyles.h4_
  329. );
  330. },
  331. infoBox: () => ({
  332. gameMode: {
  333. title: game.lang.game_modes,
  334. body: `<p>${game.lang.infoBox_mode}</p>`,
  335. img: `<table>
  336. <tr style="border-bottom: 5px solid white">
  337. <td width=70%>
  338. <img width=100% src=${game.image['c1-A-h'].src}>
  339. </td>
  340. <td>&nbsp;<b>${game.lang.mode}: A</b> - ${game.lang.infoBox_mode_c1_A}</td>
  341. </tr>
  342. <tr>
  343. <td><img width=100% src=${game.image['c1-B-h'].src}></td>
  344. <td>&nbsp;<b>${game.lang.mode}: B</b> - ${game.lang.infoBox_mode_c1_B}</td>
  345. </tr>
  346. </table>`,
  347. },
  348. gameDifficulty: {
  349. title: game.lang.difficulties,
  350. body: `<p>${game.lang.infoBox_diff}</p><p>${game.lang.infoBox_diff_obs}</p>`,
  351. img: `<table>
  352. <tr>
  353. <td style="border-right: 4px solid white">
  354. <b>${game.lang.difficulty}:</b> 1
  355. </td>
  356. <td>
  357. <b>${game.lang.difficulty}:</b> 5
  358. </td>
  359. </tr>
  360. <tr>
  361. <td>
  362. <img width=100% src="${game.image['c1-diff-1'].src}">
  363. </td>
  364. <td style="border-left: 4px solid white">
  365. <img width=100% src="${game.image['c1-diff-3'].src}">
  366. </td>
  367. </tr>
  368. </table>
  369. <br>
  370. ${game.lang.infoBox_diff_aux}
  371. <div><img width=50% src="${game.image['map-c1s2'].src}"></div>`,
  372. },
  373. gameMisc: {
  374. title: `${game.lang.show} ${self.auxText}`,
  375. body: game.lang.infoBox_misc_label,
  376. img: `<img class="mx-auto" width=60% src="${game.image['c1-label'].src}">`,
  377. },
  378. }),
  379. },
  380. map: {
  381. characterAnimation: (operation) => {
  382. return ['kid', [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10], 3];
  383. },
  384. character: (operation) => {
  385. const char = game.add.sprite(
  386. self.scene.roadPoints.x[curMapPosition],
  387. self.scene.roadPoints.y[curMapPosition],
  388. 'kid_running',
  389. 0,
  390. 0.57
  391. );
  392. char.anchor(0, 0.85);
  393. return char;
  394. },
  395. startBuilding: () => {
  396. return game.add.image(
  397. self.scene.roadPoints.x[0] - 193,
  398. self.scene.roadPoints.y[0] - 205,
  399. 'house',
  400. 1.03
  401. );
  402. },
  403. endBuilding: () => {
  404. return game.add.image(
  405. self.scene.roadPoints.x[5] - 28,
  406. self.scene.roadPoints.y[5] - 215,
  407. 'school',
  408. 0.52
  409. );
  410. },
  411. },
  412. end: {
  413. characterAnimation: () => [
  414. 'move',
  415. [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11],
  416. 3,
  417. ],
  418. character: () => {
  419. const char = game.add.sprite(
  420. 0,
  421. context.canvas.height - 240,
  422. 'kid_running',
  423. 0,
  424. 1.05
  425. );
  426. char.anchor(0.5, 0.5);
  427. return char;
  428. },
  429. building: () =>
  430. game.add
  431. .image(
  432. context.canvas.width - 620,
  433. context.canvas.height - 20 - 15,
  434. 'school',
  435. 1.3
  436. )
  437. .anchor(0, 1),
  438. },
  439. },
  440. },
  441. {
  442. gameName: 'squareTwo',
  443. gameMode: ['a', 'b'],
  444. gameOperation: ['minus'],
  445. gameDifficulty: 5,
  446. // info
  447. gameShape: 'square',
  448. assets: {
  449. menu: {
  450. gameNameBtn: 'game_2',
  451. infoBox: () => ({
  452. title: `<strong>${game.lang.game}:</strong> ${game.lang.square} II`,
  453. body: `<ul>${game.lang.infoBox_squareTwo}</ul>`,
  454. img: `<img class="mx-auto" width=60% src="${game.image['s2'].src}">`,
  455. }),
  456. },
  457. customMenu: {
  458. gameModeBtn: ['mode_4', 'mode_5'],
  459. gameOperationBtn: ['operation_equals'],
  460. gameModeDescription: ['s2_a_description', 's2_b_description'],
  461. gameOperationDescription: ['op_equals_description'],
  462. gameDifficultyDescription: [
  463. 's2_diff_1_description',
  464. 's2_diff_2_description',
  465. 's2_diff_3_description',
  466. 's2_diff_4_description',
  467. 's2_diff_5_description',
  468. ],
  469. gameLabelDescription: 'label_description',
  470. auxiliarTitle: (x, y, offsetW, offsetH) => {
  471. game.add.text(
  472. x + 5 * offsetW,
  473. y + offsetH + 50,
  474. game.lang.show + '\n' + game.lang.title,
  475. textStyles.h4_
  476. );
  477. },
  478. infoBox: () => ({
  479. gameMode: {
  480. title: game.lang.game_modes,
  481. body: `<p>${game.lang.infoBox_mode}</p>`,
  482. img: `<table>
  483. <tr>
  484. <td><b>${game.lang.mode}: A</b> - ${game.lang.infoBox_mode_s2_A}</td>
  485. <td><b>${game.lang.mode}: B</b> - ${game.lang.infoBox_mode_s2_B}</td>
  486. </tr>
  487. <tr>
  488. <td><img width=98% src="${game.image['s2-A-h'].src}"></td>
  489. <td><img width=98% src="${game.image['s2-B-h'].src}"></td>
  490. </tr>
  491. <table>`,
  492. },
  493. gameDifficulty: {
  494. title: game.lang.difficulties,
  495. body: game.lang.infoBox_diff,
  496. img: `<table>
  497. <tr>
  498. <td><b>${game.lang.difficulty}:</b> 1</td>
  499. <td><b>${game.lang.difficulty}:</b> 5</td>
  500. </tr>
  501. <tr>
  502. <td><img width=100% src="${game.image['s2-diff-1'].src}"></td>
  503. <td style="border-left: 4px solid white"><img width=100% src="${game.image['s2-diff-5'].src}"></td>
  504. </tr>
  505. </table>
  506. <br>
  507. ${game.lang.infoBox_diff_aux}
  508. <div><img width=50% src="${game.image['map-c1s2'].src}"></div>`,
  509. },
  510. gameMisc: {
  511. title: `${game.lang.show} ${self.auxText}`,
  512. body: game.lang.infoBox_misc_rect,
  513. img: `<img class="mx-auto" width=100% src="${game.image['s2-label'].src}">`,
  514. },
  515. }),
  516. },
  517. map: {
  518. characterAnimation: (operation) => {
  519. return ['kid', [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10], 3];
  520. },
  521. character: (operation) => {
  522. const char = game.add.sprite(
  523. self.scene.roadPoints.x[curMapPosition],
  524. self.scene.roadPoints.y[curMapPosition],
  525. 'kid_running',
  526. 0,
  527. 0.57
  528. );
  529. char.anchor(0, 0.85);
  530. return char;
  531. },
  532. startBuilding: () => {
  533. return game.add.image(
  534. self.scene.roadPoints.x[0] - 193,
  535. self.scene.roadPoints.y[0] - 205,
  536. 'house',
  537. 1.03
  538. );
  539. },
  540. endBuilding: () => {
  541. return game.add.image(
  542. self.scene.roadPoints.x[5] - 28,
  543. self.scene.roadPoints.y[5] - 215,
  544. 'school',
  545. 0.52
  546. );
  547. },
  548. },
  549. end: {
  550. characterAnimation: () => [
  551. 'move',
  552. [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11],
  553. 3,
  554. ],
  555. character: () => {
  556. const char = game.add.sprite(
  557. 0,
  558. context.canvas.height - 240,
  559. 'kid_running',
  560. 0,
  561. 1.05
  562. );
  563. char.anchor(0.5, 0.5);
  564. return char;
  565. },
  566. building: () =>
  567. game.add
  568. .image(
  569. context.canvas.width - 620,
  570. context.canvas.height - 20 - 15,
  571. 'school',
  572. 1.3
  573. )
  574. .anchor(0, 1),
  575. },
  576. },
  577. },
  578. // {
  579. // gameName: 'scaleOne',
  580. // gameMode: ['a'],
  581. // gameOperation: ['plus'],
  582. // gameDifficulty: 1,
  583. // // info
  584. // gameShape: 'noShape',
  585. // assets: {
  586. // menu: {
  587. // gameNameBtn: 'game_3',
  588. // // infoBox
  589. // },
  590. // customMenu: {
  591. // gameModeBtn: ['mode_6'],
  592. // gameOperationBtn: ['operation_equals'],
  593. // auxiliarTitle: (x, y, offsetW, offsetH) => {},
  594. // // infoBox
  595. // },
  596. // map: {
  597. // characterAnimation: (operation) => {
  598. // return operation === 'plus'
  599. // ? ['green_tractor', [0, 1, 2, 3, 4], 3]
  600. // : ['red_tractor', [10, 11, 12, 13, 14], 3];
  601. // },
  602. // character: (operation) => {
  603. // let char;
  604. // if (operation == 'plus') {
  605. // char = game.add.sprite(
  606. // self.scene.roadPoints.x[curMapPosition],
  607. // self.scene.roadPoints.y[curMapPosition],
  608. // 'tractor',
  609. // 0,
  610. // 0.75
  611. // );
  612. // }
  613. // if (operation === 'minus') {
  614. // char = game.add.sprite(
  615. // self.scene.roadPoints.x[curMapPosition],
  616. // self.scene.roadPoints.y[curMapPosition],
  617. // 'tractor',
  618. // 10,
  619. // 0.75
  620. // );
  621. // }
  622. // char.rotate = -30; // 25 counterclockwise
  623. // return char;
  624. // },
  625. // startBuilding: () => {
  626. // return game.add
  627. // .image(self.scene.roadPoints.x[0], self.scene.roadPoints.y[0], 'garage', 0.6)
  628. // .anchor(0.5, 1);
  629. // },
  630. // endBuilding: () => {
  631. // return game.add
  632. // .image(self.scene.roadPoints.x[5], self.scene.roadPoints.y[5], 'farm', 0.9)
  633. // .anchor(0.4, 0.7);
  634. // },
  635. // },
  636. // end: {
  637. // // TODO
  638. // },
  639. // },
  640. // },
  641. ];