2
\$\begingroup\$

I'm trying to create a turn-based strategy game on a tilemap.

I'm using design by component so far, but I can't find a nice way to fit components into the part I want to ask.

I'm struggling with the "game rules" logic. That is, the code that displays the menu, allows the player to select units, and command them, then tells the unit game objects what to do given the player input. The best way I could thing of handling this was using a big state machine, so everything that could be done in a "turn" is handled by this state machine, and the update code of this state machine does different things depending on the state.

However, this approach leads to a large amount of code (anything not model-related) going into a big class. Of course I can subdivide this big class into more classes, but it doesn't feel modular and upgradable enough. I'd like to know of better systems to handle this in order to be able to upgrade the game with new rules without having a monstruous if/else chain (or switch / case, for that matter).

Any ideas? What specific design pattern other than MVC should I be using?

\$\endgroup\$
  • \$\begingroup\$ This question is incredibly broad and appears to be entirely opinion based. What have you actually tried implementing so far? Maybe try searching game state management. \$\endgroup\$ – XNargaHuntress Aug 18 '14 at 11:50
  • \$\begingroup\$ I'd like to reformulate this into a more narrow question but I'm quite clueless about how to approach the issue. I'm actually trying what I've described, a big state machine handling all the possible states in a combat: Player selecting a tile to move to, unit moving to a tile, displaying actions menu... and so forth. And as I stated I feel like this is going to become a toilet-paper-roll class. \$\endgroup\$ – Setzer22 Aug 18 '14 at 12:39
  • \$\begingroup\$ I'd also like to add that your link has provided a lot of useful information, and that the state pattern seems like a good approach. I don't really know how to make this into a non-opinion-based question, as anything related to design patterns and software engineering is mostly opinion based so I do't really know how to ask. \$\endgroup\$ – Setzer22 Aug 18 '14 at 12:42
  • 1
    \$\begingroup\$ I think that this question winds up being very similar to yours. That said, removing/changing the "recommendations?" bit of the question would go a long way towards improving the general appearance of the question. \$\endgroup\$ – XNargaHuntress Aug 18 '14 at 13:27
  • 1
    \$\begingroup\$ I went ahead made an answer discussing making an FSM more modular, as I think that might be a bit more what's at the heart of this question. \$\endgroup\$ – XNargaHuntress Aug 19 '14 at 14:20
2
\$\begingroup\$

If you are using a State Machine and are worried about it being modular and extensible, you can follow the Strategy Pattern using Interfaces to define the various states. This answer gives a fairly good idea of how to go about doing that.

To make it even more extensible, you can drive the state transitions from a State Transition Table and populate that table at run-time from a database or a file to make the FSM data-driven instead of hard-coded.

If you want to go even further, you can define your intefaces and then develop a Plugin Architecture (which I won't really get into) to make your whole FSM completely configurable at run-time. This would mean any changes you decide to make on down the line would only require you to ship a dll instead of a whole new application.

(Ondrej Balas had a good presentation at Stir Trek 2014 on designing a plugin architecture in .NET UDPATE 08/13/2015: the slides can currently be found on slideshare, or at his github repo.)

So, as a simple "example" (C# pseudo):

public interface IState {
    public void Execute(double time);
    public void OnEnter();
    public void OnExit();
}

public enum Event {
    SomeEvent,
    SomeEvent2,
    ...
}

public class FSM {
    // This could probably be done better as far as
    // defining the keys for the dictionary. But 'tis a quick example
    public Dictionary<IState, Dictionary<Event, IState>> transitions;
    public IState currentState;

    public void Update(double time){
        currentState.Execute(time);
    }

    public IState MoveNext(Event evt){
        currentState.OnExit();
        currentState = transitions[currentState][evt];
        currentState.OnEnter();
        return currentState;
    }
}

The "Event" doesn't even have to be an enum, it could itself be an interface or an id pulled from a database or a file, thus making the design further data-driven. In this particular example, your states could be based on plugins, and the transition table could be defined in a database or file (granted, you'd then need to get into some good 'ol Reflection if you're using .NET).

\$\endgroup\$
  • \$\begingroup\$ I'll try to find a good talk or tutorial for plugin architectures and update this answer with that link/information. The speaker I saw apparently doesn't post his slides or talk (at least not yet). \$\endgroup\$ – XNargaHuntress Aug 19 '14 at 14:28
  • 1
    \$\begingroup\$ Very late here (just found this page when checking blog referrals) but the slides to my talk about plug-in architecture are online here: slideshare.net/ondrejbalas/… and I also have code on GitHub here: github.com/ondrejbalas/plugin-architecture - Hope that still helps someone out! \$\endgroup\$ – Ondrej Balas Aug 12 '15 at 23:05

Not the answer you're looking for? Browse other questions tagged or ask your own question.