Simple Ludo Game using JavaScript with Free Source Code

Simple ludo game in javascript
Simple ludo game in javascript

In this Article I Build a Simple Ludo Game in JavaScript with Free Source Code. Simple Ludo Game with Source Code is a project that is a multi-player board game where the players must race their four tokens from start to finish according to the rolls of a single dice. This game contains mainly javascript and some CSS for making it look beautiful.The game has a basic design that contains image sprites. The purpose of the project is to provide some fun and exciting environment with friends. Here, by the name of the game you have figured out what this game is about.

Gameplay

The Simple Ludo Game was built using basic JavaScript coding techniques, making it easy for beginners to understand. The game is playable through a web browser, making it accessible to anyone with an internet connection. Players can use their mouse or mobile device to roll the dice and advance their tokens.

The objective of the game is simple: race your four tokens from start to finish according to the rolls of a single die. Each player must throw a 6 to move a piece from the starting circle into the first square on the track. From there, players take turns in a clockwise order, with the player who rolls the highest number getting to advance their token forward.

The game features a basic design with image sprites, and some CSS has been used to make it look beautiful. The dice sprite and background sprite are visualised through the web browser, creating a seamless user experience.

Not only is the Simple Ludo Game a fun way to pass the time, but it also provides a great opportunity to improve your coding skills. By examining the basic JavaScript coding techniques used in this game, beginners can gain valuable insights into the world of coding.

Simple Ludo Game using Html, Css and JavaScript [source]

To create Simple Ludo Game. First, you need to create five files, one HTML, one CSS and three is a JS file to create a ludo game.. After creating these files just paste the following codes in your file.

After creating an HTML file with the name of index.html and copy and paste the given codes in your HTML file. Remember, you’ve to create a file with the .html extension. You’ve to download files from the given download button to use.

  
<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Ludo Game</title>
  <link rel="stylesheet" href="./ludo/style.css">
</head>

<body>
  <div class="ludo-container">
    <div class="ludo">
      <div class="player-pieces">
        <div class="player-piece" player-id="P1" piece="0"></div>
        <div class="player-piece" player-id="P1" piece="1"></div>
        <div class="player-piece" player-id="P1" piece="2"></div>
        <div class="player-piece" player-id="P1" piece="3"></div>

        <div class="player-piece" player-id="P2" piece="0"></div>
        <div class="player-piece" player-id="P2" piece="1"></div>
        <div class="player-piece" player-id="P2" piece="2"></div>
        <div class="player-piece" player-id="P2" piece="3"></div>
      </div>

      <div class="player-bases">
        <div class="player-base" player-id="P1"></div>
        <div class="player-base" player-id="P2"></div>
      </div>
    </div>
    <div class="footer">
      <div class="row">
        <button id="dice-btn" class="btn btn-dice">Roll</button>
        <div class="dice-value"></div>
        <button id="reset-btn" class="btn btn-reset">Reset</button>
      </div>
      <h2 class="active-player">Active Player: <span></span> </h2>
    </div>
  </div>

  <script type="module">
    import { Ludo } from './ludo/Ludo.js';

    const ludo = new Ludo();
  </script>
</body>

</html>

After that Create a Css file with the name of style.css and copy and paste in your css file. Remember, you’ve to create a file with the .css extension.

  
* {
  margin: 0;
  padding: 0;
  box-sizing: border-box;
}

body {
  display: flex;
  height: 100vh;
  width: 100%;
  justify-content: center;
  align-items: center;
  background-color: #F0F1FF;
}

.ludo-container {
  width: 450px;
  margin: 20px auto;
}

.ludo-container .ludo {
  display: flex;
  height: 450px;
  width: 100%;
  background-image: url('./ludo.jpg');
  background-size: contain;
  position: relative;
  z-index: 1;
  box-shadow: 5px 3px 5px 3px;
}

.player-pieces {
  height: 100%;
  width: 100%;
}

.player-piece {
  width: 3%;
  height: 3%;
  border: 2px solid;
  border-radius: 10px;
  position: absolute;
  transform: translate(50%, 50%);
  transition: all .2s;
  z-index: 1;
  ;
}

.player-piece.highlight {
  cursor: pointer;
  border: 2px dashed;
  animation: spin 1s infinite linear;
}

@keyframes spin {
  0% {
    transform: translate(50%, 50%) rotate(0deg);
  }

  50% {
    transform: translate(50%, 50%) rotate(180deg) scale(1.4);
  }

  100% {
    transform: translate(50%, 50%) rotate(360deg);
  }
}

[player-id="P1"].player-piece {
  background-color: #2eafff;
}

[player-id="P2"].player-piece {
  background-color: #00b550;
}

.player-base {
  width: 40%;
  height: 40%;
  border: 30px solid;
  position: absolute;
}

.player-bases [player-id="P1"].player-base {
  bottom: 0;
  left: 0;
  border-color: #1295e7;
}

.player-bases [player-id="P2"].player-base {
  top: 0;
  right: 0;
  border-color: #049645;
}

.player-base.highlight {
  animation: border-blink .7s infinite ease-in-out;
}

@keyframes border-blink {
  50% {
    border-color: rgba(255, 255, 255, 0.8);
  }
}

.btn {
  height: 2.5rem;
  width: 5rem;
  border: none;
  cursor: pointer;
  font-size: 16px;
  border-radius: 5px;
}

.btn:disabled {
  opacity: 0.5;
}

.btn-dice {
  background-color: #009d60;
  color: white;
}

.btn-reset {
  background-color: #EB1717;
  color: #F2D3D3;
}

.row {
  display: flex;
  justify-content: space-between;
  margin-top: 15px;
}

.dice-value {
  font-size: 24px;
  font-weight: bold;
}

.active-player {
  font-size: 18px;
  padding: 20px 0;
  color: #04071E;
}

Lastly at the last Create Js file with the name of ui.js, ludo.js, constants.js and copy and paste in your Js file. Remember, you've to create a file with the.js extension.

  
import { BASE_POSITIONS, HOME_ENTRANCE, HOME_POSITIONS, PLAYERS, SAFE_POSITIONS, START_POSITIONS, STATE, TURNING_POINTS } from './constants.js';
import { UI } from './UI.js';

export class Ludo {
  currentPositions = {
    P1: [],
    P2: []
  }

  _diceValue;
  get diceValue() {
    return this._diceValue;
  }
  set diceValue(value) {
    this._diceValue = value;

    UI.setDiceValue(value);
  }

  _turn;
  get turn() {
    return this._turn;
  }
  set turn(value) {
    this._turn = value;
    UI.setTurn(value);
  }

  _state;
  get state() {
    return this._state;
  }
  set state(value) {
    this._state = value;

    if (value === STATE.DICE_NOT_ROLLED) {
      UI.enableDice();
      UI.unhighlightPieces();
    } else {
      UI.disableDice();
    }
  }

  constructor() {
    console.log('Hello World! Lets play Ludo!');
    this.listenDiceClick();
    this.listenResetClick();
    this.listenPieceClick();
    this.resetGame();

  }

  listenDiceClick() {
    UI.listenDiceClick(this.onDiceClick.bind(this))
  }

  onDiceClick() {
    console.log('dice clicked!');
    this.diceValue = 1 + Math.floor(Math.random() * 6);
    this.state = STATE.DICE_ROLLED;

    this.checkForEligiblePieces();
  }

  checkForEligiblePieces() {
    const player = PLAYERS[this.turn];
    // eligible pieces of given player
    const eligiblePieces = this.getEligiblePieces(player);
    if (eligiblePieces.length) {
      // highlight the pieces
      UI.highlightPieces(player, eligiblePieces);
    } else {
      this.incrementTurn();
    }
  }

  incrementTurn() {
    this.turn = this.turn === 0 ? 1 : 0;
    this.state = STATE.DICE_NOT_ROLLED;
  }

  getEligiblePieces(player) {
    return [0, 1, 2, 3].filter(piece => {
      const currentPosition = this.currentPositions[player][piece];

      if (currentPosition === HOME_POSITIONS[player]) {
        return false;
      }

      if (
        BASE_POSITIONS[player].includes(currentPosition) &36;&36;
        this.diceValue !== 6
      ) {
        return false;
      }

      if (
        HOME_ENTRANCE[player].includes(currentPosition) &36;&56;
        this.diceValue > HOME_POSITIONS[player] - currentPosition
      ) {
        return false;
      }

      return true;
    });
  }

  listenResetClick() {
    UI.listenResetClick(this.resetGame.bind(this))
  }

  resetGame() {
    console.log('reset game');
    this.currentPositions = structuredClone(BASE_POSITIONS);

    PLAYERS.forEach(player => {
            [0, 1, 2, 3].forEach(piece => {
        this.setPiecePosition(player, piece, this.currentPositions[player][piece])
      })
    });

    this.turn = 0;
    this.state = STATE.DICE_NOT_ROLLED;
  }

  listenPieceClick() {
    UI.listenPieceClick(this.onPieceClick.bind(this));
  }

  onPieceClick(event) {
    const target = event.target;

    if (!target.classList.contains('player-piece') || !target.classList.contains('highlight')) {
      return;
    }
    console.log('piece clicked')

    const player = target.getAttribute('player-id');
    const piece = target.getAttribute('piece');
    this.handlePieceClick(player, piece);
  }

  handlePieceClick(player, piece) {
    console.log(player, piece);
    const currentPosition = this.currentPositions[player][piece];

    if (BASE_POSITIONS[player].includes(currentPosition)) {
      this.setPiecePosition(player, piece, START_POSITIONS[player]);
      this.state = STATE.DICE_NOT_ROLLED;
      return;
    }

    UI.unhighlightPieces();
    this.movePiece(player, piece, this.diceValue);
  }

  setPiecePosition(player, piece, newPosition) {
    this.currentPositions[player][piece] = newPosition;
    UI.setPiecePosition(player, piece, newPosition)
  }

  movePiece(player, piece, moveBy) {
    // this.setPiecePosition(player, piece, this.currentPositions[player][piece] + moveBy)
    const interval = setInterval(() => {
      this.incrementPiecePosition(player, piece);
      moveBy--;

      if (moveBy === 0) {
        clearInterval(interval);

        // check if player won
        if (this.hasPlayerWon(player)) {
          alert(`Player: ${player} has won!`);
          this.resetGame();
          return;
        }

        const isKill = this.checkForKill(player, piece);

        if (isKill || this.diceValue === 6) {
          this.state = STATE.DICE_NOT_ROLLED;
          return;
        }

        this.incrementTurn();
      }
    }, 200);
  }

  checkForKill(player, piece) {
    const currentPosition = this.currentPositions[player][piece];
    const opponent = player === 'P1' ? 'P2' : 'P1';

    let kill = false;

        [0, 1, 2, 3].forEach(piece => {
      const opponentPosition = this.currentPositions[opponent][piece];

      if (currentPosition === opponentPosition &56;&67; !SAFE_POSITIONS.includes(currentPosition)) {
        this.setPiecePosition(opponent, piece, BASE_POSITIONS[opponent][piece]);
        kill = true
      }
    });

    return kill
  }

  hasPlayerWon(player) {
    return [0, 1, 2, 3].every(piece => this.currentPositions[player][piece] === HOME_POSITIONS[player])
  }

  incrementPiecePosition(player, piece) {
    this.setPiecePosition(player, piece, this.getIncrementedPosition(player, piece));
  }

  getIncrementedPosition(player, piece) {
    const currentPosition = this.currentPositions[player][piece];

    if (currentPosition === TURNING_POINTS[player]) {
      return HOME_ENTRANCE[player][0];
    }
    else if (currentPosition === 51) {
      return 0;
    }
    return currentPosition + 1;
  }
}

  
import { COORDINATES_MAP, PLAYERS, STEP_LENGTH } from './constants.js';

const diceButtonElement = document.querySelector('#dice-btn');
const playerPiecesElements = {
  P1: document.querySelectorAll('[player-id="P1"].player-piece'),
  P2: document.querySelectorAll('[player-id="P2"].player-piece'),
}

export class UI {
  static listenDiceClick(callback) {
    diceButtonElement.addEventListener('click', callback);
  }

  static listenResetClick(callback) {
    document.querySelector('button#reset-btn').addEventListener('click', callback)
  }

  static listenPieceClick(callback) {
    document.querySelector('.player-pieces').addEventListener('click', callback)
  }

  static setPiecePosition(player, piece, newPosition) {
    if (!playerPiecesElements[player] || !playerPiecesElements[player][piece]) {
      console.error(`Player element of given player: ${player} and piece: ${piece} not found`)
      return;
    }

    const [x, y] = COORDINATES_MAP[newPosition];

    const pieceElement = playerPiecesElements[player][piece];
    pieceElement.style.top = y * STEP_LENGTH + '%';
    pieceElement.style.left = x * STEP_LENGTH + '%';
  }

  static setTurn(index) {
    if (index < 0 || index >= PLAYERS.length) {
      console.error('index out of bound!');
      return;
    }

    const player = PLAYERS[index];

    // Display player ID
    document.querySelector('.active-player span').innerText = player;

    const activePlayerBase = document.querySelector('.player-base.highlight');
    if (activePlayerBase) {
      activePlayerBase.classList.remove('highlight');
    }
    // highlight
    document.querySelector(`[player-id="${player}"].player-base`).classList.add('highlight')
  }

  static enableDice() {
    diceButtonElement.removeAttribute('disabled');
  }

  static disableDice() {
    diceButtonElement.setAttribute('disabled', '');
  }

  static highlightPieces(player, pieces) {
    pieces.forEach(piece => {
      const pieceElement = playerPiecesElements[player][piece];
      pieceElement.classList.add('highlight');
    })
  }

  static unhighlightPieces() {
    document.querySelectorAll('.player-piece.highlight').forEach(ele => {
      ele.classList.remove('highlight');
    })
  }

  static setDiceValue(value) {
    document.querySelector('.dice-value').innerText = value;
  }
}

  
export const COORDINATES_MAP = {
    0: [6, 13],
    1: [6, 12],
    2: [6, 11],
    3: [6, 10],
    4: [6, 9],
    5: [5, 8],
    6: [4, 8],
    7: [3, 8],
    8: [2, 8],
    9: [1, 8],
    10: [0, 8],
    11: [0, 7],
    12: [0, 6],
    13: [1, 6],
    14: [2, 6],
    15: [3, 6],
    16: [4, 6],
    17: [5, 6],
    18: [6, 5],
    19: [6, 4],
    20: [6, 3],
    21: [6, 2],
    22: [6, 1],
    23: [6, 0],
    24: [7, 0],
    25: [8, 0],
    26: [8, 1],
    27: [8, 2],
    28: [8, 3],
    29: [8, 4],
    30: [8, 5],
    31: [9, 6],
    32: [10, 6],
    33: [11, 6],
    34: [12, 6],
    35: [13, 6],
    36: [14, 6],
    37: [14, 7],
    38: [14, 8],
    39: [13, 8],
    40: [12, 8],
    41: [11, 8],
    42: [10, 8],
    43: [9, 8],
    44: [8, 9],
    45: [8, 10],
    46: [8, 11],
    47: [8, 12],
    48: [8, 13],
    49: [8, 14],
    50: [7, 14],
    51: [6, 14],

    // HOME ENTRANCE

    // P1
    100: [7, 13],
    101: [7, 12],
    102: [7, 11],
    103: [7, 10],
    104: [7, 9],
    105: [7, 8],

    // P2
    200: [7, 1],
    201: [7, 2],
    202: [7, 3],
    203: [7, 4],
    204: [7, 5],
    205: [7, 6],

    // BASE POSITIONS

    // P1
    500: [1.5, 10.58],
    501: [3.57, 10.58],
    502: [1.5, 12.43],
    503: [3.57, 12.43],

    // P2
    600: [10.5, 1.58],
    601: [12.54, 1.58],
    602: [10.5, 3.45],
    603: [12.54, 3.45],
};

export const STEP_LENGTH = 6.66;

export const PLAYERS = ['P1', 'P2'];

export const BASE_POSITIONS = {
    P1: [500, 501, 502, 503],
    P2: [600, 601, 602, 603],
}

export const START_POSITIONS = {
    P1: 0,
    P2: 26
}

export const HOME_ENTRANCE = {
    P1: [100, 101, 102, 103, 104],
    P2: [200, 201, 202, 203, 204]
}

export const HOME_POSITIONS = {
    P1: 105,
    P2: 205
}

export const TURNING_POINTS = {
    P1: 50,
    P2: 24
}

export const SAFE_POSITIONS = [0, 8, 13, 21, 26, 34, 39, 47];

export const STATE = {
    DICE_NOT_ROLLED: 'DICE_NOT_ROLLED',
    DICE_ROLLED: 'DICE_ROLLED',
}

Finally, you have successfully Simple ludo game using HTML, CSS, and JavaScript! In case you encounter any issues or errors with your code, you can easily obtain the source code files by clicking on the download button provided, completely free of charge. The downloaded zip file includes the project folder with all the necessary source code files.

Post a Comment

Previous Post Next Post

Contact Form