GAMOOGA
What is it?
A realtime backend (for
multiplayer games).
Realtime?!?
1000s of messages per second happening at < 1ms
Singleplayer vs Multiplayer ! Design ! Development ! Testing
! Design ! Development ! Testing ! MP server ! Uptime & Scalability ! Server side logic ! Deployment ! Maintenance ! Expert eng. & IT ! More $$$
Singleplayer vs Multiplayer ! Design ! Development ! Testing
! Design ! Development ! Testing ! MP server ! Uptime & Scalability ! Server side logic ! Deployment ! Maintenance ! Expert eng. & IT ! More $$$
Singleplayer vs Multiplayer ! Design ! Development ! Testing
! Design ! Development ! Testing ! MP server ! Uptime & Scalability ! Server side logic ! Deployment ! Maintenance ! Expert eng. & IT ! More $$$
Singleplayer vs Multiplayer ! Design ! Development ! Testing
! Design ! Development ! Testing ! MP server ! Uptime & Scalability ! Server side logic ! Deployment ! Maintenance ! Expert eng. & IT ! More $$$
Singleplayer vs Multiplayer ! Design ! Development ! Testing
! Design ! Development ! Testing ! MP server ! Uptime & Scalability ! Server side logic ! Deployment ! Maintenance ! Expert eng. & IT ! More $$$
Singleplayer vs Multiplayer ! Design ! Development ! Testing
! Design ! Development ! Testing ! MP server ! Uptime & Scalability ! Server side logic ! Deployment ! Maintenance ! Expert eng. & IT ! More $$$
Singleplayer vs Multiplayer ! Design ! Development ! Testing
! Design ! Development ! Testing ! MP server ! Uptime & Scalability ! Server side logic ! Deployment ! Maintenance ! Expert eng. & IT ! More $$$
Solution
Enter Gamooga!
GAMOOGA
Architecture
Device abstraction layer
Database servers HTTP API Servers
Gamooga Cloud
Auth servers
Features ! Highly realtime, very low latency transport
(1ms latency)
! Fully hosted, no infrastructure required
! Server side scriptability of backend
! No setup, tweaking, management, maintenance
! Instant deployment
! On-demand and auto scaling (~10000 CCU a room/session and unlimited sessions)
Features
! Multiple frontend APIs: ! Javascript, Actionscript, Android, iOS and Unity
! Built to cross communicate across platforms and devices by design
! Future proof ! Websocket support
! KeyValue store (MongoDB in 2 weeks!)
! External service integration with HTTP
Cost
! No upfront costs, No license
! No infrastructure investment required
! Free to start with
! Pay as you grow
! Pricing fits the bell curve based demand of games
Pro 200$
Indie 10$
Free 0$
Basic 45$
Enterprise 1900$
Basic flow on Gamooga
! ROOM
acts as a lobby to interact with other players before starting the game in a game session.
! SESSION
after interacting with other users in room, a user joins or creates a new game session for actual game play.
Basic flow on Gamooga CLIENT SIDE SERVER SIDE
var gc = new GamoogaClient(); gc.connectToRoom/ gc.createConnectToSession/gc.connectToSession gc.onconnect gc.onmessage gc.send gc.disconnect gc.ondisconnect
gamooga.onconnect gamooga.onmessage gamooga.send gamooga.ondisconnect gamooga.disconnect
Basic flow on Gamooga CLIENT SIDE SERVER SIDE
var gc = new GamoogaClient();
gc.connectToRoom(123,”-uuid-”);
gc.onconnect
gc.onmessage
gc.send
gc.onmessage
gc.send
gc.disconnect
gamooga.onconnect gamooga.send gamooga.onmessage gamooga.send gamooga.ondisconnect gamooga.send
Basic flow on Gamooga ! Download Gamooga SDK
! Develop your game and backend using dev server
! Publish your frontend
! Deploy the backend on Gamooga
Action time!
Walk-throughs
Live Draw
DEMO
Live Draw ! Client side:
function onMouseMove(evt) {! if (!mousedown) return;! var x = evt.pageX - canvasMinX;! var y = evt.pageY - canvasMinY;! ctx.lineTo(x, y);! ctx.stroke();! coorData += x+","+y+";";!} !function sendData() {! gc.send(“coordata”,coorData);! coorData = “”;!}!// ‘sendData’ is called every 250ms!
Live Draw ! Server side:
gamooga.onmessage("coordata", function(conn_id, msg)! gamooga.broadcastexcept("coordata”,! {conn_id,msg}, conn_id)!end) ! Client side:
gc.onmessage("coordata", function(d) {! coors = d[1].split(";");! for (var i=0;i<coors.length-1;i++) {! var xy = coors[i].split(",");! var x = xy[0];! var y = xy[1];! ctx.lineTo(x, y);! }! ctx.stroke();!});
Tanks
DEMO
Tanks – player join ! Server side:
Send to currently connected player his details and other players’ data and his data to already connected players.
gamooga.onconnect(function(conn_id)! uid = uid + 1! uid_map[conn_id] = uid! ! gamooga.send(conn_id, "me_spawn”,! {id=uid,c=assigned,op=player_data})! gamooga.broadcastexcept("other_spawn”,! {id=uid,c=assigned}, conn_id)! ! player_data[uid] = {}! player_data[uid]["c"] = assigned! player_data[uid]["p"] = {0,0,0}!end)!
Tanks – player join ! Client side:
We now have our data and other player’s data, show it in game
gc.onmessage("me_spawn", function(me_data) {!! mytank = new BitmapAnimation(tankSheet);! mytank.healthbar = new Shape(…);! // set mytank properties! // add to stage! ! for (var t in me_data) {! var othertank = new BitmapAnimation(…);! othertank.healthbar = new Shape(…);! // set othertank properties! // add to stage! }! stage.update();!});!
Tanks – player join ! Client side:
Other player’s get the data of currently joined player
gc.onmessage(”other_spawn", function(me_data) {!! var othertank = new BitmapAnimation(…);! othertank.healthbar = new Shape(…);! // set othertank properties! // add to stage! ! stage.update();!});!
Tanks – player join
Room
New Player
Connected player
Connected player
me_spawn
other_spawn other_spawn
Tanks – player movement ! Client side:
Player moving, send it to room
function tick() {! var nowTime = createjs.Ticker.getTime();! if (tankMove) {!! var ct = Math.cos(PI*mytank.rotation/180.0);! mytank.x += 4*ct;! var st = Math.cos(PI*mytank.rotation/180.0); mytank.y += 4*st;!! gc.send("pos”,! [mytank.x,mytank.y,mytank.rotation]);! }!}!
Tanks – player movement ! Server side:
Player move data received, send it to all others
gamooga.onmessage("pos", function(conn_id, pos_data)! puid = uid_map[conn_id]! player_data[puid]["p"] = pos_data;! ! gamooga.broadcastexcept("pos”,! {d=pos_data,f=uid_map[conn_id]}, conn_id)!end)!!!
Secure?!
Tanks – player movement ! Client side:
Other player move data received, apply it
gc.onmessage("pos", function(pos_data) {!! othertanks[pos_data['f']].x = pos_data['d'][0];! othertanks[pos_data['f']].y = pos_data['d'][1];! othertanks[pos_data['f']].rotation =! pos_data['d'][2];!});!
Tanks – player movement
Room
Moving Player
Other player Other player
pos
pos pos
Tanks – player movement
Room (validates)
Moving Player
Other player Other player
pos
pos pos
Tanks – player shoot ! Client side:
Player shooting, send bullet data to room
function tick() {! …! if (tankShoot) {! if (nowTime - lastShoot > 250) {! lastShoot = nowTime;! var newb = bullet.clone();! newb.x = mytank.x+8*ct;! newb.y = mytank.y+8*st;!
! !newb.vX = 10*ct;! newb.vY = 10*st;! newb.id = ++currBullId;! gc.send("nb”, [newb.x,newb.y,! newb.vX,newb.vY,newb.id]);! }!}!
Tanks – player shoot ! Server side:
Player bullet data received, send it to all others
gamooga.onmessage("nb", function(conn_id, bull_data)! gamooga.broadcastexcept("nb”,! {b=bull_data,f=uid_map[conn_id]},conn_id)!end)!!!
Secure?!
Tanks – player shoot ! Client side:
Other player move data received, apply it
gc.onmessage("nb", function(bdata){! var newb = bullet.clone();! newb.x = bdata['b'][0];! newb.y = bdata['b'][1];! newb.vX = bdata['b'][2];! newb.vY = bdata['b'][3];! newb.id = bdata['b'][4];!});!
Tanks – player shoot
Room (validates)
Shooting Player
Other player Other player
nb
nb nb
Tanks – player hit ! Client side:
Check player hit, send hit data to room
function tick() {! …! for(each bullet I shot) {! for (each othertank) {! if (bullet hits othertank) {! othertank.health--;! othertank.healthbar = …;! if (othertank.health == 0) {! othertank.spriteSheet = …;! othertank.gotoAndPlay("blast");! }! gc.send("hit”,! [othertank.id,bull.tid,bull.id]);! }!}!
Tanks – player hit ! Server side:
Player hit data received, send it to all others
gamooga.onmessage("hit", function(conn_id, hit_data)! gamooga.broadcastexcept("hit",hit_data, conn_id)!end)!!
Most insecure! • save bullets data (when we receive “nb” message) • we already have position data • client sends the bullet id • retrieve bullet and its current position • check hit as in the client side – O(1) operation
Tanks – player hit ! Client side:
Other player hit data received, apply it
gc.onmessage("hit", function(hdata){! var tank;! if (hdata[0] == mytank.id) {! tank = mytank;! } else {! tank = othertanks[hdata[0]];! }! tank.health--;! tank.healthbar = …;! if (tank.health == 0) {! tank.spriteSheet = …;! tank.gotoAndPlay("blast");! }!!!
Tanks – player shoot
Room (validates)
Player who hit
Other player Other player
hit
hit hit
Tanks - improvements ! Current implementation is very basic
! Latency compensation – dead reckoning, prediction
! Interpolation
! Insensitive to FPS
! A player can check to run at faster FPS (preventable with timestamps)
! A player is at loss if he is running at lower FPS
! Lockstep protocols
Thank you! Questions?