Let a graph read and change the z of an object

Until now a behavior could not move an object in front of another
while the game runs. Set position writes only x and y, and z lives on
the running object rather than in its props, so Properties cannot
reach it either. Drawing already reads the z every frame, so only the
nodes were missing.

- Get Z (data): object in, z and world z out. World z is summed up
  with the parents, the way drawing does it (worldTransformOf).
- Set Z (action): object and z in. It sets the object's own z, local
  to its parent like Set position. Higher is drawn in front from the
  next frame on.
- Two nodes of their own rather than a z port on Set position and
  Get position, as asked.

Tests:
- node-catalog: Get Z for a child (2 below 5 is world z 7) and for no
  object, Set Z writes only z and leaves x/y.
- set-z.test.ts: in a running world a key sets the lower of two
  sprites to z 2, drawSlots then draws it in front, Get Z logs 2 and 2.
- Two counter-checks bite: Set Z without the write and Get Z without
  the parent fail 3 tests.
- Gate: 233 files, 3548 tests (3542 + 6), CHECK EXIT 0.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
adminandClaude Opus 5.5 committed 2026-10-03 20:08:35 +02:00
1 parent 3e05cbbed5
commit 8452a99c64
5 files changed
+110

No files matched your search

+18
View File
@@ -0,0 +1,18 @@
import type { NodeDef } from '../../NodeRegistry';
import { asEntity, asNumber } from '../../values';
import { exec, num, obj } from '../shared';
export const SetZ: NodeDef = {
type: 'SetZ',
label: 'Set Z',
category: 'action',
description: 'Sets the z of an object, local to its parent: higher is drawn in front.',
inputs: [exec(), obj('object'), num('z')],
outputs: [exec()],
params: [],
run: (_ctx, inputs) => {
const target = asEntity(inputs.object);
if (target) target.z = asNumber(inputs.z);
return { next: 'exec' };
},
};
+19
View File
@@ -0,0 +1,19 @@
import { worldTransformOf } from '../../NodeContext';
import type { NodeDef } from '../../NodeRegistry';
import { asEntity } from '../../values';
import { num, obj } from '../shared';
export const GetZ: NodeDef = {
type: 'GetZ',
label: 'Get Z',
category: 'data',
description:
'The z of an object, which decides what is drawn in front: local to its parent (z) and summed up (world z).',
inputs: [obj('object')],
outputs: [num('z'), num('worldZ', 'world z')],
params: [],
run: (_ctx, inputs) => {
const target = asEntity(inputs.object);
return { outputs: { z: target?.z ?? 0, worldZ: target ? worldTransformOf(target).z : 0 } };
},
};
+4
View File
@@ -23,6 +23,7 @@ import { Raycast } from './action/Raycast';
import { RaycastAll } from './action/RaycastAll';
import { RestartGame } from './action/RestartGame';
import { SetPosition } from './action/SetPosition';
import { SetZ } from './action/SetZ';
import { Spawn } from './action/Spawn';
import { StopGame } from './action/StopGame';
import { StopSound } from './action/StopSound';
@@ -43,6 +44,7 @@ import { FindText } from './data/FindText';
import { FirstNotEmpty } from './data/FirstNotEmpty';
import { Floor } from './data/Floor';
import { GetPosition } from './data/GetPosition';
import { GetZ } from './data/GetZ';
import { ChildByName } from './data/ChildByName';
import { Children } from './data/Children';
import { ChildrenByName } from './data/ChildrenByName';
@@ -199,6 +201,7 @@ export const BUILT_IN_NODES: readonly NodeDef[] = [
IsEnabled,
Properties,
GetPosition,
GetZ,
TextureSize,
AnimationPlaying,
AnimationLength,
@@ -266,6 +269,7 @@ export const BUILT_IN_NODES: readonly NodeDef[] = [
Move,
MoveToward,
SetPosition,
SetZ,
GetVelocity,
ApplyForce,
ApplyImpulse,