Keep the call in the game
Three.js draws your world. Freehop connects the people in it. Your application controls gameplay, player identity, camera permissions and the interface.
This guide describes how to add comms to your own Three.js scene. For working examples of the calling layer, try Hopper or the live demo.
Divide the responsibilities
| Piece | Responsibility |
|---|---|
| Three.js | Scene, camera, geometry and render loop |
| Your game | Rules, input, collision checks, scoring and validation |
| Freehop | Peer connections, media controls and small messages |
| Your backend | Authentication, room admission, ticket delivery and authoritative state where needed |
The calling demos use public tracker introductions and a secret in the invite URL fragment. Anyone with that link can join. A production platform should use its own authenticated ticket flow; see Quickstart.
Add comms to your scene
import { connect } from 'freehop';
// Fetch a ticket from your own authenticated backend first.
const session = await connect(ticket, {
media: { audio: false, video: false },
adaptiveVideo: true
});
// Ask for devices when the player chooses to enable them.
micButton.onclick = () => session.setMicrophone(true);
cameraButton.onclick = () => session.setCamera(true);
session.on('track', ({ peer, track }) => {
session.attach(track, mediaElementFor(peer));
});
session.on('path', ({ peer, kind }) => {
showConnectionPath(peer, kind);
});
mediaElementFor and showConnectionPath are your application’s helpers. Attach audio tracks to audible media elements and handle browsers that require a user gesture to start playback. Camera textures inside a 3D scene are an optional Three.js integration; the calling demos use HTML video panels.
Send small game events
await session.send({ type: 'ready', ready: true });
session.on('message', ({ from, data }) => {
if (data?.type !== 'ready' || typeof data.ready !== 'boolean') return;
setPlayerReady(from, data.ready);
});
// On route exit or when the player leaves:
await session.leave();
Messages accept JSON values up to 4096 characters, with a receiver limit of 20 messages per second per sender. Throttle movement updates and validate all received data. This is suitable for a prototype’s positions, ready states and small interactions. Competitive games need their own authoritative simulation, anti-cheat and reconciliation; Freehop does not provide them.
Build on the SDK
- Client reference: session lifecycle, media controls, messages and events.
- Hopper source: a complete calling interface to adapt to your application.
- Three.js documentation: the rendering API.
- Desktop SDK: use the same client in Electron and optionally offer a participant gateway.
Understand the network boundary
Gates carry sealed signalling and never media. Direct paths can expose network addresses to other participants. Strict NATs and UDP-blocking networks may remain unreachable in a browser-only room; a suitable session host or desktop gateway can offer another route, and so can your own TURN relay if you opt in (turn). Forwarding through a participant decodes and re-encodes media. See Security and Limits.