// Game Programmer
Games For Love
Battle for the Kingdom is a top down strategy game where you fight a enemy army for control of a land. The game features a 15 level campaign and a endless, randomly generated mode for limitless content. Control your units and send them out to take control of towns along the path to crushing your enemy.
I was brought onboard "Battle for the Kingdom" as a lead programmer when a fellow working at Games for Love approached to volunteer for them. Games for Love is a kindness-oriented non-profit community who's purpose is to ease the suffering of children in life-threatening conditions and contribute towards building a sustainable financial future for them.
I was among the very first volunteers to work for this particular project, so the only thing developed up to that point was a game design document and a few art assets. Over the course of the next few weeks, I built up the entire codebase from scratch while the rest of the team focused on audio integration and art.
Click the buttons below to learn more about how I implemented the core features of "Battle for the Kingdom"!
From the outset, I wanted a strong emphasis on object oriented design. Each card, player, and town are neatly modularized and well-documented so that other game designers and artists (who are less experienced in C# programming) could fully edit parameters to their heart's desire.
The player object is rather simple. Each player has a hand with randomly drawn cards. Furthermore, players own towns across the island, and this is stored in an Town object list variable. The image below captures what parameters are available:
Players can obviously place a card down inside a town, but how was this accomplished? I wrote a script that passes a card object from the hand to the node (a town). I use a lerp function to smoothly animate the transition. The lerp function will take the card object in its current position and continually transform it to match the target destination. I also utilized a curve for the animation to give a sense of inertia.
Let's touch upon my implementation for triggering. When a player or AI sends a group of cards to occupy a town, the selected cards are packaged in what's known as a "card carrier". The card carrier will travel along a path at a set speed determined by a shortest path function. If a card carrier runs into an opponent's carrier or a town, it will collide with them. It can either attack or occupy a town (if it's unoccupied or player-owned).
Towns were an interesting obstacle in development. What I ended up going for is a region-based system. That means that a region controls a certain amount of towns. If a player controls all the towns in that region, they'll obtain 1 extra card per draw. Below is an image of how regions are laid out in the editor:
Much like a player or card object, towns are fully editable within the inspector too. The key parameter to note is the connections. Connecting a town will create a adjacent node graph:
One last thing to touch upon; adding cards to a town works in a very similar way of adding cards to a hand. A card is placed as a "stationed" card if no garrison exists.
Card combat! Exciting! This is a rather extensive topic, so let's dive in. Once a card carrier collides with an opponent carrier or town, combat initiates.
Now that combat has begun, it's time to sort out who's who in the battle. The combat logic itself is mathematically in nature. In essence, the first card from each combatant is selected to battle it out. The code sorts out the difference between the card's values and determines the winner. The loser card is destroyed and the winner's value is subtracted by the difference. Once one side's cards are depleted, the winning side either continues on its way if the enemy was a card carrier, or it occupies the town it was attacking. It's important to note that if another carrier collides with the two combatants in progress, then they are dynamically added into the fight as well. In other words, you could have multiple sets of cards all battling it out all at once.
The AI design I followed was using a decision tree. Before we get into the vernacular, let's discuss briefly of the AI player object. Below you'll find an image of the parameters we can edit:
Draw Card Wait
How long until the AI draws a card.
Place Card Wait
How long until the AI places a card inside a town.
Send Card Wait
How long until the AI sends 1 or more cards to another town.
How fast the card carrier's move.
Card Value Probability
The chance that the AI will draw a low or high-value card.
Max Cards In Town
How many cards the AI will place in a town.
Cards Required To Attack
How many cards are required for the AI to decide to attack another town.
As mentioned before, I used a decision tree for AI decision making. One strategy that the AI can use is as follows. The AI will first send a card to an unoccupied town. Then it will check if it has more than 4 cards in any given owned town. If it does, then it will send those cards to attack a town.
The handling of cards relies on dragging and dropping using the mouse. Once a player begins dragging a card object, it will update the position of that object according to the mouse. If a player lets go of the mouse while dragging, a line trace is fired from the position of the mouse to the map. If it hits a town, then it checks if it's owned by the player. If so, then it adds the card using a lerp function (for animation).
Several effects are in place, such as enlarging the cards once hovered over, highlighting green once selected, and rotating their object if dragging them. Speaking of, once cards have been placed inside towns, more than one card can be selected. This means that if 4 cards are selected, then the drag will include all 4 cards. See below the implementation: