Make the framework:
- intuitive
- short
- easy to scan in context
- easy to remember after time away
- simple in core, but still sharp in functionality
This plan assumes:
- active target is Klad1
- War2 is archived reference only
- old examples are not compatibility gates
These are the rules the framework should move toward.
Core should contain only things that most games need:
ObjectUnitWorld(currently stillMap)CellSceneWindowStateInputMouseKeyboardCamera- rendering helpers like
Image,Sprite,Clip,Animation
Objectgeneric scene thingUnitworld-tracked thing with collision and movementCellstores dataWorldstores cells and unit buckets
Prefer:
tiletypecanPlacecanCrossTilecanCrossUnitWorld
Avoid:
- names that hide two meanings
- names that need extra explanation every time
- old words kept only because the code evolved around them
Layers are still useful because they let the world search only inside the relevant bucket.
Layer should mean only:
- which units collide with me
Layer should not mean:
- tile passability
- render order
- special wildcard terrain behavior
These do not belong in the small framework core:
- minimap
- generation
- autotile filling
- networking
- RTS-specific selection helpers
They can exist later as optional modules.
Already simplified:
Cellnow usestileandtype- active path no longer depends on
Terrain - active path no longer depends on minimap coupling
Unituses:canPlace(...)canCrossTile(...)canCrossUnit(...)
- active Klad1 build compiles with the simplified core
Still worth simplifying:
InputMouseKeyboardPositionObjectWindowStateSprite/Clip/AnimationMaprename toWorld- optional modules moved out of core thinking
After every phase:
- compile changed framework files
- compile changed Klad1 files
- build full Klad1 target
- fix breakage before next phase
Use this rule strictly.
Use direct compile for touched files, for example:
g++ -std=c++20 -O3 -m64 -Isrc -s $(pkg-config --cflags sdl3 sdl3-image sdl3-ttf) -c src/game/input.cpp -o build/src/game/input.oUse the Klad1 build after each meaningful phase:
make klad1If make is unreliable in the shell, use the PowerShell-safe full build path already used during refactor.
After bigger phases:
- launch Klad1
- confirm startup
- confirm player can still move
- confirm world still renders
Make input handling easy to scan at a glance.
- src/game/input.h
- src/game/input.cpp
- src/game/mouse.h
- src/game/mouse.cpp
- src/game/keyboard.h
- src/game/keyboard.cpp
- Remove dead comments and debug traces from
Input - Move drag/click transitions into
Mouse - Move scancode-to-bool filling into
Keyboard - Make
Input::fetch()only:
- reset devices
- poll SDL events
- hand off to mouse/keyboard
Input::fetch() should fit on one screen and read as one simple flow.
- compile
src/game/input.cpp - compile
src/game/mouse.cpp - compile
src/game/keyboard.cpp - build Klad1
No big policy blob remains inside Input::fetch().
Make position logic understandable without reading hidden math twice.
- Remove rendering/debug behavior from
Position - Remove unnecessary includes from the header
- Make the core role obvious:
- raw rect storage
- optional parent-relative attachment
- Decide whether parent-relative scaling stays here or becomes a helper
- Reduce surprising public surface where possible
Position should read like geometry, not geometry plus UI/debug/layout logic.
- compile
src/game/position.cpp - compile
src/game/object.cpp - compile
src/game/unit.cpp - build Klad1
A reader can understand Position quickly without chasing unrelated behavior.
Keep Object boring and obvious.
- Review whether lazy id allocation is still needed
- Keep only the generic object responsibilities
- Reduce wrapper noise if
Positiongot simpler - Keep child positions only if they are still clearly justified
Object should be easy to explain in one sentence:
"A generic scene object with position, update, render, and visibility hooks."
- compile
src/game/object.cpp - compile
src/game/unit.cpp - compile
src/game/scene.cpp - build Klad1
Object no longer feels clever.
Make app startup and loop simple to follow.
- Remove leftover debug prints
- Remove duplicate includes
- Make ownership and cleanup clearer
- Keep
Windowfocused on:
- SDL window/runtime init
- scene hookup
- main loop
- Keep
Stateas a simple runtime bundle
A new reader should be able to find:
- where the app starts
- where the scene is attached
- where the frame loop runs
with almost no searching.
- compile
src/game/window.cpp - compile
src/game/state.cpp - compile
klad1_main.cpp - build Klad1
Startup path becomes obvious.
Make the sprite/animation stack predictable.
- src/game/image.h
- src/game/image.cpp
- src/game/sprite.h
- src/game/sprite.cpp
- src/game/clip.h
- src/game/clip.cpp
- src/game/animation.h
- src/game/animation.cpp
- Make ownership explicit
- Make lookups safer
- Reduce duplicate state where possible
- Remove stale debug or dead paths
It should be easy to answer:
- who owns the image?
- who owns the clips?
- how does animation pick a frame?
without guessing.
- compile all changed render files
- compile
src/klad1/player.cpp - compile
src/klad1/klad1.cpp - build Klad1
Rendering ownership is obvious.
Use the clearer name now that the class is simple enough.
- src/game/map.h
- src/game/map.cpp
- all active includes and references in
src/gameandsrc/klad1
- Rename
MaptoWorld - Rename files:
map.h->world.hmap.cpp->world.cpp
- Update include paths and types
- Keep method names short and literal
The class name matches what it really is now:
- a world grid
- cell store
- tile renderer
- unit bucket manager
- compile changed framework files
- compile changed Klad1 files
- build Klad1
No active code should still conceptually treat it as the old heavy Map.
Reduce framework mental load.
Likely:
- src/game/job.h
- src/game/move.h
- src/game/move.cpp
- src/game/client.h
- related client implementation files
- Decide which optional systems remain useful
- If kept, treat them as optional modules
- Remove debug prints and stale code from them
- Do not let them define the shape of the core framework
The core framework can be understood without first understanding:
- jobs
- networking
- RTS-like systems
- compile changed optional files
- build Klad1
Core and optional systems are mentally separate.
Make the framework easy to read in a small context window.
For each active core file, ask:
- Can the class be explained in one short sentence?
- Does the filename match the real responsibility?
- Are there comments that explain history instead of behavior?
- Are there dead code blocks or stale commented code?
- Are there hidden ownership rules?
- Are there names that cause double-guessing?
Clean whatever still fails those checks.
A small set of files where each one has one clear role.
- full Klad1 build
- quick runtime smoke test
Framework is easy for both you and an LLM to scan quickly.
Keep names:
- short
- literal
- stable
- single-purpose
Prefer:
WorldCelltiletypeObjectUnitcanPlacecanCrossTilecanCrossUnit
Avoid:
- abstract words that hide policy
- long names with redundant context
- names that need explanation in conversation
Discard from core:
- minimap
- terrain objects
- generation
- autotile filling
- legacy reference compatibility
- debug trace leftovers
Protect these ideas:
- object/unit split
- per-layer unit buckets
- world-based collision
- type/tile split
- drag behavior in mouse handling
- simple explicit APIs
For every phase:
- make one coherent change
- compile touched files
- build Klad1
- fix breakage
- only then move on
Do not batch multiple conceptual refactors into one step.