Card Craze Combat
Genre: Party, RPG, 3D, Multiplayer game
​
Duration: 6 Months
​​
Team Size: 1
​​
Games Engine: Unity
​
Programming Language: C#

Card Craze Combat is an ACM individual technical demo that was developed in order to create a solo game using algorithms, theories and programming patterns that were learned from previous projects.
The game is about choosing characters to obtain rare cards to help you move, apply status, defend from attacks and deal damage to your opponent in this turn based strategy game.
The goal is to deplete your opponent’s health to 0 by applying status effects on them or by attacking them in combat.

Design Process
Card Types
Cards in this game have four unique types:
-
Offence - Deals damage to the opponent
-
Defence - Reduce/Prevent damage from opponent's offence cards
-
Movement - Moves around the board
-
Status - Apply status effects to anyone
​
Each card has their own deck to be stored in, meaning that the player will have four decks for one of each card type, which allows the player to draw cards of a suitable deck in a certain situation such as starting their turn will allow the player to draw one status card and three movement cards for the to choose from.
Additional Card Effects
Most cards are provided with an additional card effect which can occur in unique outcomes. This means that whilst the card will have their general effects such as dealing damage, blocking damage, moving and apply certain effects, most cards can have additional effects that can affect either players, this can lead to adding more value to the player to using these cards or could provide a risk factor if there's a negative impact to the player.
Card Rarity
Card Rarity in the game provides a power balance to identify to the player how powerful of a card they have obtained. There are 4 rarities in the game:
-
Common - Default cards the players obtain when starting the game
-
Uncommon - Most common card to obtain from a card space or the market, however the least impactful card to obtain
-
Rare - The middle rarity out of the three possible rarity types to obtain, more powerful than an uncommon, but more unlikely to obtain
-
Legendary - Rarest and most powerful cards, these cards are consider as game changers, however it is very unlikely to obtain them on the card space or in the market.
Abilities
Each character has two abilities that have unique behaviours towards each other.
Passive abilities are unlimited abilities that can be triggered as many times as possible, however these abilities are conditional meaning that a certain event must happen in order to trigger the ability.
​
One use abilities are limited abilities that can be triggered once per game, however these abilities can be often be considered as game changers and can be used at any time during the player's starting state.
Statistics
The game will include statistics such as health, mana, cash and deck capacity.
​
Health is used towards the objective of defeating the opponent, once the health is depleted to 0 then the game is over and the player who is depleted has lost.
​
Mana is used towards limiting the card usage, this is because each card has their own mana cost which players can only use certain cards as long as they have more or equal mana to the card's mana cost.
​
Cash is used towards buying resources such as cards and items from the market or spinning in the fruit machine to gain more cash and a bonus item.
The game also provides multipliers to multiply the type of value such as thrust (offence multiplier), guard (defence multiplier) and roll (movement multiplier).
Unique Characters
The characters in this game are provided with unique statistics, abilities and card that they can obtain. The objective was to ensure that the player can have the most unique experience on playing a certain character in the game, which can lead the player to test out other characters to figure out their preferred one to play.
Buffs & Effects
Status effects are divided similarly to items with one good and one bad: buffs are the good effects that provide an advantage to the player whether this be increasing multiplier, blocking damage or higher chance of obtaining rarer cards. Effects are the bad effects that provide a debuff to the player whether this be dealing damage equal to the amount of cards in a deck type, preventing the player from having their turn or the game randomly choosing certain actions for the player.
Spaces
The spaces in the game provide unique behaviour to the player when landing onto any of the spaces, the player can provide a good or bad event on the space they landed. These are the spaces in the game:
-
Blue - Gain cash
-
Red - Lose cash
-
Event - Anything goes, could be good, could be bad, who knows
-
Lucky - Random good event occurs to the player
-
Item - Player can choose to either obtain a relic or give a player (including themselves) a omen
-
Card - Player can obtain a certain rarity card and choose the card type they want to obtain
-
Fruit Machine - The player can gamble cash to gain more cash and a bonus item
-
The Market - The player can purchase 4 random resources
-
Minigame - The player will be involved in a minigame to play
Fruit Machine
The fruit machine is a space that when landed on will allow the player to gamble 20 cash in order to gain cash, there is unique outcomes with big rewards being the rarest events to occur. Depending on the outcome that occurred can provide unique chances for the player to obtain a bonus relic item.
​
The fruit machine is to provide a risk and reward system in which the player will have to decide if they want to use their cash in order to gain more cash and a chance of obtaining a random relic.
Relics & Omens (Items)
Items in the game are divided into two types of items: relics are known for being the good items that can buff the player in a certain way, whereas omens are negative items that can debuff the player. When landing on a item space, the player can choose to either give themselves a relic or give anyone a omen, which provided meaningful actions to the player.
The Market
The market will have four resources for the player to obtain, these resources can go from uncommon, rare and legendary cards to possibly purchasing relics. uncommon cards are the most common resource whilst relics are the rarest resources to be sold in the market.
Minigames
Minigames are included in the game that can occur if the player lands on a minigame space. When landed on, the player can have a chance on winning cash, there is a chance that the player might be playing by themselves or against their opponent. There are 3 minigames that can occur for the player(s) to encounter and play on:
-
XIII - Players have to collect fruit cards to gain cash whilst avoiding the coconut card
-
Tic-Tac-Stash - The player has to make a row vertically, horizontally or diagonally on a 3 x 3 grid
-
Double or Nothing - The player starts off winning 10 cash and can double the prize constantly with higher risks of losing all the cash per successful double.
Combat
When the player reaches their opponent, combat will be taken place. This will provide the current player being the attacker who will be using offence cards dealing damage to the defender whilst the other player being the defender who will be using defence cards to reduce or prevent damage from the attacker.
​
The damage outcome is determined by the value and the multiplier (rounding down) to check if the attack value is higher than the defend value and dealing damage to the defender equal to the difference.
For instance: (3 * 150%) - (2 * 50%) = 3 Damage














Development Process
Character Statistics
Character statistics are storing the character's starting statistics, cards and the abilities they have for the game to use. This is done by using scriptable object that will store variables which the player controller will use to change the logic in the player object such as adding the character's abilities as a child object, identifying which cards the player can only obtained from the character or changing the player model to suitable data values.
​
This allows the players to be able to identify the unique character behaviour in the game and capable of playing unique cards, which will lead players to be capable of experience unique playstyles for each charatcer.
Even Probability
Some outcomes of events are even probability, which is when each outcome has a similar chance to occur. An example of this is using the walk card and move between 1 to 6 spaces, the player will have an even 1/6 chance for the value being either 1, 2, 3, 4, 5 or 6.
​
This makes events become have a mixture of high and low chance from occurring with small amount of outcomes having high chances and high amount of outcomes having low chances.
Odd Probability
Other outcomes of events are odd probability which is when each outcome has a unique chance to occur compare to other outcomes. An example of this is when spinning on the fruit machine where the player could have a 30% chance on winning nothing or 1% chance to win the jackpot or the market which has a 40% for a uncommon card and a 10% for a relic to appear in the market.
these outcomes can be engaging to the player to go for rarer outcomes whether this be rarity on cards or taking risk on certain events.​
Independent Probability
Some probability events in the game are independent which is when the outcome always stays consistent not matter of the events occurred throughout the game. An example of this is the lucky space that no matter the events occurred in the game each possible outcome will always be consistent towards having a 10% chance for a player to have 1 of the 10 outcomes occur to them,​
​
This makes players identify the outcomes that will stay the same throughout the whole game no matter the actions they provide.
Dependent Probability
Other probability events were planned to be independent which is when the outcome changes depending on specific events. An example is whenever the player obtain cards throughout the game, the chances of the card being drawn decreases as more cards appear is less likely to draw the card the player wants. For instance if a character's movement deck capacity is 10, at the start the player will have 100% chance on the card they want to use the most. However if the player adds 2 more cards the chances of obtaining their preferred card will become a 60% chance on the card they want and eventually a full deck will become a 30% chance on the card wanting to draw to occur due to the player drawing 3 movement cards.​
​
This makes meaningful actions to occur towards obtaining specific resources not only because of the deck capacity but as well as the player keeping their chances high on drawing the correct card for their turn.
Space Behaviour
The space behaviour is using a singleton pattern known as the space manager, this is a global component that allows other scripts to reference the singular component in the game. The space manager will have a method to call the current player object and the space type which is represented as a enum to identify which space is the current player is on and what the outcome should be for the player.
​
This methods allows me to create new spaces in the future by expanding the method to add extra spaces without changing any existing code.
Card Behaviour
Card behaviour is when the card stores the suitable values and potential additional effects to create a new card and be added into the deck pile in order for the player to use. The deck pool will enable a card and add the card type component, which will then use a method with the scriptable object of the selected card's statistics and additional effects to create the card.
​
If the selected card's scriptable object has a additional effect then the additional effect will be the child object of that created card, which leads the card to be functional for the player to use in the game.
Item Behaviour
Item behaviour works the same as the card behaviour towards enabling an existing object from the deck pool and how it would create a item and create an child object for the unique effects. However the difference is how these items behave as they can have either 1 or all 2 of the methods:
-
Pickup - The item activate an effect when the player obtains the item for the first time
-
[Item] Effect - The item is added onto a suitable subject as an observer method that when called will activate its effect
This makes the implementation unique towards the card behaviour and can provide constant behaviour if the effect is called onto one of the existing subjects in the game.
Rarity Types
The rarity is based on a enumeration class which can categorise a type of rarity into a card, using enums were a very useful towards categorising the card's rarity because I can use the enum to identify the type of rarity that needs to be given to the player when receiving any type of card (offence, defence, etc.). Leading the player obtaining suitable rarity cards that the game gives them.
Storing Buffs & Effects
Both effects and buffs are also based on a enum class that provides 2 enums one for only the effects and the other for only the buffs. This can separate the two status effects due to the method of applying status effects with effects requiring a parameter of the type itself and the cooldown with buffs doing the same procedure except requiring a float value for multipliers for resistant and impactful which increases the guard and thrust multipliers.
​
With each status effect is provided as a observer method for the observer pattern that is added onto a suitable subject, which will call the status effect's suitable actions once the subject has been invoked, leading multiple effects and buffs to be called at the same time. However, once the cooldown is set to 0 then the observer method will be removed from the subject to ensure that the status effect doesn't play again when the player isn't affected anymore.
Additional Card Effects
The additional card effects are a child object to the card object itself, using the observer pattern, the additional effect is implemented with a observer method that when enabled will be added onto the card's additional effect event subject that when the method to invoke the event is been called will then call the additional effect's observer method to apply to the suitable player(s).
​
The offence and defence cards have a interesting implementation that when the event has been invoked the observer method will be added on to one of the combat system's events which will then play the additional effect either before, during or after combat has been completed.
​
This method is suitable because the child object's method can be called by the event of the base object's event, leading the additional effects to be played
Non-Linear Pathways
The Non-linear pathways allows the player during a certain state to choose a certain path to follow, this is done by providing a struct of all the possible paths along with a restriction to prevent the player from making U-turns in the game. A script known as path selection is used to provide all of the paths when the player passes on a specific multiple pathway space and providing restrictions to prevent the player from U-turning on the board.
​
A enum is used to provide the restriction of the path being available for the player to choose from if that path is the same path as the player is currently taking. This enum is also the parameter for the method that will store all the available paths the player can take. Using the enum as the parameter to identify the current path the player is taking.
A foreach loop is used to check if each path structs' restriction is the identical type as the parameter's type, if the restriction isn't the same then this path will be added into 2 lists:
-
Game object - the path object that has the path order for the player to follow when selecting that path
-
Integer - the direction integer that identifies which direction that path takes for the player.
​
Using the path selection, the choosing state can use the lists to identify if either there is only one path to choose from and chooses that path or more than one path which will provide a for loop to add the specific path and the direction the player can take.
Player Architecture - Model-View-Presenter
Player architecture is the player behaviour of the game that is structured to divide the roles and responsibilities. In the architecture I use model-view-presenter which divides the data, logic and interface from one script to three scripts:
-
Player Model - The data of the game that store the statistics from the character data and then changed by the player data to load up the existing game.
-
Player Controller (Presenter) - The logic of the game which listens for events to occur in order to change the model and display the data onto the player view.
-
Player View - The interface of the game which will change the values on display when the logic changes the data.
Encapsulation is used for the controller to get all the variables from the model in order to change it whilst keeping the variables private to prevent any possible edits onto the model variables.
​
Using the MVP allows the player behaviour to play throughout the game with the suitable data displaying for the player to identify and the logic that occurred to the player, this leads the player to identify their statistics on the screen and identify what they're capable of the cards they can use, how many cards they have in their decks and when they're close on being defeated.
The Market
The market is a space that provides a struct that includes a enum type to identify the resource either being a uncommon, rare, legendary card or a relic, the deck type enum to identify card type of the resource, an integer of the price and a boolean to check if they bought.
This will then provide a for loop that for the four random resources uses random range to identify the resources available with a do while loop to prevent unobtainable resources from displaying in the market.
​
When the player confirms to buy a resource the confirm method inherited by the IConfirm interface is used to check if the player has already bought that struct in the list, do they have room for that resource in their deck and if they can afford the resource's price. If they can then another conditional statement will check the resource they're making and either creates a relic or a card with the rarity type as the method's parameter.
​
When the player wants to exit the market they press backspace which will play the cancel method which inherits the ICancel interface to leave the shop.
​
Implementing the market was quite the hassle, however with the techniques used was suitable to allow players to be able to purchase the resources they want and leave once they're done with the market, this also leads the cash to become a viable resource for players to use in the game.
Fruit Machine
The fruit machine is a space that allows the player to spend 20 cash to spin and possibly win more cash and a bonus relic. This implementation includes using a struct that contains an enum type of every outcome in the game, the cash prize that the player wins from that outcome, the chance out of 100 for the player to win a bonus relic, a sprite symbol to visually identify the outcome to the player and a minimum and maximum outcome to provide a range for the outcome to occur when confirming to spin.
​
This will then allow provide both the inheritance of the ICancel and IConfirm interfaces to allow the player to either spend 20 cash to spin or save their cash up for the market which if they decide to spend to spin will then have the confirm method to set a random number between 1 to 101 with random range (because an integer value excludes the max integer), which provides a for loop to check each of the winnings structs to check if the number is between the struct's minimum and maximum outcome.
Coroutines are used to provide suspense of the outcome of the spin which if they won then will have a coroutine with a integer parameter to then identify if they won the bonus item which provides suspense on if the player has won a bonus item or not.
​
Implementing the fruit machine was quite straightforward due to providing random range to most of the methods and then using for loops to check which outcome occurred in the fruit machine, which was suitable for the player since they can decide on taking a risk of spending 20 cash to win more cash and a possible relic, leading the player to have a risk and reward system on spinning the fruit machine.























Development Blogs
Conclusion
Overall this project gave me a test of my capabilities as a programmer with using programming patterns, implementing suitable algorithms which I didn’t realise at certain points of development and expanding on my creativity towards unique gameplay and mechanics.
This provided me a better understanding on using unique programming that I haven’t used before such as the observer, singleton and state pattern and technically using algorithms that benefit my game.
This project allows me to research more patterns and become practical with those patterns along with learning and practicing on algorithms to understand both logically and technically rather than understanding the technical side.
If there aren't any prototypes that I’m considering adding or revamping as technical demos then I could consider making this project a fully developed game by optimising existing coding, creating new characters and adding new content.