Describe the slider, joint motors and Joint position (#154)

Physics gets the slider with its rail and distance limits, the motor
on hinge and slider, the weak hinge motor on a long arm and the node
Joint position.

- Behaviors lists Joint position, Concepts names the slider.
- Development carries the e2e total of 1701.
admin committed 2026-10-03 10:10:09 +02:00
1 parent 8a9c36f21e
commit 5f53111750
4 files changed
+38 -9

No files matched your search

+1 -1
@@ -229,7 +229,7 @@ playing use the same two words.
float noise, a relative 1e-9, so `time - late == 6` holds without a `Round`; `Equals` does the
same for two numbers, and for a number against a typed text that is a number, like `130`), `And/Or/Not`, `Key is down`,
`Key was pressed` and `Key was released` (true for the one frame in which the key went down or came up, the frame `On key down` and `On key up` fire in; a key that stays held is not pressed again),
`Mouse position`, `Mouse button`, `Is hovered`, `Is touching`, `Layer of` (the collision layer of an object by name and number, see [Colliders](Colliders)), `Animation playing` (whether an animation runs on an object, its progress and time left) and `Animation length` (see [Animations](Animations)), `Get velocity`, `Current state` (name and id), `Is in state` (one boolean per state) ·
`Mouse position`, `Mouse button`, `Is hovered`, `Is touching`, `Layer of` (the collision layer of an object by name and number, see [Colliders](Colliders)), `Animation playing` (whether an animation runs on an object, its progress and time left) and `Animation length` (see [Animations](Animations)), `Get velocity`, `Joint position` (how far a hinge or a slider stands from how it was placed, see [Physics](Physics#joints)), `Current state` (name and id), `Is in state` (one boolean per state) ·
actions `Move` (dx, dy, scale, dt — connect an event's dt for per-second movement; in the object's own axes, which a turned parent turns too; with *Collide with solids* it slides along what it hits, less friction, and outputs `blocked x/y`, `hit` and the contact `normal x/y`, see [Colliders](Colliders)), `Set position`, `Spawn`
(asset input + x/y/z, optional parent → outputs the new object; the asset is picked on the node or arrives over an edge, from an `Asset` node, a variable or a list item. A pick saved while it was still a setting reads as that input's value, so older projects spawn as before; the same holds for the asset of `Is asset`), `Destroy` (removes the object with everything below it; with **keep children** on, only the object goes: its children move up to its parent (top level when it had none) and keep their place, rotation and size in the world, and the output `children` is the list of them, nearest level only. Its behaviors, its rigidbody and its joints go with it either way. In the editor run, children that are content of a placed container move up for the run only: their place belongs to the template, so the scene does not learn it), `Add joint` (ties an object to another while the game runs: the picked Joint asset is placed on *object* at x/y and connected to *connected*, the scene when nothing arrives; outputs the new joint, which `Destroy` lets go again, see [Physics](Physics#joints)), `Emit` (starts a particle source over, see *Particles*),
`Play sound` / `Stop sound` (see [Sounds](Sounds): the asset says how loud and whether it loops, the node's
+1 -1
@@ -20,7 +20,7 @@
| **Collider** | A shape (box or circle) for collision detection, placed as a **child** of the object it belongs to (its *body*). Drawn as a green outline in edit mode only; its area is tinted only while the collider itself is selected. |
| **Collision layer** | One of up to 16 named layers of the project (**menu → Project settings…**). A collider or tilemap names the layer it is on and the layers it **collides with**; two of them meet only when each one names the layer of the other. A new project has one layer, *Default*, which every collider is on and meets — so nothing collides differently until a layer is named. See [Colliders](Colliders#collision-layers). |
| **Rigidbody** | Placed as a **child** of an object, it hands that object to the physics engine while playing: it falls with the scene's gravity, bounces and rests on colliders, pushed by what it meets. At most one per object. See [Physics](Physics). |
| **Joint** | Placed as a **child** of an object with a rigidbody, it ties that object to another one or to the scene while playing: a hinge, a spring, a rope or a fixed joint. Where it sits is the point it holds. See [Physics](Physics#joints). |
| **Joint** | Placed as a **child** of an object with a rigidbody, it ties that object to another one or to the scene while playing: a hinge, a spring, a rope, a fixed joint or a slider. Where it sits is the point it holds. See [Physics](Physics#joints). |
| **Override** | A per-object value that replaces the asset's value for one property. Only changed keys are stored; the inspector paints their label gold and offers a reset (↺) and an **apply** (↑) that writes the value into the asset instead. Both appear only where the value really differs from its base — an override carrying the asset's own value is none. |
| **Default** | Every property has a schema default. Asset values that differ from it are marked gold in the inspector and can be reset (↺) the same way an override can. The asset's name in the **Assets** panel carries the same gold while any of them does (`assetDeviates`, `src/core/properties/deviation.ts` — the inspector marks the rows of that same schema, so the list cannot claim a deviation the inspector then fails to show). A behavior's variables are not in it: their default is declared on the variable itself, so the asset value cannot differ from it. |
| **Instance** | An object resolved from a placed container's template. Its **values** can be edited — position, name, property overrides — and only what actually deviates is stored, as a sparse `instanceEdits` entry on the container object keyed by the template path. Everything else keeps following the template. Its **structure** cannot: it can not be removed, re-parented or given a collider, and nothing of the scene can be parented into it. ↺ ▾ resets to the nearest base, which inside a container is the **template as the containers in between leave it**; ↑ ▾ offers **Apply to container** (write the value into the template, where every other instance still at the old value picks it up) and/or **Apply to asset** (which drops the template's override as well). With one base left the menu collapses to a plain ↺ / ↑, with none the buttons disappear. Gold marks the same thing the buttons offer. |
+1 -1
@@ -18,7 +18,7 @@ php tests/php/accounts.test.php # the API's accoun
# has and the web server's container has not (SKIP there)
php tests/php/snapshots.test.php # the snapshot store (#231), the same way
php tests/php/releases.test.php # the release store (#266), the same way
node tools/seed-e2e.mjs && node tools/e2e.mjs # 1699 editor checks, screenshots in /tmp/gm-e2e-*.png
node tools/seed-e2e.mjs && node tools/e2e.mjs # 1701 editor checks, screenshots in /tmp/gm-e2e-*.png
GM_STEPS=20 node tools/e2e.mjs # or 1-12, or 6,20 — a subset while working on one step
./e2e.sh start [GM_STEPS] # the same run detached, see below
./e2e.sh status # live progress, or the last run's result
+35 -6
@@ -146,6 +146,7 @@ body's colliders, since the group sits on the collider itself.
| **Set velocity** | Sets the speed in units per second, whatever the body weighs. For one direction only, feed the other from `Get velocity`. |
| **Set angular velocity** | Sets the turning speed in degrees per second, counted like the rotation. A body with *Fixed rotation* does not turn, and does not start to later either. |
| **Get velocity** | Speed (x, y) and turning speed (degrees/s); 0 for an object without a dynamic body. |
| **Joint position** | How far a hinge has turned or a slider has glided from how it was placed, and how fast; see [Joints](#joints). |
| **Set gravity** | The scene's gravity for the rest of the run; the next scene starts with its own, and the project keeps its value. |
The object is the one the rigidbody sits on (the rigidbody itself works too). They act on a
@@ -174,15 +175,27 @@ Its rows:
| Row | Default | What it does |
|---|---|---|
| Type | Hinge | **Hinge**: the object turns round the point where the joint sits (a door, a pendulum, a wheel). **Spring**: pulled towards a length, swinging about it. **Rope**: free up to a length, held beyond it. **Fixed**: kept exactly as the two were placed, moving as one. |
| Type | Hinge | **Hinge**: the object turns round the point where the joint sits (a door, a pendulum, a wheel). **Spring**: pulled towards a length, swinging about it. **Rope**: free up to a length, held beyond it. **Fixed**: kept exactly as the two were placed, moving as one. **Slider**: the object glides along one line and does not turn against the other end (a lift, a piston, a drawer). |
| Connected object | None | The other end, picked from the objects of the scene or with the eyedropper. None is a point of the scene that never moves. |
| Connected anchor X / Y | 0, 0 | Spring and rope only: where the other end is, in the connected object's own units (0, 0 is its origin, and it turns and scales with it) — with no connected object, in the scene's. A hinge and a fixed joint have one point only, the one the joint sits on. |
| Length (0 = as placed) | 0 | Spring and rope only: the length the spring rests at or the rope allows, in world units. 0 takes the distance between the two ends as they were placed. |
| Stiffness | 50 | Spring only: the force per 100 units of stretch (N/m). A body of 1 kg on 40 swings once in 0.99 s. |
| Damping | 1 | Spring only: how fast the swinging dies down; 0 swings on. |
| Limit angle | off | Hinge only. On: **Min angle** and **Max angle** say how far the object turns either way, in degrees, counted from how it was placed. |
| Limit distance | off | Slider only. On: **Min distance** (default -100) and **Max distance** (100) say how far the object glides either way, in world units, counted from where it was placed. |
| Motor | Off | Hinge and slider only. **Speed**: turns or glides on at *Motor speed*. **Target**: goes to *Motor target* at no more than *Motor speed*, slows down for the last stretch and holds there. |
| Motor speed | 90 | Degrees a second for a hinge, world units a second for a slider. Positive turns the way a positive rotation does (clockwise on screen), or glides along the rail's direction. |
| Motor target | 0 | Target only: where to go, in degrees or world units counted from how the joint was placed, like the limits. |
| Max force (0 = no limit) | 0 | Speed and Target: the most the motor pushes with, in units · kg per second² as `Apply force` counts; for a hinge, pushing 100 units from its pin. Something heavier or in the way stops it. 0 is as strong as it takes. |
| Collide with connected | off | Off: the two objects of the joint pass through each other. On: they collide like any two. |
A joint has **Scale, Rotation and Mirror X/Y** like a sprite, and the knob of the scene view turns
it. Only a slider uses them: **its rail is the joint's own x axis**, so rotation 0 is a level rail
and 90 an upright one whose positive direction points down. The joint turns with the object it sits
on, as every child does. A slider held to the scene, or to an object without a rigidbody, keeps its
object turned as it was placed. Between two rigidbodies the engine keeps the two at one angle, so
it turns the held object to match the other once, and the console says so.
**The object needs a rigidbody**, its own or one of an object above it. Without one the joint holds
nothing and the console says so once: `Physics: "Lamp joint" sits on an object without a rigidbody,
so it holds nothing.`
@@ -202,19 +215,35 @@ In the **scene view** a line leads from the joint to what it holds on to: to the
of a spring or a rope, to the connected object of a hinge or a fixed joint. The held point is
ringed, since the icon stands aside when it shares the spot with a collider's. A selected spring or
rope has a round **handle** on its far end: drag it to move the connected anchor (one undo step).
A slider also gets its **rail**, dashed through where the joint sits: between its limits, with a
tick at each, or 60 units either way without any. While the game is played the rail is drawn where
the joint is, so it travels along with the object.
A joint that is switched off lets go, and holds again when it is switched back on. `Destroy` on a
joint lets go for good. **`Add joint`** ties two objects while the game runs: it places the picked
Joint asset on *object* at (x, y) of that object, connects it to *connected* (nothing there: the
scene) and outputs the new joint. The asset is the template for the type and every value;
`Properties` with Type *Joint* changes them on a placed joint.
`Properties` with Type *Joint* changes them on a placed joint. Setting *Motor speed*, *Motor
target* or *Max force* that way changes the running motor, so a door opens by writing 90 into its
target. **`Joint position`** reads a hinge or a slider back: *value* is how far it has turned
(degrees, counting on past a full round) or glided (world units) from how it was placed, and
*speed* how fast that changes. It is 0 for the other types, for a joint that holds nothing, and in
the editor run.
A motor pushes on the turn only, so a hinge drives a door well but is weak on a small object at the
end of a long arm. Measured: a door of 100 x 20 hinged at its end reaches -90 degrees and holds it
against gravity. A box of 20 on an arm of 100 at the same 180 degrees a second swings past a target
of 90 to 105 without gravity, and with gravity it does not lift itself. The engine works the turn
out over too few rounds for that. A wheel turning round its own middle has no such trouble.
Joints hold while the game is **played**. The editor run simulates nothing (#148), so there they do
nothing, and the inspector of a placed joint says so.
Measured in the unit tests: a pendulum of 100 units crosses the middle after 0.50 s (2.007 s the
whole period), a spring of 40 N/m on 1 kg turns round after 0.50 s, a rope of 150 lets a body fall
to 150 and no further, and a hinge limited to 30 degrees stops between 27 and 33.
to 150 and no further, and a hinge limited to 30 degrees stops between 27 and 33. A wheel with a
motor of 360 degrees a second has turned 880 to 905 degrees after 2.5 s, a lift driven to -200
holds there, and a slider limited to 50 stops between 48 and 52.
## Play and the editor run
@@ -234,6 +263,6 @@ are placed, because what the editor run moves is saved. The nodes above do nothi
crates), kept a gap of up to 1.7 units and knows no friction; `Move` works out its contacts itself,
in double precision, and slides over the same seams without catching (#150).
- The simulation in the editor run (#148).
- A slider joint, and motors on a hinge (#154, second step). Raycasts (#153) with their layer
filter (#158), `Raycast all` with every hit on the line (#157), one-way platforms (#155) and the
collision layers themselves (#152) are there, see [Colliders](Colliders#raycast).
- A force that breaks a joint. Raycasts (#153) with their layer filter (#158), `Raycast all` with
every hit on the line (#157), one-way platforms (#155) and the collision layers themselves (#152)
are there, see [Colliders](Colliders#raycast).