Создание игры с пазлом с возможностью перетаскивания на React

JavaScriptBeginner
Практиковаться сейчас

Введение

В этом проекте мы создадим игру с пазлами, в которой можно перетаскивать элементы, с использованием React. Это отличный проект для начинающих, чтобы познакомиться с компонентами React, управлением состоянием и обработкой взаимодействий пользователя. В конце этого проекта у вас будет функциональная игра с пазлами.

👀 Предпросмотр

Превью анимации игры с пазлами

🎯 Задачи

В этом проекте вы научитесь:

  • настраивать новое приложение React;
  • создавать главный компонент игры с пазлами;
  • управлять состоянием и настраивать изображение пазла;
  • отображать элементы пазла на экране;
  • реализовывать функциональность перетаскивания элементов;
  • интегрировать компонент PuzzleGame в главный файл приложения;
  • добавлять CSS для стилизации пазла.

🏆 Достижения

После завершения этого проекта вы сможете:

  • настроить приложение React и создать компонент;
  • управлять состоянием и обрабатывать взаимодействия пользователя;
  • реализовать функциональность перетаскивания элементов;
  • добавить стилизацию, чтобы пазл был визуально привлекательным.

Настройка проекта

Цель: Основой нашей игры с пазлами является новое приложение React.

  • Откройте терминал.

  • Перейдите в каталог вашего проекта:

    cd puzzle-game
  • Установите зависимости проекта:

    npm install
✨ Проверить решение и практиковаться

Создать компонент PuzzleGame

Цель: Настроить главный компонент игры с пазлами.

  • Внутри директории src создайте папку с именем components.
  • Внутри components создайте новый файл с именем PuzzleGame.js.
  • Добавьте следующую базовую структуру в PuzzleGame.js:
// src/components/PuzzleGame.js
// Импортируем React и useState для управления состоянием компонента
import React, { useState, useEffect } from "react";

// Определяем компонент PuzzleGame
const PuzzleGame = () => {
  // Этот компонент будет обрабатывать игровую логику и интерфейс пользователя
  return (
    <div className="game-container">
      {/* Именно здесь будет отображаться пазл */}
    </div>
  );
};

// Экспортируем компонент для использования в других файлах
export default PuzzleGame;
✨ Проверить решение и практиковаться

Реализовать настройку состояния и изображения

Цель: Настроить состояние для управления элементами пазла и определить изображение пазла.

  • В PuzzleGame.js импортируйте useState из React.
  • Определите переменную состояния для отслеживания позиций элементов пазла.
  • Определите URL изображения пазла (поместите изображение с именем corgi.png в папку public).
// src/components/PuzzleGame.js

//...другие импорты
const PuzzleGame = () => {
  // Определите URL изображения и начальные позиции элементов пазла
  const imgUrl = "corgi.png"; // Убедитесь, что это изображение существует в папке public
  const [positions, setPositions] = useState([...Array(16).keys()]);

  useEffect(() => {
    // Перемешайте позиции для начальной настройки пазла
    setPositions((prevPositions) => {
      const newPos = [...prevPositions];
      newPos.sort(() => Math.random() - 0.5);
      return newPos;
    });
  }, []);

  // Возвращение компонента
  return (
    <div className="game-container">
      {/* Интерфейс пользователя пазла будет добавлен здесь в последующих шагах */}
    </div>
  );
};

// Экспорт компонента PuzzleGame
export default PuzzleGame;
✨ Проверить решение и практиковаться

Отобразить элементы пазла

Цель: Отобразить элементы пазла на экране.

  • Переберите состояние positions, чтобы отобразить отдельные элементы пазла.
  • Каждый элемент должен отображать часть изображения.
// src/components/PuzzleGame.js
const PuzzleGame = () => {
  //...предыдущий код

  return (
    <div className="game-container">
      <div className="reference-image">
        <img src={imgUrl} alt="Reference Image" />
      </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>
  );
};
✨ Проверить решение и практиковаться

Добавить функциональность перетаскивания

Цель: Реализовать логику для перетаскивания и вставки элементов пазла.

  • Добавьте обработчики для событий начала перетаскивания, перетаскивания над элементом и вставки.
  • Реализуйте логику для обмена элементами пазла при вставке.
// src/components/PuzzleGame.js

const PuzzleGame = () => {
  //...предыдущий код

  // Обработка начала перетаскивания
  const handleDragStart = (e, position) => {
    e.dataTransfer.setData("text/plain", position);
  };

  // Обработка события вставки
  const handleDrop = (e, position) => {
    e.preventDefault();
    const originalPosition = e.dataTransfer.getData("text");
    // Добавьте здесь логику для обмена позиций элементов пазла
    setPositions((prevPositions) => {
      const newPos = [...prevPositions];
      [newPos[originalPosition], newPos[position]] = [
        newPos[position],
        newPos[originalPosition]
      ];
      return newPos;
    });
  };

  // Разрешение действия вставки, предотвращая стандартное поведение
  const handleDragOver = (e) => {
    e.preventDefault();
  };

  // Отображение элементов пазла с добавленными обработчиками перетаскивания и вставки
};
// src/components/PuzzleGame.js
const PuzzleGame = () => {
  //...предыдущий код

  return (
    <div className="game-container">
      <div className="reference-image">
        <img src={imgUrl} alt="Reference Image" />
      </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>
  );
};
✨ Проверить решение и практиковаться

Обновление компонента App

Цель: Включить компонент PuzzleGame в главный файл приложения.

  • Откройте src/App.js.
  • Отобразите компонент PuzzleGame.
// src/App.js

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

// Компонент App, который отображает компонент PuzzleGame
function App() {
  return (
    <div className="App">
      <PuzzleGame />
    </div>
  );
}

export default App;
✨ Проверить решение и практиковаться

Стилизация пазла

Цель: Добавить CSS для того, чтобы пазл был визуально привлекательным.

  • Откройте src/App.css.
  • Добавьте стили для .game-container и .puzzle-piece, чтобы правильно расположить пазл.
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;
  /* Добавьте границу для согласованности */
  padding: 10px;
  /* Добавьте некоторый отступ вокруг изображения */
  box-shadow: 0 4px 8px rgba(0, 0, 0, 0.2);
  /* Добавьте тень для выравнивания */
}

.reference-image img {
  display: block;
  /* Удалите любое стандартное встроенное расстояние */
  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);
  /* Добавьте более крупную тень для трехмерного эффекта */
  background: #ddd;
  /* Светой фон для зазоров */
}

.puzzle-piece {
  width: 100%;
  height: 100%;
  background-size: 400px 400px;
  cursor: grab;
  box-shadow: inset 0 0 10px rgba(0, 0, 0, 0.3);
  /* Добавьте встроенную тень для каждого элемента */
}
✨ Проверить решение и практиковаться

Запуск приложения

Цель: Запустить приложение, чтобы увидеть завершенную игру с пазлом.

  • В директории вашего проекта запустите:

    npm start
  • Приложение должно открыться в вашем веб-браузере с отображением игры с пазлом.

✨ Проверить решение и практиковаться

Резюме

Поздравляем! Вы успешно создали игру с пазлом с возможностью перетаскивания на React. В этом проекте были рассмотрены настройка проекта React, создание компонентов, управление состоянием, обработка взаимодействий пользователя и применение базовых стилей. Теперь вы можете экспериментировать с добавлением дополнительных функций, таких как таймер, счет или разные уровни, чтобы улучшить игру.