Describe the game link and the new zoom steps (#266)
A project can now be released as a link that plays without the editor and without a login. - Concepts: a Release section, the new main menu entry and the zoom steps 300%, 500% and 600% in the game tab table. - API: the four release routes, and that the public one is the only route besides auth that needs no session. - Architecture: GameRun, the player page, gamePointer, projectFiles and WorldViewport in its new place under src/viewport. - Development: the PHP release test and the measured sum of 1574 e2e checks. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
1 parent
68c8798a70
commit
d0ed6bd81d
4 files changed
+48
-9
No files matched your search
+6
-2
@@ -2,7 +2,7 @@ All routes go through `api/index.php?r=…` (the site's nginx does not pass `PAT
|
|||||||
|
|
||||||
| Method | Route | Body → Result |
|
| Method | Route | Body → Result |
|
||||||
|---|---|---|
|
|---|---|---|
|
||||||
| GET | `auth/session` | `{user, role}` — the name and role (`admin` or `user`) of whoever is signed in, both `null` when nobody is. Always 200, and the only route that needs no session |
|
| GET | `auth/session` | `{user, role}` — the name and role (`admin` or `user`) of whoever is signed in, both `null` when nobody is. Always 200 |
|
||||||
| POST | `auth/login` | `{username,password}` → `{user, role}` and the session cookie; **401** `{error}` for a wrong pair |
|
| POST | `auth/login` | `{username,password}` → `{user, role}` and the session cookie; **401** `{error}` for a wrong pair |
|
||||||
| POST | `auth/logout` | 204, and the cookie is cleared |
|
| POST | `auth/logout` | 204, and the cookie is cleared |
|
||||||
| POST | `auth/password` | `{currentPassword,newPassword}` → 204. Changes the password of whoever is signed in — the only `auth` route that needs a session. **401** for a wrong current password, **422** when the new one is shorter than 8 characters. Every other session of the account ends; the one asking keeps its own |
|
| POST | `auth/password` | `{currentPassword,newPassword}` → 204. Changes the password of whoever is signed in — the only `auth` route that needs a session. **401** for a wrong current password, **422** when the new one is shorter than 8 characters. Every other session of the account ends; the one asking keeps its own |
|
||||||
@@ -10,11 +10,15 @@ All routes go through `api/index.php?r=…` (the site's nginx does not pass `PAT
|
|||||||
| POST | `projects` | `{name}` → project document (201) |
|
| POST | `projects` | `{name}` → project document (201) |
|
||||||
| GET | `projects/{id}` | `{id,name,revision,updatedAt,project}` |
|
| GET | `projects/{id}` | `{id,name,revision,updatedAt,project}` |
|
||||||
| PUT | `projects/{id}` | `{revision, project}` → `{revision,updatedAt}` or **409** `{error,revision}` when stale |
|
| PUT | `projects/{id}` | `{revision, project}` → `{revision,updatedAt}` or **409** `{error,revision}` when stale |
|
||||||
| DELETE | `projects/{id}` | 204, and the snapshots of the project go with it |
|
| DELETE | `projects/{id}` | 204, and the snapshots and the release of the project go with it |
|
||||||
| GET | `projects/{id}/snapshots` | `[{id,name,revision,createdAt}]`, newest first — see [Concepts](Concepts) |
|
| GET | `projects/{id}/snapshots` | `[{id,name,revision,createdAt}]`, newest first — see [Concepts](Concepts) |
|
||||||
| POST | `projects/{id}/snapshots` | `{name?}` → `{id,name,revision,createdAt}` (201). Copies the project as stored; a blank name becomes the UTC date and time. **422** over 120 characters |
|
| POST | `projects/{id}/snapshots` | `{name?}` → `{id,name,revision,createdAt}` (201). Copies the project as stored; a blank name becomes the UTC date and time. **422** over 120 characters |
|
||||||
| DELETE | `projects/{id}/snapshots/{sid}` | 204 |
|
| DELETE | `projects/{id}/snapshots/{sid}` | 204 |
|
||||||
| POST | `projects/{id}/snapshots/{sid}/restore` | `{revision}` → `{revision,updatedAt,before}`. Keeps the stored project as the snapshot `before` (`Before restoring <name>`), then saves the snapshot as the next revision. **409** `{error,revision}` when `revision` is stale |
|
| POST | `projects/{id}/snapshots/{sid}/restore` | `{revision}` → `{revision,updatedAt,before}`. Keeps the stored project as the snapshot `before` (`Before restoring <name>`), then saves the snapshot as the next revision. **409** `{error,revision}` when `revision` is stale |
|
||||||
|
| GET | `projects/{id}/release` | `{token,revision,publishedAt}`, or `null` while the project is not released — see [Concepts](Concepts) |
|
||||||
|
| POST | `projects/{id}/release` | → `{token,revision,publishedAt}`. Copies the project as stored; publishing again replaces the copy and keeps the token |
|
||||||
|
| DELETE | `projects/{id}/release` | 204, the link is dead; **404** when the project was not released |
|
||||||
|
| GET | `releases/{token}` | `{name,publishedAt,project}` — the released copy, **without a session**: the one route besides `auth/*` open to everybody. `project.id` is the token, not the project's id. **404** for an unknown or taken-down token |
|
||||||
| GET | `textures` | `[{file,name,width,height,bytes,updatedAt}]` — what the image picker offers |
|
| GET | `textures` | `[{file,name,width,height,bytes,updatedAt}]` — what the image picker offers |
|
||||||
| POST | `textures&name=hero.png` | **raw image bytes** → `{file,name,width,height,bytes}` (201) |
|
| POST | `textures&name=hero.png` | **raw image bytes** → `{file,name,width,height,bytes}` (201) |
|
||||||
| DELETE | `textures/{file}` | 204 |
|
| DELETE | `textures/{file}` | 204 |
|
||||||
|
|||||||
+18
-3
@@ -73,6 +73,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)
|
||||||
|
web/play.html a released game (#266) play.html built page (generated, served)
|
||||||
|
src/main.ts, play.ts the two entries; page.ts is the canvas both are (the WebGL context, root, resize)
|
||||||
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), traceCollision (#161: a frame's outlines read off its picture — the pixels from an alpha threshold on are solid, each 4-connected island is walked round along the pixel edges and cut down to a few corners without ever crossing itself; crumbs below 1 % of the frame drop out), generated (pictures that are drawn rather than uploaded, #185: the key `gen:<assetId>@<revision>`, the register of readers that tell the picture path an asset's canvas size and revision, and the `fingerprint` pixel art and vector art make their revision with), 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, a texture fill's picture included) + 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; a paint resolved to sorted stops or the picture it names) + vectorPaint (#186: gradients and texture fills — where a paint lies when it is switched on, the colour between two stops, adding, moving and removing a stop, a paint moved with its shape, and the rule that a texture fill takes uploaded pictures only) + vectorBoolean (#187: union, subtract, intersect and exclude on the sampled outlines, each shape read by the even-odd rule; the result rings in the order Pixi's hole detection needs, every outline followed by its holes and preceded by the islands inside them) + vectorCurves (#208: every sampled point remembers its cubic and its `t`, so a run of result points along one cubic becomes that cubic again, cut with de Casteljau), pixelart (#130: the palette a picture is painted in, how the layers of a frame come together, the sheet of all frames, a frame id read as a cut of it, and the revision) + pixelCel (the file of one layer on one frame, and its SHA-256 name worked out in the browser) + pixelDraw (what the tools do to the indices: brush, line, rectangle, ellipse, fill, resize about an anchor, merge, a palette colour taken out) + pixelEdit (every edit of layers, frames and cels as a function from one state to the next), 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)), tilemapMemo (what a map's cells work out to, kept while they hold the same: a version per cell map compared cell by cell, since strokes paint in place), 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), curve (#247: a drawn easing evaluated at t — each segment a cubic solved for t by bisection, held to its rules by `sanitizedCurve`: ends at 0 and 1, no point overtaking another, no handle past its neighbour — and which keys and `Lerp` nodes use one) + curvePresets (the built-in eases traced as curves, a segment halved only where it strays), graphLookup (what a graph sees of the project: behaviors to run, state machines to read, curves to ease along), structTypes (#253: Struct assets as types — every typed struct variable, struct field and `Pack`/`Expand` found and brought in line with its asset, a renamed field carried through every value first, the cycle rule), Scope (how long a shared value lives: per instance, one for the run, or one per scene and rebuilt with every scene that loads, #164 — for a state machine's current state and for the values of a Variables asset), 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), traceCollision (#161: a frame's outlines read off its picture — the pixels from an alpha threshold on are solid, each 4-connected island is walked round along the pixel edges and cut down to a few corners without ever crossing itself; crumbs below 1 % of the frame drop out), generated (pictures that are drawn rather than uploaded, #185: the key `gen:<assetId>@<revision>`, the register of readers that tell the picture path an asset's canvas size and revision, and the `fingerprint` pixel art and vector art make their revision with), 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, a texture fill's picture included) + 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; a paint resolved to sorted stops or the picture it names) + vectorPaint (#186: gradients and texture fills — where a paint lies when it is switched on, the colour between two stops, adding, moving and removing a stop, a paint moved with its shape, and the rule that a texture fill takes uploaded pictures only) + vectorBoolean (#187: union, subtract, intersect and exclude on the sampled outlines, each shape read by the even-odd rule; the result rings in the order Pixi's hole detection needs, every outline followed by its holes and preceded by the islands inside them) + vectorCurves (#208: every sampled point remembers its cubic and its `t`, so a run of result points along one cubic becomes that cubic again, cut with de Casteljau), pixelart (#130: the palette a picture is painted in, how the layers of a frame come together, the sheet of all frames, a frame id read as a cut of it, and the revision) + pixelCel (the file of one layer on one frame, and its SHA-256 name worked out in the browser) + pixelDraw (what the tools do to the indices: brush, line, rectangle, ellipse, fill, resize about an anchor, merge, a palette colour taken out) + pixelEdit (every edit of layers, frames and cels as a function from one state to the next), 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)), tilemapMemo (what a map's cells work out to, kept while they hold the same: a version per cell map compared cell by cell, since strokes paint in place), 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), curve (#247: a drawn easing evaluated at t — each segment a cubic solved for t by bisection, held to its rules by `sanitizedCurve`: ends at 0 and 1, no point overtaking another, no handle past its neighbour — and which keys and `Lerp` nodes use one) + curvePresets (the built-in eases traced as curves, a segment halved only where it strays), graphLookup (what a graph sees of the project: behaviors to run, state machines to read, curves to ease along), structTypes (#253: Struct assets as types — every typed struct variable, struct field and `Pack`/`Expand` found and brought in line with its asset, a renamed field carried through every value first, the cycle rule), Scope (how long a shared value lives: per instance, one for the run, or one per scene and rebuilt with every scene that loads, #164 — for a state machine's current state and for the values of a Variables asset), 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, clip (the region clip areas cut each object to, a convex polygon, #260) (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, clip (the region clip areas cut each object to, a convex polygon, #260) (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), color (`mixColor`, channel by channel — keys of an animation, stops of a gradient, the particles' Mix colour), recorder (#253: assignments taken back last first — the undo of an edit whose reach is not known in advance)
|
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), color (`mixColor`, channel by channel — keys of an animation, stops of a gradient, the particles' Mix colour), recorder (#253: assignments taken back last first — the undo of an edit whose reach is not known in advance)
|
||||||
@@ -92,11 +94,13 @@ src/core/store/ serialize (untrusted JSON → Project), projectPlugins (w
|
|||||||
file before it is deserialized, #119), tilemapCells (the compact form of a layer's cells in the file),
|
file before it is deserialized, #119), tilemapCells (the compact form of a layer's cells in the file),
|
||||||
http (one API call), ProjectStore/HttpProjectStore (load takes a `prepare` that sees the raw JSON first),
|
http (one API call), ProjectStore/HttpProjectStore (load takes a `prepare` that sees the raw JSON first),
|
||||||
SnapshotStore/HttpSnapshotStore (the snapshots of a project, #231),
|
SnapshotStore/HttpSnapshotStore (the snapshots of a project, #231),
|
||||||
|
ReleaseStore/HttpReleaseStore (a project's released copy and the link to it, #266),
|
||||||
AuthStore/HttpAuthStore (signing in and out, #177; changing the password, #182),
|
AuthStore/HttpAuthStore (signing in and out, #177; changing the password, #182),
|
||||||
FileStore (what the server holds of one kind) + HttpFileStore (one generic client over the three
|
FileStore (what the server holds of one kind) + HttpFileStore (one generic client over the three
|
||||||
file collections) — TextureStore, FontStore and SoundStore are its type parameters, nothing else
|
file collections) — TextureStore, FontStore and SoundStore are its type parameters, nothing else
|
||||||
src/core/time.ts the global clock: one scaled step a frame, shared by the world, the particles, the shaders and the animation preview
|
src/core/time.ts the global clock: one scaled step a frame, shared by the world, the particles, the shaders and the animation preview
|
||||||
src/runtime/ World, Entity, System interface, Input tracker, CollisionSystem (the editor run's detection),
|
src/runtime/ GameRun (one run: start, tick, `Load scene` — shared by Play and a released game, #266),
|
||||||
|
World, Entity, System interface, Input tracker, CollisionSystem (the editor run's detection),
|
||||||
solids (what `Move` collides with and how it slides — one-way solids let it through unless
|
solids (what `Move` collides with and how it slides — one-way solids let it through unless
|
||||||
it lands on them —, the first solid a ray meets, which body a collider belongs to, the
|
it lands on them —, the first solid a ray meets, which body a collider belongs to, the
|
||||||
CollisionSource both collision systems give the behaviors, the contact of a staying pair,
|
CollisionSource both collision systems give the behaviors, the contact of a staying pair,
|
||||||
@@ -116,7 +120,11 @@ src/ui/ widget toolkit (generic, knows nothing about assets); fon
|
|||||||
Source Sans 3 in 400, 500, 600 and 700, Source Code Pro 400, Latin only, #202/#214), icons +
|
Source Sans 3 in 400, 500, 600 and 700, Source Code Pro 400, Latin only, #202/#214), icons +
|
||||||
Icon (the menu's tick boxes and current-entry dot as SVG files, and a widget that shows one file
|
Icon (the menu's tick boxes and current-entry dot as SVG files, and a widget that shows one file
|
||||||
on its own: a symbol the Latin subset lacks is never written as a character, #214); SortableList + sortable (the layer list of every editor that has one: rows dragged into order, eye, duplicate, cross, rename in place; the index arithmetic of a list shown upside down, kept apart so it is measured without a canvas)
|
on its own: a symbol the Latin subset lacks is never written as a character, #214); SortableList + sortable (the layer list of every editor that has one: rows dragged into order, eye, duplicate, cross, rename in place; the index arithmetic of a list shown upside down, kept apart so it is measured without a canvas)
|
||||||
src/viewport/ view (transforms), items (what to draw), symbols (how to draw it),
|
src/viewport/ WorldViewport (the drawing of a world or a holder, the base of every view; it draws from
|
||||||
|
a `ViewSource` — the project and word of a change — so a released game draws without the
|
||||||
|
editor, #266), gamePointer (the mouse handed to a running world), projectFiles (the file
|
||||||
|
libraries pointed at the server, and what a project names fetched ahead),
|
||||||
|
view (transforms), items (what to draw), symbols (how to draw it),
|
||||||
symbolIcons (the SVG files in icons/, parsed once, in the theme's colours, #175),
|
symbolIcons (the SVG files in icons/, parsed once, in the theme's colours, #175),
|
||||||
FileLibrary (load once, never retry a failure, tell the listeners) ← TextureLibrary, FontLibrary;
|
FileLibrary (load once, never retry a failure, tell the listeners) ← TextureLibrary, FontLibrary;
|
||||||
generatedPictures (the drawn half of the picture path, #185: one picture per asset kept
|
generatedPictures (the drawn half of the picture path, #185: one picture per asset kept
|
||||||
@@ -140,6 +148,7 @@ src/editor/ App → Editor (layout + ticker), PlaySession (the run),
|
|||||||
OpenProjectDialog (the project picker behind "Open project…"),
|
OpenProjectDialog (the project picker behind "Open project…"),
|
||||||
SnapshotsDialog + snapshots (the list behind "Snapshots…" and the rule of when a
|
SnapshotsDialog + snapshots (the list behind "Snapshots…" and the rule of when a
|
||||||
snapshot may be made: only with everything saved, #231),
|
snapshot may be made: only with everything saved, #231),
|
||||||
|
ReleaseDialog + releases (the link behind "Release…", what the dialog says and warns about, #266),
|
||||||
ProjectSettingsDialog + settingsChanges (name, the start-scene switch and the collision
|
ProjectSettingsDialog + settingsChanges (name, the start-scene switch and the collision
|
||||||
layers in one dialog; the pure rule of what Apply has to carry out),
|
layers in one dialog; the pure rule of what Apply has to carry out),
|
||||||
EditorRun (run in editor), state, actions, shortcuts, clipboard (#240: copy and paste of
|
EditorRun (run in editor), state, actions, shortcuts, clipboard (#240: copy and paste of
|
||||||
@@ -179,8 +188,12 @@ src/editor/users/ the user management (#179): ManagementPane (the tab behin
|
|||||||
server's own sentence. The server decides everything: `api/lib/AccountRules.php`
|
server's own sentence. The server decides everything: `api/lib/AccountRules.php`
|
||||||
(not the own account, not the last administrator, not an account with projects),
|
(not the own account, not the last administrator, not an account with projects),
|
||||||
`Auth::requireAdmin()` (403), `Store` with `seesAll` for an administrator
|
`Auth::requireAdmin()` (403), `Store` with `seesAll` for an administrator
|
||||||
src/editor/viewport/ WorldViewport base → FreeViewport (a camera of its own: fit, pan, wheel zoom) → SceneViewport, PreviewCanvas;
|
src/player/ GameScreen (the game on the page: Auto zoom, the caption before and after a run),
|
||||||
|
Player (loads, starts on a click, ticks, stops), playerHook (`window.__gameMakerPlay`
|
||||||
|
for the check scripts) — a released game (#266), without the editor
|
||||||
|
src/editor/viewport/ FreeViewport (a camera of its own: fit, pan, wheel zoom) → SceneViewport, PreviewCanvas;
|
||||||
GameViewport follows the game's camera instead — editing tools, hence not in src/viewport/.
|
GameViewport follows the game's camera instead — editing tools, hence not in src/viewport/.
|
||||||
|
All of them extend `src/viewport/WorldViewport`.
|
||||||
A pan only moves the world and redraws the screen-space overlays (`moveCamera`); a full
|
A pan only moves the world and redraws the screen-space overlays (`moveCamera`); a full
|
||||||
`redraw()` follows only when an object crosses the edge of the view.
|
`redraw()` follows only when an object crosses the edge of the view.
|
||||||
The scene view's tools keep their own state and reach the view through `SceneViewHost`:
|
The scene view's tools keep their own state and reach the view through `SceneViewHost`:
|
||||||
@@ -258,6 +271,8 @@ api/ PHP backend: index.php (routing and the sign-in gate),
|
|||||||
lib/{Store,TextureStore,FontStore,SoundStore,PluginStore,OriginalName,Response}.php,
|
lib/{Store,TextureStore,FontStore,SoundStore,PluginStore,OriginalName,Response}.php,
|
||||||
lib/{Auth,UserStore,SessionStore}.php (#177: accounts in data/users.json, sessions in data/sessions/)
|
lib/{Auth,UserStore,SessionStore}.php (#177: accounts in data/users.json, sessions in data/sessions/)
|
||||||
lib/SnapshotStore.php (#231: data/snapshots/{projectId}/, one copy of the project per file)
|
lib/SnapshotStore.php (#231: data/snapshots/{projectId}/, one copy of the project per file)
|
||||||
|
lib/ReleaseStore.php (#266: data/releases/{token}.json and which token a project has, both 0640
|
||||||
|
so the web server does not hand them out as files)
|
||||||
data/projects/ persisted projects, data/textures/ + data/fonts/ + data/sounds/ content-addressed uploads,
|
data/projects/ persisted projects, data/textures/ + data/fonts/ + data/sounds/ content-addressed uploads,
|
||||||
data/plugins/ editor plugins, filled from plugins/ by the build and the seeder; which of them run is written
|
data/plugins/ editor plugins, filled from plugins/ by the build and the seeder; which of them run is written
|
||||||
in each project (#119)
|
in each project (#119)
|
||||||
|
|||||||
+22
-3
@@ -58,8 +58,8 @@ picture (its `width` x `height`) is drawn:
|
|||||||
|
|
||||||
| Choice | Screen pixels per camera pixel |
|
| Choice | Screen pixels per camera pixel |
|
||||||
|---|---|
|
|---|---|
|
||||||
| **100%** (default) | 1. 25%, 50%, 200% and 400% likewise draw exactly that factor. |
|
| **100%** (default) | 1. 25%, 50%, 200%, 300%, 400%, 500% and 600% likewise draw exactly that factor. |
|
||||||
| **Auto** | The largest of those five steps at which the whole picture still fits. Below 25% it stays at 25%. |
|
| **Auto** | The largest of those eight steps at which the whole picture still fits. Below 25% it stays at 25%. |
|
||||||
| **Fit** | Whatever fills the view on its tighter side, the way the tab always drew before. |
|
| **Fit** | Whatever fills the view on its tighter side, the way the tab always drew before. |
|
||||||
|
|
||||||
The camera's `zoom` magnifies the world on top: a 640x360 camera at zoom 2 shows 320x180 world
|
The camera's `zoom` magnifies the world on top: a 640x360 camera at zoom 2 shows 320x180 world
|
||||||
@@ -102,8 +102,27 @@ sounds and pixel art are stored by their content and never removed, so everythin
|
|||||||
still there. Deleting the project deletes its snapshots. Whoever can open a project can use its
|
still there. Deleting the project deletes its snapshots. Whoever can open a project can use its
|
||||||
snapshots, an administrator included.
|
snapshots, an administrator included.
|
||||||
|
|
||||||
|
**Release** (#266). *Menu → Release…* turns the project into a link that plays only the game:
|
||||||
|
no editor, no sign-in, the game view over the whole browser window on the page colour. **Publish**
|
||||||
|
copies the project as the server has it stored — the autosave is written first, and nothing is
|
||||||
|
published while anything is unsaved, the same rule as for a snapshot. The copy is frozen: what is
|
||||||
|
changed in the editor afterwards reaches players only with **Update release**, which replaces the
|
||||||
|
copy and keeps the link. The dialog says when the copy was taken and whether the saved project has
|
||||||
|
moved on since, and shows the link with **Copy link** and **Open**. **Take down** asks, then makes
|
||||||
|
the link dead; publishing again afterwards hands out a new one. Deleting the project takes its
|
||||||
|
release down. The link is `play.html?game=<token>`, the token 128 random bits and the only key.
|
||||||
|
|
||||||
|
The game on the link always starts in the start scene (the *Active scene* switch is the editor's
|
||||||
|
alone), zoomed like the game view's **Auto**: the largest zoom step at which the whole camera fits,
|
||||||
|
never a scale between the steps. It waits for a click or Enter before it starts — browsers play no
|
||||||
|
sound before one, and the keyboard would have nowhere to go. Every key belongs to the game, Tab
|
||||||
|
included. A game that stops itself (`Stop game`) offers to play again; `Restart game` and
|
||||||
|
`Load scene` work as in the editor. Persistent variables are saved in the player's browser under
|
||||||
|
the link, apart from the editor's own saves. Plugins are not loaded on the link; the dialog warns
|
||||||
|
when the project uses any, and when it has no scene to play.
|
||||||
|
|
||||||
**Toolbar and panels.** The toolbar carries five **icon buttons** and no captions (#183): the
|
**Toolbar and panels.** The toolbar carries five **icon buttons** and no captions (#183): the
|
||||||
**menu** (three bars) on the left with *New project*, *Open project…*, *Snapshots…* and *Project settings…*,
|
**menu** (three bars) on the left with *New project*, *Open project…*, *Snapshots…*, *Release…* and *Project settings…*,
|
||||||
**undo** and **redo** beside it, and **play** and **pause** in the middle — on the middle of the
|
**undo** and **redo** beside it, and **play** and **pause** in the middle — on the middle of the
|
||||||
window, not of the space the row has left over — where play turns into a stop square while a run is
|
window, not of the space the row has left over — where play turns into a stop square while a run is
|
||||||
on, and pause into a second play sign while it is held. On the right stand the
|
on, and pause into a second play sign while it is held. On the right stand the
|
||||||
|
|||||||
+2
-1
@@ -15,7 +15,8 @@ npm run build # writes dist/ and regenerates index.html
|
|||||||
php tools/make-user.php <name> <password> [admin|user] # an account; every tool signs in (see Accounts)
|
php tools/make-user.php <name> <password> [admin|user] # an account; every tool signs in (see Accounts)
|
||||||
php tests/php/accounts.test.php # the API's account rules, no server needed (CI's gate job)
|
php tests/php/accounts.test.php # the API's account rules, no server needed (CI's gate job)
|
||||||
php tests/php/snapshots.test.php # the snapshot store (#231), the same way
|
php tests/php/snapshots.test.php # the snapshot store (#231), the same way
|
||||||
node tools/seed-e2e.mjs && node tools/e2e.mjs # 1562 editor checks, screenshots in /tmp/gm-e2e-*.png
|
php tests/php/releases.test.php # the release store (#266), the same way
|
||||||
|
node tools/seed-e2e.mjs && node tools/e2e.mjs # 1574 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
|
||||||
|
|||||||
Reference in new issue
Block a user