Instantly share code, notes, and snippets.

Embed
What would you like to do?
Firebase: Assigning players in a multiplayer game. This snippet assigns you a spot in a game if the game isn't full yet.
function go() {
var userId = prompt('Username?', 'Guest');
// Consider adding '/<unique id>' if you have multiple games.
var gameRef = new Firebase(GAME_LOCATION);
assignPlayerNumberAndPlayGame(userId, gameRef);
};
// The maximum number of players. If there are already
// NUM_PLAYERS assigned, users won't be able to join the game.
var NUM_PLAYERS = 4;
// The root of your game data.
var GAME_LOCATION = 'https://SampleGame.firebaseIO-demo.com/';
// A location under GAME_LOCATION that will store the list of
// players who have joined the game (up to MAX_PLAYERS).
var PLAYERS_LOCATION = 'player_list';
// A location under GAME_LOCATION that you will use to store data
// for each player (their game state, etc.)
var PLAYER_DATA_LOCATION = 'player_data';
// Called after player assignment completes.
function playGame(myPlayerNumber, userId, justJoinedGame, gameRef) {
var playerDataRef = gameRef.child(PLAYER_DATA_LOCATION).child(myPlayerNumber);
alert('You are player number ' + myPlayerNumber +
'. Your data will be located at ' + playerDataRef.toString());
if (justJoinedGame) {
alert('Doing first-time initialization of data.');
playerDataRef.set({userId: userId, state: 'game state'});
}
}
// Use transaction() to assign a player number, then call playGame().
function assignPlayerNumberAndPlayGame(userId, gameRef) {
var playerListRef = gameRef.child(PLAYERS_LOCATION);
var myPlayerNumber, alreadyInGame = false;
playerListRef.transaction(function(playerList) {
// Attempt to (re)join the given game. Notes:
//
// 1. Upon very first call, playerList will likely appear null (even if the
// list isn't empty), since Firebase runs the update function optimistically
// before it receives any data.
// 2. The list is assumed not to have any gaps (once a player joins, they
// don't leave).
// 3. Our update function sets some external variables but doesn't act on
// them until the completion callback, since the update function may be
// called multiple times with different data.
if (playerList === null) {
playerList = [];
}
for (var i = 0; i < playerList.length; i++) {
if (playerList[i] === userId) {
// Already seated so abort transaction to not unnecessarily update playerList.
alreadyInGame = true;
myPlayerNumber = i; // Tell completion callback which seat we have.
return;
}
}
if (i < NUM_PLAYERS) {
// Empty seat is available so grab it and attempt to commit modified playerList.
playerList[i] = userId; // Reserve our seat.
myPlayerNumber = i; // Tell completion callback which seat we reserved.
return playerList;
}
// Abort transaction and tell completion callback we failed to join.
myPlayerNumber = null;
}, function (error, committed) {
// Transaction has completed. Check if it succeeded or we were already in
// the game and so it was aborted.
if (committed || alreadyInGame) {
playGame(myPlayerNumber, userId, !alreadyInGame, gameRef);
} else {
alert('Game is full. Can\'t join. :-(');
}
});
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment