Who's that Pokemon? Identify the Pokemon Game| HTML, CSS, JS

IDENTIFY THE POKEMON GAME. USING HTML, CSS, JS




Hey there guys, let me give you a small concept of how it works. Actually this works in such a way that you can select the type of trainer as you wish and at each level you will be provided with image of a pokemon and some options so that you can identify them easily. It is just a childish game. But it took me of around 2-3 hrs continuous effort on codepen. Made it as a self challenge. Ok enjoy yourself and comment your suggestions...



DEMO:


Click here to view full screen



Now let's jump right into the coding part. Here my ingredients are HTML, CSS(SCSS) and JavaScript(Babel).





HTML:



 <div id="app">
 <div
  :class="{'poke-classic': classic}"
  class="container"
 >
  <transition name="animate-section">
   <section 
    v-if="!isPlaying && !isDone" 
    class="poke-section"
   >
    <h2>What type of trainer are you?</h2>
    <div class="poke-intro-trainer">
     <div class="poke-ball"></div>
     <img 
      :class="{active: trainerHovered === 'classic'}"
      class="poke-trainer-img poke-trainer-img-classic"
      src="https://raw.githubusercontent.com/tiffachoo/pokesprites/master/trainers/red-rb.png" 
      alt="Trainer red"
     >
     <img 
      :class="{active: trainerHovered === 'master'}"
      class="poke-trainer-img poke-trainer-img-master"
      src="https://raw.githubusercontent.com/tiffachoo/pokesprites/master/trainers/red-sm.png" 
      alt="Trainer red again"
     >
    </div>
    <button 
     class="button spacer"
     @click="startGame(151)"
     @mouseover="trainerHover('classic')"
     @mouseout="trainerHover"
    >
     Classic
    </button>
    <button 
     class="button"
     @click="startGame(0)"
     @mouseover="trainerHover('master')"
     @mouseout="trainerHover"
    >
     Master
    </button>
   </section>
  </transition>
  
  <transition name="animate-section">
   <section
    v-if="isPlaying"
    class="poke-section"
   >
    <h1 class="poke-title">
     Who's that pokemon?
    </h1>
    <div class="poke-question-wrapper">
     <span class="poke-question">
      <span class="poke-question-number">
       {{ question }} 
      </span>
      <span class="poke-question-amount">
       / {{ questionAmount}}
      </span>
     </span>
     <span class="poke-score">
      {{ score }}
      <small>pts</small>
     </span>
     <div 
      class="poke-image"
      :class="{'poke-image-success': isChecked && selected.name === answer.name, 'poke-image-error': isChecked && selected.name !== answer.name}"
     >
      <img 
       :src="image" 
       alt="No cheating"
       class="poke-image-img"
      >
     </div>
     <transition-group 
      tag="div"
      name="animate-options"
      :class="{'poke-options-answers': isChecked}"
      class="poke-options"
     >
      <button 
       v-for="(pokemon, index) in options"
       :key="pokemon.name"
       :data-index="index"
       :class="{'selected': selected.index === index, 'success': isChecked && pokemon.name === answer.name , 'error': isChecked && selected.index === index && selected.name !== answer.name}"
       class="poke-options-button"
       @click="selectAnswer(pokemon.name, index)"
      >{{ pokemon.name | prettifyName }}</button>
     </transition-group>
     <footer class="poke-buttons">
      <button
       :disabled="isChecked || Object.keys(selected).length < 1"
       class="button"
       @click="checkAnswer"
      >Submit</button>
      <button 
       :disabled="!isChecked"
       class="button"
       @click="getNextQuestion"
      >Next</button>
     </footer>
    </div>
   </section>
  </transition>
  
  <transition name="animate-section">
   <section
    v-if="isDone"
    class="poke-final"
   >
    <h2>Final score</h2>
    <span class="poke-final-score">
     <span class="poke-final-score-number">{{ score }}</span>
     pts
    </span>
    <button 
     class="button"
     @click="restartGame"
    >Play again</button>
   </section>
  </transition>
 </>
</div>




CSS(SCSS):




@import 'https://fonts.googleapis.com/css?family=VT323';
$black: #333;
$white: #fff;

$primary-color: #f65a52;
$primary-color-dark: darken( $primary-color, 10% );
$primary-color-tint: lighten( $primary-color, 15% );
$primary-font: "VT323", monospace;

$secondary-color: #94acbd;
$secondary-color-dark: darken( $secondary-color, 10% );

$options-color: #c5d5ee;
$options-color-hover: darken( $options-color, 7% );
$success-color: #7bd55a;
$error-color: #ff8b62;

$border-radius-main: 1rem;
$border-width: 6px;
$border-main: solid $border-width $black;
$options-height: 48px;

* { box-sizing: border-box; }
body {
 background-color: $primary-color;
 font-family: $primary-font;
 font-size: 16px;
 line-height: 1.875em;
 color: $black;
}

.container {
 width: 100%;
 max-width: 400px;
 position: relative;
 margin: 50px auto;
}

h2 {
 font-size: 1.25rem;
 white-space: nowrap;
}

.spacer {
 margin-bottom: 0.5rem;
}

.button {
 padding: 0.5em 1.5em;
 border-radius: $border-radius-main;
 border: solid 1px transparent;
 font-family: $primary-font;
 font-size: 1.5rem;
 background-color: $primary-color-dark;
 color: $black;
 cursor: pointer;
 transition: 0.35s;
  
 &:focus {
  outline: none;
  border: 1px dotted lighten($primary-color, 8%);
 }
 
 &:not([disabled]) {
  &:hover {
   background-color: $black;
   color: $primary-color;
  }
 }
}

.poke-section {
 display: flex;
 flex-direction: column;
 align-items: center;
 position: relative;
 max-width: 500px;
 margin: auto;
}

.poke-intro-trainer {
 position: relative;
 margin-bottom: 1rem;
 height: 200px;
 width: 200px;
 
 .poke-trainer-img {
  position: absolute;
  left: 50%;
  bottom: 0;
  height: 200px;
  opacity: 0;
  transition: 0.4s cubic-bezier(.22,.75,.53,.99);
  
  @media (max-width: 479px) {
   display: none;
  }
   
  &.active {
   transform: translateX(-50%);
   opacity: 1;
  }
  
  &-classic {
   bottom: 5px;
   height: 180px;
   image-rendering: pixelated;
   transform: translateX(-80%);
  }
  
  &-master {
   transform: translateX(-20%);
  }
 }
}

.poke-ball {
 position: absolute;
 top: 50%;
 left: 50%;
 height: 150px;
 width: 150px;
 border-radius: 50%;
 background-color: $primary-color-dark;
 transform: translate(-50%, -50%);
 overflow: hidden;
 
 &::before,
 &::after {
  content: '';
  position: absolute;
 }
 
 &::before {
  z-index: 2;
  top: 50%;
  left: 50%;
  height: 40px;
  width: 40px;
  border-radius: 50%;
  border: solid $border-width $primary-color;
  background-color: $primary-color-tint;
  transform: translate(-50%, -50%);
 }
 
 &::after {
  z-index: 1;
  top: 50%;
  height: 50%;
  width: 100%;
  border-top: solid $border-width $primary-color;
  background-color: $primary-color-tint;
 }
}

.poke-title {
 position: absolute;
 top: -2rem;
}

.poke-question {
 position: absolute;
 right: calc(100% + 0.5rem);
 display: flex;
 flex-direction: column;
 align-items: flex-end;
 
 &-wrapper {
  position: relative;
  width: 250px;
 }
 
 &-number {
  font-size: 8rem;
  line-height: 0.4;
  color: $primary-color-tint;
 }
}

.poke-score {
 position: absolute;
 top: 6rem;
 right: calc(100% + 0.5rem);
 padding-top: 1rem;
 font-size: 1.25rem;
 white-space: nowrap;
 color: $black;
 
 &::before {
  content: '';
  position: absolute;
  top: 0;
  right: 0;
  width: 40px;
  height: $border-width;
  background-color: $black;
 }
}

.poke-image {
 position: relative;
 z-index: 2;
 display: flex;
 justify-content: center;
 align-items: center;
 width: 250px;
 height: 250px;
 border-radius: $border-radius-main;
 border: $border-main;
 background-color: $white;
 overflow: hidden;
 
 &::before,
 &::after {
  content: '';
  position: absolute;
  z-index: -1;
  border-radius: 50%;
 }
 
 &::before {
  width: 100px;
  height: 100px;
  background-color: $options-color;
  opacity: 1;
  transition: 0.65s ease-in-out;
 }
 
 &::after {
  width: 100px;
  height: 100px;
  border: solid ($border-width * 2) $options-color;
  transform: scale(0);
  transition: 0.4s ease-in-out;
 }
 
 &-img {
  width: auto;
  height: 150px;
 }
 
 &-success,
 &-error {
  &::before {
   transform: scale(4);
   opacity: 0.5;
  }
  
  &::after {
   transform: scale(1);
  }
 }
 
 &-success {
  &::before {
   background-color: $success-color;
  }
  
  &::after {
   border-color: $success-color;
  }
 }
 
 &-error {
  &::before {
   background-color: $error-color;
  }
  
  &::after {
   border-color: $error-color;
   width: 10px;
   border-radius: $border-radius-main;
   transform: rotate(45deg);
  }
 }
}

.poke-options {
 position: relative;
 display: flex;
 flex-direction: column;
 align-items: center;
 z-index: 3;
 top: -30px;
 padding: 0 20px;
 margin: 0 auto;
 width: 170px;
 border-radius: $border-radius-main;
 background-color: $black;
 
 &:not(.poke-options-answers) {
  .poke-options-button {
   &:not(.selected) {
    &:hover {
     background-color: $options-color-hover;
     // color: $primary-color-dark;
     transform: translateY(-$border-width / 2);
    }
  
    &:active {
     &::before {
      transform: translate(-50%, -50%) scale(1);
     }
    }
   }
  }
 }
 
 &.poke-options-answers {
  .poke-options-button {
   cursor: default;
   
   &:not(.error):not(.success) {
    color: $secondary-color;
   }
  }
 }
 
 &-button {
  position: relative;
  width: 100%;
  padding: 0.5em;
  min-width: 200px;
  max-height: $options-height;
  border: $border-main;
  border-radius: $border-radius-main;
  background-color: $options-color;
  font-family: $primary-font;
  font-size: 1.125rem;
  transition: 0.45s;
  cursor: pointer;
  overflow: hidden;
  
  &:focus {
   outline: none;
  }
  
  &::before {
   content: '';
   position: absolute;
   z-index: -1;
   left: 50%;
   top: 50%;
   height: 200px;
   width: 200px;
   border-radius: 50%;
   background-color: $secondary-color;
   transform: translate(-50%, -50%) scale(0);
   transition: 0.2s ease-in-out;
  }
  
  &:not(:last-child) {
   margin-bottom: $border-width / 2;
  }

  &.selected {
   background-color: $secondary-color;
  }
  
  &.error {
   background-color: $error-color;
  }
  
  &.success {
   background-color: $success-color;
  }
 }
}

.poke-buttons {
 text-align: center;
 
 @media (min-width: 480px) {
  position: absolute;
  top: 20px;
  left: 100%;
  
  .button {
   padding-left: calc(1em + 10px);
   border-top-left-radius: 0;
   border-bottom-left-radius: 0;
   transform: translateX(-10px);
  }
 }
 
 .button {
  padding: 1em;
  width: 110px;
  height: 100px;
  color: $white;
  
  &[disabled] {
   color: $primary-color-tint;
   opacity: 0.7;
   cursor: default;
  }
  
  &:not([disabled]) {
   &:hover {
    transform: translateX(0);
   }
  }
  
  &:not(:last-child) {
   margin-bottom: $border-width;
  }
 }
}

.poke-final {
 text-align: center;
 
 &-score {
  display: block;
  position: relative;
  margin-bottom: 1rem;
 
  &::before {
   content: '';
   position: absolute;
   z-index: -1;
   top: 50%;
   left: 50%;
   height: 100px;
   width: 100px;
   border-radius: 50%;
   border: solid ($border-width * 2) $primary-color-dark;
   transform: translate(-50%, -50%);
   opacity: 0.3;
   animation: grow 2s infinite ease-in-out;
  }
  
  &-number {
   font-size: 8rem;
   line-height: 0.4;
   color: $primary-color-tint;
  }
 }
}

.poke-classic {
 .poke-image {
  &-img {
   image-rendering: pixelated;
  }
 }
}

.animate-section {
 &-enter-active,
 &-leave-active {
  transition: 0.4s ease-in-out;
 }

 &-enter,
 &-leave-to {
  opacity: 0;
 }
 
 &-enter {
  .poke-final-score-number {
   transform: translateY(-30px);
  }
 }
 
 &-leave-active {
  transform: translateX(-30%);
 }

 &-enter-active {
  transition-delay: 0.1s;
  position: absolute;
  top: 0;
  left: 50%;
  transform: translateX(-50%);
 }
}

.animate-options {
 &-enter-active {
  transition: 0.4s ease-in-out;
  
  @for $i from 4 through 8 {
   &:nth-child(#{$i}) {
    transition-delay: 0.2s * ($i - 4);
   }
  }
 }
 
 &-enter {
  transform: rotateX(-45deg);
  transform-origin: top center;
  opacity: 0;
 }
 
 &-leave-active {
  position: absolute;
  z-index: -1;
  transition: 0.8s ease-in-out;
  
  // @for $i from 0 through 3 {
  //  $child: $i + 1;
  //  &:nth-child(#{$child}) {
  //   top: ($options-height + $border-width / 2) * $i;
  //  }
  // }
  
  &[data-index="0"] {
   top: 0;
  }
  
  &[data-index="1"] {
   top: ($options-height + $border-width / 2);
  }
  
  &[data-index="2"] {
   top: ($options-height + $border-width / 2) * 2;
  }
  
  &[data-index="3"] {
   top: ($options-height + $border-width / 2) * 3;
  }
 }
 
 &-leave-to {
  opacity: 0;
 }
}

@keyframes grow {
 0%, 100% { transform: translate(-50%, -50%) scale(1) }
 50% { transform: translate(-50%, -50%) scale(0.6) }
}



JAVASCRIPT:




console.clear();

const pkmnTotal = 802;
const url = `https://pokeapi.co/api/v2/pokemon/?limit=${pkmnTotal}`;
const optionAmount = 4;
let pokemonData = [];
const prettyNames = {
 'nidoran-f': 'nidoran♀',
 'nidoran-m': 'nidoran♂',
 'mr-mime': 'mr. mime',
 'deoxys-normal': 'deoxys',
 'wormadam-plant': 'wormadam',
 'mime-jr': 'mime jr.',
 'giratina-altered': 'giratina',
 'shaymin-land': 'shaymin',
 'basculin-red-striped': 'basculin',
 'darmanitan-standard': 'darmanitan',
 'tornadus-incarnate': 'tornadus',
 'thundurus-incarnate': 'thundurus',
 'landorus-incarnate': 'landorus',
 'keldeo-ordinary': 'keldeo',
 'meloetta-aria': 'meloetta',
 'meowstic-male': 'meowstic',
 'aegislash-shield': 'aegislash',
 'pumpkaboo-average': 'pumpkaboo',
 'gourgeist-average': 'gourgeist',
 'oricorio-baile': 'oricorio',
 'lycanroc-midday': 'lycanroc',
 'wishiwashi-solo': 'wishiwashi',
 'type-null': 'type: null',
 'minior-red-meteor': 'minior',
 'mimikyu-disguised': 'mimikyu',
 'tapu-koko': 'tapu koko',
 'tapu-lele': 'tapu lele',
 'tapu-bulu': 'tapu bulu',
 'tapu-fini': 'tapu fini'
}

const app = new Vue({
 el: '#app',
 filters: {
  prettifyName(name) {
   return prettyNames[name] || name;
  }
 },
 data() {
  return {
   pokemon: [],
   pkmnAmount: null,
   score: 0,
   question: 0,
   questionAmount: 10,
   answer: {},
   selected: {},
   options: [],
   isPlaying: false,
   isDone: false,
   isChecked: false,
   trainerHovered: null
  }
 },
 computed: {
  image() {
   let url = 'https://raw.githubusercontent.com/tiffachoo/pokesprites/master/pokemon/'
   let imageUrl = `${url}${this.classic ? 'redblue' : 'sunmoon'}/`
   let number = this.answer.url.match(/\/(\d+)/)[1];
   return `${imageUrl}${number}.png`
  },
  classic() {
   return this.pkmnAmount <= 151
  }
 },
 mounted() {
  let pokeList = localStorage.getItem('pokeList');
  
  if (pokeList) {
   pokemonData = JSON.parse(pokeList);
  } else {
   this.getData()
    .then(res => {
     pokemonData = res.results
     localStorage.setItem('pokeList', JSON.stringify(res.results));
   });
  }
 },
 methods: {
  getData() {
   return fetch(url)
    .then(res => res.json())
    .catch(err => console.log('errrr'));
  },
  startGame(val) {
   this.question = 0;
   this.score = 0;
   this.isPlaying = true;
   this.pokemon = [...pokemonData];
   
   this.pkmnAmount = val || pkmnTotal;
   
   this.getNextQuestion();
  },
  getNextQuestion() {
   this.question += 1;
   this.resetAnswer();
   
   if (this.question <= this.questionAmount) {
    let removed = '';
    for (let i = 1; i <= optionAmount; i++) {
     removed = this.pokemon.splice(this.getRandomPokemon(i), 1)[0];
     if (i === 1) {
      this.answer = removed;
     } else {
      this.options.push(removed);
     }
    }

    let pos = Math.floor(Math.random() * optionAmount);
    this.options.splice(pos, 0, this.answer);
   } else {
    this.isPlaying = false;
    this.isDone = true;
    this.resetAnswer();
   }
  },
  selectAnswer(ans, index) {
   if (!this.isChecked) {
    this.$set(this.selected, 'name', ans);
    this.$set(this.selected, 'index', index);
   }
  },
  checkAnswer() {
   this.isChecked = true;
   
   if (this.selected.name === this.answer.name) {
    this.score += 10;
   }
  },
  getRandomPokemon(index) {
   const diff = (this.question - 1) * 4 + index;
   return Math.floor(Math.random() * (this.pkmnAmount + 1 - diff));
  },
  resetAnswer() {
   this.options = [];
   this.selected = {};
   this.answer = {};
   this.isChecked = false;
  },
  restartGame() {
   this.isDone = false;
  },
  trainerHover(val) {
   this.trainerHovered = val;
  }
 }
})



Hope you enjoyed it guys..Give your time then you can see Miracles happening...

HAPPY CODING.

No comments:

Powered by Blogger.