Skip to content

AnneQuinkenstein/game_night

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

GAME NIGHT


Logo

Game Night is to have fun alone or with friends, even through a pandemic. Play a hangman game with movie titles in your favorite Language! (choosen from popular movies on OMDBApi & see the poster passed from themoviedb.org) For each wrong guess a associated giphy (fetched from Giphy API) is revealed - failure is not bad đź‘ľ
I used React Context to pass the logic of the game. I did some animations utilizing SCSS - will you find an easteregg? With Formspree the Input of the Contactform is sent to my Email.

Demo · Report Bug

Built With

Special Gotchas

Design

I started with the idea: a gameing site to have fun alone or with friends in an easy way during lockdown of Covid19. I choosed to do Hangman, which is commenly known and easy to learn even if you don't know it yet. With games you can create an atmosephere of a specifiy world - i utilized movies for the athmosphere in hangman, retro arcade athetics for the home page and retro monitor athetics for the contact page.

Wireframe

Royalty free Pics

Icons

Entrance Animation

Background-Pic

Look at a sign at the wall and if you click on the font, reach the entrance

  1. scale pic to show the wall,
  2. onclick: scale pic to cover whole Screen
.entranceBackground {
  background-image: url(arcadeEntrance.jpg);
  background-color: black;
  background-size: cover;
  background-repeat: no-repeat;
  animation-name: divMove;
  animation-duration: 5s;
  animation-timing-function: ease-in-out;
  animation-iteration-count: 1;
  animation-fill-mode: forwards;
}

@keyframes divMove {
  0% {
    height: calc(1000px + 100vh);
    background-position-x: right;
    background-position-y: -50vh;
  }
  100% {
    height: 100vh;
    width: 100vw;
    background-position: center;
  }
}

Flickering Font on the Sign

CSS Keyframes

animation: shine 2s forwards, flicker 3s infinite;
@keyframes blink {
  0%,
  45%,
  75% {
    color: $white;
    text-shadow: 0 0 0.6rem $white, 0 0 1.5rem #a6a4d6,
      -0.2rem 0.1rem 1rem #9692e6, 0.2rem 0.1rem 1rem #8480e9,
      0 -0.5rem 2rem #615be1, 0 0.5rem 3rem $purple;
  }
  28%,
  35% {
    color: #8480e9;
    text-shadow: none;
  }
  82%,
  99% {
    color: hsla(234, 77%, 53%, 0.363);
    text-shadow: none;
  }
}

@keyframes shine {
  0% {
    color: $darkred;
    text-shadow: none;
  }
  100% {
    color: $white;
    text-shadow: 0 0 1.1rem $white, 0 0 2rem #a6a4d6,
      -0.2rem 0.1rem 1.5rem #9692e6, 0.2rem 0.1rem 1.5rem #8480e9,
      0 -0.5rem 2.5rem #615be1, 0 0.5rem 3.5rem $purple;
  }
}

Font is aligned to the wall using

  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%) rotateX(8deg) rotateZ( -2deg) skewY(-0.5deg);
  perspective-origin: 150% 150%;

Easteregg

On the right wall, there is a flickering light. If you hover over ist, you will see a developer joke from Joke API

Menu

Pacman ghosts flying in using CSS Keyframes

Hangman Logic

APIs

get Movie-Data

Objective: get a reliable lists of popular movies from imdb-api & the fetch the infos for each movie more reliable from the moviedb.org

  1. render fetch-calls on first render (ex componentDidMount())
  2. render fetch-calls if [choosenLang, style, setGameState, phone, render] is changing

-fetch-calls

  1. fetch popular movies from imdb-api.com
  2. select one Movie from popluar Movie array
  • get a random number const randomNum = Math.floor(Math.random() * 90);
    as index of popular Movie array ${movie.items[randomNum].id}
  1. fetch movie infos and movie poster from themoviedb.org

Obejective: Don't display Movies longer then 25 charaters because of the screen size

  • check lenght of movie title with terenary operator data.title.length < 25 ? setMovieData(data) : setRender(!render) if length is more then 25 letters, fetch a new title

  • check with media query phone the screen-width: import { useMediaPredicate } from "react-media-hook"; if phone then movietitle should be < 10;

  useEffect(() => {
    const getMovie = () => {
      fetch(
        `https://imdb-api.com/en/API/MostPopularMovies/${process.env.REACT_APP_IMDB_KEY}`
      )
        .then((res) => res.json())
        .then((data) => setMovie(data))
        .catch((err) => console.log("Error fetching and parsing data", err));
    };
    getMovie();

    const randomNum = Math.floor(Math.random() * 90);
    const getMovieData = () => {
      if (!phone) {
        if (movie && movie.items.length > 0) {
          fetch(
            `https://api.themoviedb.org/3/movie/${movie.items[randomNum].id}?api_key=${process.env.REACT_APP_MOVIEDB_KEY}&language=${languages[choosenLang]}`
          )
            .then((res) => res.json())
            .then((data) =>
              data.title.length < 25 ? setMovieData(data) : setRender(!render)
            );
        } else {
          fetch(
            `https://api.themoviedb.org/3/movie/${items[randomNum].id}?api_key=${process.env.REACT_APP_MOVIEDB_KEY}&language=${languages[choosenLang]}`
          )
            .then((res) => res.json())
            .then((data) =>
              data.title.length < 25 ? setMovieData(data) : setRender(!render)
            );
        }
      } else {
        if (movie && movie.items.length > 0) {
          fetch(
            `https://api.themoviedb.org/3/movie/${movie.items[randomNum].id}?api_key=${process.env.REACT_APP_MOVIEDB_KEY}&language=${languages[choosenLang]}`
          )
            .then((res) => res.json())
            .then((data) =>
              data.title.length < 10 ? setMovieData(data) : setRender(!render)
            );
        } else {
          fetch(
            `https://api.themoviedb.org/3/movie/${items[randomNum].id}?api_key=${process.env.REACT_APP_MOVIEDB_KEY}&language=${languages[choosenLang]}`
          )
            .then((res) => res.json())
            .then((data) =>
              data.title.length < 10 ? setMovieData(data) : setRender(!render)
            );
        }
      }
    };
    getMovieData();
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [choosenLang, style, setGameState, phone, render]);

Contact

Let's connect!