Fixed Timestep with State Interpolation
// move your mouse around - click to reversefunction attrs(el, a) {
for (let k in a) el.setAttribute(k, a[k])
return el}document.body.style.margin = '0'
document.body.style.overflow = 'hidden'
document.body.style.background = '#ccc'
const NS = 'http://www.w3.org/2000/svg'
const svg = document.createElementNS(NS, 'svg')
document.body.appendChild(svg)
Object.assign(svg.style, {
display: 'block',
background: 'white'
})
function resize() {
attrs(svg, { width: innerWidth, height: innerHeight })
}resize()
const line = attrs(
document.createElementNS(NS, 'line'),
{ stroke: 'black' }
)svg.appendChild(line)
const circ = attrs(
document.createElementNS(NS, 'circle'),
{ r: 10, fill: 'red' }
)svg.appendChild(circ)
let mouseX = 0, mouseY = 0
let bx = 0, by = 0
let x = 0, y = 0
let px = 0, py = 0
const HZ = 60
const DT = 1 / HZ
let accumulator = 0
let lastTime = performance.now()
onmousemove = e => {
mouseX = e.pageX
mouseY = e.pageY
}ontouchmove = e => {
e.preventDefault()
const t = e.touches[0]
mouseX = t.pageX
mouseY = t.pageY
}onclick = () => {
bx *= -1
by *= -1
}function update() {
const now = performance.now()
let frameTime = (now - lastTime) * 0.001
lastTime = nowif (frameTime > 0.25) frameTime = 0.25
accumulator += frameTimewhile (accumulator >= DT) {
px = xpy = yx -= bxy -= bybx = ((x - mouseX) / 17 + bx) / 1.05
by = ((y - mouseY) / 17 + by) / 1.05
accumulator -= DT}render(accumulator / DT)
requestAnimationFrame(update)
}function render(alpha) {
const dx = x * alpha + px * (1 - alpha)
const dy = y * alpha + py * (1 - alpha)
attrs(circ, { cx: dx, cy: dy })
attrs(line, {
x1: mouseX, y1: mouseY,
x2: dx, y2: dy
})
}requestAnimationFrame(update)
onresize = resize
Used Gemini 3 Pro to create this nice smooth “Fixed Timestep with State Interpolation”. This yoyo thing is an old experiment I made to run on an iPhone 3 I think… back before canvas was hardware accelerated and SVG was faster – original version used Raphael.js – timestep logic comes from this well known article: https://gafferongames.com/post/fix_your_timestep/ by Glenn Fiedler.