cod;nncode. learn. thrive.

React Dinosaur Game

Posted Dec 24, 2022

Welcome to the #react10 Day 6 challenge.

In this challenge we will develop a game which you might already had played in Google Chrome when internet gets disconnected, which is 'The Dino Game'. We will develop the same react Dinosaur game in this challenge using useRef, useEffect, useState hooks, setTimeout & setInterval.
You will learn how to manipulate css styling based on some JS conditions. And how to get react jsx elements using useRef.
I have written minimal code to create the game as per this challenge, obviously you can enhance the game by adding more features.

If you can change html element's styling based on some user event like button press or mouse click then you can call it a game.

Demo

Get Github Code

Pre-requisites

  • Code Editor (like VS Code)
  • React basic knowledge (as in this challenge we are not focusing on explaining about the react concepts)
  • Basic knowledge of HTML & CSS

Lets Begin!

Open terminal in the vs code and run these commands,

npx create-react-app dino-game
cd dino-game
npm start

After doing all of this, your UI would look like,

react dinosaur game

Run these commands in a new terminal (let the other terminal run our project),

mkdir src\components\Dino
type NUL > src\components\Dino\Dino.js
type NUL > src\components\Dino\Dino.css

Don't get confused with the above commands, you can also create files or folders using file explorer manually. Please also add 'trex.png' & 'cactus.png' in 'img' folder. You can get the images on any free website.

Folder Structure

Note - I have removed few files which 'create-react-app' util gives us by default.
You can also remove those but that is not mandatory step for this challenge.

react dinosaur game

Lets add some code

For better understanding, I have added few comments in the code itself.

Dino.js

import React, { useEffect, useRef, useState } from "react";
import "./Dino.css";

function Dino() {
  //ref to get 'dino' html element in js
  const dinoRef = useRef();
  //ref to get 'cactus' html element in js
  const cactusRef = useRef();
  const [score, setScore] = useState(0);

  //method to add 'jump' class every '300ms' as the class jump css has jumping animation of 0.3s(300ms).
  //so on each key press we need to add animation and remove animation
  const jump = () => {
    if (!!dinoRef.current && dinoRef.current.classList != "jump") {
      dinoRef.current.classList.add("jump");
      setTimeout(function () {
        dinoRef.current.classList.remove("jump");
      }, 300);
    }
  };

  //useEffect to track whether dino position and cactus position is intersecting
  //if yes, then game over.
  useEffect(() => {
    const isAlive = setInterval(function () {
      // get current dino Y position
      const dinoTop = parseInt(
        getComputedStyle(dinoRef.current).getPropertyValue("top")
      );

      // get current cactus X position
      let cactusLeft = parseInt(
        getComputedStyle(cactusRef.current).getPropertyValue("left")
      );

      // detect collision
      if (cactusLeft < 40 && cactusLeft > 0 && dinoTop >= 140) {
        // collision
        alert("Game Over! Your Score : " + score);
        setScore(0);
      } else {
        setScore(score + 1);
      }
    }, 10);

    return () => clearInterval(isAlive);
  });

  //hook to call jump method on any keypress
  useEffect(() => {
    document.addEventListener("keydown", jump);
    return () => document.removeEventListener("keydown", jump);
  }, []);

  return (
    <div className="game">
      Score : {score}
      <div id="dino" ref={dinoRef}></div>
      <div id="cactus" ref={cactusRef}></div>
    </div>
  );
}

export default Dino;

Dino.css

.game {
  width: 600px;
  height: 225px;
  border: 1px solid black;
  margin: auto;
}

#dino {
  width: 50px;
  height: 50px;
  background-image: url(img/trex.png);
  background-size: 50px 50px;
  position: relative;
  top: 150px;
}

.jump {
  animation: jump 0.3s linear;
}

@keyframes jump {
  0% {
    top: 150px;
  }

  30% {
    top: 130px;
  }

  50% {
    top: 80px;
  }

  80% {
    top: 130px;
  }

  100% {
    top: 150px;
  }
}

#cactus {
  width: 20px;
  height: 40px;
  position: relative;
  top: 110px;
  left: 580px;
  background-image: url("img/cactus.png");
  background-size: 20px 40px;
  animation: block 1s infinite linear;
}

@keyframes block {
  0% {
    left: 580px;
  }

  100% {
    left: -5px;
  }
}

App.js

import "./App.css";
import Dino from "./components/Dino/Dino";

function App() {
  return (
    <div className="App">
      <Dino />
    </div>
  );
}

export default App;

And that's it! You have created your own react Dinosaur Game.

Final UI

react dinosaur game

Enjoy your Game :)

Your feedback is our favorite notification! Share your thoughts about this page and make us smile.