How To Structure Rogue-Like Turn Base / Action System?

Started by
1 comment, last by Scouting Ninja 6 years, 4 months ago

So I am trying to build a turn based rogue-like game and trying to figure out the best way to structure the turn base / action system. I need to be able to support the the same action taking up different amounts of "time" (for example, some enemies should be faster and slower than the player) and different actions should take different amounts of "time" (for example, eating a meal should take long than loading a gun). After thinking about it for just a little, this is my general idea at a very high level.

I would have a `ActionManager` class that would store effectively how many "action units" have pasted since the start of the game (probably be stored as a float). Any actor that can perform an action would need to register an event listener on the `ActionManager` to be notified when the "action units" have changed. The `ActionManager` would also expose itself as a singleton allowing any actor that can add to the "action units" to access it that way (right now just the player but I can foresee there being use cases where something else might need to push time forward). The singleton method might not be the best approach for this but it is probably the easiest and want to get something working before worrying about that part too much.

All actors that can perform actions would need to store 2 things. One would be the last value of "action units" that it received. The other would be a list of pending actions it wants to perform (to be loaded in some fashion, not sure right now but not critical to the topic at hand). Now any time a method on the `ActionManager` singleton is called that changes the "action units", an event is fired to all listening actors. Those actors would then check the difference from the newest value of "action units" and the last one it stored. With that value it would then loop through the queued up actions is has stored, each which would have a "wait for remaining action units to pass" value. It would take that value and subtract it from the difference. If the result is a positive number, it would just update the "wait for remaining action units to pass" value. If the number is 0, it would perform the action and take it off the queue. If it is a negative number, it would perform the action and take it off the queue and then check the next action until the calculation is 0 or higher.

With this system, I could say a player movement cost is .25 "action units" and one enemy might have .33 "action units" cost for movement. Every time the player moves, it would update the `ActionManager` and when the player has moved 4 times (resulting in an action unit of 1), the enemy would have only moved 3 times (1 / .33).

This structure for this kinda of system seems like it would be pretty flexible. The biggest concern I have with this system is that I want to make sure it has a little overhead as possible since it will be core to the performance of the game I think. The actions in the queue I hope I can make as dumb as possible where it is really just setting data and ideally I can make the task of filling up the queue be a background process (so that when the player is doing nothing, other actor queues are being filled up to a degree) but that is another topic all together that I am sure I will be making posted about here in the future.

Any kinda of critiques, opinions, ideas, suggestions, etc. for the high level system to laid out above would be most welcomed. 

Advertisement

 

Remember that your computer already runs in loops, frames per second, so your system will just run inside that loops, only updating when needed. So unlike a real time system your not running with as much power as possible, instead your waiting for actions.

2 hours ago, 3dmodelerguy said:

`ActionManager` singleton is called that changes... ...value. It would take that value and subtract it from the difference.

This is redundant, but not badly designed.:) You could just have a int named Counter and every turn you add 1 to it; so when it's 2 you know 2 turns have passed. The whole point of turn base is that you don't update everything all the time, only when needed.

You can make a class for keeping track of actions, it will just be a kind of container.


public class AttackAction{
  
  public string ActionName;
  public int TurnsToExecute;
  
  public AttackAction(string InName,int InTurnsToExecute){//This is the constructor
    ActionName = InName;
    TurnsToExecute = InTurnsToExecute;
  }
}

It should look something like this and your manager will update these actions when it's there phase.

 

2 hours ago, 3dmodelerguy said:

The biggest concern I have with this system is that I want to make sure it has a little overhead as possible since it will be core to the performance of the game I think.

For a single megabyte you can make +/- 1 000 000 integers to keep track of your data.

Int are roughly 2-4 bytes, depending on what language and other factors. A float is 4 bytes. A vector3 = 3 floats(X,Y,Z). A single pixel in a image is a vector3. That means for a single 256*256 sprite you use 65536*3*4bytes < 1mb.

 

Any system you design to create a turn based game, is only going to be a fraction of the cost that a single image will have; unless you make some very-very complex AI.

This topic is closed to new replies.

Advertisement