Hexarategy

Game development
User avatar
dendiz
Site Admin
Posts: 115
Joined: Wed Oct 10, 2018 3:48 am

Hexarategy

Post by dendiz » Tue Dec 04, 2018 3:39 am

Shield Visual Effects
=====================

Even though I had put up some text to indicate the shield status of a ship, it doesn’t go without some visual effect to indicate a shield presence. This is mainly because I’m too lazy to read that info text every time I want to give some command to the ship. A more catchy indication is required.
57f1b991b0add.png
57f1b991b0add.png (169.16 KiB) Viewed 33 times
Also during the economical phase you can't move ship or adjust power diversion. I found myself clicking on ships multiple times during the economy phase without realizing that it was that phase only to thing "why aren't my clicks registering?" followed by a "duh!"� second. So I used a similar effect to indicate that you can't select ships at the moment.
57f1b9bbcda87.png

User avatar
dendiz
Site Admin
Posts: 115
Joined: Wed Oct 10, 2018 3:48 am

Re: Hexarategy

Post by dendiz » Tue Dec 04, 2018 3:39 am

Discovering enemy units and planets
===================================

At first I though that the game could be a game of perfect information where you know where all the planets are and where your enemies are based. But then first I made the planets invisible so you have to explore around to find planets to colonize. Then I though well I’ll also make the enemies invisible until you scan them. The procedure is quite simple: Every ship and planet has a set property called exploredBy. When creating the units you add yourself to the set. Then during the Update() call of every ship in transit you scan the neighboring cells with a radius of N and if there is anything on that cell you add yourself to their explored list and make them visible. Setting a sight line of 1 is okay for planets but could be dangerous for enemy ships as you would end up right in the middle if you go the max distance. So setting this to 2 or 3 is going to better I guess. But this is also a tactical choice: Do you spend all your power on the engines and have nothing attack/defense when you end up in the attacking range of an enemy ship, or do you travel less but have your guard up?

Here is the new stuff in action on a very small map for testing purposes


User avatar
dendiz
Site Admin
Posts: 115
Joined: Wed Oct 10, 2018 3:48 am

Re: Hexarategy

Post by dendiz » Tue Dec 04, 2018 3:41 am

Turn processing and economy
===========================

2 easy parts don’t require much on the 3D side, but are a pain on the GUI part. The unity GUI is quite inferior compared to the browser that I can say. As far as I can guess it was even worse in 4.x and this is the revamped GUI system in unity 5 which still not that good. So the turn system. Turns are conducted in phases.

# Movement/exploration/combat turn
# Economical phase

Every 4 turns there is an economy return the others are for moving around, colonizing etc. During the movement phase the player still collects income from the colonies and pays ship maintenance costs but cannot buy ships or do research. In the economy phase the player cannot do the things done in the movement phase, but does the things not allowed in the movement phase. Every turn the ships also generate power and burn fuel.

At the beginning of the economy turn the player collects the income and pays the maintenance costs and whatever is left over he can use to purchase ships or technology. There is a nice report that displays what happened economy wise at the beginning of the turn like this
57f1b9d9e8099.png
One thing to mention is that if there is an enemy ship in the neighbor cells of a colony then it will not produce any income. All the colonist are fearing for their lives and will not work.

I’ve also added a nice bar at the top that displays the current star date and the credit points the player has and a button to confirm that the turn has ended.
57f1b9f14a1e0.png

User avatar
dendiz
Site Admin
Posts: 115
Joined: Wed Oct 10, 2018 3:48 am

Re: Hexarategy

Post by dendiz » Tue Dec 04, 2018 3:41 am

Planet colonization
===================

This one wasn’t tricky as I expected it to be. To colonize a planet all you have to do is send a colony ship to that planet. No resistance – no ground battle the colony is yours. The colony ship disappears from the grid as it is turned into a colony base on the surface and a colonization message is displayed. Now you can get all that extra production, yeah.


User avatar
dendiz
Site Admin
Posts: 115
Joined: Wed Oct 10, 2018 3:48 am

Re: Hexarategy

Post by dendiz » Tue Dec 04, 2018 3:43 am

Planets and some info panels
============================

over the weekend I’ve added some planets to the grid. That was straight forward, find some nice planet surface textures and apply them on to a sphere. The info panels for the planets were GUI text at first with a canvas etc. But if you rotate these along the X-axis so that they lay flat on the grid the font rendering gets screwed up big time so I changed that to 3D text mesh. The results are pleasing.
57f1ba0f67fae.png
57f1ba0f67fae.png (45.49 KiB) Viewed 32 times
the planet names are 3 arrays of 5 meaningless names and a unique selection is made at random from these arrays.

While at the subject of panes I also changed the ship info pane to a text mesh. The previous videos had examples of UI text and how ugly it looks when rotated as the ship info text. Now it’s much smoother:
57f1ba28e4ea8.png
57f1ba28e4ea8.png (57.38 KiB) Viewed 32 times
One of the tricky things here was to keep the text facing towards the user as the ship rotates. The text is a child component of the ship, and is positioned 0,0,-10 relative to the ship. When the ship rotates so does the axis for the text and it would end up in different positions for each rotation of the ship. To keep it below the ship for all rotation the positioning has to be with respect to the world axis. To accomplish this I had to get the TransformPoint for the ship location with respect to the ships origin and add the difference vector. Now when you set the position of the text you get this effect. Something along the lines of

Code: Select all

Vector3 p = ship.asset.transform.TransformPoint (Vector3.zero);
text.transform.position = p + new Vector3 (0, 0, -10f);
Here is some video action


User avatar
dendiz
Site Admin
Posts: 115
Joined: Wed Oct 10, 2018 3:48 am

Re: Hexarategy

Post by dendiz » Tue Dec 04, 2018 3:43 am

Ship mechanics
==============

over the last week I’ve been thinking about how the ship mechanics should function. I wanted to come up with something that doesn’t require micro-managing a fleet of ships but is yet flexible enough for a nice tactical combat. The method I’m going to try out has the following properties
  • Ships have a limited amount of fuel. If that fuel runs out the ship is useless. It cannot move, attack or defend itself.
  • Each turn N amount of fuel is converted into N*10 amounts of power.
  • Power can be used for shields, lasers or movement.
  • The player can decide how much of this power is used by which system, no power is wasted because after setting the shield and laser amounts the rest is used for the engines.
This looks to a like sweet spot is managing the ships vs stream lining battles but I can’t be sure until I have actually played some battles.


User avatar
dendiz
Site Admin
Posts: 115
Joined: Wed Oct 10, 2018 3:48 am

Re: Hexarategy

Post by dendiz » Tue Dec 04, 2018 3:45 am

Hex grid border highlighting
============================

So, I’ve been polishing the grid looks a little bit and one of the things I’ve seen posted around the forums and Q/A sites is how to draw a line around the hexagon cell borders to indicate possible movement ranges. Previously I’ve been doing this by actually highlighting all the possible cells, but it’s looks a lot better if you just highlight the borders. Here’s the results I’ve got after this implementation
57f1ba58dab73.png
57f1ba58dab73.png (155 KiB) Viewed 32 times
Calculating the border cells is a different task which I’ve explained over here. After we have the cells that we can navigate to we need to filter out the border cells. If you look carefully the edges that need highlighting from all the cells in range are the ones that do not have a navigable neighbor. In the image the cell (4,-6,2) and (5,-6,1) are both in range, but they share a border with a navigable cell, so that edge should not be highlighted. The algorithm should be like this:

1. Get all the cells in range and the starting cell, and add the starting cell to the cells in range.
2. for all the cells loop
1.. for all the neighboring cells of the current cell loop
1... if the cells current neighbor = null or cells in range doesn’t have the neighbor highlight that edge

The actual highlighting is done by placing a quad with a bar texture with the correct rotation and coordinates easily calculated from the current cell we are processing.


User avatar
dendiz
Site Admin
Posts: 115
Joined: Wed Oct 10, 2018 3:48 am

Re: Hexarategy

Post by dendiz » Tue Dec 04, 2018 3:46 am

Avoiding obstacles in path during movement
==========================================

Up until now there were any obstacles (excluding ship) so I really didn’t care for a proper path finding algorithm to select the cells that the ship would follow to reach it’s target. A simple rasterization of the cells were the way to calculate the path, but since I’ve added some asteroids it I also thought I’d spice up the path finding too.
57f1ba74ae111.jpg
In this picture the rasterization algorithm would pick the yellow line and the cells with the red dots on them, which are actually obscured by asteroids. The correct path is the path with the purple arrows. How to you choose these? Well luckily there are a couple of ways. The brute force version would be to do a breadth first search to find the target cell which would lead to wasted movements for sure. The next best approach is the select the next cell in the BFS not at random or in order but based on a heuristic, a good guess to which cell would lead quicker to the target cell. The easiest heuristic that comes to mind is the hex distance calculated as Math.max( x2-x1, y2-y1, z2-z1). You also add the total cost of movement to this cell, something that you know for sure. Why do we add the cost of movement? Because we may need a rotation to get to that neighbor cell, which is also a movement cost. So from the starting cell, you look at all the neighbors and calculate the distance to the target cell + the cost of movement to that cell and choose the closest one. You add the current cell to the visited list. Why? because in the next step the current cell will show up as a neighbor, and we don’t want to check that cell again. Then you advanced to that cell and do the same until you have reached your target. Is it possible that the target cell is never found or a ship will be there to block us? No because the target cell validity check is done before hand (the green cells). This is a simplified version of the A-start algorithm. Here it is in action


User avatar
dendiz
Site Admin
Posts: 115
Joined: Wed Oct 10, 2018 3:48 am

Re: Hexarategy

Post by dendiz » Tue Dec 04, 2018 3:48 am

Navigation order processing
===========================

Having ships is useless if you can’t boss them around the grid. So how would you do that, be also allowing multiple ships to move at any given time without running into each other? The first iteration of the path finder was the rasterized path finder I explained here. This method will provide a list of cells that the ship must travel through (I since have added a new algorithm that takes into account any obstacles in the way. It just returns a different list of cells which isn’t of any significance for the navigation command system). When the user clicks on a ship, we need to store that clicked cell and it’s ship into a temporary variable. The first click will also highlight the possible cells the ship can navigate to. The post about cells in range explains how there are calculated. The second time the user clicks on a cells, it can mean 3 things

1. the user wants to navigate to a cell
2. the user wants to cancel the selection
3. the user wants to select another ship from his fleet
4. the user wants to attack an enemy ship

We will address the first 3 items. Items 2 and 3 are simple so let’s get them out of the way first. If the user wants to cancel the selection, he just clicks on a cell not highlighted by the cells in range call. We just need to check if the clicked cell is in the list returned from this call. If not reset the variable that holds the clicked ship to return to the initial state. If the user wants to select another ship to move, if has clicked on a cell with one of his ships. Since he can’t attack that ship, just check if the clicked cell has a ship on it and if that ship belongs to the player. If true, set the selected cell to that one.

Here is an image of a state machine that shows to transitions and states
57f1ba8f2cd8d.jpg
The red transition is cancelling the selection, and the green transition is selecting another ship to navigate.

Now let’s explore the case where the user wants to navigate to a cell. We need to support multiple ships wandering around at the same time, so the user doesn’t have to wait for the first ship to arrive before issuing a second order. This means we need a queue of navigation orders that will be processed at each update. We create an object that will store the source cell, target cell, the path the ship will take and the ship model and the ship object that carries meta data associated with the ship. At each update call we will process each item in the command queue and make the required movement to the next cell in the path. After each item in the queue is processed it gets queued again. This way all the ships movements will be updated once for every update call. If there is another ship in the next cell for the ship we are processing just skip that command item for this frame. This will make the current ship wait if there is another ship blocking the path, until the ship moves away from that cell. There is an edge case that needs to handled here, which is that if the blocking ships final cell is that cell, then the current ship will wait forever. To mitigate this case checking if any ships will end up at a cell blocking the way needs to be considered when creating the command. Processing the cells in the path of the command object is quite similar. Each update call, dequeue the next path from the paths and move towards that cell. If the ship has reached the cell, transfer the ship to that cell and discard that cell from the path. If the path queue is empty, it means we have reached our destination. So here is the algorithm outlined in a list

1. copy the command item queue to a new queue, call it nextQueue
2. while there are items in the queue, loop

..1.. get the current command
..2.. currentCell = the cell this ship is on now
..3.. next cell = peek at the head of the path for the current command
..4.. if there is a ship on the next cell, enqueue that command in nextQueue and continue the loop
..5.. check if the ship needs a rotation to get the current cell, and process the rotation if required
..6.. move the ship towards the next cell
..7.. if the ship is in the next cell, transfer the ship to that cell.
..8.. if there are more paths to process, requeue the current command in nextQueue##

3. copy nextQueue back to command item queue

User avatar
dendiz
Site Admin
Posts: 115
Joined: Wed Oct 10, 2018 3:48 am

Re: Hexarategy

Post by dendiz » Tue Dec 04, 2018 3:49 am

Ship movement collision
=======================

So, in the last movement video there were ship passing through each other like they were ghost ships of some sort. I could have just added a mesh collider and blew up the ship when they touched each other but that wouldn’t really make sense for ship of the same player. No same captain wouldn’t deviate from a collision course with a friendly ship (unless they’re unconscious or something). So the simplest way was to let one of the ship wait until the other one passes, and then carry on with the navigation.


Post Reply