Skip to content

Trail particles behind moving ball projectiles - #127

Merged
Hugman76 merged 4 commits into
devfrom
claude/issue-125-resolution-u2jgym
Aug 27, 2026
Merged

Trail particles behind moving ball projectiles#127
Hugman76 merged 4 commits into
devfrom
claude/issue-125-resolution-u2jgym

Conversation

@Hugman76

@Hugman76 Hugman76 commented Aug 26, 2026

Copy link
Copy Markdown
Member

Overview

Fireballs, iceballs and gold fireballs used to fly across the screen as a bare sprite: particles only ever showed up at the very end, when the ball burst. They now leave a trail behind them for as long as they are moving.

Resolves #125

Changes

  • Ball gained getTrailParticle(), returning null by default for a ball that leaves no trail, and spawns that particle from tick(), client-side only.
  • The trail follows what vanilla arrows do: a couple of particles strung along the movement of the tick and pushed back the way the ball came, so that they fall behind the ball instead of riding along with it. Spreading them over the movement rather than dropping them all at the current position keeps the trail from breaking up, as a thrown ball covers about a block per tick.
  • The count does not grow with speed — a fast ball spaces its trail out instead of spawning more of it — and a ball that is not moving emits nothing.
  • Each shipped ball picks its own particle: small flames for the fireball, snowflakes for the iceball, coin sparkles for the gold fireball.

Testing

The particles themselves are client-only visuals, which neither the unit tests (no world) nor the game tests (headless server) can observe. The maths behind them is testable on its own, so Ball.trailParticleCount(double) is covered by a new BallTrailTest: a motionless ball trails nothing, a moving one always trails something, and going faster spaces the trail out rather than thickening it.

./gradlew :mubble-test:test   # whole unit suite green
./gradlew :mubble-super_mario:compileJava :mubble-core:compileClientJava :mubble-super_mario:compileClientJava

I agree to the Contributor License Agreement found in CONTRIBUTING.md.

🤖 Generated with Claude Code

https://claude.ai/code/session_01YQFygNg1DQAHDTWbpnVPAZ

claude added 4 commits August 26, 2026 17:03
Fireballs, iceballs and gold fireballs flew across the screen as a bare
sprite, with particles only ever showing up at the very end, when the ball
burst. They now leave a trail behind them for as long as they are moving.

The trail is spread over the path the ball travelled during the tick rather
than dropped in a single burst at its current position, since a thrown ball
covers over a block per tick and would otherwise leave a dotted line. It is
spawned client-side only, where particles exist in the first place, and a
ball that is not moving emits nothing.

Each ball picks its own particle: embers for the fireball, snowflakes for
the iceball and sparkles for the gold fireball. Balls that want no trail at
all can leave `getTrailParticle` returning null.

Resolves #125

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01YQFygNg1DQAHDTWbpnVPAZ
The trail was far too dense: up to eight particles per tick, and the faster
the ball went the thicker it got.

It now follows what vanilla arrows do — a couple of particles strung along
the movement of the tick, pushed back the way the ball came so they fall
behind it — and the count no longer grows with speed: a fast ball spaces its
trail out instead of spawning more of it.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01YQFygNg1DQAHDTWbpnVPAZ
One particle per tick rather than two, and the backwards push they get is now
a twentieth of the speed of the ball instead of all of it, which was fast
enough to fling the trail off rather than leave it hanging behind.

The lone particle of a tick sits halfway along the movement rather than right
at its start, so the trail stays centred on the path of the ball.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01YQFygNg1DQAHDTWbpnVPAZ
The trail was offset by half the bounding box, which put it at the top of the
ball rather than at its middle: unlike most entities, a ball is rendered
centred on its position instead of standing on it.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01YQFygNg1DQAHDTWbpnVPAZ
@Hugman76
Hugman76 merged commit f1949ea into dev Aug 27, 2026
1 check passed
@Hugman76
Hugman76 deleted the claude/issue-125-resolution-u2jgym branch August 27, 2026 20:25
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants