mla Posted November 22, 2018 Share Posted November 22, 2018 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 Quote Link to comment Share on other sites More sharing options...
b10b Posted November 22, 2018 Share Posted November 22, 2018 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. Quote Link to comment Share on other sites More sharing options...
mla Posted November 22, 2018 Author Share Posted November 22, 2018 @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. Quote Link to comment Share on other sites More sharing options...
b10b Posted November 22, 2018 Share Posted November 22, 2018 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. Quote Link to comment Share on other sites More sharing options...
mla Posted November 30, 2018 Author Share Posted November 30, 2018 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. Quote Link to comment Share on other sites More sharing options...
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.