Class Design Advice for a Collectable Card Game

Hi, I’m working on a collectable card game in Unity. The long-term (3 year+) goal is to have AI’s to practice against with popular deck types, and to have the playing of the game streamline by having the rather complex rules automatically enforced. In practice, I’m not sure of the best design.

My instinctive design is to create a BaseCard class with the properties and logic shared between all cards, then have a few children of that class that are CardArchetypes (MonsterCard, MagicCard, ItemCard), then have each individual Card inheriting from its appropriate archetype. Each individual card will likely contain its own Effect(s).

The first problem is, there are thousands of cards. If I make a class for each card, is there any performance overhead to worry about with that number of classes (especially if they contain virtual functions)? I think I remember that in C++ you get a vtable call for every function, which is usually fine unless you really need it inline’d or have a ton of virtual function calls from many classes that can cause cache misses on the vtable lookup; the good news is I’d only ever have about 100 (two decks’ worth) objects instantiated from these classes so I wouldn’t expect any problems beyond the small size increase from the scripts, which is nothing in comparison to the graphics resources. I just want to see if there are any concerns or good ideas before I dive into it.

If it makes a difference, all the basic card data [id, name, attack, defense, etc.] is stored in an sqlite database that is accessible in the game (I;m using it for the Deck Builder to be able to sort through the thousands of cards quickly and easily). If I weren’t going to automate card functions, I could get away with just that, but each card needs its own logic to do that–for example a card determining if the conditions for placing it are met.

Thanks for reading and for any advice!

Have you considered using a component based design?
Having the card effects be components.

The first example that came to mind:
OnAttack Component that just compares attack stat from the card to defense stat from the target card
OnFireAttack Component that compares attack stat to defense stat from the target card but also adds a 3 round damage application (example)

OnDefenseBoost Component that increases the defenese stat of a target card by X amount for X Turns (then the designer can specify X for the individual cards as variables on the OnDefenseBoost Component) Instead of having to subclass the card class for each card.

I personally still have some mastering to do for component based design, at the moment I would be using a hybrid approach like:
Having a Card Class that would have all the basic attributes for cards + be the container for the individual components (Attack/Defense/Boosts/Etc)

Hopefully somebody with some more experience in component/data driven design will pitch in.

It might be an easier approach to create a single class for each Card type, then get specific values and effects from XML or text files.

For example:

CardBase - Has a position, name, state (Tapped, Untapped, Hidden/UpsideDown, etc), an image, a description, and possibly a rarity.

MonsterCard - Has Attack, Defense, possibly an Effect (beyond the scope of this example), possibly an Element or Type, etc.

ItemCard - Has Effect, type rules (such as which kinds of Monsters can equip it), etc.

MagicCard - Effect, Duration, etc.

Then you read in only the cards the two players have. Each player has a “deck” that is simply the indexes of each card they are using. So the Player might have cards 1 through 100. Their deck would look like [1, 2, 3, 4, …, 98, 99, 100]. You loop through that, and load each card by reading the data in from the text files or XML. The only persistent data is the array of indexes, so you don’t really have to worry about the overhead of storing individual card objects.

This would allow you to easily create Booster DLC, and also gives you the opportunity to include in-game card creation for advanced players.

Good luck. :smile:

Fortunately, I learned after some net-surfing that there’s an excellent open-source engine for the game already, so I’m dropping the project. I was pleased to see they also used the sqlite design for the card database!

Their approach was a core engine with a single card class, single effect class, and group class (groups beings decks, and other small groupings of cards) with the individual cards each having their own script that runs through a custom LUA interpreter. Very robust, very fast–but it would have taken me ages to figure out and implement myself! So basically, I lucked out and can dive right into some of the more interesting features.

Regardless, thanks for your help!

Good luck with the project.
Would you mind posting a link to the engine that you decided to use for the project?