Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Passing turns with socket.io and Nodejs in turn-based game

I'm using Nodejs with Socket.io to make a turn based game.

Each turn must end whenever the "Pass" button is pressed or if 5 seconds have passed after the turn began. Whichever happens first must trigger the "Pass" event.

My current counter just keeps on looping even if its not the current player turn, and in certain conditions it ends the turn prematurely.

I'm having issues on what logic should I use to have my turns work properly.

My client side has this functions

//Pressing "Pass" button
$('#pass_turn').on('click', function(){
    socket.emit('pass_turn');

    $('#your_turn').hide();
    $('#not_turn').show();
});

//This runs everytime the server tells the player its their turn
socket.on('your_turn', function() {
    $('#your_turn').show();
    $('#not_turn').hide();

    var counter = 0;
    var interval = setInterval(function() {
        counter++;

        if (counter == 5) {
            console.log('pass_turn');
            clearInterval(interval);
            $('#pass_turn').trigger("click");
        }
    }, 1000);
});

This is my server side code:

socket.on('pass_turn', function () {
    var room = socket.rooms;

    for(var item in socket.rooms){
        if(item.substring(0, 7) == 'room_0.'){
            //if conditions met, emit turn to opponent
            socket.broadcast.to(item).emit('your_turn');
        }
    }
});
like image 377
Bob Lozano Avatar asked Feb 05 '23 03:02

Bob Lozano


1 Answers

I implemented your logic in my way.
I have an array to store every connected players(socket)
This will be used to track which player is current turn and emit event to the player.

Server side

   let players = [];
   let current_turn = 0;
   let timeOut;
   let _turn = 0;
   const MAX_WAITING = 5000;

   function next_turn(){
      _turn = current_turn++ % players.length;
      players[_turn].emit('your_turn');
      console.log("next turn triggered " , _turn);
      triggerTimeout();
   }

   function triggerTimeout(){
     timeOut = setTimeout(()=>{
       next_turn();
     },MAX_WAITING);
   }

   function resetTimeOut(){
      if(typeof timeOut === 'object'){
        console.log("timeout reset");
        clearTimeout(timeOut);
      }
   }

 io.on('connection', function(socket){
  console.log('A player connected');

  players.push(socket);
  socket.on('pass_turn',function(){
     if(players[_turn] == socket){
        resetTimeOut();
        next_turn();
     }
  })

  socket.on('disconnect', function(){
    console.log('A player disconnected');
    players.splice(players.indexOf(socket),1);
    _turn--;
    console.log("A number of players now ",players.length);
  });
});
  1. After players are connected to server, I push them into the array, and only the game can be started with the first connected player's request by clicking a button in client side (you can modify this).

  2. If you look at pass_turn event, only a current player can trigger events, which means other players are blocked for 5 seconds,

  3. if any player is disconnected, we remove him from the array and decrease index as well.

  4. next_turn function is triggered if 5 seconds are passed or the player presses a button in client side.

  5. triggerTimeout function is used to count 5 seconds, after 5 seconds, it trigger next_turn function to turn next player.

  6. resetTimeout function is triggered, when a current player is pressed a button in client side. time is reset and turn next player immediately

Client

 <button type="button" id="turn" name="button">Next Turn</button>
 $("#turn").on("click",function(e){
     socket.emit('pass_turn');
 })

Turn your server on, open 3~4 browsers and try it

Good luck :)

like image 78
Mia Avatar answered Feb 07 '23 17:02

Mia