Construyendo un juego de rompecabezas con arrastre y soltar en React

JavaScriptBeginner
Practicar Ahora

Introducción

En este proyecto, crearemos un juego de rompecabezas con arrastrar y soltar utilizando React. Este es un excelente proyecto para que los principiantes aprendan sobre los componentes de React, la gestión del estado y el manejo de interacciones de usuario. Al final de este proyecto, tendrás un juego de rompecabezas funcional.

👀 Vista previa

Animación de vista previa del juego de rompecabezas

🎯 Tareas

En este proyecto, aprenderás:

  • Cómo configurar una nueva aplicación de React
  • Cómo crear el componente principal del juego de rompecabezas
  • Cómo gestionar el estado y configurar la imagen del rompecabezas
  • Cómo mostrar las piezas del rompecabezas en la pantalla
  • Cómo implementar la funcionalidad de arrastrar y soltar
  • Cómo integrar el componente PuzzleGame en el archivo principal de la aplicación
  • Cómo agregar CSS para dar estilo al rompecabezas

🏆 Logros

Después de completar este proyecto, podrás:

  • Configurar una aplicación de React y crear un componente
  • Gestionar el estado y manejar las interacciones de usuario
  • Implementar la funcionalidad de arrastrar y soltar
  • Incorporar estilos para que el rompecabezas sea visualmente atractivo

Configuración del proyecto

Objetivo: La base de nuestro juego de rompecabezas es una nueva aplicación de React.

  • Abra su terminal.

  • Navegue hasta el directorio de su proyecto:

    cd puzzle-game
  • Instale las dependencias del proyecto:

    npm install
✨ Revisar Solución y Practicar

Crear el componente PuzzleGame

Objetivo: Configurar el componente principal del juego de rompecabezas.

  • Dentro del directorio src, cree una carpeta llamada components.
  • Dentro de components, cree un nuevo archivo llamado PuzzleGame.js.
  • Agregue la siguiente estructura básica a PuzzleGame.js:
// src/components/PuzzleGame.js
// Importando React y useState para manejar el estado del componente
import React, { useState, useEffect } from "react";

// Definiendo el componente PuzzleGame
const PuzzleGame = () => {
  // Este componente manejará la lógica del juego y la interfaz de usuario
  return (
    <div className="game-container">
      {/* Aquí es donde se renderizará el rompecabezas */}
    </div>
  );
};

// Exportando el componente para su uso en otros archivos
export default PuzzleGame;
✨ Revisar Solución y Practicar

Implementar el estado y la configuración de la imagen

Objetivo: Configurar el estado para gestionar las piezas del rompecabezas y definir la imagen del rompecabezas.

  • En PuzzleGame.js, importe useState de React.
  • Defina una variable de estado para controlar las posiciones de las piezas del rompecabezas.
  • Defina la URL de la imagen del rompecabezas (coloque una imagen llamada corgi.png en la carpeta public).
// src/components/PuzzleGame.js

//...otros imports
const PuzzleGame = () => {
  // Defina la URL de la imagen y las posiciones iniciales de las piezas del rompecabezas
  const imgUrl = "corgi.png"; // Asegúrese de que esta imagen exista en la carpeta public
  const [positions, setPositions] = useState([...Array(16).keys()]);

  useEffect(() => {
    // Mezcle las posiciones para la configuración inicial del rompecabezas
    setPositions((prevPositions) => {
      const newPos = [...prevPositions];
      newPos.sort(() => Math.random() - 0.5);
      return newPos;
    });
  }, []);

  // Sentencia de retorno del componente
  return (
    <div className="game-container">
      {/* La interfaz de usuario del rompecabezas se agregará aquí en pasos posteriores */}
    </div>
  );
};

// Exportando el componente PuzzleGame
export default PuzzleGame;
✨ Revisar Solución y Practicar

Renderizar piezas del rompecabezas

Objetivo: Mostrar las piezas del rompecabezas en la pantalla.

  • Recorra el estado positions para renderizar las piezas individuales del rompecabezas.
  • Cada pieza debe mostrar una porción de la imagen.
// src/components/PuzzleGame.js
const PuzzleGame = () => {
  //...código anterior

  return (
    <div className="game-container">
      <div className="reference-image">
        <img src={imgUrl} alt="Imagen de referencia" />
      </div>
      <div className="puzzle-container">
        {positions.map((pos, index) => {
          const x = (pos % 4) * 100;
          const y = Math.floor(pos / 4) * 100;
          return (
            <div
              key={index}
              className="puzzle-piece"
              style={{
                backgroundImage: `url('${imgUrl}')`,
                backgroundPosition: `-${x}px -${y}px`
              }}
            />
          );
        })}
      </div>
    </div>
  );
};
✨ Revisar Solución y Practicar

Agregar funcionalidad de arrastrar y soltar

Objetivo: Implementar la lógica para arrastrar y soltar las piezas del rompecabezas.

  • Agregar manejadores para los eventos de inicio de arrastre, arrastre sobre y soltar.
  • Implementar la lógica para intercambiar las piezas del rompecabezas cuando se suelta.
// src/components/PuzzleGame.js

const PuzzleGame = () => {
  //...código anterior

  // Manejando el inicio de un evento de arrastre
  const handleDragStart = (e, position) => {
    e.dataTransfer.setData("text/plain", position);
  };

  // Manejando el evento de soltar
  const handleDrop = (e, position) => {
    e.preventDefault();
    const originalPosition = e.dataTransfer.getData("text");
    // Agregar lógica aquí para intercambiar las posiciones de las piezas del rompecabezas
    setPositions((prevPositions) => {
      const newPos = [...prevPositions];
      [newPos[originalPosition], newPos[position]] = [
        newPos[position],
        newPos[originalPosition]
      ];
      return newPos;
    });
  };

  // Permitiendo la acción de soltar evitando el comportamiento predeterminado
  const handleDragOver = (e) => {
    e.preventDefault();
  };

  // Renderizar piezas del rompecabezas con manejadores de arrastre y soltar agregados
};
// src/components/PuzzleGame.js
const PuzzleGame = () => {
  //...código anterior

  return (
    <div className="game-container">
      <div className="reference-image">
        <img src={imgUrl} alt="Imagen de referencia" />
      </div>
      <div className="puzzle-container">
        {positions.map((pos, index) => {
          const x = (pos % 4) * 100;
          const y = Math.floor(pos / 4) * 100;
          return (
            <div
              key={index}
              className="puzzle-piece"
              draggable
              onDragStart={(e) => handleDragStart(e, index)}
              onDrop={(e) => handleDrop(e, index)}
              onDragOver={handleDragOver}
              style={{
                backgroundImage: `url('${imgUrl}')`,
                backgroundPosition: `-${x}px -${y}px`
              }}
            />
          );
        })}
      </div>
    </div>
  );
};
✨ Revisar Solución y Practicar

Actualizar el componente App

Objetivo: Incorporar el componente PuzzleGame en el archivo principal de la aplicación.

  • Abra src/App.js.
  • Renderice el componente PuzzleGame.
// src/App.js

import React from "react";
import "./App.css";
import PuzzleGame from "./components/PuzzleGame";

// Componente App que renderiza el componente PuzzleGame
function App() {
  return (
    <div className="App">
      <PuzzleGame />
    </div>
  );
}

export default App;
✨ Revisar Solución y Practicar

Dar estilo al rompecabezas

Objetivo: Agregar CSS para que el rompecabezas sea visualmente atractivo.

  • Abra src/App.css.
  • Agregue estilos para .game-container y .puzzle-piece para colocar correctamente el rompecabezas.
body {
  font-family: "Arial", sans-serif;
  text-align: center;
  padding: 20px;
  background: #f0f0f0;
}

.game-container {
  display: flex;
  justify-content: center;
  align-items: flex-start;
  gap: 20px;
}

.reference-image {
  display: flex;
  align-items: center;
  justify-content: center;
  border: 3px solid #aaa9a9;
  /* Agregar un borde para consistencia */
  padding: 10px;
  /* Agregar un poco de relleno alrededor de la imagen */
  box-shadow: 0 4px 8px rgba(0, 0, 0, 0.2);
  /* Agregar sombreado para dar profundidad */
}

.reference-image img {
  display: block;
  /* Quitar cualquier espacio en línea predeterminado */
  max-width: 200px;
}

.puzzle-container {
  width: 400px;
  height: 400px;
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 2px;
  border: 5px solid #aaa9a9;
  box-shadow: 0 8px 16px rgba(0, 0, 0, 0.3);
  /* Agregar un sombreado más grande para un efecto tridimensional */
  background: #ddd;
  /* Fondo claro para los espacios */
}

.puzzle-piece {
  width: 100%;
  height: 100%;
  background-size: 400px 400px;
  cursor: grab;
  box-shadow: inset 0 0 10px rgba(0, 0, 0, 0.3);
  /* Agregar sombreado interno para cada pieza */
}
✨ Revisar Solución y Practicar

Ejecutando la aplicación

Objetivo: Iniciar la aplicación para ver el juego de rompecabezas completado.

  • En el directorio de su proyecto, ejecute:

    npm start
  • La aplicación debería abrirse en su navegador web, mostrando el juego de rompecabezas.

✨ Revisar Solución y Practicar

Resumen

¡Felicidades! Has construido con éxito un juego de rompecabezas con arrastre y soltar en React. Este proyecto cubrió la configuración de un proyecto de React, la creación de componentes, la gestión del estado, la manipulación de interacciones de usuario y la aplicación de estilos básicos. Ahora puedes experimentar agregando más funciones como un temporizador, una puntuación o diferentes niveles para mejorar el juego.