|
Post by demonbismuth on Jan 23, 2022 23:14:43 GMT
I feel like I'm having a hard time wrapping my head around the difference between Game Actions, Phases, and Systems. Part of it is me also wanting to implement a Command Pattern, with the ability to undo and redo actions, and finding it hard to know where that would fit in.
I have a Deck class that hold cards in it. There are DeckCommand classes that perform actions to the deck. So the DrawCardCommand can take cards from a deck during Execute() and Redo(), and Undo() would put the cards back. The DrawCardCommand would be placed on a list inside a CommandHandler, which would be the class to go to to Redo or Undo.
I'm unsure how to reconcile that with GameAction. I would like my Commands to have the ability to Prepare and Cancel, but the added layer of Phases and Systems confuses me on how to move forward. Does it mean that, instead of a simple public methods for Execute, Redo(), and Undo(), they should instead be protected methods invoked via equivalent Phase variables?
And muddying the water even further is the ActionSystem. So the ActionSystem takes a GameAction, loops through its Prepare phase until it either Cancels or Executes (Performs), in which case it will loop through its Perform Phase. There doesn't seem to be a Cancel Phase in GameAction, unsure if that is added later or not. I did not want to go on ahead until I fully understood what I was implementing.
If I were to use my CommandHandler to handle these GameActions, would that mean that the CommandHandler would need to call upon an ActionSystem? Or would the CommandHandler be the ActionSystem in that case?
Thank you so much! Sorry if this is a long one. Let me know if my understanding of any part was wrong.
|
|
|
Post by Admin on Jan 24, 2022 0:54:19 GMT
Not so much a long question, but what you are wanting to do could be very tricky depending on how you try to go about it. Before I get started, I don't know if you have just looked at the project itself or have started reading the tutorial as well. If not, this post gives a good overview of the actions, phases and action system itself: theliquidfire.com/2017/09/11/make-a-ccg-action-system/A quick overview: Things you want to do in any given step of a game, like drawing a card, or casting a spell are called "game actions". The action itself is just data necessary to perform the action, so a Game Action for drawing cards may say how many cards to draw, and an action for casting a spell may hold information about what is being targeted by the spell. The application of any game action is carried out by a system. For example, one system may specialize in knowing how to apply damage to cards, and another may be used to manage your mana. When a game action is triggered, it is carried out in a sequence of "phases" which is basically, "I am about to do a thing" or "Now I am doing a thing". This gives an opportunity for other actions to occur as a reaction to an action, and also provides a way to animate viewing the action being carried out. The action system itself is what manages the way that the sequence of phases play out, including keeping track of nested actions. Hopefully that clears up "what" each thing is. The architecture that is in place was based on a game where you could not undo actions. Any given action can result in any number of reactions, and those reactions can trigger even more reactions, etc. There is no limit to the amount or kind of changes that could occur on the board, including creating new cards, modifying cards, destroying cards, etc. The system you use to damage a card may not be the same system that then determines a card is mortally wounded and is moved to the graveyard. They may not even happen at the same time or during the same phase. Trying to reverse or undo this sequence would be very difficult. Rather than trying to use a traditional command pattern to reverse an action, I would instead suggest a different approach. Take a snapshot of your game's state before an action is applied. Then if you need to "undo", you can simply reload the game based on your snapshot.
|
|
|
Post by demonbismuth on Jan 24, 2022 2:53:40 GMT
That was actually the specific page I have been referencing! Not being able to see it side by side made me feel like I wasn't getting the full grasp of what differentiated those different classes. But your explanation in your post was a helpful summary. A snapshot would probably be a good idea. Having to create an Undo() for every Execute() has already made me start scratching at my head for more complex actions. Though that feels like something that cannot be considered at the level I'm currently at, its hard to know what exactly needs to be snapshot when I barely have a concept of how a game state will look like. And the snapshot itself would likely need to be an Action as well, or work similarly, in order to get it to visualize correctly. On another note, is there a way to have the data be completely separated from having to keep track of its animations? By that I mean completely forgoing the IEnumerator used by Phases. Instead, the GameAction would execute immediately, and any animations from it, including reactions, would instead be queued and performed by a different system entirely. I have been trying to keep in mind separating data from visuals as much as possible. I'm not exactly sure how you even do the animations (haven't gotten there yet), so I don't really know how feasible of an idea this is.
|
|
|
Post by Admin on Jan 24, 2022 14:20:35 GMT
On another note, is there a way to have the data be completely separated from having to keep track of its animations? By that I mean completely forgoing the IEnumerator used by Phases. Yes, for a snapshot, I might consider something like the memento pattern. I could for example create a json representation of all the game objects, including each player, their hand, their deck, their field, etc. Applying an undo "could" be done as a game action using the action system, though it doesn't have to be. I would only implement it there if I wanted an animation (could be as simple as a screen flash, or clock moving backwards), or if I had some interesting game mechanic that reacted to the use of undos (like every undo has a random chance of a penalty). Even if you use the action system, you don't have to animate it. You will see some actions that don't use them.
|
|