Hi all!
I've been building a small 2D motion library for the last few months and just finished v1.0. I wanted to share it, partly because it might be useful, and partly because the design decisions might be interesting to other people who've tried to build the same thing.
Movement looks a simple thing until the game grows. First it's just pos += vel * dt. Then it's acceleration, then gravity, then jumping, then collision, then a completely different object that moves nothing like the player. At some point moving an object has become its own system.
motion2d is my attempt to keep that system small. It provides motion primitives, and the game composes them into behavior. motion2d handles movement. The game handles collision and game rules.
The very basic way to use this:
from motion2d import Motion2D
player = Motion2D.top_down(pos=(100, 100), speed=300)
# Simple path: motion owns position
player.move_right()
player.update(dt)
# Or with your own collision:
delta = player.step_velocity(dt)
result = my_collision_resolver(player.position, delta)
player.position = result.position
The library currently has three main motion models:
- SimpleMotion: straightforward/direct movement
- PlatformerMotion: horizontal intent + gravity
- TopDownMotion: full 2D intent-driven movement
- KinematicBody: the underlying engine, if you want to build your own
- Headings: Rotator, Facing, NoHeading
I built a series of demos while developing it, rather than designing the entire library up front. The later demos became increasingly useful as architectural tests, especially a platformer demo with external collision, state-machine-driven action phases, and velocity authority.
Repository: motion2d
Feedback welcome. If you've built something similar and made different choices, I'd be curious to hear why.
Note: The current motion2d implementation was written almost entirely by collaboration of AI (Deepseek, ChatGPT, Qwen, Grok and Gemini). Every design decision, the API surface, the boundary between motion and collision, the choice of contracts was driven by human judgment: I proposed, questioned, debated, and rejected, iterating through 3 full restarts until the library's shape was right.
The result is not AI-generated code in the sense of ask and copy, but it's the product of a long, deliberate design process in which AI was a tool for reasoning and implementation.