Skip to content

muhammadahmad1857/Chess-Game-backend-project-

Repository files navigation

Sure, here's a detailed README.md for your Node.js chess game project using Express, EJS, Socket.io, and Chess.js:

# Chess Game

This is a real-time chess game built with Node.js, Express, EJS, Socket.io, and Chess.js. It allows two players to play chess against each other and supports spectators to watch the game.

## Table of Contents

1. [Introduction](#introduction)
2. [Features](#features)
3. [Installation](#installation)
4. [Usage](#usage)
5. [File Structure](#file-structure)
6. [Technologies Used](#technologies-used)
7. [Contributing](#contributing)
8. [License](#license)

## Introduction

This project demonstrates how to build a real-time multiplayer chess game using Node.js for the backend, Express for server-side logic, EJS for templating, Socket.io for real-time communication, and Chess.js for the chess logic. The game supports multiple roles: white player, black player, and spectators.

## Features

- Real-time gameplay with Socket.io
- Chess logic handled by Chess.js
- Responsive design with Tailwind CSS
- Multiple player roles (white, black, and spectator)
- Interactive drag-and-drop chess pieces

## Installation

1. **Clone the repository:**
    ```sh
    git clone https://github.com/yourusername/chess-game.git
    cd chess-game
    ```

2. **Install dependencies:**
    ```sh
    npm install
    ```

3. **Run the server:**
    ```sh
    npm start
    ```

4. Open your browser and navigate to `http://localhost:5000`.

## Usage

- The first user to connect will be assigned the white player role.
- The second user to connect will be assigned the black player role.
- Additional users will join as spectators.
- Players can drag and drop pieces to make moves. The moves will be validated and broadcasted to all connected clients in real-time.

## File Structure

```plaintext
.
├── public
│   └── javaScript
│       └── chessGame.js   # Client-side JavaScript
├── views
│   └── index.ejs          # EJS template for the main page
├── .gitignore             # Git ignore file
├── package.json           # Project metadata and dependencies
├── server.js              # Main server file
└── README.md              # Project readme file

Technologies Used

  • Node.js: JavaScript runtime for server-side development.
  • Express: Web application framework for Node.js.
  • EJS: Templating engine for generating HTML markup with plain JavaScript.
  • Socket.io: Library for real-time web applications.
  • Chess.js: JavaScript library for chess move generation/validation, piece placement/movement, and check/checkmate/stalemate detection.
  • Tailwind CSS: Utility-first CSS framework for styling.

Contributing

Contributions are welcome! Please fork the repository and submit a pull request for any changes you'd like to make.

  1. Fork the Project
  2. Create your Feature Branch (git checkout -b feature/YourFeature)
  3. Commit your Changes (git commit -m 'Add some YourFeature')
  4. Push to the Branch (git push origin feature/YourFeature)
  5. Open a Pull Request

License

Distributed under the MIT License. See LICENSE for more information.


Example Code

Here's a brief overview of the main components of this project:

server.js

This file sets up the server using Express, configures Socket.io for real-time communication, and initializes the chess game logic.

const express = require("express");
const http = require("http");
const { Chess } = require("chess.js");
const socket = require("socket.io");
const path = require("path");

const port = 5000;
const app = express();
const server = http.createServer(app);
const io = socket(server);

const chess = new Chess();
let players = {};
let currentPlayer = "w";

app.set("view engine", "ejs");
app.use(express.static(path.join(__dirname, "public")));

app.get("/", (req, res) => {
  res.render("index", { title: "Chess Game" });
});

io.on("connection", (uniqueSocket) => {
  console.log("A user joined.");

  if (!players.white) {
    players.white = uniqueSocket.id;
    uniqueSocket.emit("playerRole", "w");
  } else if (!players.black) {
    players.black = uniqueSocket.id;
    uniqueSocket.emit("playerRole", "b");
  } else {
    uniqueSocket.emit("spectatorRole");
  }

  uniqueSocket.on("disconnect", () => {
    console.log("A user disconnected.");
    if (players.white === uniqueSocket.id) {
      delete players.white;
    } else if (players.black === uniqueSocket.id) {
      delete players.black;
    }
  });

  uniqueSocket.on("move", (move) => {
    try {
      if (
        (chess.turn() === "w" && players.white !== uniqueSocket.id) ||
        (chess.turn() === "b" && players.black !== uniqueSocket.id)
      )
        return;

      const result = chess.move(move);
      if (result) {
        currentPlayer = chess.turn();
        io.emit("move", move);
        io.emit("boardState", chess.fen());
      } else {
        console.log(`Invalid move: ${move}`);
        uniqueSocket.emit("invalidMove", move);
      }
    } catch (error) {
      console.log(error);
      uniqueSocket.emit("invalidMove", move);
    }
  });
});

server.listen(port, () => {
  console.log("Server is running on port " + port);
});

public/javaScript/chessGame.js

This file handles the client-side logic for rendering the chessboard, managing drag-and-drop events, and communicating with the server via Socket.io.

const socket = io();
const chess = new Chess();
const boardElement = document.querySelector(".chessboard");

let draggedPiece = null;
let sourceSquare = null;
let playerRole = null;

const renderBoard = () => {
  const board = chess.board();
  boardElement.innerHTML = "";
  board.forEach((row, rowIndex) => {
    row.forEach((square, squareIndex) => {
      const squareElement = document.createElement("div");
      squareElement.classList.add(
        "square",
        (rowIndex + squareIndex) % 2 === 0 ? "light" : "dark"
      );
      squareElement.dataset.row = rowIndex;
      squareElement.dataset.col = squareIndex;

      if (square) {
        const pieceElement = document.createElement("div");
        pieceElement.classList.add(
          "piece",
          square.color === "w" ? "white" : "black"
        );
        pieceElement.innerText = getPieceUnicode(square.type, square.color);
        pieceElement.draggable = playerRole === square.color;

        pieceElement.addEventListener("dragstart", (e) => {
          if (pieceElement.draggable) {
            draggedPiece = pieceElement;
            sourceSquare = { row: rowIndex, col: squareIndex };
            e.dataTransfer.setData("text/plain", "");
            console.log(`Drag started: ${pieceElement.innerText}`);
          }
        });

        pieceElement.addEventListener("dragend", (e) => {
          draggedPiece = null;
          sourceSquare = null;
          e.dataTransfer.setData("text/plain", "");
          console.log(`Drag ended`);
        });

        squareElement.appendChild(pieceElement);
      }

      squareElement.addEventListener("dragover", (e) => {
        e.preventDefault();
      });

      squareElement.addEventListener("drop", (e) => {
        e.preventDefault();
        if (draggedPiece) {
          const targetSquare = {
            row: Number(squareElement.dataset.row),
            col: Number(squareElement.dataset.col),
          };
          handleMove(sourceSquare, targetSquare);
        }
      });

      boardElement.appendChild(squareElement);
    });
  });

  if (playerRole === "b") {
    boardElement.classList.add("flipped");
  } else {
    boardElement.classList.remove("flipped");
  }
};

const handleMove = (source, target) => {
  const move = {
    from: `${String.fromCharCode(97 + source.col)}${8 - source.row}`,
    to: `${String.fromCharCode(97 + target.col)}${8 - target.row}`,
    promotion: "q",
  };
  console.log(
    `Move from ${source.row},${source.col} to ${target.row},${target.col}`
  );
  socket.emit("move", move);
};

const getPieceUnicode = (type, color) => {
  const unicodeMap = {
    p: "♟",
    r: "♜",
    n: "♞",
    b: "♝",
    q: "♛",
    k: "♚",
    P: "♙",
    R: "♖",
    N: "♘",
    B: "♗",
    Q: "♕",
    K: "♔",
  };
  return color === "w"
    ? unicodeMap[type.toUpperCase()]
    : unicodeMap[type.toLowerCase()];
};

socket.on("playerRole", (role) => {
  playerRole = role;
  console.log(`Player role set: ${role}`);
  renderBoard();
});

socket.on("spectatorRole", () => {
  playerRole = null;
  console.log(`Spect

ator role set`);
  renderBoard();
});

socket.on("boardState", (fen) => {
  chess.load(fen);
  renderBoard();
});

socket.on("move", (move) => {
  chess.move(move);
  console.log(`Move received: ${move}`);
  renderBoard();
});

renderBoard();

views/index.ejs

This file contains the HTML template for the main page, which includes the chessboard and necessary script references.

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Chess Game</title>
    <link rel="stylesheet" href="https://cdn.tailwindcss.com" />
    <style>
      .chessboard {
        display: grid;
        grid-template-columns: repeat(8, 1fr);
        grid-template-rows: repeat(8, 1fr);
        width: 400px;
        transform: rotate(0deg);
      }
      .flipped {
        transform: rotate(180deg);
      }
      .square {
        display: flex;
        justify-content: center;
        align-items: center;
      }
      .square.light {
        background-color: #f0d9b5;
      }
      .square.dark {
        background-color: #b58863;
      }
      .piece {
        font-size: 36px;
        cursor: pointer;
      }
      .piece.white {
        color: white;
        filter: drop-shadow(0 0 2px rgba(0, 0, 0, 1));
      }
      .piece.black {
        color: black;
      }
      .piece.draggable {
        cursor: grab;
      }
      .dragging {
        opacity: 0.5;
      }
      .flipped .piece {
        transform: rotate(180deg);
      }
      @media (max-width: 400px) {
        .chessboard {
          width: 100%;
        }
      }
    </style>
  </head>
  <body>
    <div class="w-full h-screen flex items-center justify-center bg-zinc-900">
      <div class="chessboard"></div>
    </div>
    <script src="https://cdn.socket.io/4.7.5/socket.io.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/chess.js/0.10.3/chess.min.js"></script>
    <script src="/javaScript/chessGame.js"></script>
  </body>
</html>

License

Distributed under the MIT License. See LICENSE for more information.


This `README.md` provides an overview of the project, instructions for setting it up, usage guidelines, a description of the file structure, and other relevant information. Adjust the repository URL and other details as needed for your specific project.

About

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors