javascriptpreloadingimage-preloader

How to load all images before the game starts? (JavaScript, Preloader)


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);

Solution

  • 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/