Skip to content

v1.4.0

Choose a tag to compare

@github-actions github-actions released this 28 May 08:34

Flux Hourglass 1.4.0

A small but very physical release. Rotate the phone and the sand and
LEDs now actually obey gravity, and the bottom controls finally stay
readable when they sit on top of a white pile.

Highlights

  • Gravity-aware orientation. The accelerometer is sampled every
    frame and snapped to one of four 90° orientations (portrait,
    upside-down, landscape-left, landscape-right). The running screen
    rotates its content so the sand always falls from the physical
    12 o'clock toward the physical 6 o'clock, and the pile always lives
    on the gravity-down edge of the device. Hold the phone sideways and
    the sand falls sideways — the way you would expect.
  • LED grid follows gravity too. The 16 × 32 LED grid fills from
    the physical bottom regardless of how you hold the device, matching
    the sand mode's behaviour.
  • Readable PAUSE / RESET pills. The bottom controls now sit on a
    semi-transparent black rounded pill so they stay legible when the
    white sand pile (or a fully lit LED grid) reaches them. The label
    alpha also went up from 0.65 to 0.95 — they read clearly without
    having to stand out against the background alone.

Implementation notes

  • A GravityOrient enum classifies device-frame gravity into the
    four 90° orientations with hysteresis: the dominant axis has to
    beat the other by 1.5× and exceed 5 m/s² before we snap, so a
    phone held near the diagonal does not flip-flop every frame.
  • The running screen wraps its Canvas + overlay in a
    BoxWithConstraints that picks logical dimensions (swapped for
    landscape) and applies graphicsLayer(rotationZ = …) to the
    inner box. The physics never sees device coordinates — it always
    runs in a logical frame where +y is gravity-down. Tilt input
    is projected through GravityOrient.logicalGravity before being
    passed to ParticleSystem.update.
  • ParticleSystem.initDimensions now rescales heights[]
    proportionally when the logical height changes, so an in-flight
    pile keeps the same fill ratio across a rotation instead of
    appearing empty or overflowing.
  • Tap detection lives on the unrotated outer container, so taps
    resolve in device coordinates regardless of rotation while the
    visual content rotates underneath.