DeckStacker v1.0
A card manager plugin for Unity games.
 
Loading...
Searching...
No Matches
DSAction Guidelines and Use

This page talks about the DSAction: A generic type for classes that execute code when called by the DSActionQueue.actionQueue List.

DSAction - A Packet of Code

This class is the core of how DeckStacker is designed: One thing happens at a time.

DSActionQueue will look at the index 0 DSAction in the actionQueue, and call its Execute() method.

The intention behind this is so the developer can queue up several actions at the time of an event, and then those actions can play out, one at a time.

The DSActionQueue.actionQueue List is a List<DSAction>, thus each class instance that is queued up is required to inherit from the DSAction class.

Let’s take a look at the DSAction class to understand more:

namespace DeckStacker
{
   public abstract class DSAction
   {
       (_type is used for logging actions to console.)
       protected System.Type _type = null;


       (Prevents an action from being logged to console multiple times.)
       protected bool _actionLogged = false;


       (Override this abstract method to call code when this DSAction is at the front of the DSActionQueue's actionQueue.)
       public abstract void Execute();


       (Resolving a DSAction removes it from the DSActionQueue.actionQueue, and allows the next DSAction to be executed on the next Update.)
       public void Resolve()
       {
           DSActionQueue.RemoveAction(this);


           if (DSDebugSettings.logActions)
           {
               Debug.Log(System.String.Format("Action: {0} resolved.", _type.ToString()));
           }
       }


       (A more friendly way of typing "_type.ToString()".)
       public string PrintType()
       {
           return _type.ToString();
       }


       (When DSDebugSettings.logActions is enabled, this allows the DSAction to print logs to the console.)
       protected void LogAction(string actionMessage)
       {
           if (DSDebugSettings.logActions && !_actionLogged)
           {
               Debug.Log(actionMessage);


               _actionLogged = true;
           }
       }
   }
}

Key takeaways:

  1. This an an abstract class
  2. There’s some code to help with logging information to the console.
  3. All derived classes are required to have an Execute() method.
    • This is actually where the action code lives.
  4. The Resolve() method removes the DSAction from the actionQueue.

One of the most critical takeaways: DSAction is not useable, on its own, and it really doesn’t do a whole lot.

The intention behind this is to be as flexible as possible, and allow developers to write their own DeckStacker Actions with ease.

DeckStacker comes equipped with a list of Core Actions to cover the basics of what a card game needs:

  • Cards Actions
    • Deal Cards Actions
      • DSDealCardsAction
      • DSDealCardsListAction
      • DSDealCardsToStackListAction
      • DSDealSingleCardAction
    • DSDeselectAllAction
    • DSDistributeCardsBetweenStackListAction
    • DSFadeCardAction
    • DSFlipCardAction
    • DSMoveCardInDirAction
    • DSMoveCardToPositionAction
    • DSOffsetCardAction
    • DSReturnCardsToPoolAction
    • DSRotateCardAction
    • DSScaleCardAction
    • DSSelectCardAction
  • Stacks Actions
    • DSChangeStackRenderOrderAction
    • DSCombineStacksAction
    • DSExchangeCardsAction
    • DSResetStackRenderOrderAction
    • DSShiftCardOrderAction
    • DSShuffleAction
  • Timing Actions
    • DSDelayAction
    • DSWaitForCardsToStopAction

Be sure to visit each of the API docs pages for these actions to understand their intention.

When forming this list of DSActions, I went through all the different systems of DeckStacker and asked myself “Would this be useful if it was timed out in a queue of actions?”.

I think this list covers most of what is useful in DeckStacker, but I find that each time I start making a game with it, the game design I am working with at the time always seems to find new scenarios that I hadn’t thought of. Don’t expect this list of DSActions to cover everything you need for a game.

In the very likely event that you’ll need to make your own DSActions (I refer to these as “Custom Actions”), a template script has been added to DeckStacker to cover the boilerplate code.

namespace DeckStacker
{
   public class DSTemplateAction : DSAction
   {
       (CONSTRUCTOR FIELDS)


       (enter fields here)

       (Standard Constructor: Add parameters if needed.)
       public DSTemplateAction()
       {
           _type = this.GetType();
       }

       (This code will execute when this DSAction is at the 0 index of the DSActionQueue.actionQueue list, and an RunUpdate call has been made.)
       public override void Execute()
       {
           LogAction(System.String.Format("Action: {0}", _type.ToString()));

           (Action code here)


           Resolve();
       }
   }
}

This template action is 90% of the way to coding a simple Custom Action.

Here are some key takeaways:

  1. Inherits from DSAction
  2. Has a constructor
    • In most cases, there will be a gap of time between when the Custom Action is created, and when it is executed.
    • This constructor should be viewed as a communicator between the moment the Custom Action is created and when it’s executed.
    • Keep in mind that the board state can change between these 2 points in time, so plan accordingly. It’s one of the key reasons this system was created.
    • For example:
      • In the situation where DSActions are queued up so that cards are dealt to a Stack(A), then those cards are shuffled, and then the 5th card is transferred to Stack(B): At the time of queueing up these actions, you will not know what the 5th card of Stack(A) will be. It’s random…
      • In this situation, the last DSAction would take in the following data into the constructor and hold onto that data until execution:
        • Stack(A) - the fromStack
        • Stack(B) - the targetStack
        • 4 - the index of Stack(A).cards that you will want to transfer
  3. Overrides the abstract Execute() method with its own.
    • In this, there is a LogAction call, for easier console logging if enabled in DSDebugSettings
    • This method ends with a Resolve() call, to clear the instance from DSActionQueue.actionQueue
    • In between these 2 is where you should write whatever code you want to execute at the time this DSAction is processed.

With that understanding, let’s discuss guidelines for making your own Custom Actions.

Creating New DSAction Scripts

Here are some basic guidelines you will want to employ when making Custom Actions:

  • Queuing up a DSAction and executing it will happen at different times
    • Be sure to pass any data that will need to be saved for execution into a constructor for your action
  • An "Execute()" method is required
    • DSActionQueue pulls the DSAction at index 0 and calls this method, every frame.
  • Be sure to call "Resolve()" after a DSAction is finished executing its code.
    • Without Resolve() being called, the DSAction will never be dismissed, and the DSActionQueue will just continually call the same DSAction every frame (effectively causing a soft lock).
    • Note: Sometimes you will want to delay the Resolve() call until some other thing has happened. Do this with caution.
      • For example: The DSShuffleAction needs to wait an additional frame after kicking off a bunch of stuff before calling Resolve() to prevent sequencing problems.

Custom Action Writing: Order of Operations

  1. Duplicate the DSTemplateAction script.
  2. A compile error is expected now, since you now have a duplicate DSTemplateAction class.
  3. Give your new DSAction a name, replacing "DSTemplateAction" in the script name, as well as the class and constructor declarations (lines 22, and 31)
  4. If you need to save specific data until time of execution, pass that data through a constructor, storing data into variables.
  5. Write whatever time-sensitive code you wish to execute in the actionQueue in "Execute()".
    • Be sure not to remove Resolve(), unless for some weird reason that is useful to you.

It's critically important to understand Custom Action writing, so read through this page carefully, and open the provided DSAction scripts for examples. It is inevitable that you'll need to write your own DSActions, unless your usecase for DeckStacker is extremely limited.

Now go forth and make fun card games!