Sign in to follow this  
mla

Multi-player simultaneous game moves causing issues

Recommended Posts

Hi,

I have a multiplayer game that works, except when two players click at the exact same time. 

For example 6 players are in a game.  The game consists of balls being sent from one player to another. The ball is animated from sender player to receiving player. Which means when the sender sends the ball, it is no longer in his/her hands. The ball is now is the hands of the receiving player. This works perfectly except if a move is made by another sending player at the exact same time. 

For example, 6 players are in a game. Player1 passes Player2 the ball at the same time, Player3 passes Player4 the ball. Player1 and Player2 will work correctly, however in the case of the other two players, what happens is Player3 sends the ball to Player4 who receives it but Player3 is still holding the ball even after he/she passed the ball over to Player4.

Does this issue mean I should be using a Callback?

Thanks,

MLA

Share this post


Link to post
Share on other sites

What is the message structure and data you are sending?  Does it represent the whole state of all balls, or is it distinct per ball?  Overall this doesn't sound like a hard problem to solve if thinking from the perspective of the ball - a ball has one owner at a time, and assignment to a new owner can only be issued by the existing owner.  When the new owner receives the ball, the ball will announce to the world it's new owner, etc.

Share this post


Link to post
Share on other sites

@b10b to pass the ball from one player to another, you click on the player. 

The structure is set up that the client will listen for a mousedown event. When a mousedown occurs, it will capture the coordinates to know where the receiving player is standing to pass the Ball over. Then the ball will be removed from the sending players hands and will animate over to the receiving player.  

//Listen for player passing a ball
BALLS.onmousedown = function(e) {	
	var mouseX = e.pageX - this.offsetLeft;						//get clicked x coordinate
	var mouseY = e.pageY - this.offsetTop;						//get clicked y coordinate
	
	socket.emit('player-click', {remotePlayers: remotePlayers, mouseX:mouseX, mouseY:mouseY, remoteRole:remoteRole, myID: socket.id}, function(responseData){
	console.log(responseData);
	playerClicked(mouseX, mouseY, timesup, responseData.myID);
		});	
}

//The player would like to pass a ball
function playerClicked(mouseX, mouseY, timesup, myID) {
    senderPlayer = myID;
	var mouseX = mouseX ;
	var mouseY = mouseY;
	getPlayerDetails(senderPlayer);
	myChain = senderChain;
	
	passBall();
    animateBall();
}

//Ball must be removed from the sender and passed to the receiver
function passBall(){
    socket.emit('update-ballmove', {senderBall:senderBall, senderPlayer:senderPlayer}, 
    function(responseData){
    console.log('Callback called with data:', responseData);
		
	});

}

//Animate the Ball movement
function animateBall() {
	var getXCords = 'getp'+receiverPlayerNumber+'x';
	var getYCords = 'getp'+receiverPlayerNumber+'y';
	for (var i = 0; i < remotePlayers.length; i++) {
		console.log("id: " + senderPlayer);
		if(remotePlayers[i].id == senderPlayer) {
			Xcords = remotePlayers[i][getXCords];
			Ycords = remotePlayers[i][getYCords];
		}
	}	
	var lastX = Xcords[4];
	var lastY = Ycords[4];
	socket.emit('show-animation', {Xcords:Xcords, Ycords:Ycords, senderChainURL:senderChainURL, receiverID:receiverID}, function(animateData){
		console.log(animateData);
	}); 
}

Meanwhile on the Server side, we want to broadcast to all players that a pass has been made. I remove the ball by slicing the ball from the senderPlayer's array. I then animate the ball movement and save the ball to the receivingPlayer's array. 

//Remove Ball from senderPlayer
socket.on ('update-ballmove', function (data, callback){
		var players = data.remotePlayers;
		PLAYER_LIST = data.cPlayers;
		var senderPlayer = data.senderPlayer;
		var senderBall = data.senderBall;
		newBall = senderBall.slice(0, -1);
		
		for (var c = 0; c < players.length; c++){
			if(senderPlayer == players[c].id){
				players[c].getBall = newBall;
			}
		}	
			
		for (var i in PLAYER_LIST) {
			if (PLAYER_LIST[i].id == senderPlayer){
				PLAYER_LIST[i].getBall = newBall;
			}
		}
		
		io.sockets.in(roomID).emit('update-Ball', {totPlayers, players});
		io.sockets.in(roomID).emit('load-player', {Players:PLAYER_LIST});
		
        var responseData;
		responseData = 'done';
		callback(responseData);
	});

//Broadcast to all players that a player wants to pass a ball
	socket.on('player-click', function (data, callback) {
		var myID = data.myID;

		for (var i in PLAYER_LIST) {
			if (PLAYER_LIST[i].id == myID){
				myroom = PLAYER_LIST[i].roomID;
				gameID = PLAYER_LIST[i].gameID;
			}
		}
		
		var responseData = {myID:myID};
		callback(responseData);
    });

//Update animation of Ball movements
	socket.on ('show-animation', function (data, animCallback){
		io.sockets.in(roomID).emit('animateBalls', data);
		var animateData = 'drawn';
		animCallback(animateData);
	});




While this works great if one player passes to another while all other players wait, it won't if players are passing simultaneously. What does work is if two players try to pass the same ball to the one same player, the fastest player will be able to pass the ball, while the slower player will receive a message stating that that player is currently in the middle of a play. 

Share this post


Link to post
Share on other sites

What's the purpose of the socket.on('player-click') round trip?  It achieves nothing from what I can see (and could just be skipped directly at client).  Where is senderBall in passBall() defined?  Unless balls are interceptable issuing their positions from server is counter productive - just issue their owner, and when they last changed owner (use client side data to tween the difference).  From the scenarios described there is only need to emit player position changes and ball ownership changes.  Generally my advice is refactor all this and use some OOP to assist clarity.

Share this post


Link to post
Share on other sites

Is there also a way to factor in the timing it takes to make updates on the server side?

For example, 3 players click on one player, but only one ball can be sent to that one player. The sending player will send that he clicked first and update the receiving player to state he is in a move. 

This would mean the other two players who clicked at the same time, would then receive a message stating that that player is in play. 

 

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
Sign in to follow this  

  • Recently Browsing   0 members

    No registered users viewing this page.