Whack a Dino(Game) | Made of HTML, CSS and JavaScript
Whack a Dino(Game) | Made of HTML, CSS and JavaScript
Whack a Dino |
Hey guys, in this post i am here with a Simple game that most of us has played many years ago. Here i tried to make such a game using my favourite languages HTML, CSS and JavaScript. Ok first of all Enjoy the game and then we can move into the coding section where the magic happened.
RESULT:
Now let's jump right into the coding section.
HTML:
<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>
CSS(SCSS):
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; }
JavaScript:
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(); });
Hope you guys enjoyed it.
“That's the thing about people who think they hate computers. What they really hate is lousy programmers.”
―
No comments: