Write the usage guide as thirteen chapters in docs/
Some checks failed
akbasic CI Build / cmake_build (push) Successful in 3m0s
akbasic CI Build / sanitizers (push) Successful in 3m45s
akbasic CI Build / coverage (push) Failing after 3m22s
akbasic CI Build / akgl_build (push) Failing after 21s
akbasic CI Build / mutation_test (push) Successful in 11m26s
Some checks failed
akbasic CI Build / cmake_build (push) Successful in 3m0s
akbasic CI Build / sanitizers (push) Successful in 3m45s
akbasic CI Build / coverage (push) Failing after 3m22s
akbasic CI Build / akgl_build (push) Failing after 21s
akbasic CI Build / mutation_test (push) Successful in 11m26s
Organised the way the C128 Programmer's Reference Guide is: the language first, then each hardware area, then the reference sections. One markdown file per chapter. The verb and function references are generated from the interpreter's own dispatch table, with an assertion that every row is described, so they cannot drift out of step with what the program accepts. 98 verbs and 30 functions. Every example was run before it was written down, which caught three claims that were wrong: a whole FOR loop on one line prints nothing rather than looping once, MID and INSTR count from zero where a C128 counts from one, and a multi-line DEF returns a value the caller has to assign away. Chapter 13 is the list a BASIC 7.0 programmer needs -- roughly sixty documented differences, including the two known FOR defects and the fact that drawing does not survive a frame. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
130
docs/08-sprites.md
Normal file
130
docs/08-sprites.md
Normal file
@@ -0,0 +1,130 @@
|
||||
# 8. Sprites
|
||||
|
||||
Eight sprites, numbered 1 to 8, as on a C128. They need the SDL build.
|
||||
|
||||
A sprite here is a real object in the host's graphics library, registered alongside
|
||||
whatever the host's own game is drawing — so a game that embeds this interpreter can
|
||||
see and manipulate a script's sprites.
|
||||
|
||||
## Giving a sprite a picture
|
||||
|
||||
`SPRSAV` does it, and it takes three kinds of source.
|
||||
|
||||
### From an image file
|
||||
|
||||
```
|
||||
10 SPRSAV "ship.png", 1
|
||||
```
|
||||
|
||||
The most useful form, and not one a C128 has. The path is tried against the working
|
||||
directory first and then against the directory the running program was loaded from — so
|
||||
a `.bas` stored beside its artwork works wherever you launch it from. Anything the
|
||||
image library can decode will do.
|
||||
|
||||
A sprite loaded this way takes **the image's own size**. It is not forced to 24 by 21.
|
||||
|
||||
### From a saved region
|
||||
|
||||
```
|
||||
10 BOX 1, 0, 0, 24, 21
|
||||
20 SSHAPE A$, 0, 0, 24, 21
|
||||
30 SPRSAV A$, 1
|
||||
```
|
||||
|
||||
Draw it with the graphics verbs, capture it, install it. The C128 documents `SPRSAV`'s
|
||||
string as the `SSHAPE` data format at a fixed 24 by 21, so sharing the mechanism is
|
||||
faithful rather than a shortcut.
|
||||
|
||||
### From data
|
||||
|
||||
```
|
||||
10 DIM P#(63)
|
||||
20 FOR I# = 0 TO 62
|
||||
30 READ P#(I#)
|
||||
40 NEXT I#
|
||||
50 SPRSAV P#, 1
|
||||
60 DATA 255, 129, 129, ...
|
||||
```
|
||||
|
||||
63 bytes: three per row, twenty-one rows, most significant bit leftmost. This is the
|
||||
form a type-in listing uses.
|
||||
|
||||
**It takes an integer array, not a string.** A C128 puts the raw bytes in a string; a
|
||||
string here is NUL-terminated, so it cannot hold a zero byte and therefore cannot hold
|
||||
a sprite. `DIM P#(63)` is exactly the right size.
|
||||
|
||||
Writing a sprite back out — `SPRSAV 1, A$` — is refused. That would be a disk
|
||||
operation.
|
||||
|
||||
## Showing and moving
|
||||
|
||||
```
|
||||
10 SPRITE 1, 1, 3
|
||||
20 MOVSPR 1, 100, 50
|
||||
```
|
||||
|
||||
`SPRITE n [,on] [,colour] [,priority] [,xexpand] [,yexpand] [,multicolour]`. Only the
|
||||
number is required and **an argument you leave out is left alone**, so `SPRITE 1, 1`
|
||||
turns sprite 1 on without disturbing its colour.
|
||||
|
||||
`MOVSPR` has four forms, and the punctuation is what tells them apart:
|
||||
|
||||
| Form | What it does |
|
||||
|---|---|
|
||||
| `MOVSPR 1, 100, 50` | put it at (100, 50) |
|
||||
| `MOVSPR 1, +10, -20` | move it *by* that much |
|
||||
| `MOVSPR 1, 10 ; 90` | move it 10 pixels along bearing 90 |
|
||||
| `MOVSPR 1, 45 # 8` | set it moving along bearing 45 at speed 8 |
|
||||
|
||||
A bearing is degrees **clockwise from straight up**, so 0 is north and 90 is east. In
|
||||
the polar form the distance comes first and the angle second — the opposite order from
|
||||
the continuous form, which is a trap worth remembering.
|
||||
|
||||
The continuous form does not move anything on the statement itself. The sprite moves as
|
||||
the program runs, paced by the host's clock. Speed 0 stops it.
|
||||
|
||||
Coordinates are the same 320 by 200 space the drawing verbs use, not the VIC-II's
|
||||
raster coordinates.
|
||||
|
||||
## Collision
|
||||
|
||||
```
|
||||
10 COLLISION 1, BUMPED
|
||||
20 REM ... main loop ...
|
||||
90 GOTO 20
|
||||
100 LABEL BUMPED
|
||||
110 PRINT "HIT: " + BUMP(1)
|
||||
120 RETURN
|
||||
```
|
||||
|
||||
`COLLISION 1, target` calls a subroutine when two sprites overlap. The handler is
|
||||
entered between lines and must end in `RETURN`, exactly like a `GOSUB` body. Omitting
|
||||
the target disarms it.
|
||||
|
||||
`BUMP(1)` returns a bitmask of which sprites have collided — bit 0 is sprite 1 — and
|
||||
**reading it clears it**, which is what makes "has anything hit me since I last looked"
|
||||
answerable.
|
||||
|
||||
Only type 1, sprite-to-sprite, is implemented. Types 2 and 3 are refused by name.
|
||||
|
||||
Collision is by bounding box, not by pixel: two sprites whose boxes overlap but whose
|
||||
artwork does not are reported as colliding.
|
||||
|
||||
## Reading state back
|
||||
|
||||
| Function | Gives |
|
||||
|---|---|
|
||||
| `RSPPOS(n, 0)` | x |
|
||||
| `RSPPOS(n, 1)` | y |
|
||||
| `RSPPOS(n, 2)` | speed |
|
||||
| `RSPRITE(n, f)` | one of `SPRITE`'s settings, in `SPRITE`'s own argument order |
|
||||
| `RSPCOLOR(1)` or `RSPCOLOR(2)` | one of the shared multicolour registers |
|
||||
|
||||
These read the interpreter's own state rather than asking the device, so they work
|
||||
even with no device attached.
|
||||
|
||||
## SPRDEF
|
||||
|
||||
Not implemented, and deliberately. It is an interactive full-screen sprite editor
|
||||
driven by single keystrokes, not something a program can call — and this interpreter
|
||||
does not own the screen it would take over. The three `SPRSAV` forms replace it.
|
||||
Reference in New Issue
Block a user