Rendering
gamehoster-frontend-render.js runs every animation frame. Read the world off
Gamehoster.Instance,
Gamehoster.Players and
Gamehoster.Entities, and draw it into the context you set
up in setup. The fields you read are already interpolated for this frame,
so draw them straight.
The frame clock
Gamehoster.Frame gives the timing for the frame being
drawn.
| Field | Holds |
|---|---|
number | the frame count since boot |
time | seconds since boot |
dt | seconds since the previous frame |
tick | the render clock's tick, the point the world is interpolated to |
var ctx = Gamehoster.Persistent.Get('ctx')
ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height)
var me = Gamehoster.Players.self
if (me) drawShip(ctx, me.x, me.y, me.angle)
for (var p of Gamehoster.Players.values()) if (!p.self) drawShip(ctx, p.x, p.y, p.angle)
for (var rock of Gamehoster.Entities.ofType('rock')) drawRock(ctx, rock, Gamehoster.Frame.tick)
How interpolation works
The library keeps the drawn world a fixed buffer behind the server's leading edge, so a straddling pair of samples is always on hand and every read is smooth.
- each object keeps tick-stamped samples
- the render point sits a fixed buffer behind the server's leading edge
- numeric fields lerp between the two straddling samples, wrapped axes taken the short way
- other fields snap to the newer sample
- ballistic entities compute their position from a formula rather than a sample stream
- a
-smooth.jsbody may override any field for one object
Any target
The renderer is target-agnostic. Draw the world into a 2D or 3D canvas, an SVG, or plain HTML elements. The abstraction reads the same interpolated world whichever you draw into, so the choice of target is yours.