<link href="https://fonts.googleapis.com/css2?family=New+Rocker&display=swap" rel="stylesheet">

<div id="video">
  <iframe width="100%" height="100%" src="https://www.youtube.com/embed/OH9A6tn_P6g?controls=0&autoplay=1" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
</div>

<div id="points"></div>
<div id="streak"></div>
<div id="booster"></div>

<div id="drumset">
  <div class="drum" id="drum-2"></div>
  <div class="drum" id="drum-3"></div>
  <div class="drum" id="drum-0"></div>
  <div class="drum" id="drum-1"></div>
</div>
* {
  font-family: "New Rocker", sans-serif;  
}

#drumset {
  position: absolute;
  bottom: 0;
  left: 0;
  width: 100%;
  text-align: center;
}

.drum {
  width: 20vmin;
  height: 20vmin;
  background: #ccc;
  border-radius: 50%;
  box-sizing: border-box;
  border: 1vmin solid #333;
  display: inline-block;
  position: relative;
  margin-bottom: 5vmin;
}

#drum-0 {
  box-shadow: inset 0 0 0 2vmin blue;
  top: -5vmin;
}

#drum-1 {
  box-shadow: inset 0 0 0 2vmin green;
}

#drum-2 {
  box-shadow: inset 0 0 0 2vmin red;
}

#drum-3 {
  box-shadow: inset 0 0 0 2vmin yellow;
  top: -5vmin;
}

#drumset.drum-0 #drum-0 { background: #00f8; }
#drumset.drum-1 #drum-1 { background: #0f08; }
#drumset.drum-2 #drum-2 { background: #f008; }
#drumset.drum-3 #drum-3 { background: #ff08; }

#points, #streak, #booster {
  position: absolute;
  top: 5vmin;
  right: 5vmin;
  font-size: 18vmin;
  color: #fff;
  text-shadow: 0 -1px #000, 1px -1px #000, 1px 0 #000, 1px 1px #000, 0 1px #000, -1px 1px  #000, -1px 0 #000, -1px -1px #000;
}

#booster {
  top: 22vmin;
  font-size: 7vmin;
}

#streak {
  top: 30vmin;
  right: 50vw;
  transform: translate(50%, 0);
  text-align: center;
  font-size: 12vmin;
}

#streak:not(:empty)::before {
  content: "Streak: ";
}

#video {
  position: absolute;
  top: 0;
  left: 0;
  width: 100vw;
  height: 100vh;
}
const gamepads = {};
const buttonState = {};
let active = 0;
let points = 0;
let streak = 0;

function generateRandomActive() {
  active = Math.floor(Math.random() * 4);
  document.querySelector("#drumset").className = `drum-${active}`;
  document.querySelector("#points").textContent = points;
  document.querySelector("#streak").textContent = streak;
}

function buttonPressed(id) {
  let booster = 1;
  console.log(`Button ${id} pressed.`);
  if (id === active) {
    streak++;
    booster = Math.min(streak, 5);
    points += booster;
    generateRandomActive();
  } else {
    streak = 0;
  }
  document.querySelector("#streak").textContent = streak;
  document.querySelector("#booster").textContent = `x${booster}`;
}

function readValue() {
  const connectedGamepads = navigator.getGamepads();
  const gamepadIndexes = Object.keys(gamepads);
  
  for (let x = 0; x < gamepadIndexes.length; x++) {
    const buttons = connectedGamepads[gamepadIndexes[x]].buttons;
    for (let y = 0; y < buttons.length; y++) {
      if (buttons[y].pressed) {
        if (!buttonState[y]) {
          buttonState[y] = true;
          buttonPressed(y);
        }
      } else {
        delete buttonState[y];
      }
    }
  }
  
  if (gamepadIndexes.length > 0) {
    window.requestAnimationFrame(readValue);
  }
}

window.addEventListener("gamepadconnected", function(e) {
  console.log("Gamepad connected!");
  gamepads[e.gamepad.index] = true;
  generateRandomActive();
  readValue();
});

window.addEventListener("gamepaddisconnected", function(e) {
  console.log("Gamepad disconnected!");
  delete gamepads[e.gamepad.index];
});

External CSS

This Pen doesn't use any external CSS resources.

External JavaScript

This Pen doesn't use any external JavaScript resources.