React を使ったドラッグアンドドロップパズルゲームの作成

JavaScriptBeginner
オンラインで実践に進む

はじめに

このプロジェクトでは、React を使ってドラッグアンドドロップのパズルゲームを作成します。これは、React コンポーネント、状態管理、ユーザーインタラクションの処理を学ぶ初心者にとって素晴らしいプロジェクトです。このプロジェクトが終了すると、機能するパズルゲームが完成します。

👀 プレビュー

Puzzle game preview animation

🎯 タスク

このプロジェクトで学ぶことは以下の通りです。

  • 新しい 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 = () => {
  // このコンポーネントはゲームのロジックと UI を処理する
  return (
    <div className="game-container">
      {/* ここにパズルがレンダリングされる */}
    </div>
  );
};

// 他のファイルで使用するためにコンポーネントをエクスポートする
export default PuzzleGame;
✨ 解答を確認して練習

状態と画像のセットアップを実装する

目的:パズルピースを管理するための状態をセットアップし、パズル画像を定義する。

  • PuzzleGame.js で、React から useState をインポートする。
  • パズルピースの位置を追跡するための状態変数を定義する。
  • パズル画像の URL を定義する(public フォルダに corgi.png という名前の画像を配置する)。
// 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">
      {/* ここに後のステップでパズルの UI が追加される */}
    </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";

// PuzzleGame コンポーネントをレンダリングする App コンポーネント
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);
  /* 3D 効果のために大きな影を追加 */
  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
  • アプリケーションが Web ブラウザで開き、パズルゲームが表示されるはずである。

✨ 解答を確認して練習

まとめ

おめでとうございます!あなたは React でドラッグアンドドロップのパズルゲームを成功裏に作成しました。このプロジェクトでは、React プロジェクトのセットアップ、コンポーネントの作成、状態の管理、ユーザーインタラクションの処理、および基本的なスタイルの適用について学びました。これで、タイマー、スコア、または異なるレベルなど、さらに機能を追加してゲームを向上させる実験を行うことができます。