1 parent
e1e8bbdc98
commit
1ee4e0e41c
7 files changed
+75
-6
No files matched your search
+3
-2
@@ -66,8 +66,8 @@
|
|||||||
|
|
||||||
```
|
```
|
||||||
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 and the slice grid), 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, and where one sits in the world), 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)
|
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 outline), polygon (an outline checked and cut into convex pieces), 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, and where one sits in the world), 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)
|
||||||
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, 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, convex (capsules and polygons: rounded convex pieces against each other), 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/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
|
||||||
src/core/graph/ graph model, NodeRegistry/NodeContext/values, interpreter, dropTarget, nested (behaviors as nodes),
|
src/core/graph/ graph model, NodeRegistry/NodeContext/values, interpreter, dropTarget, nested (behaviors as nodes),
|
||||||
emitGraph (the walk both graph compilers share: each node once, in dependency order; cycles and property names reported),
|
emitGraph (the walk both graph compilers share: each node once, in dependency order; cycles and property names reported),
|
||||||
@@ -96,6 +96,7 @@ src/viewport/ view (transforms), items (what to draw), symbols (how to
|
|||||||
so tests reach it freely
|
so tests reach it freely
|
||||||
src/editor/ App → Editor (layout + ticker), PlaySession (the run), ProjectSession (load/create),
|
src/editor/ App → Editor (layout + ticker), PlaySession (the run), ProjectSession (load/create),
|
||||||
EditorRun (run in editor), state, actions, shortcuts, debugHook, autosave,
|
EditorRun (run in editor), state, actions, shortcuts, debugHook, autosave,
|
||||||
|
polygonEdit (corners of an outline: what is under the pointer, put / move / take away – scene view and Texture tab),
|
||||||
fileImport (drop/paste) → assetImport (one upload pipeline, an ImportKind per sort) ← textureImport / fontImport / soundImport,
|
fileImport (drop/paste) → assetImport (one upload pipeline, an ImportKind per sort) ← textureImport / fontImport / soundImport,
|
||||||
FilePicker (the shared "+ → Texture / Font / Sound" dialog; ImagePicker/FontPicker/SoundPicker only describe their row),
|
FilePicker (the shared "+ → Texture / Font / Sound" dialog; ImagePicker/FontPicker/SoundPicker only describe their row),
|
||||||
framing (fit/marquee/snap maths), FormDialog (the small modal forms: label column, Cancel + confirm, one open at a time), AssetTabEditor (the shared shell of the asset tabs), TabHeader (the bar across the top of a tab – asset tabs, Plugins tab, NodeBoard),
|
framing (fit/marquee/snap maths), FormDialog (the small modal forms: label column, Cancel + confirm, one open at a time), AssetTabEditor (the shared shell of the asset tabs), TabHeader (the bar across the top of a tab – asset tabs, Plugins tab, NodeBoard),
|
||||||
|
|||||||
+27
-2
@@ -1,4 +1,5 @@
|
|||||||
A **collider** is an asset (`shape` box/circle, `width`/`height` or `radius`) placed like any
|
A **collider** is an asset (`shape` box, circle, capsule or polygon – see
|
||||||
|
[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
|
||||||
collider* to get one with one click: a box collider sized like the
|
collider* to get one with one click: a box collider sized like the
|
||||||
@@ -12,6 +13,28 @@ circle grows (see *Transform* in [Scene editing](Scene-editing)). A turned box i
|
|||||||
box it is — separating axes, not its upright frame — so a wall turned by 45 degrees blocks along
|
box it is — separating axes, not its upright frame — so a wall turned by 45 degrees blocks along
|
||||||
its slant.
|
its slant.
|
||||||
|
|
||||||
|
## Shapes
|
||||||
|
|
||||||
|
- **Box** – `width` × `height`.
|
||||||
|
- **Circle** – `radius`.
|
||||||
|
- **Capsule** (#151) – fills `width` × `height` and is rounded along the longer side: its radius is
|
||||||
|
half the shorter side. As wide as tall it is a circle. The shape for a figure that should slide
|
||||||
|
over edges instead of catching on them.
|
||||||
|
- **Polygon** (#151) – `points`, a list of `{x, y}` corners in the collider's own units, so they
|
||||||
|
turn, grow and mirror with the object. A new polygon collider is a triangle. With the collider
|
||||||
|
selected in the scene view every corner has a handle: **drag** a corner to move it, **press on an
|
||||||
|
edge** to put a corner there (and drag it on), **double-click** a corner to take it away – three
|
||||||
|
corners always stay. Each is one undo step. The list can also be edited in the inspector.
|
||||||
|
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
|
||||||
|
area is drawn **red** and collides with nothing.
|
||||||
|
|
||||||
|
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
|
||||||
|
set of convex pieces, each piece a point, a segment or a polygon grown by a radius, and two pieces
|
||||||
|
are tested along their separating axes, apart by their real distance. A square polygon meets
|
||||||
|
everything exactly as the box it stands for – a unit test holds the two against each other.
|
||||||
|
|
||||||
Before the behaviors, every frame sorts the colliders that overlap (world transforms applied;
|
Before the behaviors, every frame sorts the colliders that overlap (world transforms applied;
|
||||||
touching edges do not count) into *enter*, *stay* and *exit*. While playing that is the physics
|
touching edges do not count) into *enter*, *stay* and *exit*. While playing that is the physics
|
||||||
engine's work (`PhysicsSystem`, see [Physics](Physics)), which also simulates rigidbodies; the
|
engine's work (`PhysicsSystem`, see [Physics](Physics)), which also simulates rigidbodies; the
|
||||||
@@ -38,7 +61,9 @@ dynamic body bounces (see [Physics](Physics)). The outputs: `blocked x` / `block
|
|||||||
the object's own axes something stood against (a floor blocks y, a wall x, a slope each axis the
|
the object's own axes something stood against (a floor blocks y, a wall x, a slope each axis the
|
||||||
move went along);
|
move went along);
|
||||||
`hit` whether anything was met; `normal x` / `normal y` which way the first surface faces, in the
|
`hit` whether anything was met; `normal x` / `normal y` which way the first surface faces, in the
|
||||||
world, pointing away from it — enough to build a bounce or a wall jump in the graph. All are `false`
|
world, pointing away from it (where a corner meets a corner of a capsule or polygon, any direction
|
||||||
|
between the two faces is right; the one taken is the one that stands least in the move's way, so a
|
||||||
|
figure walking into the foot of a slope climbs it) — enough to build a bounce or a wall jump in the graph. All are `false`
|
||||||
/ 0 with the setting off. An object without a solid collider of its own moves freely. In Play a
|
/ 0 with the setting off. An object without a solid collider of its own moves freely. In Play a
|
||||||
dynamic body that stops the move is pushed into the contact (see [Physics](Physics)). A collider with
|
dynamic body that stops the move is pushed into the contact (see [Physics](Physics)). A collider with
|
||||||
**Trigger (no blocking)** enabled (`isTrigger`, drawn amber instead of green) still produces
|
**Trigger (no blocking)** enabled (`isTrigger`, drawn amber instead of green) still produces
|
||||||
|
|||||||
+1
-1
@@ -12,7 +12,7 @@ npm run check # typecheck + lint + format:check + tests, the gate CI runs
|
|||||||
# code is lost (tail's is reported), so a red run reads as green
|
# code is lost (tail's is reported), so a red run reads as green
|
||||||
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
|
||||||
node tools/seed-e2e.mjs && node tools/e2e.mjs # 1057 editor checks, screenshots in /tmp/gm-e2e-*.png
|
node tools/seed-e2e.mjs && node tools/e2e.mjs # 1067 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
|
||||||
|
|||||||
+12
-1
@@ -41,6 +41,17 @@ 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.
|
||||||
|
|
||||||
|
## Shapes in the engine
|
||||||
|
|
||||||
|
A capsule collider is the engine's capsule; a polygon is one convex polygon 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
|
||||||
|
notch. A rigidbody's fixed **Mass** is shared out among the pieces by area, and density weighs each
|
||||||
|
by its own area.
|
||||||
|
|
||||||
|
A body that lands fast sinks in a little before the engine pushes it back out: measured 0.9 units
|
||||||
|
for a capsule landing at about 6 units a frame, 0.02 twenty frames later.
|
||||||
|
|
||||||
## Gravity and units
|
## Gravity and units
|
||||||
|
|
||||||
The **scene** has **Gravity X** and **Gravity Y**, default (0, 980). Everything is in world units
|
The **scene** has **Gravity X** and **Gravity Y**, default (0, 980). Everything is in world units
|
||||||
@@ -118,4 +129,4 @@ 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,
|
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).
|
in double precision, and slides over the same seams without catching (#150).
|
||||||
- The simulation in the editor run (#148), and `On collision stay` with contact data (#149).
|
- The simulation in the editor run (#148), and `On collision stay` with contact data (#149).
|
||||||
- Capsules and polygons, collision layers, raycasts, joints, one-way platforms (#144).
|
- Collision layers, raycasts, joints, one-way platforms (#144).
|
||||||
+14
@@ -71,6 +71,20 @@ undo step. Deleting a frame leaves the sprites pointing at it: a dangling refere
|
|||||||
plain colour and comes back by itself on undo. Deleting the whole texture counts the sprites
|
plain colour and comes back by itself on undo. Deleting the whole texture counts the sprites
|
||||||
wearing *any* of its frames, not just the ones naming the texture directly.
|
wearing *any* of its frames, not just the ones naming the texture directly.
|
||||||
|
|
||||||
|
## Collision outline
|
||||||
|
|
||||||
|
A frame can carry an **outline** a tile made of it blocks with (#141; see
|
||||||
|
[Tilemaps](Tilemaps#outlined-tiles)). Switch **Collision** on in the Texture tab's header: a press
|
||||||
|
then edits the selected frame's outline instead of the frames. Click inside the frame to add a
|
||||||
|
corner after the last one – that is how an outline is drawn from nothing –, drag a corner to move
|
||||||
|
it, press on an edge to put a corner there, double-click a corner to take it away. Corners land on
|
||||||
|
whole pixels inside the frame and are stored relative to its top-left corner, so they move with the
|
||||||
|
frame. Every step is one undo step. The outlines of all frames are always shown; one that crosses
|
||||||
|
itself is drawn red. Switch **Collision** off to move and resize frames again.
|
||||||
|
|
||||||
|
When the project is loaded, corners that are no numbers fall away, and an outline with fewer than
|
||||||
|
three corners left is none.
|
||||||
|
|
||||||
## Nine-slice — a frame that keeps its corners
|
## Nine-slice — a frame that keeps its corners
|
||||||
|
|
||||||
A frame carries four **borders** and a **fill**, and a sprite wearing it is drawn as nine parts
|
A frame carries four **borders** and a **fill**, and a sprite wearing it is drawn as nine parts
|
||||||
|
|||||||
+16
@@ -153,6 +153,22 @@ wall of bushes at 0.5 is one narrower wall, not a string of beads with gaps to s
|
|||||||
|
|
||||||
The outline in the scene view shows the drawn-in or grown shapes.
|
The outline in the scene view shows the drawn-in or grown shapes.
|
||||||
|
|
||||||
|
### Outlined tiles
|
||||||
|
|
||||||
|
A plain tile (kind *None*) whose first picture is a frame with a **collision outline** (drawn in
|
||||||
|
the Texture tab, see [Textures](Textures#collision-outline)) blocks with that outline instead of
|
||||||
|
its whole square (#141): a slope, a rock, a tree trunk. The outline is scaled from the frame onto
|
||||||
|
the cell, and the tile's collision scale draws it in or out about the cell's centre. Such cells are
|
||||||
|
not merged – each brings its own polygon – and the scene view outlines each one.
|
||||||
|
|
||||||
|
- Only plain tiles: a floor or wall autotile's cell is pieced together from quarters of a block,
|
||||||
|
where no single frame is the cell. Those keep blocking as their square.
|
||||||
|
- Only the first picture of an animated tile counts: a blocking shape that twitched with the
|
||||||
|
animation is rarely wanted.
|
||||||
|
- A plain solid tile without an outline on another layer of the same cell covers the whole cell,
|
||||||
|
so there the outline is left out.
|
||||||
|
- An outline that crosses itself blocks as the square it would have replaced.
|
||||||
|
|
||||||
In the running game the placed map is a **body of its own** in the collision system:
|
In the running game the placed map is a **body of its own** in the collision system:
|
||||||
|
|
||||||
- **Move** with *Collide with solids* stops at it and slides along it, like at a solid collider.
|
- **Move** with *Collide with solids* stops at it and slides along it, like at a solid collider.
|
||||||
|
|||||||
+2
@@ -63,6 +63,8 @@ asks for; a picture that does not fit is kept and named, never silently dropped.
|
|||||||
- **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).
|
||||||
|
- A plain tile whose picture is a frame with a **collision outline** blocks with that outline
|
||||||
|
instead of its square (#141); see [Tilemaps](Tilemaps#outlined-tiles).
|
||||||
|
|
||||||
Kind, rate, playback, the solid switch and the collision scale are ordinary properties, so the inspector shows them like any other asset's
|
Kind, rate, playback, the solid switch and the collision scale are ordinary properties, so the inspector shows them like any other asset's
|
||||||
— undo, defaults and the gold mark for a non-default value come for free.
|
— undo, defaults and the gold mark for a non-default value come for free.
|
||||||
|
|||||||
Reference in new issue
Block a user