Document frame collision and tile surfaces (#193)
- Colliders: the shape "Frame collision", how it is measured and when it turns red. - Physics, Tiles, Tilemaps: friction and bounciness on a tile, and why cells of different surfaces never merge. - Textures: an outline drawn on a frame can serve as a collider. - Architecture: frameOutline.ts and the surface grouping. - Development: check sum 1198. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
1 parent
102ab47430
commit
a79833f4bb
7 files changed
+33
-7
No files matched your search
+1
-1
@@ -68,7 +68,7 @@
|
|||||||
|
|
||||||
```
|
```
|
||||||
web/index.html Vite source page (dev) index.html built page (generated, served)
|
web/index.html Vite source page (dev) index.html built page (generated, served)
|
||||||
src/core/model/ Project (object holders), Asset + AssetTypes, SceneObject, Properties (value types), hierarchy, walk (generic parent/child walks), instance (container content resolved from its template), usages (where an asset is used), container (the cycle guard), placement (what may be dropped where), texture (frames, the slice grid, a frame's collision outlines), generated (pictures that are drawn rather than uploaded, #185: the key `gen:<assetId>@<revision>` and the register of readers that tell the picture path an asset's canvas size and revision), vectorart (#129: the canvas as a property, which ring is worth drawing, and the revision as a fingerprint of the drawing rather than a counter) + vectorPath (what a shape draws, as plain commands: closed rings fill, every ring strokes, a segment is a line while neither of its ends carries a handle), polygon (an outline checked, cut into convex pieces and clipped to a rectangle), tile (the three kinds and their block shapes, reading a tile's pictures, the animation step), autotile (which quarter tile a neighbourhood asks for, the 47/16 tiles a block produces, 1 for a plain tile), tilemap (the cells of a layer, which neighbours a cell is joined to, the cells a stroke or a rectangle covers), tilemapCollision (the solid cells of a map, drawn in or out by their tile's collision scale and merged into rectangles, the outlined cells as polygons — an autotile's outlines cut into its quarters and pieced together per cell like its picture —, where one sits in the world, and which cells of a placed map a world rectangle can reach, in cells (`cellsWithin`, #184)), animation (which frame at time t, a row's value there, what a row may aim at, the players on an object; KeyRef and its lookups) + animationPreview (the root at a frame, written into copies), graphLookup (what a graph sees of the project: behaviors to run, state machines to read), Scope (where a state machine's current state lives: per instance or one for the run — variables are shared by living on a Variables asset instead), collisionLayers (which colliders may meet: the project's named layers, a collider's layer and mask, and the one rule `layersMeet` the engine, Solids and the event pair search all answer by)
|
src/core/model/ Project (object holders), Asset + AssetTypes, SceneObject, Properties (value types), hierarchy, walk (generic parent/child walks), instance (container content resolved from its template), usages (where an asset is used), container (the cycle guard), placement (what may be dropped where), texture (frames, the slice grid, a frame's collision outlines), frameOutline (#193: a frame's outlines as a collider wears them, centred, a pixel to a unit, cut into pieces once per drawn list), generated (pictures that are drawn rather than uploaded, #185: the key `gen:<assetId>@<revision>` and the register of readers that tell the picture path an asset's canvas size and revision), vectorart (#129: the canvas as a property, which ring is worth drawing, and the revision as a fingerprint of the drawing rather than a counter) + vectorPath (what a shape draws, as plain commands: closed rings fill, every ring strokes, a segment is a line while neither of its ends carries a handle), polygon (an outline checked, cut into convex pieces and clipped to a rectangle), tile (the three kinds and their block shapes, reading a tile's pictures, the animation step), autotile (which quarter tile a neighbourhood asks for, the 47/16 tiles a block produces, 1 for a plain tile), tilemap (the cells of a layer, which neighbours a cell is joined to, the cells a stroke or a rectangle covers), tilemapCollision (the solid cells of a map, drawn in or out by their tile's collision scale and merged into rectangles, one group per one-way angle and per surface (`tileMaterials`, #193), the outlined cells as polygons — an autotile's outlines cut into its quarters and pieced together per cell like its picture —, where one sits in the world, and which cells of a placed map a world rectangle can reach, in cells (`cellsWithin`, #184)), animation (which frame at time t, a row's value there, what a row may aim at, the players on an object; KeyRef and its lookups) + animationPreview (the root at a frame, written into copies), graphLookup (what a graph sees of the project: behaviors to run, state machines to read), Scope (where a state machine's current state lives: per instance or one for the run — variables are shared by living on a Variables asset instead), collisionLayers (which colliders may meet: the project's named layers, a collider's layer and mask, and the one rule `layersMeet` the engine, Solids and the event pair search all answer by)
|
||||||
src/core/properties/ PropertySchema, kinds (one row per value kind), listItems (an item's kind, read off its value), resolve (the only override merge), deviation (what is gold), collider/camera/bounds geometry (with the side a one-way collider blocks from, and the rectangle around a shape a broad phase looks at first, #184), convex (capsules and polygons: rounded convex pieces against each other), ray (where a ray meets a shape, in double precision), rigidbody (what the engine reads off a rigidbody, a collider's material and the scene), aspect, enabled, editorRun, assetRef/textureRef (how a reference reads), declaredRows (the row a Property node declares in a shader or particle graph, and the params that node has in both)
|
src/core/properties/ PropertySchema, kinds (one row per value kind), listItems (an item's kind, read off its value), resolve (the only override merge), deviation (what is gold), collider/camera/bounds geometry (with the side a one-way collider blocks from, and the rectangle around a shape a broad phase looks at first, #184), convex (capsules and polygons: rounded convex pieces against each other), ray (where a ray meets a shape, in double precision), rigidbody (what the engine reads off a rigidbody, a collider's material and the scene), aspect, enabled, editorRun, assetRef/textureRef (how a reference reads), declaredRows (the row a Property node declares in a shader or particle graph, and the params that node has in both)
|
||||||
src/core/util/ list (take out, put back and move an item — what a command's undo is made of), vec (dot, the closest point on a segment — shared by the collider maths, the outline hit area and the polygon grips)
|
src/core/util/ list (take out, put back and move an item — what a command's undo is made of), vec (dot, the closest point on a segment — shared by the collider maths, the outline hit area and the polygon grips)
|
||||||
src/core/commands/ undoable commands, CommandStack, SetBagValueCommand base, RenameCommand base (undone by renaming back: variable, struct field, port), one import command shape for texture/font/sound, require.ts (validated lookups, and what an instance may not change), naming.ts
|
src/core/commands/ undoable commands, CommandStack, SetBagValueCommand base, RenameCommand base (undone by renaming back: variable, struct field, port), one import command shape for texture/font/sound, require.ts (validated lookups, and what an instance may not change), naming.ts
|
||||||
|
|||||||
+13
-2
@@ -1,4 +1,4 @@
|
|||||||
A **collider** is an asset (`shape` box, circle, capsule or polygon — see
|
A **collider** is an asset (`shape` box, circle, capsule, polygon or frame collision — see
|
||||||
[Shapes](#shapes)) placed like any
|
[Shapes](#shapes)) placed like any
|
||||||
other object — typically as a child of the sprite it belongs to, so its position is the offset
|
other object — typically as a child of the sprite it belongs to, so its position is the offset
|
||||||
from that *body* and it moves with it. Right-click an object in **Scene objects** → *Add
|
from that *body* and it moves with it. Right-click an object in **Scene objects** → *Add
|
||||||
@@ -28,6 +28,17 @@ its slant.
|
|||||||
A polygon may be concave: it is cut into convex pieces (ear clipping, then the cuts that are not
|
A polygon may be concave: it is cut into convex pieces (ear clipping, then the cuts that are not
|
||||||
needed are joined again), which is what collision works with. One that crosses itself or has no
|
needed are joined again), which is what collision works with. One that crosses itself or has no
|
||||||
area is drawn **red** and collides with nothing.
|
area is drawn **red** and collides with nothing.
|
||||||
|
- **Frame collision** (#193) — wears the collision outlines of a texture frame, the ones drawn in the
|
||||||
|
Texture tab for tiles (see [Textures](Textures#collision-outline)). The **Frame** row picks the
|
||||||
|
frame like a sprite's texture. The collider stays **linked**: redraw the outline and every collider
|
||||||
|
wearing that frame blocks with the new one, in the editor and in the next Play. The frame is
|
||||||
|
centred on the collider's origin, one image pixel to one unit, so a collider on a sprite of that
|
||||||
|
frame at its own size lies exactly over the picture. It turns, grows and mirrors with the object
|
||||||
|
like any shape. A frame with several outlines blocks with all of them, each cut into convex pieces
|
||||||
|
like a polygon. The corners are edited in the Texture tab, not in the scene view. Without a frame,
|
||||||
|
with a whole texture instead of a frame, or on a frame nobody outlined, the collider is drawn
|
||||||
|
**red** as a box and collides with nothing: the frame's box when there is one, else its own
|
||||||
|
`width` × `height`.
|
||||||
|
|
||||||
Box against box, circle against circle and box against circle keep their own exact tests. Every
|
Box against box, circle against circle and box against circle keep their own exact tests. Every
|
||||||
pair with a capsule or a polygon goes one common way (`core/properties/convex.ts`): each shape is a
|
pair with a capsule or a polygon goes one common way (`core/properties/convex.ts`): each shape is a
|
||||||
@@ -55,7 +66,7 @@ which a turned parent turns as well — until one runs into a solid collider; th
|
|||||||
flush (`exitDistance` in `collider.ts`: the travel at which the shapes stop overlapping). What is left
|
flush (`exitDistance` in `collider.ts`: the travel at which the shapes stop overlapping). What is left
|
||||||
of the move then goes on **along the surface**: the part into it is dropped, and the part along it
|
of the move then goes on **along the surface**: the part into it is dropped, and the part along it
|
||||||
is shortened by **friction × the part into it** (Coulomb; the pair's friction is the average of both
|
is shortened by **friction × the part into it** (Coulomb; the pair's friction is the average of both
|
||||||
colliders, a tile counts 0.5). The contact's normal decides which way "along" is, so a circle that
|
colliders, a solid tile brings its own, see [Physics](Physics#the-material)). The contact's normal decides which way "along" is, so a circle that
|
||||||
runs into an edge rolls up over it, an object pressed onto a slope slides down it unless the pair
|
runs into an edge rolls up over it, an object pressed onto a slope slides down it unless the pair
|
||||||
is rough enough to hold it (friction ≥ tan of the slope), and one pressed against a wall slides
|
is rough enough to hold it (friction ≥ tan of the slope), and one pressed against a wall slides
|
||||||
along it the slower the harder it presses. Up to four contacts are followed per move (a corner
|
along it the slower the harder it presses. Up to four contacts are followed per move (a corner
|
||||||
|
|||||||
+1
-1
@@ -13,7 +13,7 @@ npm run check # typecheck + lint + format:check + tests, the gate CI runs
|
|||||||
npm run build # writes dist/ and regenerates index.html
|
npm run build # writes dist/ and regenerates index.html
|
||||||
./build.sh # the same under `set -o pipefail`, for callers that pipe the output
|
./build.sh # the same under `set -o pipefail`, for callers that pipe the output
|
||||||
php tools/make-user.php <name> <password> # an account; every tool signs in (see Accounts)
|
php tools/make-user.php <name> <password> # an account; every tool signs in (see Accounts)
|
||||||
node tools/seed-e2e.mjs && node tools/e2e.mjs # 1195 editor checks, screenshots in /tmp/gm-e2e-*.png
|
node tools/seed-e2e.mjs && node tools/e2e.mjs # 1198 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
|
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 start [GM_STEPS] # the same run detached, see below
|
||||||
./e2e.sh status # live progress, or the last run's result
|
./e2e.sh status # live progress, or the last run's result
|
||||||
|
|||||||
+8
-2
@@ -41,10 +41,16 @@ Every collider has three more rows, read wherever a rigidbody takes part:
|
|||||||
|
|
||||||
A trigger (`isTrigger`) weighs nothing and never pushes; it only reports.
|
A trigger (`isTrigger`) weighs nothing and never pushes; it only reports.
|
||||||
|
|
||||||
|
A **solid tile** has Friction and Bounciness too (#193), with the same defaults and the same
|
||||||
|
mixing, shown in the inspector once *Solid* is on. It has no Density: a map never moves, so what its
|
||||||
|
cells would weigh counts for nothing. Tiles of different surfaces never merge into one rectangle,
|
||||||
|
so an ice patch in a stone floor is its own shape, and `Move` slides along each cell by the tile it
|
||||||
|
belongs to (see [Tilemaps](Tilemaps#collision)). The scene view still outlines the floor as one.
|
||||||
|
|
||||||
## Shapes in the engine
|
## Shapes in the engine
|
||||||
|
|
||||||
A capsule collider is the engine's capsule; a polygon is one convex polygon per piece it is cut
|
A capsule collider is the engine's capsule; a polygon, and a *Frame collision* collider, is one convex polygon
|
||||||
into (see [Colliders](Colliders#shapes)), all on the same body, so a concave shape rests and rolls
|
per piece it is cut into (see [Colliders](Colliders#shapes)), all on the same body, so a concave shape rests and rolls
|
||||||
as the shape it is — a crate dropped into a U lands on its inner floor, not on the lid across the
|
as the shape it is — a crate dropped into a U lands on its inner floor, not on the lid across the
|
||||||
notch. A rigidbody's fixed **Mass** is shared out among the pieces by area, and density weighs each
|
notch. A rigidbody's fixed **Mass** is shared out among the pieces by area, and density weighs each
|
||||||
by its own area.
|
by its own area.
|
||||||
|
|||||||
+2
-1
@@ -74,7 +74,8 @@ wearing *any* of its frames, not just the ones naming the texture directly.
|
|||||||
## Collision outline
|
## Collision outline
|
||||||
|
|
||||||
A frame can carry **outlines** a tile made of it blocks with (#141; see
|
A frame can carry **outlines** a tile made of it blocks with (#141; see
|
||||||
[Tilemaps](Tilemaps#outlined-tiles)). Several, because an autotile's block holds several shapes –
|
[Tilemaps](Tilemaps#outlined-tiles)), and a collider of the shape *Frame collision* too (#193; see
|
||||||
|
[Colliders](Colliders#shapes)). Several, because an autotile's block holds several shapes –
|
||||||
its bordered tile and its notches. Switch **Collision** on in the Texture tab's header: a press
|
its bordered tile and its notches. Switch **Collision** on in the Texture tab's header: a press
|
||||||
then edits the selected frame's outlines instead of the frames.
|
then edits the selected frame's outlines instead of the frames.
|
||||||
|
|
||||||
|
|||||||
+6
@@ -150,6 +150,12 @@ that blocks (#173): where two rectangles or the pieces of outlined cells meet, n
|
|||||||
so a wall of several rectangles or a lake of many pieces shows as one shape. Collision itself keeps
|
so a wall of several rectangles or a lake of many pieces shows as one shape. Collision itself keeps
|
||||||
the pieces.
|
the pieces.
|
||||||
|
|
||||||
|
A solid tile's **Friction** and **Bounciness** (#193) are what a cell of it offers, read by `Move`
|
||||||
|
and by the physics engine like a collider's (see [Physics](Physics#the-material)). Cells of tiles
|
||||||
|
with a different surface are never merged into one rectangle, the same way one-way tiles are kept
|
||||||
|
apart from walls. A tile with a smaller collision scale therefore does not stay flush with a
|
||||||
|
neighbour of another surface: towards it, it is drawn in like towards an open side.
|
||||||
|
|
||||||
A placed tilemap carries **Layer** and **Collides with** like a collider does, for the whole map
|
A placed tilemap carries **Layer** and **Collides with** like a collider does, for the whole map
|
||||||
(see [Colliders](Colliders#collision-layers)): ground only some things walk on is a map on its own
|
(see [Colliders](Colliders#collision-layers)): ground only some things walk on is a map on its own
|
||||||
layer. Per layer of the map or per tile it is not — a cell belongs to the map.
|
layer. Per layer of the map or per tile it is not — a cell belongs to the map.
|
||||||
|
|||||||
+2
@@ -65,6 +65,8 @@ asks for; a picture that does not fit is kept and named, never silently dropped.
|
|||||||
platform one jumps through from below (#155); see [Tilemaps](Tilemaps#one-way-tiles).
|
platform one jumps through from below (#155); see [Tilemaps](Tilemaps#one-way-tiles).
|
||||||
- **One-way angle** — 45 by default, 0 to 90, shown while *One-way* is on. How far a contact may
|
- **One-way angle** — 45 by default, 0 to 90, shown while *One-way* is on. How far a contact may
|
||||||
lean from straight up and still land on the tile (#159).
|
lean from straight up and still land on the tile (#159).
|
||||||
|
- **Friction** and **Bounciness** — 0.5 and 0 by default, shown while *Solid* is on. The surface a
|
||||||
|
cell offers to what meets it, mixed like two colliders' (#193); see [Physics](Physics#the-material).
|
||||||
- **Collision scale** — 1 by default. How big a solid cell blocks against its square, drawn in or
|
- **Collision scale** — 1 by default. How big a solid cell blocks against its square, drawn in or
|
||||||
out only on the sides without a blocking neighbour (#140); see
|
out only on the sides without a blocking neighbour (#140); see
|
||||||
[Tilemaps](Tilemaps#collision-scale).
|
[Tilemaps](Tilemaps#collision-scale).
|
||||||
|
|||||||
Reference in new issue
Block a user