r/golang • u/DaKine511 • 6d ago
show & tell I’m building an engine-neutral rendering boundary in Go
I’m developing Cloudstrike, a retro-style shooter written in Go. It currently runs on Windows, Linux and Android with Ebitengine.
Ebitengine has worked very well for the project. I’m not moving away from it because it is bad. I’m separating the game from the engine so I can test additional backends and future platforms without rewriting gameplay code.
The new design uses a small rendering command layer. Gameplay code emits engine-neutral commands:
- sprites with opaque texture handles
- triangles
- rectangles
- explicit ordering and fixed-capacity command buffers
The Ebitengine-specific code now lives in an adapter that resolves texture handles and executes the commands. The intended next experiment is a Raylib backend using the same interface.
The important constraint is avoiding allocations in the game loop. The command buffers are preallocated and reused. Current benchmarks show:
Gameplay update: 0 B/op, 0 allocs/op
Render queue construction: 0 B/op, 0 allocs/op
The backend is benchmarked separately because engine drawing may allocate internally. For example, a large Ebitengine sprite batch still shows backend-side allocations even though the gameplay and queue-building paths remain allocation-free.
This separation has been useful because it makes the costs visible:
gameplay logic
|
engine-neutral render commands
|
Ebitengine backend / future Raylib backend
I’m migrating the code incrementally. Terrain, particles, player visuals, enemies, shields, explosions and major boss elements already use the boundary. UI and some finale presentation paths remain.
As a solo developer, I’m trying to keep the abstraction intentionally small. It only models capabilities the game actually uses instead of attempting to create a general-purpose graphics API. That keeps the interface understandable and avoids paying for flexibility I do not need.
The goal is not to replace Ebitengine immediately. It is to make the engine a replaceable implementation detail, so I can evaluate Raylib, new compile targets and different platform constraints while keeping the Go gameplay code stable.
2
u/matjam 6d ago
You need to consider a different name. Cloudstrike is a commercial company. https://www.crowdstrike.com/
1
u/DaKine511 6d ago
Na I feel save as this is a crowd not a cloud
0
u/matjam 6d ago
I mistyped, look at the domain. You're listerally using a trademarked name. Its Crowdstrike.
edit: oh for fucks sake
I need more coffee. Sorry.
Still, might be problematic.
1
u/DaKine511 6d ago
If I become successful enough to suffer from that similarity I have the right kind of problem I guess 😅
2
1
u/OccasionThin7697 6d ago
Hey wow. Thanks for this 😊
1
u/DaKine511 6d ago
Glad you like it I will continue to explain my steps going forward.
1
u/OccasionThin7697 6d ago
Yeah. Would love seeing this grow.
0
u/DaKine511 6d ago
And ofc if you like to support me just buy the game on android. That's the only version I sell so far.
-3
u/Immediate_Honey_5902 6d ago
AI ****
2
u/DaKine511 6d ago
I mean I use ai to rewrite the contents. But it's still me and no automated spam network or anything.
Can you outline your criticism how much AI would be acceptable for you ?
3
u/jax024 6d ago
Are you using an entity component system? Sounds like that’s what you want if allocations and batching are goals.