Engine Integration
How Galaxy Eggbert uses CNA directly, with cna-engine's strict modules as small helpers beside it.
Direct CNA — Not an Abstraction Layer
Unlike the older Simple3D direction (which wrapped Urho3D behind an abstraction so the engine
could theoretically be swapped), GalaxyEggbertCNA calls CNA directly.
CNA is an XNA-compatible, SDL3-based C++ game framework — game code uses its
Microsoft::Xna::Framework::* namespaces and types with no engine-selection
indirection layer.
cna-engine's Role — a Helper, Not a Hiding Layer
The strict modules of cna-engine (CMake targets CnaEngine::Core and
CnaEngine::Graphics, namespace CnaEngine::Graphics; XNA 4.0 types only)
live beside CNA, not above it. Game code still calls CNA directly for anything the engine modules
don't specifically help with. Their job here is narrow: a camera, texture regions, CPU-side mesh
building for boxes, plates and billboards, and GPU meshes drawn with the game's own effects. They
are not a scene graph and not a replacement engine.
Until 2026-10-20 this role was filled by the sibling helper library easy-3d
(namespace Easy3D). easy-3d was removed that day and replaced by cna-engine's strict
modules; the meshes the game builds are the same vertices and indices, bit for bit (verified by
cna-engine's Easy3DEquivalenceTests).
What cna-engine provides, used by GalaxyEggbertCNA
| Class | Role | Replaced (easy-3d) |
|---|---|---|
CnaEngine::Graphics::Camera | Drives View/Projection every frame: SetLookAt(position, target, up) (view exactly XNA Matrix::CreateLookAt), SetPerspective(fov, aspect, near, far), View(), Projection(). The game keeps the look-at target itself (cameraTarget_). | Easy3D::Camera3D |
CnaEngine::Graphics::UvRect / TextureAtlas | Texture regions: UvRect (u0, v0, u1, v1); TextureAtlas is cna-engine's counterpart of Easy3D::TextureAtlas. GETileAtlas returns UvRects, still computed with the game's own BlockTypes::tileUV() (unchanged) | Easy3D::UvRect (U0, V0, U1, V1), Easy3D::TextureAtlas |
CnaEngine::Graphics::MeshBuilder | CPU-side mesh building, positions + one texture coordinate: AddBox, AddPlate, AddCrossedPlates, AddBillboard, AddVertex/AddTriangle/AddQuad | CubeBatch, BillboardBatch, BuildCubeMesh, Append*Mesh |
CnaEngine::Graphics::GpuMesh | Upload(device, mesh, VertexLayout::PositionTexture()) to CNA buffers; Draw(device, effect) applies each pass of a caller-supplied BasicEffect | Easy3D::CubeMeshRenderer, BillboardMeshRenderer |
The game's own header src/GalaxyEggbert/Game/TexturedMesh.hpp adds four small helpers
for its one vertex format: MakeTexturedMeshBuilder(), TexturedVertex(position, uv),
AddCenteredBox(mesh, center, size, faces | uv) and UploadTexturedMesh(device, meshData).
The teleporter's pyramid tip (easy-3d's AppendPyramidTipMesh) is now the game's own
AddPyramidTip() in src/GalaxyEggbert/Game/TerrainRenderer.cpp.
Not taken over from easy-3d
easy-3d's separate CPU batches were not taken over — the builder is the batch. easy-3d's
DebugDraw was never used by the game.
CNA APIs Used Directly by GalaxyEggbertCnaGame
| CNA type | Used for |
|---|---|
Microsoft::Xna::Framework::Game | Base class for GalaxyEggbertCnaGame |
GameTime | Delta time passed to Update/Draw |
Graphics::Texture2D | Loads object-m.png |
Graphics::BasicEffect | Textured, untextured-vertex-color-off shader for terrain draw |
Input::Keyboard / Keys | Arrow keys + Space each frame |
Color, Rectangle, Matrix | Standard XNA-compatible math/graphics types |
VertexBuffer / IndexBuffer / DrawIndexedPrimitives | Behind GETerrainRenderer's meshes, created and drawn through cna-engine's GpuMesh (Upload once, Draw(device, effect) per frame) |
Entry Point
// src/GalaxyEggbertCNA/main.cpp
int main() {
auto* game = new GalaxyEggbert::CNA::GalaxyEggbertCnaGame();
game->Run();
delete game;
}
Lifecycle Overrides
class GalaxyEggbertCnaGame : public Microsoft::Xna::Framework::Game {
void LoadContent() override; // load world, texture, build terrain renderer
void Update(GameTime& gameTime) override; // advance anim phase, read input, step Blupi, update camera
void Draw(const GameTime& gameTime) override; // clear, set effect matrices, draw terrain
};
Comparison: Simple3D vs. CNA Integration Style
| Aspect | GalaxyEggbertSimple3D | GalaxyEggbertCNA |
|---|---|---|
| Engine access | Through Simple3D's Urho3D-shaped abstraction | Direct CNA API calls, no abstraction layer |
| Helper library | None (Simple3D itself is the abstraction) | cna-engine's strict modules (CnaEngine::Core, CnaEngine::Graphics), explicitly small and non-hiding — easy-3d until 2026-10-20 |
| Rendering | Scene-graph nodes with StaticModel/BillboardSet | Meshes built with MeshBuilder, drawn with explicit GpuMesh::Draw calls via BasicEffect |
| Status | Only fully playable target | Terrain + collision-only movement only |