View: Multi-Page Single Page

Quick Start

Get a battle running in four steps.

Step 1: Implement ICombatant

ICombatant is the only interface your characters need to implement. You own the stats, the properties, the logic. SimpleJRPG just needs a name, alive status, team index, speed, and methods to take damage and heal.

public class MyCombatant : ICombatant
{
    public string Name { get; }
    public bool IsAlive => HP > 0;
    public int Team { get; }
    public float Speed { get; }

    public int HP { get; private set; }
    public int MaxHP { get; }

    public MyCombatant(string name, int hp, float speed, int team)
    {
        Name = name;
        HP = hp;
        MaxHP = hp;
        Speed = speed;
        Team = team;
    }

    public void TakeDamage(int amount) => HP = Math.Max(0, HP - amount);
    public void Heal(int amount) => HP = Math.Min(MaxHP, HP + amount);
}
Your class, your rules. Add whatever stats you need — MP, defense, elemental resistances, equipment slots. SimpleJRPG never inspects those. It only touches what ICombatant defines.

Step 2: Create a Battle

Create a Battle instance, build your party and enemy lists, then call Start() with all combatants and a turn system.

var battle = new Battle();
var party = new List<ICombatant>
{
    new MyCombatant("Hero", 100, 10f, 0),
    new MyCombatant("Mage", 70, 12f, 0),
};
var enemies = new List<ICombatant>
{
    new MyCombatant("Goblin", 50, 8f, 1),
    new MyCombatant("Orc", 80, 6f, 1),
};
var all = new List<ICombatant>();
all.AddRange(party);
all.AddRange(enemies);
battle.Start(all, new ClassicTurnSystem());
Team convention. Team 0 is the player party. All other team values are enemies. CheckBattleEnd() uses this to determine Victory vs. Defeat.

Step 3: Subscribe to Events

Every combat verb fires an event. Subscribe to drive your UI, play sound effects, trigger animations, or log to console — whatever your game needs.

battle.OnDamageDealt += e => Debug.Log($"{e.Source.Name} hits {e.Target.Name} for {e.Amount}!");
battle.OnKO += e => Debug.Log($"{e.Target.Name} was knocked out!");
battle.OnBattleEnd += (b, state) => Debug.Log($"Battle ended: {state}");

Events are the primary way SimpleJRPG communicates what happened. There are no built-in UI components, no logging systems, no animation controllers. You subscribe to exactly the events you care about and handle them however you want.

Step 4: Run the Battle Loop

Ask the battle for the next actor, execute your game logic (pick targets, calculate damage with your own formulas), call combat verbs, end the turn, and check if the battle is over.

while (battle.State == BattleState.WaitingForCommands)
{
    ICombatant actor = battle.BeginNextTurn();
    // Your game logic: pick targets, calculate damage, etc.
    var target = battle.GetEnemies(actor)[0];
    int damage = CalculateDamage(actor, target); // Your formula
    battle.DealDamage(actor, target, damage, "physical", "none");
    battle.EndTurn();
    battle.CheckBattleEnd();
}
You do the math. CalculateDamage() is your function, not ours. SimpleJRPG never calculates damage, hit rates, or any other formula. You pass in the final number, we apply it and fire the event.

What's Next

You have a working battle. Here is where to go from here:

  • Battle Core — All combat verbs: DealDamage, Heal, Kill, Revive, ApplyStatus, ApplyBuff, Flee, and the events they fire.
  • Turn Systems — Alternatives to ClassicTurnSystem: ATB, Timeline/CTB, Press Turn, and Action Point.
  • API Reference — Full details on every class, interface, method, and event.
↓ ↑