| Typical fps | Common use | Δt = seconds per frame |
|---|---|---|
| 24 fps | Cinema / film | 1/24 ≈ 0.0417 s |
| 30 fps | Television, most web video | 1/30 ≈ 0.0333 s |
| 60 fps | Interactive games, high‑performance UI | 1/60 ≈ 0.0167 s |
Choosing a frame‑rate balances visual smoothness against processing power and file size. For most A‑Level projects 30 fps (smooth) or 60 fps (high‑performance) is recommended.
f(t) = tf(t) = 3t² – 2t³f(t) = t³ · ( t · (6t – 15) + 10 ) (also known as “smoothstep3”).Here t is the normalised progress (0 → 1). The output replaces the simple linear factor Δt in the position update, giving more natural start‑and‑stop motion.
Uniform linear motion (constant velocity):
$$ x_{\text{new}} = x_{\text{old}} + v_x \,\Delta t,\qquad y_{\text{new}} = y_{\text{old}} + v_y \,\Delta t $$
When acceleration is present (e.g., gravity, friction):
$$ v_{x,\text{new}} = v_{x,\text{old}} + a_x \,\Delta t,\qquad v_{y,\text{new}} = v_{y,\text{old}} + a_y \,\Delta t $$
Friction can be modelled as a simple scalar multiplier on velocity each frame (e.g., vX *= 0.98).
Export formats
| Format | Type | Typical use | File‑size considerations |
|---|---|---|---|
| GIF | Lossless (palette‑limited) raster | Simple looping UI effects | Large for many frames; limited to 256 colours. |
| MP4 / WebM | Lossy video (H.264 / VP9) | Pre‑rendered sequences, background videos | High compression → small files, but artefacts at low bitrate. |
| SVG animation | Vector, XML‑based | Scalable UI icons, interactive web graphics | Typically very small; depends on script size. |
| JSON sprite‑sheet data | Metadata (frame coordinates) + PNG sprites | Game character animation | Separate image (PNG) may dominate size; JSON is tiny. |
| Variable | Purpose | Typical initial value |
|---|---|---|
| posX | Horizontal position (px) | 0 |
| posY | Vertical position (px) | 0 |
| velX | Horizontal velocity (px / s) | 100 |
| velY | Vertical velocity (px / s) | 0 |
| accX | Horizontal acceleration (px / s²) | 0 |
| accY | Vertical acceleration (px / s²) – e.g., gravity | 0 |
| friction | Scalar (0 → 1) applied each frame to velocity | 1 (no friction) |
| deltaTime | Time between frames (s) = 1 / fps | 1/60 |
| easingFactor | Result of interpolation function (0 → 1) | 1 (linear) |
requestAnimationFrame).velX += accX * ΔtvelY += accY * ΔtvelX *= friction, velY *= frictionp = elapsed / duration (clamp 0‑1).easingFactor = f(p) using the chosen interpolation.posX += velX * Δt * easingFactorposY += velY * Δt * easingFactor(posX, posY).// -------------------------------------------------
// 1. INITIALISATION
// -------------------------------------------------
let canvasWidth = 800, canvasHeight = 600;
let objectWidth = 50, objectHeight = 50;
let posX = 0;
let posY = 150;
let velX = 120; // px/s
let velY = 0; // px/s
let accX = 0;
let accY = 200; // px/s² – simple “gravity”
let friction = 0.99; // slight air resistance
let deltaTime = 1/60; // fallback value
let useEasing = true;
let duration = 4; // seconds for a full travel
let elapsed = 0;
// -------------------------------------------------
// 2. INTERPOLATION FUNCTION (quadratic smoothstep)
// -------------------------------------------------
function easeInOut(t) {
// t is clamped between 0 and 1
return 3*t*t - 2*t*t*t;
}
// -------------------------------------------------
// 3. ANIMATION LOOP (requestAnimationFrame)
// -------------------------------------------------
let previousTimestamp = performance.now();
function animate(timestamp) {
// ---- 3.1 Calculate real Δt (seconds) ----
deltaTime = (timestamp - previousTimestamp) / 1000; // ms → s
previousTimestamp = timestamp;
// ---- 3.2 Update velocity (acceleration + friction) ----
velX += accX * deltaTime;
velY += accY * deltaTime;
velX *= friction;
velY *= friction;
// ---- 3.3 Easing factor (optional) ----
let easingFactor = 1;
if (useEasing) {
elapsed += deltaTime;
let progress = Math.min(elapsed / duration, 1); // 0 → 1
easingFactor = easeInOut(progress);
}
// ---- 3.4 Update position using easing ----
posX += velX * deltaTime * easingFactor;
posY += velY * deltaTime * easingFactor;
// ---- 3.5 Boundary detection – bounce back ----
if (posX > canvasWidth - objectWidth) {
posX = canvasWidth - objectWidth;
velX = -Math.abs(velX);
}
if (posX < 0) {
posX = 0;
velX = Math.abs(velX);
}
if (posY > canvasHeight - objectHeight) {
posY = canvasHeight - objectHeight;
velY = -Math.abs(velY);
}
if (posY < 0) {
posY = 0;
velY = Math.abs(velY);
}
// ---- 3.6 Render ----
clearCanvas(); // implementation‑specific
drawRectangle(posX, posY, objectWidth, objectHeight, 'steelblue');
// ---- 3.7 Request next frame ----
requestAnimationFrame(animate);
}
// -------------------------------------------------
// 4. START THE LOOP
// -------------------------------------------------
requestAnimationFrame(animate);
sprites[i].posX) and loop through the update/render steps.sourceX / sourceY each render).| Condition | Action |
|---|---|
| posX > canvasWidth – objectWidth | posX = canvasWidth – objectWidth; velX = –|velX| // bounce left |
| posX < 0 | posX = 0; velX = |velX| // bounce right |
| posY > canvasHeight – objectHeight | posY = canvasHeight – objectHeight; velY = –|velY| // bounce up |
| posY < 0 | posY = 0; velY = |velY| // bounce down |
Δt = (currentTimestamp‑previousTimestamp)/1000 and use it in the motion equations?Create an account or Login to take a Quiz
Log in to suggest improvements to this note.
Your generous donation helps us continue providing free Cambridge IGCSE & A-Level resources, past papers, syllabus notes, revision questions, and high-quality online tutoring to students across Kenya.