Flappy Bird Juego en JavaScript

Flappy Bird es un juego sin fin que involucra a un pájaro que el jugador puede controlar. El jugador tiene que evitar que el pájaro choque con los obstáculos como tuberías. Cada vez que el pájaro pasa por las tuberías, la puntuación se incrementa en uno. El juego termina cuando el pájaro choca con las tuberías o cae por la gravedad. Las siguientes secciones describen los pasos que deben seguirse para construir este juego.

Sección HTML: En esta sección se crean y cargan los elementos del juego. Se seleccionan las imágenes para el fondo, el pájaro, los obstáculos y los elementos de puntuación. A continuación, creamos y vinculamos el archivo style.css e index.js.

HTML

<!DOCTYPE html>
<html>
  
<head>
    <link rel="stylesheet" href="style.css">
</head>
  
<body>
    <div class="background"></div>
    <img class="bird" src="logo.png" alt="bird-img">
    <div class="message">
        Press Enter To Start Game
    </div>
    <div class="score">
        <span class="score_title"></span>
        <span class="score_val"></span>
    </div>
    <script src="gfg.js"></script>
</body>
  
</html>

Sección CSS: en esta sección, el tamaño, la posición y el estilo de los objetos del juego se modifican según las necesidades.

CSS

* {
    margin: 0;
    padding: 0;
    box-sizing: border-box;
}
  
body {
    height: 100vh;
    width: 100vw;
}
  
.background {
    height: 100vh;
    width: 100vw;
    background-color: skyblue;
}
  
.bird {
    height: 100px;
    width: 160px;
    position: fixed;
    top: 40vh;
    left: 30vw;
    z-index: 100;
}
  
.pipe_sprite {
    position: fixed;
    top: 40vh;
    left: 100vw;
    height: 70vh;
    width: 6vw;
    background-color: green;
}
  
.message {
    position: fixed;
    z-index: 10;
    height: 10vh;
    font-size: 10vh;
    font-weight: 100;
    color: black;
    top: 12vh;
    left: 20vw;
    text-align: center;
}
  
.score {
    position: fixed;
    z-index: 10;
    height: 10vh;
    font-size: 10vh;
    font-weight: 100;
    color: goldenrod;
    top: 0;
    left: 0;
}
  
.score_val {
    color: gold;
}

Sección de JavaScript: esta sección contiene la parte del código que controla el estado del juego y los objetos en movimiento. En este apartado se deben seguir los siguientes pasos.

  • Obtenga una referencia al pájaro y la imagen de fondo en el archivo JavaScript.
  • Establezca algunos valores para la velocidad de desplazamiento de fondo, la velocidad de vuelo del ave y la gravedad.
  • Crea el fondo de desplazamiento infinito. Una guía para hacer esto se puede leer desde este enlace.
  • Agregue un detector de eventos para escuchar la pulsación de la tecla «enter» para cambiar el estado del juego al estado de juego y aplicar gravedad al ave al disminuir el valor de gravedad de la coordenada y del ave en cada cuadro.
  • Genere obstáculos (tuberías) al final del ancho de la vista para que no sean visibles inicialmente, pero a medida que se mueve el fondo, disminuya la coordenada x de la tubería por el valor de desplazamiento del fondo para que parezca que el pájaro se está moviendo.
  • Aplique la colisión con el suelo y las tuberías y, si el pájaro choca, cambie el estado del juego al estado final y muestre un mensaje para reiniciar el juego.
  • Incrementa el valor de la puntuación después de cada navegación exitosa entre las tuberías.

JavaScript

// Background scrolling speed
let move_speed = 3;
    
// Gravity constant value
let gravity = 0.5;
    
// Getting reference to the bird element
let bird = document.querySelector('.bird');
    
// Getting bird element properties
let bird_props = bird.getBoundingClientRect();
let background =
    document.querySelector('.background')
            .getBoundingClientRect();
    
// Getting reference to the score element
let score_val =
    document.querySelector('.score_val');
let message =
    document.querySelector('.message');
let score_title =
    document.querySelector('.score_title');
    
// Setting initial game state to start
let game_state = 'Start';
    
// Add an eventlistener for key presses
document.addEventListener('keydown', (e) => {
    
  // Start the game if enter key is pressed
  if (e.key == 'Enter' &&
      game_state != 'Play') {
    document.querySelectorAll('.pipe_sprite')
              .forEach((e) => {
      e.remove();
    });
    bird.style.top = '40vh';
    game_state = 'Play';
    message.innerHTML = '';
    score_title.innerHTML = 'Score : ';
    score_val.innerHTML = '0';
    play();
  }
});
function play() {
  function move() {
      
    // Detect if game has ended
    if (game_state != 'Play') return;
      
    // Getting reference to all the pipe elements
    let pipe_sprite = document.querySelectorAll('.pipe_sprite');
    pipe_sprite.forEach((element) => {
        
      let pipe_sprite_props = element.getBoundingClientRect();
      bird_props = bird.getBoundingClientRect();
        
      // Delete the pipes if they have moved out
      // of the screen hence saving memory
      if (pipe_sprite_props.right <= 0) {
        element.remove();
      } else {
        // Collision detection with bird and pipes
        if (
          bird_props.left < pipe_sprite_props.left +
          pipe_sprite_props.width &&
          bird_props.left +
          bird_props.width > pipe_sprite_props.left &&
          bird_props.top < pipe_sprite_props.top +
          pipe_sprite_props.height &&
          bird_props.top +
          bird_props.height > pipe_sprite_props.top
        ) {
            
          // Change game state and end the game
          // if collision occurs
          game_state = 'End';
          message.innerHTML = 'Press Enter To Restart';
          message.style.left = '28vw';
          return;
        } else {
          // Increase the score if player
          // has the successfully dodged the 
          if (
            pipe_sprite_props.right < bird_props.left &&
            pipe_sprite_props.right + 
            move_speed >= bird_props.left &&
            element.increase_score == '1'
          ) {
            score_val.innerHTML = +score_val.innerHTML + 1;
          }
          element.style.left = 
            pipe_sprite_props.left - move_speed + 'px';
        }
      }
    });
  
    requestAnimationFrame(move);
  }
  requestAnimationFrame(move);
  
  let bird_dy = 0;
  function apply_gravity() {
    if (game_state != 'Play') return;
    bird_dy = bird_dy + gravity;
    document.addEventListener('keydown', (e) => {
      if (e.key == 'ArrowUp' || e.key == ' ') {
        bird_dy = -7.6;
      }
    });
  
    // Collision detection with bird and
    // window top and bottom
  
    if (bird_props.top <= 0 ||
        bird_props.bottom >= background.bottom) {
      game_state = 'End';
      message.innerHTML = 'Press Enter To Restart';
      message.style.left = '28vw';
      return;
    }
    bird.style.top = bird_props.top + bird_dy + 'px';
    bird_props = bird.getBoundingClientRect();
    requestAnimationFrame(apply_gravity);
  }
  requestAnimationFrame(apply_gravity);
  
  let pipe_seperation = 0;
    
  // Constant value for the gap between two pipes
  let pipe_gap = 35;
  function create_pipe() {
    if (game_state != 'Play') return;
      
    // Create another set of pipes
    // if distance between two pipe has exceeded
    // a predefined value
    if (pipe_seperation > 115) {
      pipe_seperation = 0
        
      // Calculate random position of pipes on y axis
      let pipe_posi = Math.floor(Math.random() * 43) + 8;
      let pipe_sprite_inv = document.createElement('div');
      pipe_sprite_inv.className = 'pipe_sprite';
      pipe_sprite_inv.style.top = pipe_posi - 70 + 'vh';
      pipe_sprite_inv.style.left = '100vw';
        
      // Append the created pipe element in DOM
      document.body.appendChild(pipe_sprite_inv);
      let pipe_sprite = document.createElement('div');
      pipe_sprite.className = 'pipe_sprite';
      pipe_sprite.style.top = pipe_posi + pipe_gap + 'vh';
      pipe_sprite.style.left = '100vw';
      pipe_sprite.increase_score = '1';
        
      // Append the created pipe element in DOM
      document.body.appendChild(pipe_sprite);
    }
    pipe_seperation++;
    requestAnimationFrame(create_pipe);
  }
  requestAnimationFrame(create_pipe);
}

Producción:

Publicación traducida automáticamente

Artículo escrito por vivshubham y traducido por Barcelona Geeks. The original can be accessed here. Licence: CCBY-SA

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *