JSFiddle - React, Tailwind, and code Playground

by David Kyle

HTML

<div class="liner center-aligned">
  <div class="header drop-shadow primary">
    <h1 class="h1">Mystery Clicker</h1>
  </div>
  <div class="output">
    <div class="player-wrapper">
      <h3>
        Player Name: <span class="player-target"></span>
      </h3>
    </div>
    <div class="score-wrapper">
      <h3>
        Score: <span class="score-target"></span>
      </h3>
    </div>
  </div>
  <div class="game-wrapper">
    <img class="game-image" src="https://upload.wikimedia.org/wikipedia/en/thumb/3/3e/FettbobaJB.png/220px-FettbobaJB.png" alt="Boba Fett?!" />
  </div>
</div>

CSS

@font-face {
  font-family: 'LCDBOLD';
  src: url('https://fontsforweb.com/public/fonts/523/LCDBOLD.eot');
  src: url('https://fontsforweb.com/public/fonts/523/LCDBOLD.ttf') format('truetype');
}


body {
  background-color: rgba(0, 0, 0, .3);
  color: rgb(255, 255, 255);
  font-family: Verdana, Arial, sans-serif;
  font-size: 12px;
  padding: 0px;
  margin: 0px;
}

.click-box {
  width: 10px;
  height: 10px;
  position: absolute;
  cursor: pointer;
}

.animate {
  box-shadow: 4px 4px 4px 4px white;
  transition: all 1s ease-in-out;
}

.output {
  margin: auto 1rem;
  display: flex;
  justify-content: space-between;
}

.liner {
  margin: .4rem;
}

.center-aligned {
  text-align: center;
  margin: 0px auto;
}

.player-target,
.score-target {
  font-family: 'LCDBOLD';
  letter-spacing: .2rem;
  color: lightgreen;
}

.primary {
  background-color: rgba(80, 120, 80, .5);
}

.header {
  padding: .2rem;
  border-bottom: inset 1px rgba(100, 100, 100, .5);
  margin-bottom: 1rem;
}

.drop-shadow {
  box-shadow: 1px 2px 12px 2px rgba(255, 255, 255, .2);
}

.game-image {
  transition: all 1s ease-in-out;
}

JavaScript

'use strict';

let Game = (function() {
	let self = {};
  const local = {
  	player: '',
    score: 0,
    scoreTarget: null,
    image: {
    	height: 0,
      width: 0,
      top: 0,
      left: 0
    }
  };
  self.Initialize = function(args) {
  	if (args) {
    	if (args.playerName) {
      	local.player = args.playerName;
      }
      
      setTimeout(function() {
      	const playerTarget = document.getElementsByClassName('player-target')[0];
        local.scoreTarget = document.getElementsByClassName('score-target')[0];
      	playerTarget.innerText = local.player;
        local.scoreTarget.innerText = local.score;
        
        const image = document.getElementsByClassName('game-image')[0];
        local.image.height = image.height;
        local.image.width = image.width;
        local.image.top = image.getBoundingClientRect().top;
        local.image.left = image.getBoundingClientRect().left;
				
        self.generateBox();
        }, 100);
    } else {
    	throw new Error('No initialization arguments provided.');
    }
  };
  
  self.boxClicked = function(e) {
  	document.getElementsByClassName('game-image')[0].classList.add('animate');
    setTimeout(function() {
    	document.getElementsByClassName('game-image')[0].classList.remove('animate');
    }, 1000);
  	local.score++;
    local.scoreTarget.innerText = local.score;
    var element = document.querySelector('.click-box');
    element.onclick = null;
    element.remove();
    self.generateBox();
  };
  
  self.generateBox = function() {
  	
  	const element = document.createElement('a');
    element.style.borderWidth = 2;
    const randomTop = Math.floor(Math.random() * (local.image.top - local.image.height) + local.image.height);
    const randomLeft = local.image.left + Math.floor(Math.random() * (local.image.left - local.image.width));
    element.setAttribute('class', 'click-box');
    element.setAttribute('style', 'top: ' + randomTop + 'px; left: ' + randomLeft + 'px');
   ...