Skip to main content

JARU 0.9.6: a new physics engine, sound and music, and an ESP32-P4 VM

· 8 min read
Jon Otero Fernández
Author of JARU
JARU 0.9.6PhysicsSoundESP32-P4struct

JARU 0.9.6 is out, and it is by far the biggest step the project has taken so far. This is not a round of touch-ups: there is a new physics engine written from scratch, a sound and music system that simply did not exist before, a new virtual machine for the ESP32-P4, and two additions to the language itself.

If you are coming from 0.9.5, it is worth reading the breaking changes section before you rebuild your projects: there are only a few, but three of them may require touching code.

JARU IDE overview

A new physics and collision engine

The previous engine has been replaced by a complete new one — broadphase, narrowphase, contact solver, and grid collision — present in all three VMs and validated with its own test batteries.

What it brings in practice:

  • Real rotation: the center of mass is now the center of the collider, the collider rotates with the sprite, and spin invalidates the rotation cache. Before, an impulse could create a phantom torque and make a body orbit its own corner.
  • Coulomb friction, bounded by the normal impulse, with genuine static friction on ramps.
  • Contact-island sleeping: resting bodies stop consuming CPU, and bodies that touch each other wake up together.
  • Torque: applyTorque(t) for pure torque and applyForceAt(fx, fy, px, py) for a force applied at a world point.
  • CCD via sprite.bullet: a fast projectile no longer tunnels through another body between two simulation steps.
  • Bitmask collision filters with category and collideWith, plus per-body properties such as gravityScale, damping, angularDamping, and rotates.

Collision against GridMap has been rebuilt: absolute repositioning onto the tile face, internal-face filtering (the ghost collisions that forced the double-collider trick), a redesigned anti-embedding net, and hitsGrid() reporting all overlapping tiles again, exactly as the documentation said it did.

Angry Birds style impact callbacks

The reactive way to handle hits: instead of polling hits() every frame, the engine calls you with the strength of the impact and lets you set a minimum threshold.

// Only strong hits count
box.onCollision(fn(me, other, impulse, nx, ny):
println("hit with ", impulse, "!")
me.active = false
end, 300)

A known limitation

I would rather say this up front than let you discover it: the engine does not hold stacks of two or more dynamic bodies at rest. Energy gets pumped into the stack because contact warm-starting is missing. It is measured and analyzed, and no option in your .aru avoids it. A tower of still boxes is not a realistic use case yet; the rest of the physics is.

Sound and music

This whole section is new: 0.9.5 had no sound system at all.

  • Seven channels: four tone channels, one noise channel, and two PCM channels.
  • Per-instrument ADSR envelopes, with a SID-style gate model.
  • Waveforms: square, saw, triangle, pulse, and sine, with a polyBLEP filter.
  • PWM and tremolo per instrument and per channel (Sound.pwm, Sound.tremolo), on top of vibrato.
  • Exact millihertz tuning, independent of the sample rate, with the low notes properly in tune. Sound.tone, pulse, and slideFreq accept fractional frequencies: Sound.tone(0, 65.406, 200).
  • Sample rate per board profile (22050 or 44100), with a fixed noise clock so a song sounds the same on both.
  • Anti-click: legato retrigger without cutting to zero, free oscillator phase, and every waveform starting at its zero crossing.

JARU IDE Music Tracker

In the IDE, the music tracker is no longer an experiment: it has a graphical instrument editor with ADSR, PWM, and tremolo, a General MIDI preset picker, copy/cut/paste, multi-row selection, and a preview player that mirrors the VM engine — the same anti-click work, the same master bus, and the sample rate of the active board profile — so what you hear while composing is what plays on the board.

The MIDI importer improved too: it now honors expression (CC11 combined with CC7), preserves each timbre's nominal volume, and tunes pitch bend in millihertz.

ESP32-P4 VM

There is a new VM for the ESP32-P4, with double-buffer handling and MIPI-DSI display drivers (ST7703 and ST7701). On ESP32 and ESP32-S3, there is now an automatic fallback to PSRAM when the double buffer does not fit in SRAM.

Also: LovyanGFX updated to 1.2.21, a QSPI driver, unified SPI buses, and a platformio.ini that supports both boards at once without swapping files.

Language: struct, fn lambdas, and unified callbacks

The struct type is a lightweight data record: fixed fields stored by index in a compact block, no hash tables. It uses several times less memory than a class instance and is much faster to create — which you notice on an ESP32.

struct Point
var x = 0
var y = 0
end

var p = Point(3, 4)
println(p.x, ", ", p.y)

fn lambdas are anonymous functions with capture by reference (including this inside a method):

var double = fn(x): return x * 2 end
println(double(21)) // 42

Timer.every(1000, fn(id, p, u):
println("tick")
end)

And callbacks are now unified: where each module used to accept something different, Timer, gpio interrupts, MQTT.subscribe, and sprite.onCollision all accept the same four styles — a direct reference (myFunction), an object method (object.method), a name as a string ("myFunction"), or an inline fn lambda.

IDE

JARU IDE ESP32 tools

  • Redesigned ESP32 Tools, with hardware profiles and user devices, and display bus management decoupled from the controller chip: every controller and every bus (SPI, QSPI, I80, MIPI-DSI) shows up on any SoC and you pick the right combination.
  • Stronger code intelligence: inherited members in autocomplete and call-tips, Ctrl+click and hover resolving chains three levels deep or more, full struct support (including the expandable Watch and field completion) and fn lambda support, inheritance cycle detection, and fewer false positives.
  • Resource editors: undo/redo in the tilemap editor, a fix for the image editor's crop, icons across the toolbars, and a modified-state indicator in the sprite editor.
  • AI-powered I2C driver generation agent, launched from the IDE's embedded Python.

Breaking changes

ChangeWhat to do
sprite.spin now really honors degrees per second (it carried an extra factor of 60)Multiply old values by 60 to keep the speed you were seeing
sprite.acceleration is deprecated as an alias of sprite.force; it will be removed in 1.0Rename it to force when convenient
scene.maxDelta is now a per-scene property, not a file-level globalSet it in every scene that needs it
friction and elasticity are clamped to 0-1Out-of-range values produced NaN or gained energy; they are no longer accepted
Sprite-to-sprite friction is now Coulomb frictionGames that relied on the old viscous damping will feel the difference
VM error messages are all in English nowOnly affects code comparing the text of e.message; compare the error code instead
The ESP32-S3 application partition grows to 0x160000A full flash is required, firmware and filesystem

One general note: rebuild your project after updating, so resources are regenerated with the new compiler. Older .jmu songs and bytecode will not load.

Download

JARU IDE 0.9.6 for Windows is available on the site:

Unzip the file and run the installer inside it. If you already have the IDE installed, it will tell you a new version is available.

FAQ

Do I have to rebuild my 0.9.5 projects?

Yes. The compiler and the resource formats changed, so bytecode and music need to be regenerated. Also check the breaking changes table: sprite.spin, sprite.acceleration, and scene.maxDelta are the three points that may require code edits.

Is the physics engine good enough for a platformer?

Yes, and that is the case tested most: GridMap collision with one-way platforms, reliable onGround, real friction, and collision filters. What it does not handle well yet is stacks of dynamic bodies at rest.

Do I need an ESP32-P4 board to use 0.9.6?

No. Development still starts on the Windows VM, and the release works the same on ESP32 and ESP32-S3. The P4 VM is one more platform, for those who have that board and want MIPI-DSI displays.

Can the music run on a plain ESP32?

Yes. The sound engine is in all three VMs. The sample rate is chosen per board profile (22050 or 44100) and the noise clock is fixed, so the same song sounds the same across boards.