AI EXPERIMENTS

This site is a collection of experiments to explore the range of code we can make using AI tools.

Built with Hono, Deno, JSX/React components and modern web standards.

Focus is on wide range of experiements with a large code base (monorepo) but keep dev sane, fast and fun while keeping performance high.

Mini Experiments

These are small experiments to explore the range of code we can make using AI tools.

Time/Lag Test

How it works

Offset = ServerTime - (T1 + T2)/2

Assumes Symmetric Latency (Request time = Response time). In real networks, asymmetry adds error to the offset.
Animation Speed
1000ms RTT
Feedback Loop
1 Hz
Get the Code

A robust, copy-pasteable TypeScript class for your game.

typescript
export class TimeSync {
  offset = 0;
  rtt = 0;

  async sync() {
    const t1 = Date.now();
    const serverTime = await fetchTime();
    const t2 = Date.now();
    this.rtt = t2 - t1;
    this.offset = serverTime - (t1 + this.rtt/2);
  }

  async syncBatch(count = 10) {
    const offsets = [];
    for(let i=0; i<count; i++) {
      await this.sync();
      offsets.push(this.offset);
    }
    offsets.sort((a,b) => a-b);
    const mid = Math.floor(offsets.length/2);
    this.offset = offsets.length % 2 !== 0 
      ? offsets[mid]
      : (offsets[mid-1] + offsets[mid]) / 2; 
  }

  now() {
    return Date.now() + this.offset;
  }
}

Game Dev Implications

Interpolation Delay

Don't render at exactly ServerTime. Render at ServerTime - 100ms (or 2-3 tick duration) to smooth out jitter and prevent snapping when packets arrive late.

measure vs use

Metrics (this tool) measure the network.Game Clock should be a smooth, monotonically increasing value that chases the measured offset over time, avoiding sudden jumps.

Clock Drift

Hardware clocks vary (drift). You must re-sync periodically (e.g. every 30s) or continuously adjust your game speed (e.g. run at 1.01x speed) to stay aligned without snapping.

Network Concepts

Ping (Latency)

Travel time for a packet to reach the server and back. Measured in ms.

Lower is always better. Depends on distance (speed of light) & routing.

Tick Rate (Frequency)

How often the server processes inputs and updates the world. Measured in Hz.

Low (20Hz)
Minecraft, RPGs. Saves CPU & Bandwidth. Good for slow-paced games.
High (60Hz+)
CS:GO, Valorant. Max precision. High CPU/Net cost.

The Loop

What "20Hz" looks like in code:

typescript
const TICK_MS = 50; // 1000ms / 20Hz

while (serverRunning) {
  const start = Date.now();
  updateGamePhysics();
  broadcastState();

  // Wait for remainder of the 50ms
  await sleep(TICK_MS - (Date.now() - start));
}

Total Delay

Why you lag even with 0ms Ping:

Ping (Travel):20ms
Tick Delay (Wait):+50ms
Real Lag:70ms

Interpolation Lab

WAIT
Network Latency0ms
Server Tick Rate
Interpolation Buffer100ms
0ms250ms500ms
ALPHA: --
BUF: 100ms
typescript
// 1. Find the two snapshots we are between
const T_render = Date.now() - BUFFER_MS;
const A = buffer.find(snap => snap.t <= T_render);
const B = buffer.find(snap => snap.t > T_render);

// 2. Calculate progress (Alpha) 0.0 to 1.0
const progress = (T_render - A.t) / (B.t - A.t);

// 3. Lerp!
const x = lerp(A.x, B.x, progress);

// Helper
function lerp(start, end, alpha) {
  return start + (end - start) * alpha;
}
How it works
1. Why Interpolate?Game servers tick much slower than your 144Hz monitor (often only 20Hz). If we rendered players exactly where the server said they were when the packet arrived, they would teleport 20 times a second (see the Red Ghost).
2. The Problem: JitterInternet latency isn't constant. Some packets arrive fast, others get delayed ("Jitter"). If a packet is late, we run out of data to draw.
3. The Solution: Render in the PastWe deliberately delay rendering ("Buffering") to ensure we always have a future snapshot to move towards.
  • Green Box (Smooth): We have a future snapshot. We can smoothly slide between the past and future.
  • Yellow (Underrun): The buffer was too short! The future packet hasn't arrived yet, so we have to stop or guess.
4. What is Lerp?Short for Linear Interpolation. It means finding a point partway between two others based on a percentage (alpha).
e.g. "I am 50% (alpha=0.5) of the way from point A to point B."
5. What is the Buffer?A **Safety Margin** for data. Just like buffering a video, we deliberately wait (lag) to ensure we have a queue of packets ready to play.
It prevents stuttering when the internet hiccups, but makes the game feel slightly delayed.
6. How do we implement this?We don't draw the *latest* packet. Instead, we keep a list of recent packets. We calculate a `RenderTime = Now - Buffer`. Then we find the two packets surrounding that time (one slightly older, one slightly newer) and blend (Lerp) between them.