make your-game-multiplayer
DESCRIPTION
Andrew Lee from Firebase presenting techniques for building multiplayer games at the O'Reilly Fluent conference.TRANSCRIPT
Make Your Game Multiplayer
Twitter: @StartupAndrew
Andrew Lee
Founder:
GitHub: StartupAndrew
Tic Tac Toe
Why Multiplayer?
Real people are more fun
Replayability
Virality
Why Now?
Rich clients
HTML5 + libraries (D3, Raphael, etc.)
Ubiquitous, fast networks
Expectations - Facebook, Twitter
ModelModel
Single Player
ViewView
ControllerController
Client 2Client 2 Client 3Client 3Client 1Client 1
Multi Player
ModelModel
ViewView
ControllerController ModelModel
ViewView
ControllerController ModelModel
ViewView
ControllerController
Synchronization Synchronization ServiceService
Demo
Updating Your Model
var boardRef = new Firebase("http://gamma.firebase.com/firetactoe/board");
$("#canvas0").click(function(a) { var cellRow = Math.floor(a.offsetX / cell_width); var cellCol = Math.floor(a.offsetY / cell_height); boardRef.child(cellRow).child(cellCol).set(myXorO);});
Displaying Your Model
boardRef.on("value", function(d) { for(var x = 0; x < 3; x++) { for(var y = 0; y < 3; y++) { renderSquare(x, y, d.child(x).child(y).val()); } }});
But...
Cheating
Change previous turns
Play out-of-turn
Spoof the other player’s turns
Client 2Client 2Client 1Client 1
Validating Data: Server
ModelModel
ViewView
ControllerController ModelModel
ViewView
ControllerController
Synchronization Synchronization ServiceService ServerServer
Client 1Client 1 Client 2Client 2
Validating Data: Client
ModelModel
ViewView
ControllerController ModelModel
ViewView
ControllerController
Synchronization Synchronization ServiceService
Validation Validation LogicLogic
Validation Validation LogicLogic
Validating Data: Client
var previousBoard = [[null, null, null], [null, null, null], [null, null, null]];boardRef.on("value", function(d) { for(var x = 0; x < 3; x++) { for(var y = 0; y < 3; y++) { if(d.child(x).child(y).val() !== previousBoard[x][y] &&
previousBoard[x][y] !== null) { alert("Cheater!"); } previousBoard[x][y] = d.child(x).child(y).val();; } }});
Demo
Pong
setInterval(function() { gamestateRef.child("paddle" + myPlayerNum).transaction(function(v) { //move my paddle var retVal = v + direction;
//handle collisions with the top and bottom ...
return retVal; });}, 50);
The Problem
Client 1
Client 2
??????
Server-side AI
Client 1 Client 1 (paddle 1)(paddle 1)
Client 2Client 2(paddle 2)(paddle 2)
Synchronization Synchronization ServiceService
ServerServer(ball)(ball)
sdfsdf
var curX = INITIAL_X, curY = INITIAL_Y;
setInterval(function() { //move the ball to its next position curX += velX; curY += velY; //next, check for collisions ... //now, update the ball position in our shared model gamestateRef.child("ball").set({x: curX, y: curY});}, 50);
Demo
Client-side AI
Client 1 Client 1 (paddle 1 & ball)(paddle 1 & ball)
Client 2Client 2(paddle 2)(paddle 2)
Synchronization Synchronization ServiceService
Client 1Client 1 Client 2Client 2
Peer-to-peer Lock-step
Model Model (History of actions)(History of actions)
ViewView(Paddle 1, Paddle 2, and Ball)(Paddle 1, Paddle 2, and Ball)
ControllerController
Synchronization Synchronization ServiceService
Model Model (History of actions)(History of actions)
ViewView(Paddle 1, Paddle 2, and Ball)(Paddle 1, Paddle 2, and Ball)
ControllerController
Peer-to-peer Lock-step
Calculate Next Calculate Next Game StateGame State
Collect Inputs Collect Inputs from All Playersfrom All Players
IncrementIncrement““Step Number”Step Number”
One more...
http://mmoasteroids.com
A more complicated example...
http://firebase.com
5 minute tutorial at:
Questions?