script.js 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149
  1. //document.addEventListener("DOMContentLoaded", main, false);
  2. const startGameButton = document.getElementById("start-game-button");
  3. const currentScoreElement = document.getElementById("current-score");
  4. const finalScoreElement = document.getElementById("final-score");
  5. const canvas = document.getElementById("game-canvas");
  6. const context = canvas.getContext("2d");
  7. canvas.width = window.innerWidth;
  8. canvas.height = window.innerHeight;
  9. const gameOverContainer = document.getElementById("game-over-container-div");
  10. /* utilities */
  11. function colorToStyle(r, g, b, a) {
  12. return "rgb(" + r + ", " + g + ", " + b + ", " + a + ")";
  13. }
  14. /* WASM imported symbols */
  15. function jsRandom() {
  16. return Math.random();
  17. }
  18. function jsClearRectangle(x, y, width, height) {
  19. // context.clearRect(x, y, width, height);
  20. context.fillStyle = "rgba(0, 0, 0, .1)";
  21. context.fillRect(x, y, width, height);
  22. }
  23. function jsDrawCircle(x, y, radius, r, g, b, a) {
  24. context.beginPath();
  25. context.arc(x, y, radius, 0, Math.PI * 2);
  26. context.fillStyle = colorToStyle(r, g, b, a);
  27. context.fill();
  28. }
  29. function jsDrawRectangle(x, y, width, height, r, g, b, a) {
  30. context.beginPath();
  31. context.strokeRect(x, y, width, height);
  32. context.fillStyle = colorToStyle(r, g, b, a);
  33. context.lineWidth = 5;
  34. context.fill();
  35. }
  36. function jsUpdateScore(score) {
  37. currentScoreElement.innerHTML = score;
  38. }
  39. // Lots of jsConsole<type> functions. Leaving it here until I find a better way to print to console from wasm.
  40. function jsConsoleLogu32(n) {
  41. console.log("u32: " + n);
  42. }
  43. function jsConsoleLogf32(n) {
  44. console.log("f32: " + n);
  45. }
  46. function jsConsoleLogbool(b) {
  47. console.log("bool: " + b);
  48. }
  49. function jsConsoleLogVector2D(x, y) {
  50. console.log("{x: " + x + ", y:" + y + "}");
  51. }
  52. var memory = new WebAssembly.Memory({
  53. initial: 10 /* pages */,
  54. maximum: 10 /* pages */,
  55. });
  56. const wasm = {
  57. imports: {
  58. env: {
  59. jsRandom: jsRandom,
  60. jsClearRectangle: jsClearRectangle,
  61. jsDrawCircle: jsDrawCircle,
  62. jsDrawRectangle: jsDrawRectangle,
  63. jsUpdateScore: jsUpdateScore,
  64. jsConsoleLogu32: jsConsoleLogu32,
  65. jsConsoleLogf32: jsConsoleLogf32,
  66. jsConsoleLogbool: jsConsoleLogbool,
  67. jsConsoleLogVector2D: jsConsoleLogVector2D,
  68. memory: memory,
  69. },
  70. },
  71. exports: {},
  72. };
  73. function loadGame() {
  74. WebAssembly.instantiateStreaming(fetch("game.wasm"), wasm.imports).then((result) => {
  75. wasm.exports = result.instance.exports;
  76. window.addEventListener("keydown", (event) => {
  77. const key = event.key;
  78. const char = key.charCodeAt(0);
  79. wasm.exports.key_down(char);
  80. });
  81. window.addEventListener("keyup", (event) => {
  82. const key = event.key;
  83. const char = key.charCodeAt(0);
  84. wasm.exports.key_up(char);
  85. });
  86. window.addEventListener("click", (event) => {
  87. const client_x = event.clientX;
  88. const client_y = event.clientY;
  89. wasm.exports.shoot_projectile(client_x, client_y);
  90. });
  91. startGameButton.addEventListener("click", (event) => {
  92. restartGame();
  93. });
  94. wasm.exports.game_init(canvas.width, canvas.height);
  95. restartGame();
  96. // gameOverContainer.style.display = "flex";
  97. });
  98. }
  99. function resetGame() {
  100. currentScoreElement.innerHTML = 0;
  101. gameOverContainer.style.display = "none";
  102. wasm.exports.game_reset();
  103. }
  104. function runGame() {
  105. wasm.exports.game_step();
  106. if (!wasm.exports.is_game_over()) {
  107. window.requestAnimationFrame(runGame);
  108. } else {
  109. // If the game is over, show the Game Over container (with the start buttong) and the achieved score.
  110. gameOverContainer.style.display = "flex";
  111. finalScoreElement.innerHTML = wasm.exports.get_score();
  112. }
  113. }
  114. function restartGame() {
  115. resetGame();
  116. // Set the rate at which the enemies will be spawned.
  117. setInterval(wasm.exports.spawn_enemy, 500);
  118. runGame();
  119. }
  120. function main() {
  121. loadGame();
  122. }
  123. main();