1

I've designed this game, it's my first project. It's a spin-off from "The Pig Game" in a JavaScript course. I tweaked the HTML and CSS templates of the Pig Game for the UI, but I did the game design and coding from scratch. You can play the game here: https://jeffparadox.000webhostapp.com/

I've got some questions, if anyone cares:

  1. What do you think, do you see any problems? Can anything be clearer (especially in terms of UI) than it is now?

  2. Game works fast on my comp. But when I visit the site, images don't start spinning right away; it takes about 30 seconds to start seeing images spin visibly. I think it's because the browser is loading the images but the code runs faster. Is there a way to pre-load these images in the code, so the game starts properly? Or, if I clean up my code, will the game load faster without needing to pre-load the images?

  3. Here's my JS code. If anyone's interested in checking it and telling me which parts I can clean-up and optimize, I'd really appreciate it. Thanks in advace:

"use strict";

// Selecting elements
const player0El = document.querySelector(".player--0");
const player1El = document.querySelector(".player--1");
const tries0El = document.getElementById("tries--0");
const tries1El = document.getElementById("tries--1");
const current0El = document.getElementById("current--0");
const current1El = document.getElementById("current--1");

const animalEl = document.querySelector(".animal");
const btnSpin = document.querySelector(".btn--spin");
const btnReset = document.querySelector(".btn--reset");
const btnRestart = document.querySelector(".btn--restart");

const youWin0El = document.querySelector("#you-win--0");
const youWin1El = document.querySelector("#you-win--1");

const highScore0El = document.querySelector(".high-score--0");
const highScore1El = document.querySelector(".high-score--1");

// Declare let variables
let triesLeft,
  playerScores,
  highScores,
  activePlayer,
  round,
  currentScore,
  playing;

// Starting conditions
const init = function () {
  youWin0El.classList.add("hidden");
  youWin1El.classList.add("hidden");
  youWin1El.textContent = "You Win! ";
  youWin0El.textContent = "You Win! ";
  currentScore = 0;
  triesLeft = [10, 10];
  playerScores = [0, 0];
  highScores = [0, 0];
  activePlayer = 0;
  round = 3;
  playing = true;

  btnRestart.textContent = ` ROUND: ${round}`;

  tries0El.textContent = 10;
  tries1El.textContent = 10;
  current0El.textContent = 0;
  current1El.textContent = 0;

  animalEl.src = "noAnimal.jpg";
  player0El.classList.remove("player--winner");
  player1El.classList.remove("player--winner");
  player0El.classList.add("player--active");
  player1El.classList.remove("player--active");
};

// Initialize game
init();

// ***GAME FUNCTIONS***

// Switch players
const switchPlayer = function () {
  activePlayer = activePlayer === 0 ? 1 : 0;
  player0El.classList.toggle("player--active");
  player1El.classList.toggle("player--active");
};

// Check how many rounds left
const checkRound = function () {
  btnRestart.textContent = ` ROUND: ${round}`;
  if (round < 1) {
    gameOver();
  } else if (triesLeft[activePlayer] < 1 && round > 0) {
    if (triesLeft[0] === 0 && triesLeft[1] === 0) {
      triesLeft[0] = 10;
      triesLeft[1] = 10;
      tries0El.textContent = 10;
      tries1El.textContent = 10;
    }
    switchPlayer();
  }
};

// End of game
const gameOver = function () {
  playing = false;
  if (playerScores[0] > playerScores[1]) {
    youWin0El.classList.remove("hidden");
  } else if (playerScores[0] < playerScores[1]) {
    youWin1El.classList.remove("hidden");
  } else if (playerScores[0] === playerScores[1]) {
    youWin1El.textContent = "It's a Tie ";
    youWin0El.textContent = "It's a Tie ";
    youWin1El.classList.remove("hidden");
    youWin0El.classList.remove("hidden");
  }
};

// Check the rabbit, increase and log the score
const checkRabbit = function () {
  if (imageNumber === 0) {
    currentScore =
      Number(document.getElementById(`current--${activePlayer}`).textContent) +
      1;
    playerScores[activePlayer] = currentScore;
    document.getElementById(
      `current--${activePlayer}`
    ).textContent = currentScore;
  }
};

// Update tries left
const triesUpdate = function () {
  triesLeft[activePlayer] -= 1;
  document.getElementById(`tries--${activePlayer}`).textContent =
    triesLeft[activePlayer];
};

// Update high scores
const registerHighScore = function () {
  if (playerScores[activePlayer] > highScores[activePlayer]) {
    highScores[activePlayer] = playerScores[activePlayer];
    document.getElementById(
      `high-score--${activePlayer}`
    ).textContent = `High Score: ${highScores[activePlayer]}`;
  }
};

// ***GAME ENGINE***

// Declare game engine variables
let interval, imageNumber;

// Spinning images
btnSpin.addEventListener("click", function () {
  if (playing) {
    // Change button to Stop
    btnSpin.textContent = `⛔ STOP!`;
    // Stop the spinning (Runs only when interval is declared)
    if (interval) {
      clearInterval(interval);
      interval = null;
      btnSpin.textContent = ` SPIN!`;
      triesUpdate();
      checkRabbit();
      registerHighScore();
      if (triesLeft[0] < 1 && triesLeft[1] < 1) {
        round -= 1;
      }
      checkRound();
      // Start the spinning (Runs only when interval is null or undefined)
    } else {
      // Loop with time intervals
      interval = setInterval(function () {
        // Genarate image number
        imageNumber = Math.trunc(Math.random() * 10);
        // Show image with the generated number
        animalEl.src = `animal-${imageNumber}.jpg`;
      }, 5);
    }
  }
});

// ***RESET GAME***
btnReset.addEventListener("click", init);
  • For getting opinions about generally working code, https://codereview.stackexchange.com is the place you want to visit. – tevemadar Mar 26 '21 at 00:32
  • I'm new here. Sure thing. Thank you! – Treves Studios Mar 26 '21 at 00:35
  • 1
    As a littlle feedback: I like the UI, it is very clean. The animal image could be larger, and the button "Spin!" and the non-button "Round" look the same, but that's minor. One thing that I missed the first time was that the goal was to "catch the rabbit" -- it's written on the small placeholder rabbit image, but not anywhere else. Also you set the rotation to 5ms per step -- 200 fps -- which is not even possible on most monitors, thus making the game purely luck-based. Try experimenting with longer intervals, so it actually tests your reflexes. – Jan Pokorný Mar 26 '21 at 00:43
  • Great suggestions, thanks a lot! – Treves Studios Mar 26 '21 at 00:52

1 Answers1

0

You can preload images by putting this in your <head> for each image you use:

<link rel="preload" as="image" href="animal-1.png">

More documentation here: https://developer.mozilla.org/en-US/docs/Web/HTML/Preloading_content

As for the other questions, they may be a better fit at SE Code Review: https://codereview.stackexchange.com/

Jan Pokorný
  • 1,418
  • 15
  • 22
  • Thanks a lot for the help. Now I have one more problem: Math.random creates the same number twice in a row sometimes, which gives the player more time to catch the rabbit than the interval I set. Is there a way to random without repetition? I can do this to minimize the chances but it still doesn't eliminate the problem: – Treves Studios Mar 26 '21 at 01:59
  • `interval = setInterval(function () { imageNumber = Math.trunc(Math.random() * 10); if (imageNumber !== isSameNumber) { animalEl.src = `animal-${imageNumber}.jpg`; isSameNumber = imageNumber; } else { imageNumber = Math.trunc(Math.random() * 10); animalEl.src = `animal-${imageNumber}.jpg`; isSameNumber = imageNumber; } }, 500); ` – Treves Studios Mar 26 '21 at 02:00
  • 1
    I would use something like `let nextNumber = Math.trunc(Math.random() * 9); if(nextNumber == previousNumber) nextNumber++;` – Jan Pokorný Mar 26 '21 at 02:18