Inspiration
We set out to merge two seemingly opposite design philosophies: the deliberate, punishing combat of Dark Souls and the agile, fluid traversal of Hollow Knight: Silksong. But instead of a dark gothic palette, we wrapped our mechanics in a Pokémon-style retro RPG world.
The result is Soulsong: a 2D pixel-art hack-and-slash where overworld exploration feels nostalgic—colorful villages, grassy routes, dungeon tilesets—while combat delivers precision-driven duels.
Our north star was simple: create a mastery-driven experience where difficulty feels earned. A fair but punishing design loop where
skill × timing × anticipation = satisfaction.
What it does
Soulsong is a combat-first adventure set in a retro, tile-based world. Players explore a Pokémon-style overworld with routes, towns, and NPCs—but when enemies engage, the system shifts to real-time duels that demand precision.
Core mechanics:
- Readable telegraphs (retro-sprite enemies with exaggerated windups)
- Tight dodge and parry windows (skill > luck)
- Resource trade-offs (stamina vs. opportunity)
The visual design emphasizes 16-bit nostalgia: vibrant palettes, tile-mapped environments, and charming overworld sprites. But once combat starts, dynamic lighting, hit-flash effects, and retro particle bursts add intensity. Think “Pokémon overworld meets Soulslike duel.”
How we built it
We approached development with a data-driven, iterative workflow:
- Combat Framework
- Retro sprites are animated on a frame grid, letting us measure i-frames and attack cancels exactly.
- Formula for dodge balance:
$$ \text{Survivability} = \frac{\text{Invincibility Duration}}{\text{Enemy Attack Window}} - \text{Stamina Cost Factor} $$
Our target was a survivability ratio of ~0.8–1.0.
// Dodge tuned to retro pacing
if (Phaser.Input.Keyboard.JustDown(this.keys.Z) && this.playerStamina >= 15) {
this.player.setData("isDodging", true);
this.playerStamina -= 15;
this.time.delayedCall(180, () => this.player.setData("invincible", true));
this.time.delayedCall(360, () => this.player.setData("invincible", false));
this.time.delayedCall(500, () => this.player.setData("isDodging", false));
}
- Enemy AI
- Instead of chaotic RNG, each retro enemy telegraphs with sprite windups—a “blink” animation or a glowing tile.
- Players always see a cue before damage.
if (distance < 100 && this.time.now > this.enemy.getData("nextAttack")) {
this.enemy.play("windup"); // retro sprite flash
this.time.delayedCall(300, () => this.enemy.play("attack"));
this.enemy.setData("nextAttack", this.time.now + 1000);
}
- Animation Blending
- Heavy swings originally felt stiff.
- We added cancel windows—retro animation can chain at 60% progress.
this.player.play("sword_heavy");
this.player.setData("locked", true);
this.time.delayedCall(480, () => {
this.player.setData("locked", false); // chain at 0.48s
});
- Retro Optimization
- Overworld uses tilemaps for Pokémon-style environments.
- Particle pooling ensures effects (slash arcs, dust clouds) cost <5% frame time.
if (!this.slashEmitter) {
this.slashEmitter = this.add.particles("spark").createEmitter({
speed: { min: -100, max: 100 },
lifespan: 400,
quantity: 3,
on: false
});
}
this.slashEmitter.emitParticleAt(x, y);
Challenges we ran into
- Tone Balance: Retro Pokémon charm vs. Soulslike intensity.
- Clarity vs. Nostalgia: Keeping telegraphs obvious while staying in an 8×8 or 16×16 sprite grid.
- Performance: Tile-based maps plus dynamic combat effects pushed memory usage.
- Combat Readability: Retro overworld sprites weren’t enough—so we added glow/tile effects for attacks.
Accomplishments we’re proud of
- Hybrid Aesthetic: Overworld exploration feels like Pokémon Red/Blue, but combat feels like Souls.
- Combat Mastery Loop: Playtesters describe duels as “brutal but fair.”
- Cohesive Retro Visual Identity: Pixel tiles + sprite telegraphs + chiptune audio = unique identity.
- System Interconnection: Overworld exploration feeds into combat; stamina/positioning drive moment-to-moment decisions.
What we learned
- Fairness is measurable—even in a retro system.
- Scope matters: building the overworld in a Pokémon-style tilemap gave us fast iteration.
- Performance is gameplay: optimized effects = smooth duels at 60 FPS.
- Retro doesn’t mean simple: we can have nostalgia and depth.
What’s next for Soulsong
- Expanded Overworld: New biomes (icy routes, lava caves, haunted forests).
- Enemy Archetypes: Retro bosses with multi-phase duels.
- Player Progression: Unlockable weapons, abilities, retro-style equipment menus.
- Public Demo: To validate the hybrid identity with retro RPG + Soulslike fans.
The takeaway
Soulsong proves you can marry retro RPG charm with Soulslike precision combat.
It is evidence of a team that can:
- Frame design as measurable systems,
- Solve problems with disciplined iteration,
- Build a game that balances Pokémon nostalgia with Dark Souls intensity,
- And scale toward a commercially viable release.
The foundation is solid, the vision is unique, and the execution is systematic. The next stage is to expand this retro-Soulslike hybrid into a full content-rich release.

Log in or sign up for Devpost to join the conversation.