Create Your First Multiplayer Function
Let’s build a simple multiplayer cursor tracking game where players can see each other’s mouse positions in real-time.Step 1: Create the Cloud Function
curl -X POST http://localhost:8000/projects/YOUR_PROJECT_ID/functions \
-H "Content-Type: application/json" \
-d '{
"name": "cursor_game",
"function_type": "websocket",
"description": "Multiplayer cursor tracking game",
"code": "YOUR_CODE_HERE"
}'
Step 2: Define Event Handlers
Here’s the complete function code with all event handlers:Python (Cloud Function)
async def on_connect():
"""Called when a player connects"""
player_name = request.get('player_name', 'Guest')
# Join a room (auto-created if doesn't exist)
room.join(request.get('room_id', 'lobby'), max_players=10)
# Initialize room state on first player
if not room.state:
room.state = {'players': {}}
# Add player to state
room.state['players'][session.player_id] = {
'name': player_name,
'x': 400,
'y': 300,
'color': '#ff6b6b'
}
# Broadcast join event to all players
await room.broadcast({
'type': 'player_joined',
'player_id': session.player_id,
'player_name': player_name
})
# Return welcome message to connecting player
return {
'type': 'welcome',
'your_id': session.player_id,
'players': room.state['players']
}
async def on_message():
"""Called when a player sends a message"""
action = request.get('action')
if action == 'move':
# Update player position
x = request.get('x', 0)
y = request.get('y', 0)
if session.player_id in room.state['players']:
room.state['players'][session.player_id]['x'] = x
room.state['players'][session.player_id]['y'] = y
# Broadcast movement to all other players
await room.broadcast({
'type': 'player_moved',
'player_id': session.player_id,
'x': x,
'y': y
}, exclude=[session.player_id])
async def on_disconnect():
"""Called when a player disconnects"""
if session.player_id in room.state['players']:
player_name = room.state['players'][session.player_id]['name']
del room.state['players'][session.player_id]
await room.broadcast({
'type': 'player_left',
'player_id': session.player_id,
'player_name': player_name
})
Step 3: Connect from Client
<!DOCTYPE html>
<html>
<head>
<title>Cursor Game</title>
<style>
body { margin: 0; overflow: hidden; background: #1a1a2e; }
canvas { display: block; }
</style>
</head>
<body>
<canvas id="canvas"></canvas>
<script>
const canvas = document.getElementById('canvas');
const ctx = canvas.getContext('2d');
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
// Connect to WebSocket
const ws = new WebSocket(
'ws://localhost:8000/ws/YOUR_PROJECT_ID/cursor_game'
);
let myId = null;
let players = {};
// Send initial connection message
ws.onopen = () => {
ws.send(JSON.stringify({
room_id: 'lobby',
player_name: 'Player' + Math.floor(Math.random() * 1000)
}));
};
// Handle incoming messages
ws.onmessage = (event) => {
const data = JSON.parse(event.data);
switch (data.type) {
case 'welcome':
myId = data.your_id;
players = data.players;
break;
case 'player_joined':
console.log(data.player_name + ' joined!');
break;
case 'player_moved':
if (players[data.player_id]) {
players[data.player_id].x = data.x;
players[data.player_id].y = data.y;
}
break;
case 'player_left':
delete players[data.player_id];
console.log(data.player_name + ' left');
break;
}
};
// Send cursor position on mouse move
canvas.addEventListener('mousemove', (e) => {
if (ws.readyState === WebSocket.OPEN && myId) {
ws.send(JSON.stringify({
action: 'move',
x: e.clientX,
y: e.clientY
}));
// Update local state immediately
if (players[myId]) {
players[myId].x = e.clientX;
players[myId].y = e.clientY;
}
}
});
// Render loop
function render() {
ctx.fillStyle = '#1a1a2e';
ctx.fillRect(0, 0, canvas.width, canvas.height);
// Draw all players
for (const [id, player] of Object.entries(players)) {
ctx.fillStyle = player.color || '#fff';
ctx.beginPath();
ctx.arc(player.x, player.y, 10, 0, Math.PI * 2);
ctx.fill();
// Draw name
ctx.fillStyle = '#fff';
ctx.font = '14px Arial';
ctx.fillText(player.name, player.x + 15, player.y + 5);
}
requestAnimationFrame(render);
}
render();
</script>
</body>
</html>
Test It Out!
- Open the HTML file in multiple browser tabs
- Move your mouse - you should see cursors from other tabs
- Each player has a different color and name
Next Steps
Add Game Loop
Learn how to use on_tick for continuous game updates
API Reference
Explore all available methods and objects
Examples
See more complete game examples
Best Practices
Tips for production-ready multiplayer apps
