1
\$\begingroup\$

I've been trying to program a video game adaptation of the popular trading card game "Magic: The Gathering". If you've played MTG before, you'll know most cards have an effect, which is activated at a certain time, usually when it's played. But I'm unsure how to implement effects into my game.

I'm thinking of creating a method that assigns a card its effect when it's played based on the card's name, but that doesn't really work when a card's effect isn't supposed to be activated when it's played, like in the case of Deathrattle cards, or when it's a continuous effect. I've thought of creating a thread for each effect which activates it whenever needed, but... that's a LOT of unique threads. I haven't found any similar java programs anywhere, so I wanna ask here. How do you think card effects should be handled?

\$\endgroup\$
1
\$\begingroup\$

Threads would definitely be overkill here. I would use event listeners.

First, make an ICommand interface. (The param is so that you can optionally pass data to your command)

public interface ICommand{
    public void execute(Object param);
}

Then make sure you clearly define every scenario in which a card will activate and create a ICommand variable in your Card class essentially creating a "slot" for each event type.

//Card class
ICommand onDeathrattleCommand;
ICommand onCardPlayedCommand;
//... other event types

When you create each card type, you initialize the appropriate event slots

Card deathrattleCard = new Card();
deathrattleCard.onDeathrattleCommand= new ICommand(){
   public void execute(Object param){
       foreach(Card opponentCard: opponentsCards){
           opponentCard.applyDamage(6);
       }
   }
};

Then trigger these events at the appropriate time

//Card class
public void onPlayed()
{
    if(onCardPlayedCommand != null){
       onCardPlayedCommand.execute(null);
    }
}

public void applyDamage(int damage)
{
   hp -= damage;
   if(hp <= 0 && onDeathrattleCommand != null){
     onDeathrattleCommand.execute(null);
   }
}
| improve this answer | |
\$\endgroup\$
  • \$\begingroup\$ An event based solution was recommend to me for a turn based game (also in Java) using table top / card based mechanics. In my case, I also needed to ensure repeatable outcomes which would have added a lot of extra complexity to a thread based solution. \$\endgroup\$ – Pikalek Jun 1 '16 at 17:58
0
\$\begingroup\$

The representation of game state should be the core of your architecture, because it ties everything else together. Player actions, the sequence of events in a turn, card effects are strictly layered on top of game state.

For example, you can have an index of triggered abilities by the type of event that triggers them, and when anything happens you could

  1. Enumerate all relevant triggered abilities for the event (e.g. a permanent enters the battlefield, a player draws a card, a creature deals combat damage, etc.)
  2. Check if they actually trigger (e.g. "when a creature enters the battlefield" doesn't trigger for a land)
  3. Ask the players in which order they want to stack the triggers
  4. Put trigger ability objects on the stack
  5. And the rest is the common procedure of giving priority to players, resolving stack contents, checking state-based actions, etc.
| improve this answer | |
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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