Add a Lerp node that blends from a to b with an ease (#246)
game-maker / gate (push) Successful in 3m23s
game-maker / suite (push) Failing after 9m24s

Every animation in a behavior had to build its interpolation from
Subtract, Multiply and Add, once per axis. The gold pickup in
"Garden of Sacrifices" needed about 30 nodes for that alone. A single
Lerp node with an ease makes those chains one node each.

- Lerp has the inputs a (default 0), b (1) and t (0) and the output
  result. It sits in the data category next to Clamp.
- The Ease setting offers Linear, In, Out and In-out, all quadratic.
  The node row shows it as "Ease: Out".
- t is held in 0..1. A timer that overshoots in the last frame still
  lands exactly on b.

Tests:
- ./check.sh: 178 files, 2583 tests, CHECK EXIT 0
- 7 new cases in the node catalog test. Without the clamp on t,
  2 of them fail.
- e2e 6z-iii (2 checks): typing "lerp" in the palette adds a linear
  Lerp, and picking "Out" in the inspector reaches the node and its
  row. GM_STEPS=1-6: ALL PASSED, 267 checks.
- README check sum is 1459, computed, not counted.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
adminandClaude Opus 5.5 committed 2026-09-27 14:49:22 +02:00
1 parent 3a3401f8ac
commit 320d3e27e1
5 files changed
+122 -2

No files matched your search

+42
View File
@@ -0,0 +1,42 @@
import type { NodeDef } from '../../NodeRegistry';
import { asNumber } from '../../values';
import { num, withDefault } from '../shared';
import { textOf } from '../../../model/Properties';
/** Quadratic curves over t in 0…1, each running from 0 to 1. */
const EASES: Record<string, (t: number) => number> = {
linear: (t) => t,
in: (t) => t * t,
out: (t) => 1 - (1 - t) * (1 - t),
inOut: (t) => (t < 0.5 ? 2 * t * t : 1 - 2 * (1 - t) * (1 - t)),
};
export const Lerp: NodeDef = {
type: 'Lerp',
label: 'Lerp',
category: 'data',
description: 'Blends from a to b as t runs from 0 to 1, along the chosen ease. t is held in 0…1.',
inputs: [withDefault(num('a'), 0), withDefault(num('b'), 1), withDefault(num('t'), 0)],
outputs: [num('result')],
params: [
{
key: 'ease',
label: 'Ease',
kind: 'enum',
default: 'linear',
options: [
{ value: 'linear', label: 'Linear' },
{ value: 'in', label: 'In' },
{ value: 'out', label: 'Out' },
{ value: 'inOut', label: 'In-out' },
],
},
],
run: (_ctx, inputs, params) => {
const a = asNumber(inputs.a);
const t = Math.min(Math.max(asNumber(inputs.t), 0), 1);
const ease = EASES[textOf(params.ease)] ?? EASES.linear!;
return { outputs: { result: a + (asNumber(inputs.b) - a) * ease(t) } };
},
};
+2
View File
@@ -47,6 +47,7 @@ import { IsTouching } from './data/IsTouching';
import { Join } from './data/Join';
import { KeyIsDown } from './data/KeyIsDown';
import { Length } from './data/Length';
import { Lerp } from './data/Lerp';
import {
AnimationLiteral,
AssetLiteral,
@@ -186,6 +187,7 @@ export const BUILT_IN_NODES: readonly NodeDef[] = [
Abs,
Sqrt,
Clamp,
Lerp,
Floor,
Ceil,
Round,