skip to Main Content

I am doing a rock, paper, scissors screensaver and i wanted to implement a counter, which shows you the current amount of each emoji but my implementation doesnt work. It only shows the amount what the user is typing at the beginning.

Here is my script part

const navbar               = document.querySelector('#navbar');
const formContainer        = document.querySelector('#form-container');
const emojiCountInput      = document.querySelector('#emoji-count');
const startButton          = document.querySelector('#start');
const emojisContainer      = document.querySelector('#emojis');
const resetButton          = document.querySelector('#reset');
const pauseButton          = document.querySelector('#pause');
const playButton           = document.querySelector('#play');
const scissorsCountElement = document.querySelector('#scissors-count');
const rockCountElement     = document.querySelector('#rock-count');
const paperCountElement    = document.querySelector('#paper-count');
let interval;

startButton.addEventListener('click', () => {
  formContainer.classList.add('hidden');

  emojisContainer.innerHTML = '';

  const emojiCount = parseInt(emojiCountInput.value);
  for (let i = 0; i < emojiCount; i++) {
    emojisContainer.innerHTML += '<div class="emoji scissors">✂️</div>';
    emojisContainer.innerHTML += '<div class="emoji rock">🪨</div>';
    emojisContainer.innerHTML += '<div class="emoji paper">📄</div>';
  }

  const emojis = document.querySelectorAll('.emoji');

  function moveEmojis() {
    emojis.forEach(emoji => {
      if (!emoji.x) emoji.x = Math.random() * window.innerWidth;
      if (!emoji.y) emoji.y = Math.random() * (window.innerHeight - navbar.offsetHeight) + navbar.offsetHeight;
      if (!emoji.vx) emoji.vx = Math.random() * 10 - 5;
      if (!emoji.vy) emoji.vy = Math.random() * 10 - 5;

      emoji.x += emoji.vx;
      emoji.y += emoji.vy;

      // abprallen vom Bild
      if (emoji.x < 0 || emoji.x > window.innerWidth) emoji.vx = -emoji.vx;
      if (emoji.y < navbar.offsetHeight || emoji.y > window.innerHeight) emoji.vy = -emoji.vy;

      emoji.style.left = emoji.x + 'px';
      emoji.style.top = emoji.y + 'px';
    });
  }

  function checkCollision(emoji1, emoji2) {
    const rect1 = emoji1.getBoundingClientRect();
    const rect2 = emoji2.getBoundingClientRect();
    return !(rect1.right < rect2.left ||
      rect1.left > rect2.right ||
      rect1.bottom < rect2.top ||
      rect1.top > rect2.bottom);
  }

  function updateState(emoji1, emoji2) {
    if (emoji1.textContent === '✂️' && emoji2.textContent === '📄') {
      emoji2.textContent = '✂️';
    } else if (emoji1.textContent === '📄' && emoji2.textContent === '✂️') {
      emoji1.textContent = '✂️';
    } else if (emoji1.textContent === '🪨' && emoji2.textContent === '✂️') {
      emoji2.textContent = '🪨';
    } else if (emoji1.textContent === '✂️' && emoji2.textContent === '🪨') {
      emoji1.textContent = '🪨';
    } else if (emoji1.textContent === '📄' && emoji2.textContent === '🪨') {
      emoji2.textContent = '📄';
    } else if (emoji1.textContent === '🪨' && emoji2.textContent === '📄') {
      emoji1.textContent = '📄';
    }
  }

  function updateCounters() {
    const scissorsCount = document.querySelectorAll('.scissors').length;
    const rockCount = document.querySelectorAll('.rock').length;
    const paperCount = document.querySelectorAll('.paper').length;
    scissorsCountElement.textContent = scissorsCount;
    rockCountElement.textContent = rockCount;
    paperCountElement.textContent = paperCount;
  }

  function resetEmojis() {
    emojis.forEach(emoji => {
      delete emoji.x;
      delete emoji.y;
      delete emoji.vx;
      delete emoji.vy;
      delete emoji.locked;
    });
  }

  resetButton.addEventListener('click', () => {

    formContainer.classList.remove('hidden');
    emojisContainer.innerHTML = '';
    clearInterval(interval);

  });
  pauseButton.addEventListener('click', () => {

    clearInterval(interval);
  });

  playButton.addEventListener('click', () => {

    interval = setInterval(() => {
      moveEmojis();
      for (let i = 0; i < emojis.length; i++) {
        for (let j = i + 1; j < emojis.length; j++) {
          if (checkCollision(emojis[i], emojis[j])) {
            updateState(emojis[i], emojis[j]);
          }
        }
      }
      updateCounters();
    }, 100);
  });

  internal = setInterval(() => {
    moveEmojis();
    for (let i = 0; i < emojis.length; i++) {
      for (let j = i + 1; j < emojis.length; j++) {
        if (checkCollision(emojis[i], emojis[j])) {
          updateState(emojis[i], emojis[j]);
        }
      }
    }
    updateCounters();
  }, 100);
});

function handleResize() {
  const emojis = document.querySelectorAll('.emoji');
  emojis.forEach(emoji => {
    if (emoji.x > window.innerWidth) emoji.x = window.innerWidth;
    if (emoji.y > window.innerHeight) emoji.y = window.innerHeight - navbar.offsetHeight;
  });
}

window.addEventListener('resize', handleResize);
body {
  background-color: black;
  color: white;
  font-family: 'Roboto', sans-serif;
}

.emoji {
  position: absolute;
  font-size: 24px;
}

#navbar {
  position: fixed;
  top: 0;
  left: 0;
  width: 100%;
  height: 50px;
  background-color: #8585ad;
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 0 20px;
}

#form-container {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
}

#form-container.hidden {
  display: none;
}

#counters {
  margin: auto;
}
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Roboto:ital@1&display=swap" rel="stylesheet">

<div id="navbar">
  <div>
    <button id="reset">Reset</button>
    <button id="pause">Pause</button>
    <button id="play">Play</button>
  </div>

  <div id="counters">
    <span>✂️ <span id="scissors-count">0</span></span>
    <span>🪨 <span id="rock-count">0</span></span>
    <span>📄 <span id="paper-count">0</span></span>
  </div>
</div>

<div id="form-container">
  <label for="emoji-count">Number of emoji:</label>
  <input type="number" id="emoji-count" value="50">
  <button id="start">Start</button>
</div>
<div id="emojis"></div>

You can also visit my github repo on that, to maybe see what I mean.

https://github.com/Naigun/SSP-ScreenSaver/tree/test

3

Answers


  1. In your code, when a collisions happens, you set the text of the losing element (i.e. rock when rock and paper fight) to the emoji of the winning emoji.

    What you do not do, is update the class of the losing element to the class of the winning element.

    This is important as you calculate the number of a specific emoji by getting the number of elements with a rock/paper/scissor class with the this chunk of code:

    const scissorsCount = document.querySelectorAll('.scissors').length;
    const rockCount = document.querySelectorAll('.rock').length;
    const paperCount = document.querySelectorAll('.paper').length;
    scissorsCountElement.textContent = scissorsCount;
    rockCountElement.textContent = rockCount;
    paperCountElement.textContent = paperCount;
    

    See Remove CSS class from element with JavaScript (no jQuery) to remove a class (remove the losing class when an emoji loses), and see How to add a class to a given element? to add the class of the winning emoji to the losing emoji.

    An alternative to calculating the number of elements with a given class name would be to just have 3 variables (one for each emoji type) which you increment of decrement when a collisions happens.

    Login or Signup to reply.
  2. The problem here is you didn’t update your class name of the element. You were only updating the textContent.

    Corrected Code:

    function updateState(emoji1, emoji2) {
        if (emoji1.textContent === '✂️' && emoji2.textContent === '📄') {
          emoji2.textContent = '✂️';
          emoji2.classList.add("scissors");
          emoji2.classList.remove("paper");
        } else if (emoji1.textContent === '📄' && emoji2.textContent === '✂️') {
          emoji1.textContent = '✂️';
          emoji1.classList.add("scissors");
          emoji1.classList.remove("paper");
        } else if (emoji1.textContent === '🪨' && emoji2.textContent === '✂️') {
          emoji2.textContent = '🪨';
          emoji2.classList.add("rock");
          emoji2.classList.remove("scissors");
        } else if (emoji1.textContent === '✂️' && emoji2.textContent === '🪨') {
          emoji1.textContent = '🪨';
          emoji1.classList.add("rock");
          emoji1.classList.remove("scissors");
        } else if (emoji1.textContent === '📄' && emoji2.textContent === '🪨') {
          emoji2.textContent = '📄';
          emoji2.classList.add("paper");
          emoji2.classList.remove("rock");
        } else if (emoji1.textContent === '🪨' && emoji2.textContent === '📄') {
          emoji1.textContent = '📄';
          emoji1.classList.add("paper");
          emoji1.classList.remove("rock");
        }
      }
    
    Login or Signup to reply.
  3. Your problem is that in updateCounters you count your elements by their classes, but in updateState you only ever change the textContent of your elements but never their classes.

    So you need to also change the class of your element when you change their text content:

    function updateState(emoji1, emoji2) {
        if (emoji1.textContent === '✂️' && emoji2.textContent === '📄') {
            emoji2.textContent = '✂️';
            emoji2.className = "emoji scissors";
        } else if (emoji1.textContent === '📄' && emoji2.textContent === '✂️') {
            emoji1.textContent = '✂️';
            emoji1.className = "emoji scissors";
        } else if (emoji1.textContent === '🪨' && emoji2.textContent === '✂️') {
            emoji2.textContent = '🪨';
            emoji2.className = "emoji rock";
        } else if (emoji1.textContent === '✂️' && emoji2.textContent === '🪨') {
            emoji1.textContent = '🪨';
            emoji1.className = "emoji rock";
        } else if (emoji1.textContent === '📄' && emoji2.textContent === '🪨') {
            emoji2.textContent = '📄';
            emoji2.className = "emoji paper";
        } else if (emoji1.textContent === '🪨' && emoji2.textContent === '📄') {
            emoji1.textContent = '📄';
            emoji1.className = "emoji paper";
        }
    }
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search