Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 30 additions & 0 deletions test/CoordinateSystem/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
# SPX coordinate-system regression demo

This demo exercises the coordinate ownership introduced by:

- goplus/spx#1702
- goplus/godot#327
- goplus/spx#1703

Expected behavior:

1. The stage center is SPX `(0, 0)`, `+X` points right, and `+Y` points up.
2. The black cross is the sprite's logical root. Pressing `Space` cycles the
same SVG through three costume centers. The selected colored anchor must
stay on the black cross while the rendered SVG moves around it.
The SVG source dimensions are declared explicitly as `120 × 80`, so each
center is interpreted in the same source-image pixel coordinate space.
3. `R` rotates around the logical root. `F` flips left/right around the same
root. `N` restores normal rotation.
4. `P` draws a cyan pen segment in SPX `+Y`, so the segment must go upward.
5. `S` stamps the current rendered costume and then moves the live sprite to
the right. The stamp must remain exactly where the rendered costume was.
6. Arrow keys move both the logical root and its rendering together. `C`
resets the demo and `E` clears pen drawings and stamps.

Run with the native SPX runtime:

```sh
cd test/CoordinateSystem
spx runnative
```
2 changes: 2 additions & 0 deletions test/CoordinateSystem/RootMarker.spx
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
// The marker is a separate sprite at Subject's logical SPX position. It must
// not inherit Subject's costume render offset, rotation, or horizontal flip.
143 changes: 143 additions & 0 deletions test/CoordinateSystem/Subject.spx
Original file line number Diff line number Diff line change
@@ -0,0 +1,143 @@
import "fmt"
import "math"

const coordinateStep = 40.0

var (
expectedX = 0.0
expectedY = 100.0
flipped bool
)

func syncLogicalRoot() {
RootMarker.SetXYpos xpos, ypos
}

func acceptLogicalPosition() {
// Motion can be clamped by the stage fence. Use the resulting logical SPX
// position as the baseline for later costume/rotation invariants.
expectedX, expectedY = xpos, ypos
}

func verifyLogicalPosition(action string) {
if math.Abs(xpos-expectedX) > 0.001 || math.Abs(ypos-expectedY) > 0.001 {
msg := fmt.Sprintf("FAIL %s: got (%.1f, %.1f), want (%.1f, %.1f)", action, xpos, ypos, expectedX, expectedY)
println msg
say msg
return
}
println fmt.Sprintf("PASS %s: logical SPX position = (%.1f, %.1f)", action, xpos, ypos)
}

func reportState(action string) {
verifyLogicalPosition action
syncLogicalRoot
say fmt.Sprintf("%s\nanchor=%s\nSPX=(%.0f, %.0f)", action, costumeName, xpos, ypos)
}

func resetCoordinateDemo() {
expectedX, expectedY = 0, 100
setXYpos expectedX, expectedY
setRotationStyle Normal
setHeading 90
setCostume 0
flipped = false
reportState "reset"
}

onStart => {
setPenSize 4
setPenColor HSB(52, 80, 90)
resetCoordinateDemo

// Exercise each asset-space center once. Only RenderRoot should move.
for i := 0; i < 3; i++ {
setCostume i
reportState "startup center conversion"
wait 0.8s
}
setCostume 0
reportState "ready"
}

onClick => {
setCostume Next
reportState "click: next costume center"
}

onKey KeySpace, => {
setCostume Next
reportState "next costume center"
}

onKey KeyUp, => {
changeYpos coordinateStep
acceptLogicalPosition
reportState "move +Y"
}

onKey KeyDown, => {
changeYpos -coordinateStep
acceptLogicalPosition
reportState "move -Y"
}

onKey KeyLeft, => {
changeXpos -coordinateStep
acceptLogicalPosition
reportState "move -X"
}

onKey KeyRight, => {
changeXpos coordinateStep
acceptLogicalPosition
reportState "move +X"
}

onKey KeyR, => {
setRotationStyle Normal
turn 30
reportState "rotate around logical root"
}

onKey KeyF, => {
setRotationStyle LeftRight
if flipped {
setHeading 90
} else {
setHeading -90
}
flipped = !flipped
reportState "flip around logical root"
}

onKey KeyN, => {
setRotationStyle Normal
setHeading 90
flipped = false
reportState "normal rotation"
}

onKey KeyP, => {
penDown
changeYpos 80
penUp
acceptLogicalPosition
reportState "pen moved +Y"
}

onKey KeyS, => {
stamp
changeXpos 140
acceptLogicalPosition
reportState "stamp then move +X"
}

onKey KeyC, => {
resetCoordinateDemo
}

onKey KeyE, => {
eraseAll
reportState "erase pen and stamps"
}
42 changes: 42 additions & 0 deletions test/CoordinateSystem/assets/coordinate-grid.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
28 changes: 28 additions & 0 deletions test/CoordinateSystem/assets/index.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
{
"run": {
"title": "SPX Coordinate System",
"width": 640,
"height": 480
},
"backdrops": [
{
"name": "coordinate-grid",
"path": "coordinate-grid.svg"
}
],
"backdropIndex": 0,
"zorder": [
{
"type": "sprite",
"target": "Subject",
"x": 0,
"y": 100
},
{
"type": "sprite",
"target": "RootMarker",
"x": 0,
"y": 100
}
]
}
21 changes: 21 additions & 0 deletions test/CoordinateSystem/assets/sprites/RootMarker/index.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
{
"costumes": [
{
"bitmapResolution": 1,
"imageWidth": 24,
"imageHeight": 24,
"name": "logical-root",
"path": "root-marker.svg",
"x": 12,
"y": 12
}
],
"costumeIndex": 0,
"heading": 90,
"isDraggable": false,
"rotationStyle": "none",
"size": 1,
"visible": true,
"x": 0,
"y": 100
}
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
42 changes: 42 additions & 0 deletions test/CoordinateSystem/assets/sprites/Subject/index.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
{
"costumes": [
{
"bitmapResolution": 1,
"imageWidth": 120,
"imageHeight": 80,
"name": "geometric-center",
"path": "subject.svg",
"faceRight": 0,
"x": 60,
"y": 40
},
{
"bitmapResolution": 1,
"imageWidth": 120,
"imageHeight": 80,
"name": "asset-20-20",
"path": "subject.svg",
"faceRight": 0,
"x": 20,
"y": 20
},
{
"bitmapResolution": 1,
"imageWidth": 120,
"imageHeight": 80,
"name": "asset-100-60",
"path": "subject.svg",
"faceRight": 0,
"x": 100,
"y": 60
}
],
"costumeIndex": 0,
"heading": 90,
"isDraggable": false,
"rotationStyle": "normal",
"size": 1,
"visible": true,
"x": 0,
"y": 100
}
12 changes: 12 additions & 0 deletions test/CoordinateSystem/assets/sprites/Subject/subject.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 4 additions & 0 deletions test/CoordinateSystem/main.spx
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
onStart => {
println "CoordinateSystem demo ready"
println "Space: costume center | arrows: move | R/F/N: rotate/flip/reset | P: +Y pen | S: stamp | C: reset | E: erase"
}
Loading