The world of Let Thrones Beware is yours to conquer. Occupy countries, seize planets, dominate solar systems, and expand your sphere of influence across galaxies. Unlock a detailed technology tree containing hundreds of unique items that provide meaningful contributions to the progress of your society. Deploy your forces to conquer enemy territory and occupy their cities. Expand your reach to the stars and seize what is rightfully yours. Combine technologies to design and produce weapons of war based on your priorities.
Welcome to part two of our code review - in which we start to tackle the substantive problems of implementing hex-based combat. We'll do this in two steps: firstly, we'll take stock of what currently exists by examining how the code-base currently generates terrain and going over how it's stored in the database. Secondly, we'll begin implementation - by developing a new database architecture.
Part One
When we find ourselves in a campaign, one of the first things we need to do is initialize a battlefield for the troops to fight over. In the current implementation, battlefields are transitory creatures; they're created for a campaign and discarded when combat finishes.
// Establish Battlefield
$battlefield = $this->New_Battlefield( $gamedata[ 'field_length' ], $gamedata[ 'field_width' ] );
That's a pretty simple implementation, isn't it? Hooray for easy to remember. Let's delve deeper and see what this does for us!
// This method creates a battlefield array $length by $width elements
//
// Composition (array)
// - 'terrain' => terrain type
// - 'side' => side
// - 'army' => army
// - 'division' => division
private function New_Battlefield( $length, $width )
{
$rv = FALSE;
$battlefield = array();
for( $i = 1; $i < $length; $i ++ )
{
for( $j = 1; $j < $width; $j ++ )
{
$battlefield[ $i ][ $j ] = array( 'terrain' => 0, 'side' => NULL, 'army' => NULL, 'division' => NULL );
}
}
$rv = $battlefield;
return $rv;
}
Okay! So ... that's it. It spins up a multi-dimensional array containing essentially a bunch of nulls, and that's it. How groundbreaking and innovative.Well, if there's nothing more here, let's check out the database and see what interesting things we can find.
CREATE TABLE IF NOT EXISTS `campaign_logging` (
...snip...
`position_length` tinyint(3) unsigned DEFAULT NULL,
`position_width` tinyint(3) unsigned DEFAULT NULL,
...snip...
) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=99991 ;
Alas, my secret shame. The battlefield is a simple x,y coordinate for tracking division positions during combat. There's no greater purpose, and there's no differentiation between terrain types. City icons are pasted into the display algorithm and have little consequence to the battle. It's all a big to-do about nothing!
Part Two
Fortunately, since the whole point of this exercise is to improve upon the existing feature-set, we're in a good place to make up for past mistakes.
Let's start by talking goals. Obviously, we want to make things better through redesign, so what are things that we can do?
This is a pretty awesome list of advantages over the current system, so let's forge ahead! I'm basing a lot of the mechanics on a series of excellent posts made by Amit over at Red Blob Games (Here's a crazy coincidence - Amit wrote the BBS game Solar Realms Elite, that game's successor, Barren Realms Elite was the game that originally inspired me to start game design)This will be how do I define the data structure we will use:
CREATE TABLE `planet_node_hex` (
`id` INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY ,
`node_id` INT UNSIGNED NOT NULL ,
`x` TINYINT NOT NULL ,
`y` TINYINT NOT NULL ,
`terrain_id` TINYINT UNSIGNED NOT NULL ,
`structure_id` SMALLINT UNSIGNED NOT NULL
) ENGINE = INNODB;
This handy table will link hexes to an existing planetary node. Depending on map size I decide to go with, we'll end up with quite a few of these suckers. Fortunately, we're in 2015, and data size constraints aren't a huge deal for a hobby project.
CREATE TABLE `terrain` (
`terrain_id` SMALLINT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY ,
`game_style_id` TINYINT UNSIGNED NOT NULL ,
`terrain_name` VARCHAR( 32 ) NOT NULL
) ENGINE = INNODB;
Adding a terrain table will let me enhance gameplay by allowing for a nigh-unlimited number of terrain types. Fields, mountains, hills, swamps, moonrock.... the choices are endless! The game style field is a special one that crops up all over this game. Essentially, pretty much all content in the game is tied to a style, and by changing that style, one could switch from playing a journey from the early 20th century to deepspace exploration to one based around epic fantasy, or virtually any other theme.
CREATE TABLE `terrain_benefit` (
`id` SMALLINT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY ,
`terrain_id` SMALLINT UNSIGNED NOT NULL ,
`name` VARCHAR( 32 ) NOT NULL ,
`description` VARCHAR( 256 ) NOT NULL ,
`category` VARCHAR( 32 ) NOT NULL ,
`benefit` DECIMAL( 5, 2 ) NOT NULL ,
`prefix` VARCHAR( 3 ) NOT NULL ,
`suffix` VARCHAR( 3 ) NOT NULL
) ENGINE = INNODB;
What's a moonrock hex without a bunch of associated bonuses and penalties, right? This funky table means that the benefits of terrain aren't hard-coded, making it much easier to balance down the road.
Next Time
With our data structures defined, the next installment will focus on taking advantage of the new components with game objects.
Website - Dev Blog - Facebook - @afuriousengine - /r/LetThronesBeware
On this week's episode, we begin to dig into the code behind Let Thrones Beware in an effort to make it better.
Public Alpha 10's just been launched, and it features an entirely new graphics engine built on Phaser 2.3.0!