# Crash BASIC 1.40.0 Release Notes

*~written by Crash-tan~*

## THE "GET OFF THE FLOOR" UPDATE

For your entire life with me, the world has been flat. Two numbers — x and
y — and that was the whole story. Sprites slid around on a sheet of glass,
the background was a sheet of glass behind it, and "depth" was something
you faked by drawing things bigger.

No more. As of 1.40.0 the floor *tilts*, and your sprites can *leave it*.

This is the big one — a third dimension threaded through the renderer, the
sprites, and the behavior engine all at once. Two halves: **plane layers**
(a floor that recedes into the distance) and **elevation** (height off
that floor, with real gravity behind it). Let me show you.

And before you worry: **every flat thing you already wrote still works,
unchanged.** All of this is opt-in. A 2D game stays a 2D game and never
pays a cent for the new machinery.

---

## Plane layers: the floor goes 3D

A layer can now be projected into the distance like a tilted plane — the
classic racing-game / RPG-overworld "Mode 7" look. Build a tilemap layer
as usual, then tell it to lie down:

```basic
CREATE MAP FROM map TILESET "tiles" TILESIZE 32 AS LAYER 0 WRAPX WRAPY
SET LAYER 0 PERSPECTIVE HORIZON(110) HEIGHT(90)
```

`PERSPECTIVE` gives you the full receding-to-a-horizon floor; `HORIZON`
sets where the ground meets the sky on screen, `HEIGHT` is your camera's
height above it. Then drive the camera around with scroll + rotation:

```basic
SET SCROLL 256, 120 ANGLE(playerHeading)
```

Pan with the scroll, spin the whole world with `ANGLE`. If you want a
plain rotate-and-scale floor without the horizon falloff, use `AFFINE`
instead of `PERSPECTIVE` — same idea, flat.

What you get for free on a plane layer:

- **Sprites stand on it correctly** — they're projected onto the floor
  and scale with distance, near things big, far things small.
- **Depth sorting** — sprites draw far-to-near, so closer ones correctly
  cover the ones behind them.
- **Layer alpha** works on plane tilemaps, and **tile animation** keeps
  animating while projected.
- **Your shaders work on it too** — custom WGSL shaders apply to plane
  layers (projected, then shaded), so the floor can shimmer, fog, ripple,
  whatever you've got.

---

## Sprites get a height: ELEVATION

Here's the other half. A sprite now has a **z** — its elevation above the
plane it lives on. Floor is `0`; bigger numbers float higher toward the
camera.

```basic
SET SPRITE hero ELEVATION(40)        ' lift it 40 units off the floor
```

Coordinates were already 3D-capable, so `LOCATION` takes the third number
directly now:

```basic
SET SPRITE hero LOCATION(160, 120, 40)   ' x, y, and height in one go
```

And you can read it back any time:

```basic
h = SPRITEELEVATION(hero)
```

Elevation rides the same per-tick sprite sync as position, so it's smooth
(lerped) over the network and in WASM just like x/y — no popping.

---

## Every motion behavior learned the third axis

The behavior verbs you already use grew an optional z. Old calls are
untouched; the new third value is the elevation axis:

```basic
BMOVE 0, 0, 3                       ' drift straight up off the floor
BOSCILLATE AMPLITUDE 0, 0, 20       ' bob up and down (vertical amplitude)
PATH (10,10,0), (50,40,30), (90,10,0)   ' waypoints with height
```

Plus a dedicated tween, in the BALPHA / BSCALE / BROTATE family:

```basic
BELEVATE 0 TO 60 DURATION 30 LOOP   ' rise and fall over 30 ticks, forever
```

---

## Real vertical physics: gravity, jumps, bounce

The z axis isn't just a number you animate — it's a **physics axis**.
There's z-velocity, z-acceleration, a ground at elevation 0, and the whole
thing integrates every tick.

So a jump is exactly what a jump should be — one upward kick, and gravity
does the rest:

```basic
BEHAVIOR "jump"
  BIMPULSE 0, 0, 16     ' kick straight up...
  BGRAVITY 1            ' ...and fall back down. Lands on the floor on its own.
END BEHAVIOR
```

**`BGRAVITY`** is new — constant downward pull, the everyday way to give a
plane sprite weight. The motion verbs all take their z component now too:
`BACCELERATION dx, dy, dz`, `BVELOCITY vx, vy, vz`, `BIMPULSE ix, iy, iz`,
and `BSTOP` zeroes the vertical axis along with the rest.

And things can **bounce**. `BBOUNCE` got a third coefficient — restitution
off the ground:

```basic
BEHAVIOR "ball"
  BGRAVITY 0.4
  BBOUNCE 0, 0, 0.7    ' rebounds at 70% each hit, loses energy, settles
END BEHAVIOR
```

`BFRICTION` got a third one too — air resistance on the vertical axis, for
a terminal fall speed (`terminal ≈ gravity / z_friction`).

---

## Orbits and follows go 3D

**`BORBIT`** can now circle in any plane, not just flat on the floor. The
new **`AXIS`** clause is the axis of rotation — the normal of the plane the
sprite circles in:

```basic
BORBIT (256, 280, 60) DISTANCE 70 AXIS (1, 0, 0)   ' a vertical ring, lifted off the floor
```

- `AXIS (0, 0, 1)` is the default — the flat floor orbit you already had,
  bit-for-bit.
- `AXIS (1, 0, 0)` stands the ring up into a vertical wheel.
- Any tilted vector gives a tilted ring, foreshortened correctly by the
  plane projection.

The center can be 3D too (`(x, y, z)`) to lift the whole ring, and a ring
of sprites at staggered `STARTANGLE`s traces a rotating 3D ring. Orbit a
*sprite* in 3D and it rides that sprite's own height as it jumps.

**`BFOLLOW`** gained an **`ELEVATION`** clause — now the follower can track
the target's height, not just its x/y:

```basic
BFOLLOW 0 DISTANCE 24 SPEED 3 ELEVATION 30   ' a drone hovering 30 units above the target
```

---

## Compatibility

Nothing breaks. The whole z story is additive:

- 2D games never set an elevation, never tilt a layer, and behave exactly
  as in 1.39.
- Default orbit axis is `(0, 0, 1)` — the old flat orbit, reproduced
  exactly.
- All the new behavior arguments (the third coordinate, `AXIS`,
  `ELEVATION`, `BGRAVITY`) are optional. Omit them and you get the old
  behavior.
- Elevation only *renders* as height on a `PERSPECTIVE`/`AFFINE` plane
  layer — off a plane it's just a number, harmless.
