Autotiles: floor and wall blocks, pictures as animation steps, the Autotile tab (#118)
1 parent
de58de1d95
commit
8a03318e1f
5 files changed
+80
-7
No files matched your search
+4
-2
@@ -19,7 +19,7 @@
|
||||
the scrolling part — and it *measures* that chrome (a search box, a header, a row of buttons)
|
||||
rather than repeating it as a number, so no popup can forget one. A fixed cap would waste a tall
|
||||
screen or overflow a short one, and a constant gap that frames a popup on a laptop is a hairline
|
||||
on a large screen. It is what holds the whole `+` menu of fifteen asset types on screen, and what
|
||||
on a large screen. It is what holds the whole `+` menu of sixteen asset types on screen, and what
|
||||
lets the image, font and sound pickers show six rows of what the server has instead of two.
|
||||
A popup that does not fit below its anchor is still *moved* up rather than squeezed, and
|
||||
`clampPopupY()` enforces the tenth while moving it — otherwise the gap ends up entirely above it
|
||||
@@ -61,7 +61,7 @@
|
||||
|
||||
```
|
||||
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), 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 and the slice grid), autotile (the two block kinds, which quarter tile a neighbourhood asks for, the 47/16 tiles a block produces), 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, 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/graph/ graph model, NodeRegistry/NodeContext/values, interpreter, dropTarget, nested (behaviors as nodes),
|
||||
@@ -106,6 +106,8 @@ src/editor/texture/ TextureEditor (header + picker), TextureCanvas (picture +
|
||||
src/editor/animation/ AnimationEditor (header + picker, preview over timeline), PreviewCanvas (the root at the playhead, a FreeViewport
|
||||
over animationPreview.ts), TimelineCanvas (rows, keys, ruler, clipboard), timelineView (its geometry),
|
||||
RowDialog + FramesDialog (FormDialogs)
|
||||
src/editor/autotile/ AutotileEditor (header + picker + kind), AutotileCanvas (every tile of the block and a sample map, animated),
|
||||
PictureStrip (the pictures as animation steps; dropIndex is the reorder maths)
|
||||
src/editor/statemachine/ StateMachineEditor (header + picker, on the graph canvas)
|
||||
src/editor/particles/ ParticlesEditor (graph canvas left of a preview panel, splitter between them),
|
||||
ParticlePreview (the panel: the asset's own particles, wearing its own rows)
|
||||
|
||||
+69
@@ -0,0 +1,69 @@
|
||||
A tile that draws its own edges. Paint a patch of grass onto a map and the borders towards
|
||||
everything else — the rounded corners, the straight edges, the notch where two edges meet — are
|
||||
picked per tile from one hand-drawn **block**. That block is what an **autotile asset** holds.
|
||||
|
||||
The asset exists on its own, not inside a map: the same grass is used by several maps, the same
|
||||
way a texture is worn by several sprites. Placing one is the tilemap, which is
|
||||
[#128](https://git.nockal.com/meleki/game-maker/issues/128) and not built yet — until then an
|
||||
autotile is visible in its own tab, where every tile it can produce is drawn.
|
||||
|
||||
## The block
|
||||
|
||||
A block is a picture cut into **quarter tiles**. Two kinds, the two shapes the classic RPG-Maker
|
||||
sheets use:
|
||||
|
||||
| Kind | Block | Tiles it produces | Has |
|
||||
|---|---|---|---|
|
||||
| **Floor (2 × 3)** | 2 tiles wide, 3 tall | 47 | edges, convex corners and **notches** (inner corners) |
|
||||
| **Wall (2 × 2)** | 2 tiles wide, 2 tall | 16 | edges and convex corners, no notches |
|
||||
|
||||
The bottom 2 × 2 tiles of either block are one fully bordered tile: its middle four quarters are
|
||||
the inside, the ring around them the borders and the convex corners. A floor block has one tile row
|
||||
more, and that row holds the four notches — the piece for a corner whose two sides are joined but
|
||||
whose diagonal is not. A wall knows no diagonals, which is why it is a row shorter and has 16 tiles
|
||||
instead of 47.
|
||||
|
||||
**The tile size comes from the picture**: a block is two tiles wide by definition, so a 96 px wide
|
||||
block means 48 px tiles and 24 px quarters. There is no field for it — a second number could only
|
||||
ever disagree with the picture. What the tab does check is that the block has the shape its kind
|
||||
asks for; a picture that does not fit is kept and named, never silently dropped.
|
||||
|
||||
## The asset
|
||||
|
||||
**+ → Autotile** makes an empty one. What it holds:
|
||||
|
||||
- **Pictures** — one block per animation step, in the order they run. A picture is either a
|
||||
**texture** (a file that holds nothing but the one block) or a **frame** of a texture (one block
|
||||
cut out of a sheet that holds many). Cutting them is the [Textures](Textures) tab, by hand or
|
||||
with **Slice…** where the sheet is a regular grid.
|
||||
- **Kind** — *Floor (2 × 3)* or *Wall (2 × 2)*. Chosen, not guessed: a sheet whose rows alternate
|
||||
between the two shapes (`Outside_A4` in RPG Maker) would be read wrong either way, and the choice
|
||||
is one click.
|
||||
- **Frames per second** and **Playback** (*Loop* or *Ping-pong*) — how the pictures run. One
|
||||
picture is a still tile whatever they say; three, as in an animated water sheet, are three steps.
|
||||
Ping-pong turns on the last picture, so 0 1 2 1 rather than 0 1 2 2 1.
|
||||
|
||||
Kind, rate and playback 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.
|
||||
|
||||
## The tab
|
||||
|
||||
- The **picker** in the header chooses the autotile, the one beside it the kind, **Fit** frames the
|
||||
board. The readout on the right says kind, tile size, pictures, rate and how many tiles the block
|
||||
produces — or *not usable yet* with the reason written under the board.
|
||||
- The **board** shows every tile the block can produce, captioned with the neighbours that ask for
|
||||
it: `NESW-nw` is "joined on all four sides, with a notch towards the north-west", `·` is a lone
|
||||
tile. Below the grid a **sample map** is composed from the same quarters — a ring with a hole and
|
||||
a step, which is where one sees whether the edges really continue across tile borders. Both run
|
||||
the animation at the set rate.
|
||||
- A drag pans the board, the wheel zooms it; nothing on it is edited.
|
||||
- The **picture list** on the right is the animation: **+ Picture** adds a texture or a frame,
|
||||
**Remove** takes the selected one out, and dragging a row to another place reorders the steps.
|
||||
Every one of those is an undo step.
|
||||
|
||||
## What it does not do yet
|
||||
|
||||
Nothing places an autotile: there is no tilemap, no painting in the Scene tab and nothing of it in
|
||||
a running game — all of that is [#128](https://git.nockal.com/meleki/game-maker/issues/128). Two
|
||||
different autotiles do not join each other, and there is no way to say which one wins where they
|
||||
meet; that question belongs to the tilemap as well.
|
||||
+5
-5
@@ -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
|
||||
npm run build # writes dist/ and regenerates index.html
|
||||
./build.sh # the same under `set -o pipefail`, for callers that pipe the output
|
||||
node tools/seed-e2e.mjs && node tools/e2e.mjs # 969 editor checks, screenshots in /tmp/gm-e2e-*.png
|
||||
node tools/seed-e2e.mjs && node tools/e2e.mjs # 989 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
|
||||
@@ -64,7 +64,7 @@ The e2e run is a list of steps in `tools/e2e/` (hierarchy, inspector, play, asse
|
||||
graph, parenting, colliders, containers, text/enabled, menus, textures, frames, overflow, aspect,
|
||||
container tab, run-in-editor, pause, nested behaviors, key repeat, list tab, struct variable,
|
||||
variable nodes, property nodes, animations, state machines, console, shaders, transforms, fonts,
|
||||
particles, shared scope, render on change, sounds, load scene, graph groups, nine-slice, plugins) that build on each other's
|
||||
particles, shared scope, render on change, sounds, load scene, graph groups, nine-slice, plugins, autotiles) that build on each other's
|
||||
scene state and share the CDP driver in `tools/lib/harness.mjs` — `press`, `undo`, `play`,
|
||||
`object(id)`, `world()`, `mutate(js)` and friends, so a check reads like the interaction it
|
||||
exercises.
|
||||
@@ -104,8 +104,8 @@ whole suite down the day the Particles tab was added.
|
||||
The same holds for the **`+` menu**: it has one entry per asset type, and an entry below the mask
|
||||
edge is still found by `locate` while a click on it lands on nothing. The fourteenth type
|
||||
(Variables) pushed `Font` under that edge and took the font step down, because only the particles
|
||||
step had carried a workaround of its own; sound is the fifteenth. Since #43 a menu may grow to the
|
||||
height of the canvas, so on the test window all fifteen stand on screen at once — the step still
|
||||
step had carried a workaround of its own; sound is the fifteenth and the autotile the sixteenth. Since #43 a menu may grow to the
|
||||
height of the canvas, so on the test window all sixteen stand on screen at once — the step still
|
||||
picks a type with `pickAssetType(t, 'Font')` from the same file, which keeps the scroll as insurance
|
||||
for a shorter window. The menu's own order is checked in the assets step through `__gm.menuRows()`:
|
||||
two alphabetical groups, placeable types then library ones, one separator between them. Order is
|
||||
@@ -232,4 +232,4 @@ widths to find click points. The **render device is not in this repo** — `/dev
|
||||
and a 1 GB `/dev/shm` come from `container.options` in the runner's own `config.yaml`, which
|
||||
applies to every job on that runner. Without them chromium falls back to llvmpipe, which gets
|
||||
WebGL 1.0 only. Measured in the job container: `ANGLE (Intel, Vulkan 1.3.230, HD Graphics 630)`,
|
||||
WebGL 2.0, and the same 969 checks as here.
|
||||
WebGL 2.0, and the same 989 checks as here.
|
||||
+1
@@ -18,6 +18,7 @@ Live: <https://nockal.com/game-maker/> · Widget playground: <https://nockal.com
|
||||
| [Fonts](Fonts) | Uploading a typeface, what a text wears, what the editor falls back to |
|
||||
| [Sounds](Sounds) | Uploading a sound, what the asset says, `Play sound` and `Stop sound`, what a pause and a stop do to a voice |
|
||||
| [Animations](Animations) | Animation assets, the Animation tab, how they run |
|
||||
| [Autotiles](Autotiles) | The autotile asset, the two block kinds, the pictures as animation steps, the Autotile tab |
|
||||
| [State machines](State-machines) | The state machine asset, its scope, named transitions, the start state, `State branch` and its `else`, `Set state`, `Set state by name`, `State transition`, the two state events and the live highlight |
|
||||
| [Shaders](Shaders) | The shader asset, the Shader tab, the node set, the Adjust colors recipe, wearing a shader |
|
||||
| [Particles](Particles) | The particles asset, a particle as a formula of its age, the source's rows, the Particles tab |
|
||||
|
||||
+1
@@ -9,6 +9,7 @@
|
||||
- [Fonts](Fonts)
|
||||
- [Sounds](Sounds)
|
||||
- [Animations](Animations)
|
||||
- [Autotiles](Autotiles)
|
||||
- [State machines](State-machines)
|
||||
- [Shaders](Shaders)
|
||||
- [Particles](Particles)
|
||||
|
||||
Reference in new issue
Block a user