There is a big difference between a game prototype that technically works and one that feels like a game.
Movement, spawning, upgrades, and collision can be built with colored rectangles. That is often the right way to start. But the moment you want an animated player, a family of enemies, weapon variety, collectibles, and a consistent visual identity, the art pipeline can become the project.
For a recent experiment, I wanted to see how far I could get by combining three tools:
- Phaser 3 for the game runtime
- Codex for implementation and iteration
- SpriteShip for game-ready visual assets through its MCP/API workflow
The result was Last Light, a top-down survival game that runs in desktop and mobile browsers. It has an animated player, multiple enemy families, a large humanoid with separate walk and attack animations, sixteen weapons, sixteen collectibles, upgrades, an objective, and a boss encounter.
Play Last Light: https://spriteship.github.io/sample_games/last-light/
Browse the source repository: https://github.com/spriteship/sample_games
More importantly, it became playable through a surprisingly natural loop: describe an asset, generate it in SpriteShip, inspect or revise it, and let Codex wire the exported data into Phaser.
Starting with gameplay, not presentation
The first version was intentionally plain. It established the systems that mattered:
- Top-down movement
- Automatic targeting and firing
- Enemy spawning and difficulty progression
- Experience drops and upgrades
- Desktop and touch input
- A camera following the player across a large map
That gave us something useful to evaluate. Once the loop was playable, every art decision could be judged in motion rather than in isolation.
This order mattered. SpriteShip did not have to invent the game design; it could supply assets for systems that already existed.
Creating a coherent project in SpriteShip
Instead of making unrelated images one at a time, we created a top-down overhead project in SpriteShip. That project context helped keep the blackout-survival direction consistent across characters, enemies, weapons, and collectibles.
The player went through a normal creative selection process. We generated options, selected a character, refined the camera angle and facing direction, and then added animation states. The same process produced:
- A player walk cycle
- A separate idle animation
- Four creature enemies
- A larger weaponless humanoid enemy
- Humanoid walk and attack animations
- A 4×4 weapon set
- A 4×4 collectible set
The useful part was not just getting PNG files. SpriteShip returned structured animation data: atlas frames, FPS, looping behavior, source sizes, previews, and collision-body definitions.
That is where the MCP integration started to feel less like image generation and more like a game-development tool.
Wiring SpriteShip animations into Phaser
Phaser’s atlas support maps naturally to SpriteShip’s exports. The loader only needs the sheet and its JSON metadata:
this.load.atlas(
PLAYER_ATLAS,
"assets/spriteship/player/spritesheet_walk_256.png",
"assets/spriteship/player/atlas_walk_256.json"
);
Animation registration can use the frame list supplied by the atlas instead of assuming a fragile numeric range:
const definition = atlasData.animations.walk;
scene.anims.create({
key: "player-walk",
frames: definition.frames.map((frame) => ({
key: PLAYER_ATLAS,
frame,
})),
frameRate: 60,
repeat: -1,
});
The player switches to the walk cycle while moving and to SpriteShip’s idle_2 animation while stationary. Because the animation data is named and versionable, updating a dashboard edit is much safer than manually rebuilding frame sequences.
Collision data was more useful than I expected
SpriteShip supplied normalized rectangular collision bodies for individual animation states. We converted those values into rotated world-space rectangles inside Phaser.
For the humanoid enemy, the body changes when the attack animation begins. The attack pose is wider and lower than the walk pose, so using a single circular approximation would have produced misleading hits.
The final game uses the same authored rectangle for:
- Projectile collision
- Enemy melee contact
- Debug visualization
That last point was important. Drawing the rectangle on screen made it immediately obvious whether gameplay matched the artwork. It also turned collision tuning into something a non-programmer could evaluate visually.
The dashboard-and-agent loop worked well
One of my favorite parts of the workflow was mixing dashboard edits with Codex-driven integration.
At one point, the humanoid attack animation was adjusted in the SpriteShip dashboard. Instead of manually exporting everything and explaining what changed, the updated asset could be fetched again and repackaged for the game. The same happened with collectible cleanup.
The division of labor felt sensible:
- The human selected and visually edited assets.
- SpriteShip managed the project and generated structured outputs.
- Codex synchronized files, generated runtime variants, updated Phaser code, and ran tests.
It was a much smoother loop than downloading miscellaneous images, renaming them by hand, and guessing how they should be sliced.
Resolution is not only width and height
The most useful lesson from the project was that two 256×256 frames are not necessarily the same visual size.
The player’s walk and idle animations both had 256×256 runtime frames, but the character initially occupied a much smaller part of the idle frame. When the game switched states, the player appeared to shrink.
We measured the visible pixel bounds and found roughly:
- Walk footprint: 158×179 pixels
- Initial idle footprint: 109×111 pixels
The fix was to rebuild the idle runtime sheet from SpriteShip’s original 512×512 frames, normalize the character around the same ground anchor, and then export back to 256×256 frames. That produced a much closer 176×178 pixel footprint without throwing away source detail.
This was not a failure of the integration. It was a reminder that a real asset pipeline must consider transparent padding, subject scale, ground contact, and intended display size—not just file dimensions.
The same principle guided the other assets:
- Weapons: 32×32 source and runtime display target
- Collectibles: 64×64 source and runtime display target
- Animated characters: larger source frames with consistent visual occupancy
Once those rules were explicit, the game looked much sharper and more cohesive.
What SpriteShip made easy
Several things that normally consume a lot of setup time were refreshingly straightforward:
Consistent asset families
The player, enemies, weapons, and collectibles belong to the same visual world. Achieving that consistency across dozens of independent assets is usually difficult.
Animation metadata
Named animations, FPS, loop state, frame lists, and preview GIFs made integration predictable.
Multiple runtime sizes
Having access to larger sources and smaller runtime variants let us make sensible choices for desktop and mobile instead of scaling one image everywhere.
MCP/API access
The API key stayed in the local environment, and Codex could work with SpriteShip as part of the development process. There was no need to build an asset-management service inside the game.
Human-in-the-loop editing
The dashboard remained valuable even in an agent-driven workflow. This was not “type one prompt and accept everything.” It was a collaborative process where visual judgment and automation complemented each other.
The results were not magically perfect—and that is fine
A believable account of AI-assisted creation should include the iterations.
The first character direction was not exactly right. One collectible sheet included labels that were useful for review but not for runtime use. Animation families needed scale normalization. Playback speed needed tuning after a walk cycle changed frame count. Collision bodies needed to be visualized before they could be trusted.
What impressed me was how inexpensive those corrections were in the overall workflow. We did not have to discard the pipeline every time something changed. We could revise an asset, fetch the new version, and update the game.
That is a more meaningful kind of speed than getting a perfect image from one prompt.
Building a sample repository
The finished game became the first entry in a dedicated SpriteShip sample-games repository:
spriteship-game-samples/
├── README.md
├── package.json
└── games/
└── last-light/
├── README.md
├── PRD.md
├── public/
├── tests/
└── package.json
Each future game can live in its own workspace with independent assets, tests, and build scripts. The root repository acts as a catalog rather than forcing every sample into one application.
This structure also makes the examples useful to developers. They can inspect the actual atlases, animation registration, collision conversion, and resolution choices instead of only seeing a promotional demo.
What I would do next
The obvious next step is to add samples in other genres and engines:
- A platformer with state transitions and hit reactions
- A tactics prototype using character directions and tilemaps
- A Godot sample using the same SpriteShip project concepts
- A small multiplayer arena with cosmetic variants
I would also like to see engine-specific SpriteShip exports become even more opinionated: a Phaser loader module, recommended display sizes, per-frame opaque bounds, and a compact synchronization manifest would make an already smooth workflow nearly automatic.
Final thoughts
Codex made it possible to keep implementation, asset processing, testing, and iteration in one development thread. Phaser made the runtime lightweight and immediate. SpriteShip supplied the piece that usually holds prototypes back: enough coherent, animated art to make the game feel intentional.
The standout feature was not simply that SpriteShip generated good images. It was that the service fit into a real engineering loop. Assets had identities, versions, animations, collision data, previews, and dashboard edits. The MCP/API interface made those capabilities accessible without turning the project into an asset-management exercise.
Last Light still involved judgment and iteration, as every game does. But the distance between “I want a top-down survival game” and “I can play one with a coherent animated cast” was much shorter than I expected.
That is the kind of AI-assisted workflow I find genuinely useful: not replacing the creative process, but removing enough friction that the process can keep moving.
Play the game: https://spriteship.github.io/sample_games/last-light/
Project repository: https://github.com/spriteship/sample_games
Tools: SpriteShip, Codex, Phaser 3
Top comments (0)