#example_game
View Compiled
$base-size: 12.5vmin;
$base-border-width: 0.07rem;
$base-border-color: #000000;
$base-border: solid $base-border-width $base-border-color;
$base-chars: ('a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', ' ');

$before-move-pause-time: 500ms;

$screen-background-color: #a4fc20;
$screen-width: 8rem;
$screen-height: 8rem;

$turret-background-color: #1bad00;
$turret-width: 0.8rem;
$turret-height: 0.8rem;
$turret-border: $base-border;

$gun-width: 0.3rem;
$gun-height: 1rem;

$fire-background-image: radial-gradient(
	circle at 50% 50%,
	#ef7d00 0%,
	#f5b300 50%,
	transparent 100%
);
$fire-width: 0.25rem;
$fire-height: 0.25rem;

$zombie-width: 0.65rem;
$zombie-height: 1.2rem;
$zombie-border: solid $base-border-width $base-border-color;

$zombie-head-background-color: #0ddd63;

$zombie-head-width: $zombie-width;
$zombie-head-height: 0.55rem;

$zombie-eyes-width: 0.2rem;
$zombie-eyes-height: 0.2rem;

$zombie-eye-background-color: #ffffff;
$zombie-eye-width: $zombie-eyes-height;
$zombie-eye-height: $zombie-eyes-height;
$zombie-eye-border: solid 0.05rem $base-border-color;
$zombie-eye-top: 0.07rem;
$zombie-eye-left: 0.08rem;
$zombie-eye-right: 0.35rem;

$zombie-body-background-color: #b37500;
$zombie-body-width: 0.35rem;
$zombie-body-height: 0.35rem;
$zombie-body-transform: translate(0.09rem, -0.07rem);

$zombie-arm-width: 0.3rem;
$zombie-arm-height: 0.1rem;
$zombie-arm-top: 0.52rem;
$zombie-arm-left: 0.05rem;
$zombie-arm-right: 0.35rem;

$zombie-leg-background-color: #a2a2a2;
$zombie-leg-width: 0.23rem;
$zombie-leg-height: 0.32rem;
$zombie-leg-top: 0.75rem;
$zombie-leg-left: 0.09rem;
$zombie-leg-right: 0.21rem;

$zombie-foot-width: 0.1rem;
$zombie-foot-height: 0.2rem;
$zombie-foot-top: 0.19rem;

$zombie-hole-background-color: #000000;
$zombie-hole-width: $zombie-width;
$zombie-hole-height: $zombie-width;

$life-top: 0.4rem;
$life-left: 0.4rem;

$heart-background-color: #e41435;
$heart-width: 0.4rem;
$heart-height: 0.4rem;
$heart-border-color: #000000;
$heart-transition: background-color 500ms ease-out;

$score-top: 0.25rem;
$score-right: 0.25rem;

$title-background-color: #a4fc20;
$title-endln-margin: 0.2rem;

$zombie-dying-background-image: radial-gradient(
	circle at 50% 80%,
	rgba(#ef7d00, 0.8) 0%,
	rgba(#f5b300, 0.8) 50%,
	transparent 100%
);

@mixin render-character($i, $pixel-size) {
	$pixel-color: #000000;
	width: $pixel-size * 3;
	height: $pixel-size * 5;
	margin-left: $pixel-size / 2;
	&:before {
		content: '';
		width: $pixel-size;
		height: $pixel-size;
		display: block;
		transform: translate(-100%, -100%);
		@if ($i == "0" or $i == "o") {
			box-shadow: ($pixel-size * 1) ($pixel-size * 1) $pixel-color, ($pixel-size * 2) ($pixel-size * 1) $pixel-color, ($pixel-size * 3) ($pixel-size * 1) $pixel-color, ($pixel-size * 1) ($pixel-size * 2) $pixel-color, ($pixel-size * 3) ($pixel-size * 2) $pixel-color, ($pixel-size * 1) ($pixel-size * 2) $pixel-color, ($pixel-size * 3) ($pixel-size * 2) $pixel-color, ($pixel-size * 1) ($pixel-size * 3) $pixel-color, ($pixel-size * 3) ($pixel-size * 3) $pixel-color, ($pixel-size * 1) ($pixel-size * 4) $pixel-color, ($pixel-size * 3) ($pixel-size * 4) $pixel-color, ($pixel-size * 1) ($pixel-size * 5) $pixel-color, ($pixel-size * 2) ($pixel-size * 5) $pixel-color, ($pixel-size * 3) ($pixel-size * 5) $pixel-color;
		}
		@elseif ($i == "1") {
			box-shadow: 
				($pixel-size * 1) ($pixel-size * 1) $pixel-color, ($pixel-size * 2) ($pixel-size * 1) $pixel-color, ($pixel-size * 2) ($pixel-size * 2) $pixel-color, ($pixel-size * 2) ($pixel-size * 3) $pixel-color, ($pixel-size * 2) ($pixel-size * 4) $pixel-color, ($pixel-size * 1) ($pixel-size * 5) $pixel-color, ($pixel-size * 2) ($pixel-size * 5) $pixel-color, ($pixel-size * 3) ($pixel-size * 5) $pixel-color;
		}
		@elseif ($i == "2") {
			box-shadow: ($pixel-size * 1) ($pixel-size * 1) $pixel-color, ($pixel-size * 2) ($pixel-size * 1) $pixel-color, ($pixel-size * 3) ($pixel-size * 1) $pixel-color, ($pixel-size * 3) ($pixel-size * 2) $pixel-color, ($pixel-size * 1) ($pixel-size * 3) $pixel-color, ($pixel-size * 2) ($pixel-size * 3) $pixel-color, ($pixel-size * 3) ($pixel-size * 3) $pixel-color, ($pixel-size * 1) ($pixel-size * 4) $pixel-color, ($pixel-size * 1) ($pixel-size * 5) $pixel-color, ($pixel-size * 2) ($pixel-size * 5) $pixel-color, ($pixel-size * 3) ($pixel-size * 5) $pixel-color;
		}
		@elseif ($i == "3") {
			box-shadow: ($pixel-size * 1) ($pixel-size * 1) $pixel-color, ($pixel-size * 2) ($pixel-size * 1) $pixel-color, ($pixel-size * 3) ($pixel-size * 1) $pixel-color, ($pixel-size * 3) ($pixel-size * 2) $pixel-color, ($pixel-size * 1) ($pixel-size * 3) $pixel-color, ($pixel-size * 2) ($pixel-size * 3) $pixel-color, ($pixel-size * 3) ($pixel-size * 3) $pixel-color, ($pixel-size * 3) ($pixel-size * 4) $pixel-color, ($pixel-size * 1) ($pixel-size * 5) $pixel-color, ($pixel-size * 2) ($pixel-size * 5) $pixel-color, ($pixel-size * 3) ($pixel-size * 5) $pixel-color;
		}
		@elseif ($i == "4") {
			box-shadow: ($pixel-size * 1) ($pixel-size * 1) $pixel-color, ($pixel-size * 3) ($pixel-size * 1) $pixel-color, ($pixel-size * 1) ($pixel-size * 2) $pixel-color, ($pixel-size * 3) ($pixel-size * 2) $pixel-color, ($pixel-size * 1) ($pixel-size * 3) $pixel-color, ($pixel-size * 2) ($pixel-size * 3) $pixel-color, ($pixel-size * 3) ($pixel-size * 3) $pixel-color, ($pixel-size * 3) ($pixel-size * 4) $pixel-color, ($pixel-size * 3) ($pixel-size * 5) $pixel-color;
		}
		@elseif ($i == "5" or $i == "s") {
			box-shadow: ($pixel-size * 1) ($pixel-size * 1) $pixel-color, ($pixel-size * 2) ($pixel-size * 1) $pixel-color, ($pixel-size * 3) ($pixel-size * 1) $pixel-color, ($pixel-size * 1) ($pixel-size * 2) $pixel-color, ($pixel-size * 1) ($pixel-size * 3) $pixel-color, ($pixel-size * 2) ($pixel-size * 3) $pixel-color, ($pixel-size * 3) ($pixel-size * 3) $pixel-color, ($pixel-size * 3) ($pixel-size * 4) $pixel-color, ($pixel-size * 1) ($pixel-size * 5) $pixel-color, ($pixel-size * 2) ($pixel-size * 5) $pixel-color, ($pixel-size * 3) ($pixel-size * 5) $pixel-color;
		}
		@elseif ($i == "6" or $i == "g") {
			box-shadow: ($pixel-size * 1) ($pixel-size * 1) $pixel-color, ($pixel-size * 2) ($pixel-size * 1) $pixel-color, ($pixel-size * 3) ($pixel-size * 1) $pixel-color, ($pixel-size * 1) ($pixel-size * 2) $pixel-color, ($pixel-size * 1) ($pixel-size * 3) $pixel-color, ($pixel-size * 2) ($pixel-size * 3) $pixel-color, ($pixel-size * 3) ($pixel-size * 3) $pixel-color, ($pixel-size * 1) ($pixel-size * 4) $pixel-color, ($pixel-size * 3) ($pixel-size * 4) $pixel-color, ($pixel-size * 1) ($pixel-size * 5) $pixel-color, ($pixel-size * 2) ($pixel-size * 5) $pixel-color, ($pixel-size * 3) ($pixel-size * 5) $pixel-color;
		}
		@elseif ($i == "7") {
			box-shadow: ($pixel-size * 1) ($pixel-size * 1) $pixel-color, ($pixel-size * 2) ($pixel-size * 1) $pixel-color, ($pixel-size * 3) ($pixel-size * 1) $pixel-color, ($pixel-size * 3) ($pixel-size * 2) $pixel-color, ($pixel-size * 3) ($pixel-size * 3) $pixel-color, ($pixel-size * 3) ($pixel-size * 4) $pixel-color, ($pixel-size * 3) ($pixel-size * 5) $pixel-color;
		}
		@elseif ($i == "8") {
			box-shadow: ($pixel-size * 1) ($pixel-size * 1) $pixel-color, ($pixel-size * 2) ($pixel-size * 1) $pixel-color, ($pixel-size * 3) ($pixel-size * 1) $pixel-color, ($pixel-size * 1) ($pixel-size * 2) $pixel-color, ($pixel-size * 3) ($pixel-size * 2) $pixel-color, ($pixel-size * 1) ($pixel-size * 3) $pixel-color, ($pixel-size * 2) ($pixel-size * 3) $pixel-color, ($pixel-size * 3) ($pixel-size * 3) $pixel-color, ($pixel-size * 1) ($pixel-size * 4) $pixel-color, ($pixel-size * 3) ($pixel-size * 4) $pixel-color, ($pixel-size * 1) ($pixel-size * 5) $pixel-color, ($pixel-size * 2) ($pixel-size * 5) $pixel-color, ($pixel-size * 3) ($pixel-size * 5) $pixel-color;
		}
		@elseif ($i == "9") {
			box-shadow: ($pixel-size * 1) ($pixel-size * 1) $pixel-color, ($pixel-size * 2) ($pixel-size * 1) $pixel-color, ($pixel-size * 3) ($pixel-size * 1) $pixel-color, ($pixel-size * 1) ($pixel-size * 2) $pixel-color, ($pixel-size * 3) ($pixel-size * 2) $pixel-color, ($pixel-size * 1) ($pixel-size * 3) $pixel-color, ($pixel-size * 2) ($pixel-size * 3) $pixel-color, ($pixel-size * 3) ($pixel-size * 3) $pixel-color, ($pixel-size * 3) ($pixel-size * 4) $pixel-color, ($pixel-size * 1) ($pixel-size * 5) $pixel-color, ($pixel-size * 2) ($pixel-size * 5) $pixel-color, ($pixel-size * 3) ($pixel-size * 5) $pixel-color;
		}
		@elseif ($i == "a") {
			box-shadow: ($pixel-size * 1) ($pixel-size * 1) $pixel-color, ($pixel-size * 2) ($pixel-size * 1) $pixel-color, ($pixel-size * 3) ($pixel-size * 1) $pixel-color, ($pixel-size * 1) ($pixel-size * 2) $pixel-color, ($pixel-size * 3) ($pixel-size * 2) $pixel-color, ($pixel-size * 1) ($pixel-size * 3) $pixel-color, ($pixel-size * 2) ($pixel-size * 3) $pixel-color, ($pixel-size * 3) ($pixel-size * 3) $pixel-color, ($pixel-size * 1) ($pixel-size * 4) $pixel-color, ($pixel-size * 3) ($pixel-size * 4) $pixel-color, ($pixel-size * 1) ($pixel-size * 5) $pixel-color, ($pixel-size * 3) ($pixel-size * 5) $pixel-color;
		}
		@elseif ($i == "b") {
			box-shadow: ($pixel-size * 1) ($pixel-size * 1) $pixel-color, ($pixel-size * 2) ($pixel-size * 1) $pixel-color, ($pixel-size * 3) ($pixel-size * 1) $pixel-color, ($pixel-size * 1) ($pixel-size * 2) $pixel-color, ($pixel-size * 3) ($pixel-size * 2) $pixel-color, ($pixel-size * 1) ($pixel-size * 3) $pixel-color, ($pixel-size * 2) ($pixel-size * 3) $pixel-color, ($pixel-size * 1) ($pixel-size * 4) $pixel-color, ($pixel-size * 3) ($pixel-size * 4) $pixel-color, ($pixel-size * 1) ($pixel-size * 5) $pixel-color, ($pixel-size * 2) ($pixel-size * 5) $pixel-color, ($pixel-size * 3) ($pixel-size * 5) $pixel-color;
		}
		@elseif ($i == "c") {
			box-shadow: ($pixel-size * 1) ($pixel-size * 1) $pixel-color, ($pixel-size * 2) ($pixel-size * 1) $pixel-color, ($pixel-size * 3) ($pixel-size * 1) $pixel-color, ($pixel-size * 1) ($pixel-size * 2) $pixel-color, ($pixel-size * 1) ($pixel-size * 3) $pixel-color, ($pixel-size * 1) ($pixel-size * 4) $pixel-color, ($pixel-size * 1) ($pixel-size * 5) $pixel-color, ($pixel-size * 2) ($pixel-size * 5) $pixel-color, ($pixel-size * 3) ($pixel-size * 5) $pixel-color;
		}
		@elseif ($i == "d") {
			box-shadow: ($pixel-size * 1) ($pixel-size * 1) $pixel-color, ($pixel-size * 2) ($pixel-size * 1) $pixel-color, ($pixel-size * 1) ($pixel-size * 2) $pixel-color, ($pixel-size * 3) ($pixel-size * 2) $pixel-color, ($pixel-size * 1) ($pixel-size * 3) $pixel-color, ($pixel-size * 3) ($pixel-size * 3) $pixel-color, ($pixel-size * 1) ($pixel-size * 4) $pixel-color, ($pixel-size * 3) ($pixel-size * 4) $pixel-color, ($pixel-size * 1) ($pixel-size * 5) $pixel-color, ($pixel-size * 2) ($pixel-size * 5) $pixel-color;
		}
		@elseif ($i == "e") {
			box-shadow: ($pixel-size * 1) ($pixel-size * 1) $pixel-color, ($pixel-size * 2) ($pixel-size * 1) $pixel-color, ($pixel-size * 3) ($pixel-size * 1) $pixel-color, ($pixel-size * 1) ($pixel-size * 2) $pixel-color, ($pixel-size * 1) ($pixel-size * 3) $pixel-color, ($pixel-size * 2) ($pixel-size * 3) $pixel-color, ($pixel-size * 3) ($pixel-size * 3) $pixel-color, ($pixel-size * 1) ($pixel-size * 4) $pixel-color, ($pixel-size * 1) ($pixel-size * 5) $pixel-color, ($pixel-size * 2) ($pixel-size * 5) $pixel-color, ($pixel-size * 3) ($pixel-size * 5) $pixel-color;
		}
		@elseif ($i == "f") {
			box-shadow: ($pixel-size * 1) ($pixel-size * 1) $pixel-color, ($pixel-size * 2) ($pixel-size * 1) $pixel-color, ($pixel-size * 3) ($pixel-size * 1) $pixel-color, ($pixel-size * 1) ($pixel-size * 2) $pixel-color, ($pixel-size * 1) ($pixel-size * 3) $pixel-color, ($pixel-size * 2) ($pixel-size * 3) $pixel-color, ($pixel-size * 3) ($pixel-size * 3) $pixel-color, ($pixel-size * 1) ($pixel-size * 4) $pixel-color, ($pixel-size * 1) ($pixel-size * 5) $pixel-color;
		}
		@elseif ($i == "h") {
			box-shadow: ($pixel-size * 1) ($pixel-size * 1) $pixel-color, ($pixel-size * 3) ($pixel-size * 1) $pixel-color, ($pixel-size * 1) ($pixel-size * 2) $pixel-color, ($pixel-size * 3) ($pixel-size * 2) $pixel-color, ($pixel-size * 1) ($pixel-size * 3) $pixel-color, ($pixel-size * 2) ($pixel-size * 3) $pixel-color, ($pixel-size * 3) ($pixel-size * 3) $pixel-color, ($pixel-size * 1) ($pixel-size * 4) $pixel-color, ($pixel-size * 3) ($pixel-size * 4) $pixel-color, ($pixel-size * 1) ($pixel-size * 5) $pixel-color, ($pixel-size * 3) ($pixel-size * 5) $pixel-color;
		}
		@elseif ($i == "i") {
			box-shadow: ($pixel-size * 1) ($pixel-size * 1) $pixel-color, ($pixel-size * 2) ($pixel-size * 1) $pixel-color, ($pixel-size * 3) ($pixel-size * 1) $pixel-color, ($pixel-size * 2) ($pixel-size * 2) $pixel-color, ($pixel-size * 2) ($pixel-size * 3) $pixel-color, ($pixel-size * 2) ($pixel-size * 4) $pixel-color, ($pixel-size * 1) ($pixel-size * 5) $pixel-color, ($pixel-size * 2) ($pixel-size * 5) $pixel-color, ($pixel-size * 3) ($pixel-size * 5) $pixel-color;
		}
		@elseif ($i == "j") {
			box-shadow: ($pixel-size * 3) ($pixel-size * 1) $pixel-color, ($pixel-size * 3) ($pixel-size * 2) $pixel-color, ($pixel-size * 3) ($pixel-size * 3) $pixel-color, ($pixel-size * 1) ($pixel-size * 4) $pixel-color, ($pixel-size * 3) ($pixel-size * 4) $pixel-color, ($pixel-size * 1) ($pixel-size * 5) $pixel-color, ($pixel-size * 2) ($pixel-size * 5) $pixel-color, ($pixel-size * 3) ($pixel-size * 5) $pixel-color;
		}
		@elseif ($i == "k") {
			box-shadow: ($pixel-size * 1) ($pixel-size * 1) $pixel-color, ($pixel-size * 3) ($pixel-size * 1) $pixel-color, ($pixel-size * 1) ($pixel-size * 2) $pixel-color, ($pixel-size * 3) ($pixel-size * 2) $pixel-color, ($pixel-size * 1) ($pixel-size * 3) $pixel-color, ($pixel-size * 2) ($pixel-size * 3) $pixel-color, ($pixel-size * 1) ($pixel-size * 4) $pixel-color, ($pixel-size * 3) ($pixel-size * 4) $pixel-color, ($pixel-size * 1) ($pixel-size * 5) $pixel-color, ($pixel-size * 3) ($pixel-size * 5) $pixel-color;
		}
		@elseif ($i == "l") {
			box-shadow: ($pixel-size * 1) ($pixel-size * 1) $pixel-color, ($pixel-size * 1) ($pixel-size * 2) $pixel-color, ($pixel-size * 1) ($pixel-size * 3) $pixel-color, ($pixel-size * 1) ($pixel-size * 4) $pixel-color, ($pixel-size * 1) ($pixel-size * 5) $pixel-color, ($pixel-size * 2) ($pixel-size * 5) $pixel-color, ($pixel-size * 3) ($pixel-size * 5) $pixel-color;
		}
		@elseif ($i == "m") {
			box-shadow: ($pixel-size * 1) ($pixel-size * 1) $pixel-color, ($pixel-size * 3) ($pixel-size * 1) $pixel-color, ($pixel-size * 1) ($pixel-size * 2) $pixel-color, ($pixel-size * 2) ($pixel-size * 2) $pixel-color, ($pixel-size * 3) ($pixel-size * 2) $pixel-color, ($pixel-size * 1) ($pixel-size * 3) $pixel-color, ($pixel-size * 3) ($pixel-size * 3) $pixel-color, ($pixel-size * 1) ($pixel-size * 4) $pixel-color, ($pixel-size * 3) ($pixel-size * 4) $pixel-color, ($pixel-size * 1) ($pixel-size * 5) $pixel-color, ($pixel-size * 3) ($pixel-size * 5) $pixel-color;
		}
		@elseif ($i == "n") {
			box-shadow: ($pixel-size * 1) ($pixel-size * 1) $pixel-color, ($pixel-size * 1) ($pixel-size * 2) $pixel-color, ($pixel-size * 2) ($pixel-size * 2) $pixel-color, ($pixel-size * 1) ($pixel-size * 3) $pixel-color, ($pixel-size * 3) ($pixel-size * 3) $pixel-color, ($pixel-size * 1) ($pixel-size * 4) $pixel-color, ($pixel-size * 3) ($pixel-size * 4) $pixel-color, ($pixel-size * 1) ($pixel-size * 5) $pixel-color, ($pixel-size * 3) ($pixel-size * 5) $pixel-color;
		}
		@elseif ($i == "p") {
			box-shadow: ($pixel-size * 1) ($pixel-size * 1) $pixel-color, ($pixel-size * 2) ($pixel-size * 1) $pixel-color, ($pixel-size * 3) ($pixel-size * 1) $pixel-color, ($pixel-size * 1) ($pixel-size * 2) $pixel-color, ($pixel-size * 3) ($pixel-size * 2) $pixel-color, ($pixel-size * 1) ($pixel-size * 3) $pixel-color, ($pixel-size * 2) ($pixel-size * 3) $pixel-color, ($pixel-size * 3) ($pixel-size * 3) $pixel-color, ($pixel-size * 1) ($pixel-size * 4) $pixel-color, ($pixel-size * 1) ($pixel-size * 5) $pixel-color,
		}
		@elseif ($i == "q") {
			box-shadow: ($pixel-size * 1) ($pixel-size * 1) $pixel-color, ($pixel-size * 2) ($pixel-size * 1) $pixel-color, ($pixel-size * 3) ($pixel-size * 1) $pixel-color, ($pixel-size * 1) ($pixel-size * 2) $pixel-color, ($pixel-size * 3) ($pixel-size * 2) $pixel-color, ($pixel-size * 1) ($pixel-size * 3) $pixel-color, ($pixel-size * 2) ($pixel-size * 3) $pixel-color, ($pixel-size * 3) ($pixel-size * 3) $pixel-color, ($pixel-size * 3) ($pixel-size * 4) $pixel-color, ($pixel-size * 3) ($pixel-size * 5) $pixel-color;
		}
		@elseif ($i == "r") {
			box-shadow: ($pixel-size * 1) ($pixel-size * 1) $pixel-color, ($pixel-size * 2) ($pixel-size * 1) $pixel-color, ($pixel-size * 3) ($pixel-size * 1) $pixel-color, ($pixel-size * 1) ($pixel-size * 2) $pixel-color, ($pixel-size * 3) ($pixel-size * 2) $pixel-color, ($pixel-size * 1) ($pixel-size * 3) $pixel-color, ($pixel-size * 2) ($pixel-size * 3) $pixel-color, ($pixel-size * 1) ($pixel-size * 4) $pixel-color, ($pixel-size * 3) ($pixel-size * 4) $pixel-color, ($pixel-size * 1) ($pixel-size * 5) $pixel-color, ($pixel-size * 3) ($pixel-size * 5) $pixel-color;
		}
		@elseif ($i == "t") {
			box-shadow: ($pixel-size * 1) ($pixel-size * 1) $pixel-color, ($pixel-size * 2) ($pixel-size * 1) $pixel-color, ($pixel-size * 3) ($pixel-size * 1) $pixel-color, ($pixel-size * 2) ($pixel-size * 2) $pixel-color, ($pixel-size * 2) ($pixel-size * 3) $pixel-color, ($pixel-size * 2) ($pixel-size * 4) $pixel-color, ($pixel-size * 2) ($pixel-size * 5) $pixel-color,
		}
		@elseif ($i == "u") {
			box-shadow: ($pixel-size * 1) ($pixel-size * 1) $pixel-color, ($pixel-size * 3) ($pixel-size * 1) $pixel-color, ($pixel-size * 1) ($pixel-size * 2) $pixel-color, ($pixel-size * 3) ($pixel-size * 2) $pixel-color, ($pixel-size * 1) ($pixel-size * 3) $pixel-color, ($pixel-size * 3) ($pixel-size * 3) $pixel-color, ($pixel-size * 1) ($pixel-size * 4) $pixel-color, ($pixel-size * 3) ($pixel-size * 4) $pixel-color, ($pixel-size * 1) ($pixel-size * 5) $pixel-color, ($pixel-size * 2) ($pixel-size * 5) $pixel-color, ($pixel-size * 3) ($pixel-size * 5) $pixel-color;
		}
		@elseif ($i == "v") {
			box-shadow: ($pixel-size * 1) ($pixel-size * 1) $pixel-color, ($pixel-size * 3) ($pixel-size * 1) $pixel-color, ($pixel-size * 1) ($pixel-size * 2) $pixel-color, ($pixel-size * 3) ($pixel-size * 2) $pixel-color, ($pixel-size * 1) ($pixel-size * 3) $pixel-color, ($pixel-size * 3) ($pixel-size * 3) $pixel-color, ($pixel-size * 1) ($pixel-size * 4) $pixel-color, ($pixel-size * 3) ($pixel-size * 4) $pixel-color, ($pixel-size * 2) ($pixel-size * 5) $pixel-color,
		}
		@elseif ($i == "w") {
			box-shadow: ($pixel-size * 1) ($pixel-size * 1) $pixel-color, ($pixel-size * 3) ($pixel-size * 1) $pixel-color, ($pixel-size * 1) ($pixel-size * 2) $pixel-color, ($pixel-size * 3) ($pixel-size * 2) $pixel-color, ($pixel-size * 1) ($pixel-size * 3) $pixel-color, ($pixel-size * 3) ($pixel-size * 3) $pixel-color, ($pixel-size * 1) ($pixel-size * 4) $pixel-color, ($pixel-size * 2) ($pixel-size * 4) $pixel-color, ($pixel-size * 3) ($pixel-size * 4) $pixel-color, ($pixel-size * 1) ($pixel-size * 5) $pixel-color, ($pixel-size * 3) ($pixel-size * 5) $pixel-color;
		}
		@elseif ($i == "x") {
			box-shadow: ($pixel-size * 1) ($pixel-size * 1) $pixel-color, ($pixel-size * 3) ($pixel-size * 1) $pixel-color, ($pixel-size * 1) ($pixel-size * 2) $pixel-color, ($pixel-size * 3) ($pixel-size * 2) $pixel-color, ($pixel-size * 2) ($pixel-size * 3) $pixel-color, ($pixel-size * 1) ($pixel-size * 4) $pixel-color, ($pixel-size * 3) ($pixel-size * 4) $pixel-color, ($pixel-size * 1) ($pixel-size * 5) $pixel-color, ($pixel-size * 3) ($pixel-size * 5) $pixel-color;
		}
		@elseif ($i == "y") {
			box-shadow: ($pixel-size * 1) ($pixel-size * 1) $pixel-color, ($pixel-size * 3) ($pixel-size * 1) $pixel-color, ($pixel-size * 1) ($pixel-size * 2) $pixel-color, ($pixel-size * 3) ($pixel-size * 2) $pixel-color, ($pixel-size * 2) ($pixel-size * 3) $pixel-color, ($pixel-size * 2) ($pixel-size * 4) $pixel-color, ($pixel-size * 2) ($pixel-size * 5) $pixel-color,
		}
		@elseif ($i == "z") {
			box-shadow: ($pixel-size * 1) ($pixel-size * 1) $pixel-color, ($pixel-size * 2) ($pixel-size * 1) $pixel-color, ($pixel-size * 3) ($pixel-size * 1) $pixel-color, ($pixel-size * 3) ($pixel-size * 2) $pixel-color, ($pixel-size * 2) ($pixel-size * 3) $pixel-color, ($pixel-size * 1) ($pixel-size * 4) $pixel-color, ($pixel-size * 1) ($pixel-size * 5) $pixel-color, ($pixel-size * 2) ($pixel-size * 5) $pixel-color, ($pixel-size * 3) ($pixel-size * 5) $pixel-color;
		}
		@else {
			// Nothing to do here... Maybe spaces?
		}
	}
}

html, body, #example_game {
	width: 100%;
	height: 100%;
	margin: 0;
	padding: 0;
}

html {
	// For responsive purposes
	font-size: $base-size;
}

#example_game {
	background-color: #000000;
	display: flex;
	align-items: center;
	justify-content: center;
	overflow: auto;
}

.screen {
	background-color: $screen-background-color;
	width: $screen-width;
	height: $screen-height;
	position: relative;
	overflow: hidden;
	flex-shrink: 0;
}

.debug {
	color: #00ff00;
	font-family: courier;
	font-size: 0.5rem;
	text-align: center;
	background-color: black;
	width: 2rem;
	height: 1rem;
	line-height: 1rem;
	display: none;
	position: absolute;
	top: 0;
	left: 0;
	&.shown {
		display: block;
	}
}

.turret {
	width: $turret-width;
	height: $turret-height;
	position: absolute;
	top: calc(50% - #{$turret-height / 2});
	left: calc(50% - #{$turret-width / 2});
	box-sizing: border-box;
	.gun {
		background-color: $turret-background-color;
		width: $gun-width;
		height: $gun-height;
		border: $turret-border;
		position: absolute;
		bottom: calc(100% - #{$gun-height / 2});
		left: calc(50% - #{$gun-width / 2});
		box-sizing: border-box;
	}
	.body {
		background-color: $turret-background-color;
		width: $turret-width;
		height: $turret-height;
		border: $turret-border;
		position: absolute;
		top: 0;
		left: 0;
		box-sizing: border-box;
		border-radius: 50%;
	}
}

.fire {
	background-image: $fire-background-image;
	width: $fire-width;
	height: $fire-height;
	border-radius: 50%;
	position: absolute;
	animation: animate-fire 100ms infinite;
}

.zombie {
	width: $zombie-width;
	height: $zombie-height;
	overflow: hidden;
	position: absolute;
	&:not(.zombie-dying):not(.zombie-hiding).zombie-walking .zombie-wrapper {
		transform: translateY(0%);
		.leg.left {
			animation: zombie-walk-left 1500ms linear infinite;
		}
		.leg.right {
			animation: zombie-walk-right 1500ms linear infinite;
		}
	}
	&:not(.zombie-walking):not(.zombie-dying):not(.zombie-hiding) .zombie-wrapper {
		animation: summon-zombie 500ms ease-out 1000ms forwards;
		.hole {
			animation: animate-zombie-hole 500ms forwards,
				animate-hole-at-bottom 500ms ease-out 1000ms forwards,
				clear-hole 300ms ease-out 1500ms forwards;
		}
	}
	&:not(.zombie-walking):not(.zombie-dying).zombie-hiding {
		.zombie-wrapper {
			transform: translateY(0%);
			animation: zombie-hiding 500ms ease-out forwards 500ms;
			.hole {
				display: none;
			}
		}
	}
	&.zombie-dying {
		animation: zombie-fade-out 500ms ease-out forwards 500ms;
	}
	&.flip {
		transform: scaleX(-1);
	}
	&.zombie-dying:after {
		content: '';
		background-image: $zombie-dying-background-image;
		width: 100%;
		height: 100%;
		display: block;
		position: absolute;
		top: 0;
		left: 0;
		border-radius: 50% / 50% 50% 20% 20%;
		animation: animate-fire 100ms infinite;
	}
	&.zombie-dying .zombie-wrapper {
		transform: translateY(0%);
	}
	.zombie-wrapper {
		width: 100%;
		height: 100%;
		position: relative;
		transform: translateY(100%);
	}
	.head {
		background-color: $zombie-head-background-color;
		width: $zombie-head-width;
		height: $zombie-head-height;
		border: $zombie-border;
		box-sizing: border-box;
		border-radius: 50% / 50% 50% 50% 30%;
		.eyes {
			width: $zombie-head-width;
			height: $zombie-eyes-height;
			position: relative;
			&:before, &:after {
				content: '';
				background-color: $zombie-eye-background-color;
				width: $zombie-eye-width;
				height: $zombie-eye-height;
				border: $zombie-eye-border;
				position: absolute;
				top: $zombie-eye-top;
				box-sizing: border-box;
				border-radius: 50%;
			}
			&:before {
				left: $zombie-eye-left;
			}
			&:after {
				left: $zombie-eye-right;
			}
		}
	}
	.body {
		background-color: $zombie-body-background-color;
		width: $zombie-body-width;
		height: $zombie-body-height;
		border: $zombie-border;
		box-sizing: border-box;
		transform: $zombie-body-transform;
	}
	.arm {
		width: $zombie-arm-width;
		height: $zombie-arm-height;
		border: $zombie-border;
		border-bottom: none;
		border-left: none;
		box-sizing: border-box;
		position: absolute;
		top: $zombie-arm-top;
		transform-origin: top left;
		transform: rotate(15deg);
		&.left {
			left: $zombie-arm-left;
		}
		&.right {
			left: $zombie-arm-right;
		}
	}
	.leg {
		background-color: $zombie-leg-background-color;
		width: $zombie-leg-width;
		height: $zombie-leg-height;
		border: $zombie-border;
		position: absolute;
		top: $zombie-leg-top;
		box-sizing: border-box;
		transform-origin: top left;
		&.left {
			left: $zombie-leg-left;
		}
		&.right {
			left: $zombie-leg-right;
		}
		&:after {
			content: '';
			width: $zombie-foot-width;
			height: $zombie-foot-height;
			border: $zombie-border;
			border-top: none;
			border-right: none;
			display: block;
			position: absolute;
			top: $zombie-foot-top;
			box-sizing: border-box;
		}
	}
	.hole {
		background-color: $zombie-hole-background-color;
		width: $zombie-hole-width;
		height: $zombie-hole-height;
		position: absolute;
		top: 0;
		left: 0;
		border-radius: 50%;
		transform-origin: bottom center;
		transform: translate(0%, -100%) rotateX(-55deg) scale(0);
	}
}

.life {
	position: absolute;
	top: $life-top;
	left: $life-left;
	display: flex;
	flex-direction: row-reverse;
}

.heart {
	width: $heart-width;
	height: $heart-height;
	margin-right: $heart-width;
	transform: rotate(45deg);
	border-radius: 0 0 30% 0;
	position: relative;
	transition: $heart-transition;
	&:before, &:after {
		content: '';
		width: 100%;
		height: 100%;
		border-radius: 50%;
		display: block;
		position: absolute;
		top: 0;
		left: 0;
		transition: $heart-transition;
	}
	&:before {
		transform: translateY(-50%);
	}
	&:after {
		transform: translateX(-50%);
	}
	&.empty {
		background-color: $heart-border-color;
		&:before, &:after {
			background-color: $heart-border-color;
		}
	}
	&.full {
		background-color: $heart-background-color;
		&:before, &:after {
			background-color: $heart-background-color;
		}
	}
}

@each $char in $base-chars {
	.char-small-#{$char} {
		@include render-character(#{$char}, 0.06rem);
	}
	.char-#{$char} {
		@include render-character(#{$char}, 0.12rem);
	}
	.char-large-#{$char} {
		@include render-character(#{$char}, 0.14rem);
	}
}

.score {
	display: flex;
	position: absolute;
	top: $score-top;
	right: $score-right;
}

.title {
	background-color: $title-background-color;
	width: 100%;
	height: 100%;
	position: absolute;
	top: 0;
	left: 0;
	display: flex;
	align-items: center;
	justify-content: center;
	flex-direction: column;
	&.hide {
		transform: scale(0);
	}
}

.game-title {
	display: flex;
	flex-direction: column;
	&:not(:last-child) {
		margin-bottom: ($title-endln-margin * 2.5);
	}
	.title-content {
		display: flex;
		justify-content: center;
		&:not(:last-child) {
			margin-bottom: $title-endln-margin;
		}
	}
}

@keyframes animate-fire {
	0%   { transform: scale(1); }
	50%  { transform: scale(1.5); }
	100% { transform: scale(1); }
}

@keyframes animate-zombie-hole {
	0%   { transform: translate(5%, -100%) rotateX(-55deg) scale(0); }
	20%  { transform: translate(-5%, -100%) rotateX(-55deg) scale(0.2); }
	40%  { transform: translate(5%, -100%) rotateX(-55deg) scale(0.4); }
	60%  { transform: translate(-5%, -100%) rotateX(-55deg) scale(0.6); }
	80%  { transform: translate(5%, -100%) rotateX(-55deg) scale(0.8); }
	100% { transform: translate(0%, -100%) rotateX(-55deg) scale(1); }
}

@keyframes animate-hole-at-bottom {
	from { transform: translate(0%, -100%) rotateX(-55deg); }
	to   { transform: translate(0%, calc(#{$zombie-height} - 100%)) rotateX(-55deg); }
}

@keyframes clear-hole {
	from { opacity: 1; }
	to   { opacity: 0; }
}

@keyframes summon-zombie {
	from { transform: translateY(100%); }
	to   { transform: translateY(0%); }
}

@keyframes zombie-walk-left {
	0%   { transform: skewX(0deg); }
	25%  { transform: skewX(10deg); }
	50%  { transform: skewX(0deg); }
	75%  { transform: skewX(-10deg); }
	100% { transform: skewX(0deg); }
}

@keyframes zombie-walk-right {
	0%   { transform: skewX(0deg); }
	25%  { transform: skewX(-10deg); }
	50%  { transform: skewX(0deg); }
	75%  { transform: skewX(10deg); }
	100% { transform: skewX(0deg); }
}

@keyframes zombie-fade-out {
	from { opacity: 1; }
	to   { opacity: 0; }
}

@keyframes zombie-hiding {
	from { transform: scale(1); }
	to   { transform: scale(0); }
}
View Compiled
class ExampleGame extends React.Component {
	// ReactJS (or should I say Javascript) constructor
	// Basically, I declare variables and states here
	constructor(props) {
		super(props);

		// ----- Constants
		this.fps          = 1000 / 30;
		this.rotateSpd    = 4;
		this.fireInterval = 300;
		this.fireSpd      = 0.15;
		this.spdPerSummon = 250;
		this.minSummonSpd = 500;
		this.zombieSpd    = 0.025;
		this.zombieDelay  = 2000;
		this.lifeCount    = 3;
		this.center       = {x: 4, y: 4};
		this.screen       = {width: 8, height: 8};
		this.turret       = {width: 0.8, height: 0.8};
		this.fire         = {width: 0.25, height: 0.25};
		this.zombie       = {width: 0.65, height: 1.2};
		this.noSummonArea = {x1: 2, x2: 7, y1: 2, y2: 7};

		this.state = {
			// ----- Rendering/Animation
			time: performance.now(),
			// ----- Events/Controls
			holdLeft: false,
			holdRight: false,
			// ----- Movement
			rotation: 0,
			lastFire: 0,
			summonSpd: 5000,
			summonTime: 0,
			// ----- Game Objects
			turret: [],
			fires: [],
			// ^ Data structure: {a: angle, x: top, y: left}
			zombies: [],
			// ^ Data structure: {a: angle, x: top, y: left,
			// c: className, d: delay, s: stopFlag}
			life: this.lifeCount,
			score: 0,
			// ----- Game Option
			pause: true,
			showTitle: true,
			showTryAgain: false,
			// ----- Debug
			debugText: ''
		};
		
		// this.gameLoop;
	}

	// ReactJS componentDidMount() method to initialize event listeners
	componentDidMount() {
		// Event listeners
		window.addEventListener('keydown', (evt) => {
			if (this.state.pause === true) {
				return false;
			}

			if (evt.keyCode === 32) {
				if (
					this.state.lastFire == 0 || (
						performance.now() - this.state.lastFire > this.fireInterval &&
						this.state.fires.length < 2
					)
				) {
					this.setState({lastFire: performance.now()});
					this.throwFire();
				}
			} else if (evt.keyCode === 37) {
				this.setState({holdLeft: true});
			} else if (evt.keyCode === 39) {
				this.setState({holdRight: true});
			}
		});

		window.addEventListener('keyup', (evt) => {
			if (evt.keyCode === 32 || evt.keyCode === 13) {
				if (this.state.showTitle === true) {
					if (this.state.showTryAgain === false) {
						this.setState({showTitle: false});
						this.setState({pause: false});

						// Trigger the animation start
						this.animate();
					} else {
						this.restartGame();
						
						this.setState({showTryAgain: false});
					}
				}
			} else if (evt.keyCode === 37) {
				if (this.state.pause === true) {
					return false;
				}

				this.setState({holdLeft: false});
			} else if (evt.keyCode === 39) {
				if (this.state.pause === true) {
					return false;
				}

				this.setState({holdRight: false});
			}
		});

		// Initialize Turry the turret's initial position.
		// He can't move anyway, so...
		this.setState({turret: [{
			x: this.center.x - (this.turret.width / 2),
			y: this.center.y - (this.turret.height / 2)
		}]});
	}

	// ----- Helpers/Methods

	// Returns the value of number as 'rem'
	remVal(value) {
		return `${value}rem`;
	}

	// Generate random numbers
	randomNum(value) {
		return Math.floor(Math.random() * Math.floor(value));
	}

	// The time for Turry to fire a fire
	throwFire() {
		let tmpFire = this.state.fires;
		let angle   = (this.state.rotation - 90) * Math.PI / 180;
		let half    = {w: this.fire.width / 2, h: this.fire.height / 2};

		tmpFire.push({
			a: angle,
			x: this.center.x - half.w + Math.cos(angle),
			y: this.center.y - half.h + Math.sin(angle)
		});

		this.setState({fires: tmpFire});
	}

	// Timeout in summoning Zoomy the Zombie
	summonZombieTrigger() {
		if (this.state.summonTime > this.state.summonSpd) {
			this.summonZombie();

			let nextSummonSpd = (this.state.summonSpd > this.minSummonSpd) ?
					this.state.summonSpd - 100 : this.minSummonSpd;

			this.setState({summonTime: 0});
			this.setState({summonSpd: nextSummonSpd});
		}
		else {
			this.setState({summonTime: this.state.summonTime + this.fps});
		}
	}

	// The time for Zoomy the zombie will be summoned
	summonZombie() {
		let tmpZombie = this.state.zombies;
		let half = {
			width: this.zombie.width / 2,
			height: this.zombie.height / 2
		};
		let random = {
			x: (this.randomNum(this.screen.width * 100) / 100) - half.width,
			y: (this.randomNum(this.screen.height * 100) / 100) - half.height
		};
		let addClass = (random.x > this.center.x) ? 'flip' : '';
		let angle    = 0;

		if (
			random.x > this.noSummonArea.x1 &&
			random.x < this.noSummonArea.x2 &&
			random.y > this.noSummonArea.y1 &&
			random.y < this.noSummonArea.y2
		) {
			this.summonZombie();

			return false;
		}

		let a = this.center.y - random.y;
		let b = this.center.x - random.x;

		angle = Math.atan2(a, b);

		tmpZombie.push({
			a: angle,
			x: random.x,
			y: random.y,
			c: addClass,
			d: performance.now(),
			s: false
		});

		this.setState({zombies: tmpZombie});
	}
	
	// Reset the game
	restartGame() {
		this.setState({time: performance.now()});
		this.setState({holdLeft: false});
		this.setState({holdRight: false});
		this.setState({rotation: 0});
		this.setState({lastFire: 0});
		this.setState({summonSpd: 5000});
		this.setState({summonTime: 0});
		this.setState({fires: []});
		this.setState({zombies: []});
		this.setState({life: this.lifeCount});
		this.setState({score: 0});
		this.setState({pause: true});
		this.setState({showTitle: true});
		this.setState({showTryAgain: false});
	}

	// ----- Collisions

	// When an object/s collided into the edge of the screen
	edgeCollision(i, arr, width, height) {
		let tmpArr = arr;
		let tmpObj = tmpArr[i];

		if (
			tmpObj.x + width < 0 ||
			tmpObj.y + height < 0 ||
			tmpObj.x > this.screen.width ||
			tmpObj.y > this.screen.height
		) {
			tmpArr.splice(i, 1);
		}

		return tmpArr;
	}

	// When an object/s collided into another object
	objectCollision(i, arr1, width1, height1, arr2, width2, height2, callback) {
		let tmpArr1 = arr1;
		let tmpArr2 = arr2;
		let tmpObj1 = tmpArr1[i];

		for (let j = 0; j < tmpArr2.length; j++) {
			let tmpObj2 = tmpArr2[j];

			if (
				typeof tmpObj1 !== 'undefined' &&
				tmpObj1.x + width1 > tmpObj2.x &&
				tmpObj1.x < tmpObj2.x + width2 &&
				tmpObj1.y + width1 > tmpObj2.y &&
				tmpObj1.y < tmpObj2.y + width2
			) {
				callback(i, j, tmpArr1, tmpArr2);

				break;
			}
		}

		return {fire: tmpArr1, zombie: tmpArr2};
	}

	// Call the possible collisions of Turry's fire
	fireCollision(i) {
		let tmpArr = this.edgeCollision(
			i,
			this.state.fires,
			this.fire.width,
			this.fire.height
		);
		let objArr = this.objectCollision(
			i,
			this.state.fires,
			this.fire.width,
			this.fire.height,
			this.state.zombies,
			this.zombie.width,
			this.zombie.height,
			(i, j, tmpArr1, tmpArr2) => {
				tmpArr1.splice(i, 1);

				var zombies = this.state.zombies;

				if (zombies[j].s === false) {
					this.setState({score: this.state.score + 1});
				}

				zombies[j].c = zombies[j].c + ' zombie-dying';
				zombies[j].s = true;

				this.setState({zombies: zombies});
			}
		);

		tmpArr = objArr.fire;

		this.setState({zombie: objArr.zombie});

		return tmpArr;
	}

	// Call the possible collisions of Zoomy
	zombieCollision(i) {
		let tmpZombie = this.edgeCollision(
			i,
			this.state.zombies,
			this.zombie.width,
			this.zombie.height
		);
		let objArr = this.objectCollision(
			i,
			this.state.zombies,
			this.zombie.width,
			this.zombie.height,
			this.state.turret,
			this.turret.width,
			this.turret.height,
			(i, j, tmpArr1, tmpArr2) => {
				let zombies = this.state.zombies;
				
				if (zombies[i].c.indexOf('zombie-hiding') < 0) {
					zombies[i].c = zombies[i].c.replace(/zombie\-walking/g, 'zombie-hiding');
					zombies[i].s = true;

					this.setState({zombies: zombies});
					this.setState({life: this.state.life - 1});
				}

				if (this.state.life === 0) {
					this.setState({pause: true});
					
					let tryAgainTimeout = setTimeout(() => {
						clearTimeout(tryAgainTimeout);
						
						// cancelAnimationFrame(this.gameLoop);
						
						this.setState({showTryAgain: true});
						this.setState({showTitle: true});
					}, 500);
				}
			}
		);

		return tmpZombie;
	}

	// ----- Animation

	// Animate when Turry changes its angle
	// Press LEFT key to turn anti-clockwise
	// Press RIGHT key to turn clockwise
	animateRotation() {
		if (this.state.holdLeft === true) {
			if (this.state.rotation > 0) {
				this.setState({rotation: this.state.rotation - this.rotateSpd});
			} else {
				this.setState({rotation: 360});
			}
		} else if (this.state.holdRight === true) {
			if (this.state.rotation < 360) {
				this.setState({rotation: this.state.rotation + this.rotateSpd});
			} else {
				this.setState({rotation: 0});
			}
		}
	}

	// Animate the movement of a/an o/object with array
	animateMoveByArray(arr, spd, collision, delay = 0, callback = null) {
		let tmpArr = arr;

		for (let i = 0; i < tmpArr.length; i++) {
			if (
				(delay > 0 &&
				performance.now() - tmpArr[i].d < delay) ||
				tmpArr[i].s === true
			) {
				continue;
			}

			tmpArr[i].x += spd * Math.cos(tmpArr[i].a);
			tmpArr[i].y += spd * Math.sin(tmpArr[i].a);

			tmpArr = collision(i);

			if (callback !== null) {
				callback(i);
			}
		}

		return tmpArr;
	}

	// Animate the movement of the fire when Turry fires it
	animateFire() {
		this.setState({
			fires: this.animateMoveByArray(
				this.state.fires,
				this.fireSpd,
				this.fireCollision.bind(this),
				0
			)
		});
	}

	// Animate the movement of Zoomy, because he wants to eat Turry's brain
	animateZombie() {
		this.setState({
			zombies: this.animateMoveByArray(
				this.state.zombies,
				this.zombieSpd,
				this.zombieCollision.bind(this),
				this.zombieDelay,
				(i) => {
					let zombies = this.state.zombies;

					if (
						zombies[i].c.indexOf('zombie-walking') < 0 &&
						zombies[i].c.indexOf('zombie-hiding') < 0
					) {
						zombies[i].c = zombies[i].c + ' zombie-walking';
					}

					this.setState({zombies: zombies});
				}
			)
		});
	}

	// The animation, or the game loop, or whatever it is called
	animate() {
		let gameLoop = requestAnimationFrame(this.animate.bind(this));
		
		if (this.state.pause === true) {
			cancelAnimationFrame(gameLoop);
		}

		// Perform animation for 30 frames per second
		// FPS is set at constructor()
		if (
			performance.now() - this.state.time > this.fps &&
			this.state.pause === false
		) {
			this.setState({time: performance.now()});

			this.animateRotation();
			this.animateFire();
			this.animateZombie();

			this.summonZombieTrigger();
		}
	}

	// ----- Rendering

	// Rendering of objects using array
	renderByArray(className, object, innerJSX = null, callback = null) {
		let objs     = object;
		let objArray = [];

		for (let i = 0; i < objs.length; i++) {
			let obj      = objs[i];
			let style    = {top: this.remVal(obj.y), left: this.remVal(obj.x)};
			let addClass = (typeof obj.c !== 'undefined') ?
				(`${className} ${obj.c}`) : className;

			if (callback === null) {
				objArray.push(
					<div className={addClass} style={style}>{innerJSX}</div>
				);
			} else {
				objArray.push(
					<div
						className={addClass}
						style={style}
						onAnimationEnd={callback.bind(this, i)}
					>{innerJSX}</div>
				);
			}
		}

		return objArray;
	}

	// Tender the fire when Turry shoots a fire
	renderFire() {
		return this.renderByArray('fire', this.state.fires);
	}

	// Render Turry the turret: The main character
	renderTurret() {
		let style = {transform: 'rotate(' + this.state.rotation + 'deg)'};

		return (
			<div className="turret" style={style}>
				<div className="gun"></div>
				<div className="body"></div>
			</div>
		);
	}

	// Render Zoomy the zombie: He's trying to eat Turry's brain (wut?)
	renderZombie() {
		return this.renderByArray(
			'zombie',
			this.state.zombies,
			<div className="zombie-wrapper">
				<div className="hole"></div>
				<div className="head">
					<div className="eyes"></div>
				</div>
				<div className="body"></div>
				<div className="arm right"></div>
				<div className="arm left"></div>
				<div className="leg right"></div>
				<div className="leg left"></div>
			</div>,
			(i, event) => {
				if (['zombie-fade-out', 'zombie-hiding'].indexOf(event.animationName) >= 0) {
					let zombies = this.state.zombies;

					zombies.splice(i, 1);

					this.setState({zombies: zombies});
				}
			}
		);
	}

	// Render Turry's life points
	renderLife() {
		let lifeArray = [];

		for (let i = 1; i <= this.lifeCount; i++) {
			let lifeClassName = (i <= this.state.life) ?
					'heart full' : 'heart empty';

			lifeArray.push(<div className={lifeClassName}></div>)
		}

		return (
			<div className="life">{lifeArray}</div>
		);
	}

	// Render the current score
	renderScore() {
		let score    = this.state.score.toString();
		let scoreArr = score.split('');
		let scoreElm = [];

		for (let i = 0; i < scoreArr.length; i++) {
			let scoreClassName = `char-${scoreArr[i]}`;

			scoreElm.push(<div className={scoreClassName}></div>);
		}

		return <div className="score">{scoreElm}</div>;
	}

	// Render the word
	renderWord(words, size = '') {
		let textSize  = (size !== '') ? (size + '-') : size;
		let tmpJSX    = [];
		let returnJSX = [];

		for (let i in words) {
			tmpJSX = [];
			
			for (let j in words[i]) {
				let textClassName = 'char-' + textSize + words[i][j];

				tmpJSX.push(<div className={textClassName}></div>);
			}
			
			returnJSX.push(
				<div className="title-content">{tmpJSX}</div>
			);
		}

		return returnJSX;
	}

	// Render the game title
	renderTitle() {
		let titleClass   = (this.state.showTitle === true) ? 'title' : 'title hide';
		let titleText    = (this.state.showTryAgain === false) ?
				['turret', 'shooting game'] : ['you lose'];
		let subTitleText = (this.state.showTryAgain === false) ?
				['shoot the never', 'ending zombies'] :
				['these zombies has', 'eaten your brain'];
		let startText    = (this.state.showTryAgain === false) ?
				[
					'press space to start',
					'',
					'directions',
					'press left to turn anti clockwise',
					'press right to turn clockwise',
					'press space to fire'
				] : ['press space to restart'];
		let titleJSX     = this.renderWord(titleText, 'large');
		let subTitleJSX  = this.renderWord(subTitleText, '');
		let startJSX     = this.renderWord(startText, 'small');

		return (
			<div className={titleClass}>
				<div className="game-title">
					{titleJSX}
				</div>
				<div className="game-title">
					{subTitleJSX}
				</div>
				<div className="game-title">
					{startJSX}
				</div>
			</div>
		);
	}

	// ReactJS' render() method
	render() {
		return (
			<div className="screen">
				<div className="debug">{this.state.debugText}</div>
				{this.renderZombie()}
				{this.renderFire()}
				{this.renderTurret()}
				{this.renderLife()}
				{this.renderScore()}
				{this.renderTitle()}
			</div>
		);
	}
}

ReactDOM.render(<ExampleGame />, document.querySelector('#example_game'));
View Compiled

External CSS

This Pen doesn't use any external CSS resources.

External JavaScript

  1. https://cdnjs.cloudflare.com/ajax/libs/react/16.8.6/umd/react.production.min.js
  2. https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.6/umd/react-dom.production.min.js