<div class="game">
<header>
<div class="title">Whack a Dino!</div>
<div class="scoreboard">
<div>Score: <span class="score">0</span></div>
<div>Time: <span class="time">60</span>s</div>
</div>
</header>
<div class="field">
<div class="dino dino--original">
<div class="points">100</div>
<!--<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" style="isolation:isolate"
viewBox="96.697 225 109.78 96.182" width="109.78" height="96.182">
<clipPath id="_clipPath_L6vxxCNIG6i2DxHyDoWTljFPc2CxYa6J">
<path d=" M 116.641 305 Q 110.155 304.779 96.832 305 L 96.697 225 L 206.237 225 L 206.477 305 L 186.2 305 C 186.48 312.567 173.087 321.196 151.936 321.182 C 137.187 321.172 117.677 315.365 116.641 305 Z "
id="PeekingDino" fill="rgb(255,255,255)" />
</clipPath>
<g clip-path="url(#_clipPath_L6vxxCNIG6i2DxHyDoWTljFPc2CxYa6J)">
<ellipse vector-effect="non-scaling-stroke" cx="151.4330128244587" cy="304.87000090967086" rx="34.697922494492445"
ry="16.31926107003602" id="Hole" fill="rgb(93,93,93)" />
<clipPath id="_clipPath_AbMXbnqGifFFNKhxLpyvgc3WAvs60BpG">
<ellipse vector-effect="non-scaling-stroke" cx="151.4330128244587" cy="304.87000090967086" rx="34.697922494492445"
ry="16.31926107003602" id="Hole" fill="rgb(93,93,93)" />
</clipPath>
<g clip-path="url(#_clipPath_AbMXbnqGifFFNKhxLpyvgc3WAvs60BpG)">
<path d=" M 117.782 309.212 C 117.782 299.896 132.692 291.912 151.37 291.912 C 170.048 291.912 185.613 300.121 185.613 309.438 C 185.613 318.754 170.174 327.9 151.496 327.9 C 132.818 327.9 117.782 318.529 117.782 309.212 Z "
id="Hole" fill="rgb(66,66,66)" />
</g>
<g id="Dino">
<path d=" M 128.804 298.415 Q 125.475 303.13 125.767 304.39 C 126.059 305.649 126.628 306.203 127.451 306.548 C 128.274 306.892 129.515 306.953 130.357 306.602 Q 131.199 306.251 133.148 300.653 L 128.804 298.415 Z "
id="Tongue" fill="rgb(238,81,76)" />
<path d=" M 152.602 304.156 C 145.848 304.494 135.579 303.617 131.528 301.876 C 127.477 300.135 124.447 297.583 124.482 293.582 C 124.517 289.582 126.082 287.991 128.774 285.746 Q 131.465 283.501 140.329 280.036 Q 143.751 264.32 155.832 265.068 C 163.876 265.566 169.406 270.291 171.884 277.858 Q 174.362 285.425 175.289 299.067 L 177.604 355.799 L 153.757 358.395 Q 153.209 304.126 152.602 304.156 Z "
id="Path" fill="rgb(216,69,1)" />
<g id="Eyes">
<ellipse vector-effect="non-scaling-stroke" cx="142.8571718083349" cy="282.3434321286788" rx="2.8239805295291376"
ry="2.626211886374506" id="Ellipse" fill="rgb(0,0,0)" />
<ellipse vector-effect="non-scaling-stroke" cx="150.57965298493306" cy="284.84937354038675" rx="2.8239805295291376"
ry="2.626211886374506" id="Ellipse" fill="rgb(0,0,0)" />
</g>
<g id="DeadEyes">
<g id="Group">
<line x1="148.148" y1="287.208" x2="152.899" y2="282.433" id="Path" vector-effect="non-scaling-stroke"
stroke-width="1.8" stroke="rgb(0,0,0)" stroke-linejoin="miter" stroke-linecap="square"
stroke-miterlimit="3" />
<line x1="148.148" y1="282.433" x2="152.899" y2="287.208" id="Path" vector-effect="non-scaling-stroke"
stroke-width="1.8" stroke="rgb(0,0,0)" stroke-linejoin="miter" stroke-linecap="square"
stroke-miterlimit="3" />
</g>
<g id="Group">
<line x1="140.388" y1="284.528" x2="145.14" y2="279.752" id="Path" vector-effect="non-scaling-stroke"
stroke-width="1.8" stroke="rgb(0,0,0)" stroke-linejoin="miter" stroke-linecap="square"
stroke-miterlimit="3" />
<line x1="140.388" y1="279.752" x2="145.14" y2="284.528" id="Path" vector-effect="non-scaling-stroke"
stroke-width="1.8" stroke="rgb(0,0,0)" stroke-linejoin="miter" stroke-linecap="square"
stroke-miterlimit="3" />
</g>
</g>
<g id="Nose">
<g opacity="0.43" style="mix-blend-mode:multiply;">
<ellipse vector-effect="non-scaling-stroke" cx="128.19110091447448" cy="289.0511362516258" rx="1.4166421843752417"
ry="0.9380682199951593" id="Ellipse" fill="rgb(0,0,0)" />
</g>
<g opacity="0.43" style="mix-blend-mode:multiply;">
<ellipse vector-effect="non-scaling-stroke" cx="132.38971821959944" cy="291.7215801121933" rx="1.4166421843752346"
ry="0.9380682199951593" id="Ellipse" fill="rgb(0,0,0)" />
</g>
</g>
<g id="AngryEyebrows">
<line x1="149.378" y1="282.5" x2="156.333" y2="280.033" id="Path" vector-effect="non-scaling-stroke"
stroke-width="1.8" stroke="rgb(0,0,0)" stroke-linejoin="miter" stroke-linecap="square"
stroke-miterlimit="3" />
<line x1="144.659" y1="280.897" x2="140.188" y2="276.456" id="Path" vector-effect="non-scaling-stroke"
stroke-width="1.8" stroke="rgb(0,0,0)" stroke-linejoin="miter" stroke-linecap="square"
stroke-miterlimit="3" />
</g>
<path d=" M 148.781 272.837 C 148.57 269.208 149.266 266.066 150.991 262.86 Q 152.716 259.655 156.461 256.578 Q 155.808 259.491 155.521 261.417 C 155.171 263.763 155.481 265.589 155.863 267.105 C 156.245 268.62 156.374 269.637 156.803 270.968 Q 154.623 273.841 148.781 272.837 Z "
id="Horn" fill="rgb(255,255,255)" />
<g opacity="0">
<rect x="96.519" y="254.467" width="109.828" height="66.808" transform="matrix(1,0,0,1,0,0)" id="Rectangle"
fill="rgb(235,235,235)" />
</g>
</g>
</g>
</svg>-->
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" style="isolation:isolate" viewBox="158.22 300.71 109.78 106.41" width="109.78" height="106.41">
<clipPath id="_clipPath_iyFpZlomJkfyPxMy5FoWrjPUsTxfrOtl">
<path d=" M 178.312 390.733 Q 171.834 390.756 158.355 390.818 L 158.22 300.71 L 267.759 300.71 L 268 390.818 L 247.86 390.728 C 247.759 399.508 232.844 407.191 213.092 407.12 C 196.053 407.058 178.797 401.189 178.312 390.733 Z "
id="PeekingDino_2" fill="rgb(255,255,255)" />
</clipPath>
<g clip-path="url(#_clipPath_iyFpZlomJkfyPxMy5FoWrjPUsTxfrOtl)">
<ellipse vector-effect="non-scaling-stroke" cx="213.1098590741296" cy="390.81926107003596" rx="34.697922494492445"
ry="16.319261070035964" id="Hole" fill="rgb(93,93,93)" />
<clipPath id="_clipPath_c8QjgyLlDC94cLkhLSUMTysbC6Mandia">
<ellipse vector-effect="non-scaling-stroke" cx="213.1098590741296" cy="390.81926107003596" rx="34.697922494492445"
ry="16.319261070035964" id="Hole" fill="rgb(93,93,93)" />
</clipPath>
<g clip-path="url(#_clipPath_c8QjgyLlDC94cLkhLSUMTysbC6Mandia)">
<ellipse vector-effect="non-scaling-stroke" cx="213.1098590741296" cy="394.1380159686848" rx="34.29522846510352"
ry="16.129864457083556" id="Hole" fill="rgb(66,66,66)" />
</g>
<g id="Dino">
<path d=" M 190.327 384.232 Q 186.998 388.948 187.29 390.208 C 187.582 391.467 188.151 392.021 188.974 392.366 C 189.797 392.71 191.038 392.77 191.88 392.42 Q 192.722 392.069 194.671 386.471 L 190.327 384.232 Z "
id="Tongue" fill="rgb(238,81,76)" />
<path d=" M 214.125 389.974 C 207.37 390.312 197.102 389.435 193.051 387.694 C 189 385.952 185.97 383.401 186.005 379.4 C 186.04 375.399 187.605 373.809 190.296 371.564 Q 192.987 369.319 201.851 365.854 Q 205.274 350.138 217.354 350.886 C 225.398 351.384 230.929 356.109 233.406 363.676 Q 235.884 371.243 236.811 384.884 L 239.127 441.617 L 215.28 444.213 Q 214.732 389.944 214.125 389.974 Z "
id="Path" fill="rgb(216,69,1)" />
<g id="Eyes">
<ellipse vector-effect="non-scaling-stroke" cx="204.3797819812316" cy="368.16127867739544" rx="2.8239805295291376"
ry="2.626211886374506" id="Ellipse" fill="rgb(0,0,0)" />
<ellipse vector-effect="non-scaling-stroke" cx="212.10226315782975" cy="370.66722008910335" rx="2.8239805295291376"
ry="2.626211886374506" id="Ellipse" fill="rgb(0,0,0)" />
</g>
<g id="DeadEyes">
<g id="Group">
<line x1="209.67" y1="373.026" x2="214.422" y2="368.251" id="Path" vector-effect="non-scaling-stroke"
stroke-width="1.8" stroke="rgb(0,0,0)" stroke-linejoin="miter" stroke-linecap="square"
stroke-miterlimit="3" />
<line x1="209.67" y1="368.251" x2="214.422" y2="373.026" id="Path" vector-effect="non-scaling-stroke"
stroke-width="1.8" stroke="rgb(0,0,0)" stroke-linejoin="miter" stroke-linecap="square"
stroke-miterlimit="3" />
</g>
<g id="Group">
<line x1="201.911" y1="370.345" x2="206.662" y2="365.57" id="Path" vector-effect="non-scaling-stroke"
stroke-width="1.8" stroke="rgb(0,0,0)" stroke-linejoin="miter" stroke-linecap="square"
stroke-miterlimit="3" />
<line x1="201.911" y1="365.57" x2="206.662" y2="370.345" id="Path" vector-effect="non-scaling-stroke"
stroke-width="1.8" stroke="rgb(0,0,0)" stroke-linejoin="miter" stroke-linecap="square"
stroke-miterlimit="3" />
</g>
</g>
<g id="Nose">
<g opacity="0.43" style="mix-blend-mode:multiply;">
<ellipse vector-effect="non-scaling-stroke" cx="189.71371108737117" cy="374.86898280034245" rx="1.4166421843752346"
ry="0.9380682199951593" id="Ellipse" fill="rgb(0,0,0)" />
</g>
<g opacity="0.43" style="mix-blend-mode:multiply;">
<ellipse vector-effect="non-scaling-stroke" cx="193.91232839249614" cy="377.53942666090995" rx="1.4166421843752346"
ry="0.9380682199951593" id="Ellipse" fill="rgb(0,0,0)" />
</g>
</g>
<g id="AngryEyebrows">
<line x1="210.901" y1="368.318" x2="217.856" y2="365.851" id="Path" vector-effect="non-scaling-stroke"
stroke-width="1.8" stroke="rgb(0,0,0)" stroke-linejoin="miter" stroke-linecap="square"
stroke-miterlimit="3" />
<line x1="206.181" y1="366.714" x2="201.71" y2="362.273" id="Path" vector-effect="non-scaling-stroke"
stroke-width="1.8" stroke="rgb(0,0,0)" stroke-linejoin="miter" stroke-linecap="square"
stroke-miterlimit="3" />
</g>
<g opacity="0">
<rect x="158.042" y="334.991" width="109.828" height="72.072" transform="matrix(1,0,0,1,0,0)" id="Rectangle"
fill="rgb(235,235,235)" />
</g>
<path d=" M 210.303 358.654 C 210.092 355.026 210.789 351.883 212.514 348.678 Q 214.239 345.473 217.984 342.396 Q 217.331 345.309 217.044 347.235 C 216.694 349.581 217.004 351.407 217.385 352.923 C 217.767 354.438 217.896 355.455 218.326 356.785 Q 216.146 359.659 210.303 358.654 Z "
id="Horn" fill="rgb(255,255,255)" />
<g id="TopHat">
<path d=" M 213.713 350.463 L 214.089 349 L 217.682 334.991 L 231.098 338.432 L 227.125 353.918 L 229.275 354.471 L 228.914 355.878 L 211.289 351.338 L 211.65 349.932 L 213.713 350.463 Z "
fill-rule="evenodd" id="Compound Shape" fill="rgb(62,62,62)" />
<rect x="213.731" y="350.322" width="13.85" height="1.901" transform="matrix(0.969,0.248,-0.248,0.969,94.213,-43.814)"
id="Rectangle" fill="rgb(235,235,235)" />
</g>
<circle vector-effect="non-scaling-stroke" cx="212.30986650808822" cy="370.69013349191187" r="4.5" id="Monocle"
fill="rgb(255,253,253)" fill-opacity="0.4" style=":undefined;" stroke-width="0.4" stroke="rgb(83,83,83)"
stroke-linejoin="miter" stroke-linecap="square" stroke-miterlimit="3" />
</g>
</g>
</svg>
</div>
</div>
<button class="start">START!</button>
</div>
html,
body {
height: 100%;
}
body {
background-color: #4dbd76;
background: rgb(77,189,118);
background: radial-gradient(circle, rgba(77,189,118,1) 0%, rgba(60,136,143,1) 100%);
font-family: "Open Sans", Arial, Helvetica, sans-serif;
}
.game {
width: 100%;
height: 100%;
box-sizing: border-box;
display: grid;
grid-template-rows: auto 1fr 40px;
justify-items: center;
padding: 20px 10px;
}
.title {
font-family: Modak, sans-serif;
color: #ff8c00;
font-size: 36px;
letter-spacing: 2px;
text-shadow: 1px 1px rgb(123, 67, 0);
text-transform: uppercase;
}
.scoreboard {
width: 100%;
text-align: center;
color: #FFF;
font-size: 18px;
display: flex;
justify-content: space-around;
}
.start {
position: relative;
top: -20px;
background-color: darkorange;
color: #FFF;
letter-spacing: 2px;
font-weight: 600;
font-size: 20px;
border-radius: 4px;
padding: 6px 20px;
border: none;
box-sizing: border-box;
height: 40px;
width: 200px;
box-shadow: 2px 2px 4px rgb(123, 67, 0);
text-shadow: -1px -1px rgba(0,0,0,0.3);
cursor: pointer;
}
.start:focus {
outline: none;
}
.start:active {
box-shadow: inset 1px 1px 1px rgba(123, 67, 0, 0.49);
outline: none;
}
@keyframes shake {
45% { transform: translateX(0); }
50% { transform: translateX(-6px); }
60% { transform: translateX(6px); }
65% { transform: translateX(0); }
}
.shake {
animation: shake 300ms linear;
}
.field {
width: 100%;
max-width: 360px;
margin: auto;
position: relative;
top: -30px;
display: grid;
grid-template-columns: repeat(3, 1fr);
justify-content: center;
align-content: center;
}
.dino {
display: flex;
justify-content: center;
align-items: center;
height: 110px;
position: relative;
}
.dino:nth-child(3n),
.dino:nth-child(3n+1){
position: relative;
top: 60px;
}
.dino:last-child {
grid-column-start: 2;
top: 0;
}
@keyframes fadeUp {
from {
transform: translateY(0) scale(1);
opacity: 0;
}
to {
transform: translateY(-15px) scale(1.2);
opacity: 1;
}
}
.fadeUp {
animation: fadeUp 500ms ease-out;
}
.points {
position: absolute;
top: 0;
opacity: 0;
color: #ffeb3b;
text-shadow: 1px 1px #000;
font-family: monospace;
font-size: 1.4em;
font-weight: bold;
z-index: 1;
pointer-events: none;
}
.points--red {
color: #EF5350;
}
@keyframes slowly-peeking {
0% { transform: translateY(80%); }
20% { transform: translateY(80%); }
40% { transform: translateY(10%); }
42% { transform: translateY(25%); }
70% { transform: translateY(25%); }
90% { transform: translateY(-26%); }
97.5% { transform: translateY(-26%); }
99% { transform: translateY(-34%); }
100% { transform: translateY(80%); }
}
@keyframes peeking {
10% { transform: translateY(80%); }
25% { transform: translateY(-26%); }
27.5% { transform: translateY(-26%); }
29% { transform: translateY(-26%); }
30% { transform: translateY(-26%); }
34% { transform: translateY(-34%); }
36% { transform: translateY(80%); }
}
.dino #Dino {
transform: translateY(80%);
animation: slowly-peeking 10s infinite;
}
.no-touch .dino #Dino {
cursor: pointer;
}
svg {
user-select: none;
outline: none;
}
.hide {
visibility: hidden;
pointer-events: none;
}
View Compiled
let dinoOriginal = document.querySelector('.dino--original');
let fieldEl = document.querySelector('.field');
let scoreEl = document.querySelector('.score');
let startEl = document.querySelector('.start');
let timeEl = document.querySelector('.time');
let dinosFrag = document.createDocumentFragment();
let max = 7;
let dinos = [];
let score = 0;
let isTouch = true;
let isRunning = false;
let time = 60;
let timer = null;
function shake() {
fieldEl.classList.add('shake');
fieldEl.addEventListener('animationend', () => {
fieldEl.classList.remove('shake');
});
}
function setTimer() {
time = 60;
timeEl.innerText = time;
timer = setInterval(function() {
time = time - 1;
timeEl.innerText = time;
if (time <= 0) {
gameOver();
}
}, 1000);
}
function start() {
for (let i = 0; i < dinos.length; i++) {
let dinoSVG = dinos[i].querySelector('#Dino');
dinoSVG.style.transform = 'translateY(80%)';
dinoSVG.style.animation = 'peeking 5.5s infinite';
dinoSVG.querySelector('#DeadEyes').style.display = 'none';
dinoSVG.querySelector('#Tongue').style.display = 'none';
dinoSVG.querySelector('#AngryEyebrows').style.display = 'none';
dinoSVG.style.animationDelay = (1000 + (i * 700)) + Math.floor((Math.random() * 4000)) + 'ms'
}
if (!isRunning) {
setTimer();
startEl.classList.add('hide');
score = 0;
scoreEl.innerText = score;
isRunning = true;
}
}
function gameOver() {
clearInterval(timer);
isRunning = false;
startEl.classList.remove('hide');
for (let i = 0; i < dinos.length; i++) {
let dinoSVG = dinos[i].querySelector('#Dino');
dinoSVG.style.transform = 'translateY(80%)';
dinoSVG.style.animation = 'slowly-peeking 10s infinite';
dinoSVG.style.animationDelay = (Math.random() * 5000) + 'ms';
}
}
function init() {
for (let i = 0; i < max; i++) {
let dino = dinoOriginal.cloneNode(true);
let dinoSVG = dino.querySelector('#Dino');
let dir = [1, -1][Math.floor(Math.random() * 2)];
let showHorn = (Math.random() * 10) > 5;
let isGentleman = (Math.random() * 10) > 9;
dino.querySelector('svg').style.transform = `scaleX(${dir})`;
dinoSVG.style.animation = 'slowly-peeking 10s infinite';
dinoSVG.style.animationDelay = (Math.random() * 5000) + 'ms';
dinoSVG.querySelector('#DeadEyes').style.display = 'none';
dinoSVG.querySelector('#Tongue').style.display = 'none';
dinoSVG.querySelector('#AngryEyebrows').style.display = 'none';
dinoSVG.querySelector('#TopHat').style.display = 'none';
dinoSVG.querySelector('#Monocle').style.display = 'none';
if (showHorn) {
dinoSVG.querySelector('#Horn').style.display = 'block';
} else {
dinoSVG.querySelector('#Horn').style.display = 'none';
}
if (isGentleman) {
dinoSVG.querySelector('#TopHat').style.display = 'block';
dinoSVG.querySelector('#Monocle').style.display = 'block';
dinoSVG.querySelector('#Horn').style.display = 'none';
}
dino.addEventListener('animationiteration', function(ev) {
let dir = [1, -1][Math.floor(Math.random() * 2)];
let showHorn = (Math.random() * 10) > 5;
let isGentleman = (Math.random() * 10) > 9;
dino.querySelector('svg').style.transform = `scaleX(${dir})`;
dinoSVG.querySelector('#DeadEyes').style.display = 'none';
dinoSVG.querySelector('#Tongue').style.display = 'none';
dinoSVG.querySelector('#AngryEyebrows').style.display = 'none';
dinoSVG.querySelector('#Eyes').style.display = 'block';
dinoSVG.querySelector('#TopHat').style.display = 'none';
dinoSVG.querySelector('#Monocle').style.display = 'none';
if (showHorn) {
dinoSVG.querySelector('#Horn').style.display = 'block';
} else {
dinoSVG.querySelector('#Horn').style.display = 'none';
}
if (isGentleman) {
dinoSVG.querySelector('#TopHat').style.display = 'block';
dinoSVG.querySelector('#Monocle').style.display = 'block';
dinoSVG.querySelector('#Horn').style.display = 'none';
}
});
function whack(ev) {
if (isRunning) {
let pointsEl = dino.querySelector('.points');
if (dinoSVG.querySelector('#Horn').style.display === 'none') {
score = score + 60;
dinoSVG.querySelector('#DeadEyes').style.display = 'block';
dinoSVG.querySelector('#Tongue').style.display = 'block';
dinoSVG.querySelector('#Eyes').style.display = 'none';
pointsEl.innerText = '60';
} else {
score = score - 20;
score = Math.max(0, score);
dinoSVG.querySelector('#AngryEyebrows').style.display = 'block';
pointsEl.innerText = '-20';
pointsEl.classList.add('points--red');
shake();
}
pointsEl.classList.add('fadeUp');
pointsEl.addEventListener('animationend', () => {
pointsEl.classList.remove('fadeUp');
pointsEl.classList.remove('points--red');
});
scoreEl.innerText = score;
}
}
if (isTouch) {
dinoSVG.addEventListener('touchend', whack);
} else {
dinoSVG.addEventListener('click', whack);
}
dinosFrag.appendChild(dino);
dinos.push(dino);
}
fieldEl.appendChild(dinosFrag);
dinoOriginal.remove();
startEl.addEventListener('click', start);
}
window.addEventListener('load', function() {
isTouch = document.querySelector('html').classList.contains('touch');
init();
});