How shfahimdev/formulanegativeone works
1. Project shape
- This is a small native C simulation program, built as a single executable rather than a framework-based app.
- The architecture is deliberately split into a few low-level modules: input capture, vehicle state, physics, rendering, and the main loop.
2. Top-level control flow
- main.c is the orchestrator.
- It runs a fixed-rate loop at roughly 60 Hz, pulls the latest input state, translates that into forces, advances the physics, and then hands the updated state to rendering.
3. Input subsystem
- keyhold.c/h is a background-thread input reader using Linux’s /dev/input event system.
- It tracks key-down duration with microsecond precision, which is important because the simulator cares about continuous hold time rather than discrete key presses.
4. Simulation state boundary
- object.c/h defines the rigid-body state of the car: position, velocity, acceleration, mass, and friction parameters.
- This module is the shared data model passed between input interpretation, physics integration, and rendering.
5. Physics subsystem
- physics.c/h contains the core motion model: force application, Euler integration, and kinetic friction.
- The simulation currently treats the car as a body moving on a 2D X/Z plane, so physics is simplified to translational motion with no heading/orientation yet.
6. Control-to-force mapping
- The keyboard controls are not directly “move object” commands; they become forces applied to the rigid body.
- W/S drive forward and braking/reverse forces, while A/D apply lateral forces in the current model.
7. Rendering boundary
- render.c/h is isolated as the presentation layer.
- Even if the visual system is minimal today, the file split shows the intended boundary: rendering should consume simulation state, not contain simulation logic.
8. System-level dependencies
- The build uses plain gcc with -lm and -lpthread, so the runtime depends on the math library and POSIX threads.
- Access to the keyboard device requires elevated privileges (sudo) because it reads from /dev/input.
9. Current architectural constraints
- The simulator is intentionally “bare metal”: no engine, no ECS, no networking, no persistence, and no asset pipeline.
- The main technical constraints are the hardcoded input device path, fixed timestep integration, and the absence of car orientation and tire dynamics.
10. Likely architecture diagram framing
- A good diagram would show one central simulation loop in main.c, with arrows from the Linux input device into keyhold, then into main, then into physics, updating object state, and finally into render.
- The key boundary is that input is asynchronous, while physics/rendering are driven synchronously by the loop.
Main entry points: main.c Main loop · object.c Car state · keyhold.c Keyhold · physics.c Physics
Components 6
Control loop
Main orchestration and asynchronous input capture.
Simulation
Shared vehicle state and physics integration.
Rendering
Presentation boundary consuming simulation state.
- Render · Consumes simulation state and presents the current frame.
render.c
Connections 8
- /dev/input → Keyhold: events · Keyboard events are streamed from the Linux input device.
- Keyhold → Main loop: input state · The main loop polls the latest hold durations and key state.
- Main loop → Physics: forces · Main translates controls into forces and advances the simulation.
- Physics → Car state: updates · Physics mutates the shared vehicle state through integration.
- Main loop → Car state: reads/writes · Main uses the state as the boundary between input interpretation and simulation.
- Car state → Render: frame state · Rendering consumes the updated vehicle state.
- Main loop → Render: draw · Each tick ends by handing the current state to the renderer.
- Keyhold → Car state: control intent · Continuous key holds are mapped into movement intent before physics.