A video where I take manual control of individual ships during combat. As you can see, the AI is much better at this. I’m planning to add parameters on how good or bad the ship is at flying. With this I can then do an experience system or a battle computer system etc. Bad pilots or ships with bad computers would then make mistakes and miss more often while experienced pilots with good tech would have this kind of almost perfect performance.
In the first posts in the blog I talked about the space flight model and controls. Now that I have a nice way to take manual control of the ships I can show it a bit more. Essentially it uses real physics but has some restrictions to prevent some unwanted things. For example, there is a common upper limit for all velocities. If that velocity is exceeded, the object is slowed down gradually to the upper limit. There also is a max speed limit for each ship depending on the ship’s mass and drives etc. These speed limits are of course unrealistic. Mass and drives should only affect acceleration and not set any max speed limits, every ship should be able to accelerate to any speed they want (well, at least up to the speed of light). However, having no max speed leads to too complicated and unwanted situations in the game so this is why these restrictions exist. Angular velocities work in a similar manner.
Other than that, space flight works as expected. The ships are controlled by linear thrusters accelerating the ship along three axes: up-down, left-right and forward-backward. The most powerful of these thrusters is the forward thruster, others are only for fine tuning the velocity. Then there are angular thrusters to apply torque to the ship. These thrusters provide angular velocity around roll, yaw and pitch axes. Mass of the ship naturally makes all of these accelerations smaller. The physical size of the ship (height, width, depth) affects the rotational accelerations.
The result is that big ships and small ships have quite similar linear accelerations and max speed, but big ships are much slower to turn.
It is nice to see everything from the perspective of individual ships, so I made an action camera feature for that purpose. I made the camera follow the ship smoothly so the velocities can be sensed from the camera lag. I’m planning to add an option to toggle manual flight on when in action camera mode.
Some music and nicer camera
I refined the combat camera to be smoother and also added a feature to follow units with the camera. It helps a lot that you don’t have to manually follow the flying ships while trying to do something. However, in follow mode the camera is not locked to the unit(s) followed: instead the reference point for the camera moves with the unit(s) and the camera can still be moved around normally. Camera can also be snapped to move to selected units by pressing a button or by double pressing the unit group.
Also, I’m glad to say that Jarkko Rotstén was interested enough to join the project to provide music. Currently we are trying to find the right style for the music and I feel we are on the right track.
I made a video for the music and to show the new camera features. The video starts from fleet creation before the combat and also has some explanations on what’s going on. The music starts at 1:30.
I have done so much panels and UI stuff recently so I wanted to add something different next. I decided to add target finding logics for turrets at this point. Until now the turrets have targeted only the one target set for the ship but now they find their targets autonomously, prioritizing missiles. So if there are missiles present they work as point defence.
First tech tree
Moving on to implement the first version of the technology system and tech trees. I like the idea of randomness in technologies: you should not know for certain what scientific discovery you are going to make next or in the whole future. Still the randomness should be balanced to avoid the situation that one civilization gets all of the good techs and some other civilization gets bad ones. The solution I made is that the technology tree is random but same for all civilizations. The tree represents the scientific laws of that universe: It dictates what kind of technologies can be found and in which order and those laws are the same for everyone.
At the start of the game some of the technologies will be omitted from that game altogether, those things do not exist in this universe. The rest forms a tech tree which is common for all civs. Civilizations will see only the techs they can research next and also how many new technology choices those techs will open up. How far in the tech tree civs can see beforehand might become variable depending on acquired techs and racial bonuses (or penalties). In addition, not all of the tech opportunities will be visible for all civilizations. This means that different parts of the common tech tree will be hidden for each civilizations and techs in those parts have to be gained via espionage or capturing bases or enemy ships. There also might be racial factors which affect how freely the common tech tree can be progressed. For example, creative races might see all options and non-creative have to follow a very predetermined path. In any case, it should be guaranteed that there are enough techs available for every civilization and that there is a path to at least some of the best techs.
In the video you can see a first version of a randomized tech tree. I ran it three times with different amounts of techs. It is designed in a way that it only reveals the parts which are known to the player’s civ. This info (and only this same info) should be available for the civs controlled by the AI also.
Expanding AI and colony ships
I started with the strategy map AI and decided to make a basic game AI which just produces colony ships and sends them to new planets. That sounds quite simple: just take a colony ship and order it to the closest free planet. But what if there happens to be multiple colony ships available, some of which would go to the same closest planet? What if a new colony ship is produced and is closer to some habitable planet than an existing colony ship en route to that planet? What if some of the colony ships can colonize only certain types of planets? What if some of the colony ships have a huge jump range and would be better to be spent on planets farther away?
I decided to solve this optimization problem by implementing Hungarian algorithm. Now the ships are assigned to free planets optimally in a way that the overall time spent on flying is minimized. It also takes different jump ranges and colonizing restrictions into account. It is also run every turn so if the situation changes, the ships will adapt accordingly.
In the first video there are four civilizations expanding to the stars. In the second video there is one civilization which starts with a huge amount of colony ships. Turn counter can be seen at the top right corner of the screen.
Testing the ship pipeline from design to production and to flying to fight some enemies. Currently there are not many restrictions on what can be put on the ship, but soon I have to start improving the ship designing system by adding things like power sources, power consumption, mass and cost of weapons and other modules. Note the nice ship blueprint card in the planet panel in the lower left corner of the screen which shows the actual design of the ship with the weapons it currently has.
I started to design the planet mechanics I have had in mind in a bit more detail. Mainly working with population growth and food mechanics and how to control the population on planets. People have to eat food to stay alive, but they will require more food to reproduce. Also, the growth rate is affected by the remaining free space on the planet. I feel this is quite realistic and simple. So the growth rate of the population on a planet is affected by the surplus of food and the size of the planet. As players can affect the growth rate by allocating work for farming, I find it convenient that the population’s work allocations can be set to meet desired goals. The goals are: sustain population size, max population growth and max food output (surplus can later be stored or sent to other planets). The allocation of workers then changes automatically once the requirements to meet these goals change. In addition, there is also a weight parameter assigned with the farming plan, which interpolates between these goals. With these tools the player can easily set the desired goals for the planets, hopefully reducing the amount of needed micromanagement.
After some (or all) of the workers have been allocated for farming (thematically all kinds of agricultural tasks, not just farming, whatever is required to get food on that planet) the rest of the workers are allocated to industry and research. There is another slider to set the ratio for this allocation.
All planets have base multipliers for food, industry and research output as well as a starting size. Now they are just randomized, but in the future there will be some kind of correlation between these numbers. Probably by having different types of planets and then using that base type as a starting point for some randomization.
I have been thinking about and preparing how to make the saving system for the game right from the start. Now the individual pieces can finally be connected and tested. This system allows me to do the scene transitions seen in the previous post and the saving of the game seen in this video. In the video I set courses for the ships and make new blueprints and save to see that things are loaded correctly. For debugging purposes I save the state of the game into binary and JSON. JSON so that human can inspect it easily and binary because that’s what I’m going to really use in the end. Every time the game loads it loads both files and checks that everything matches.
I like to make only a few prefabs for the UI objects and then use them in different places and customize them via code instead of the inspector. This way only a small number of UI objects have to be maintained, it is not always fun to fiddle with those. For example the saving and loading panels are actually the same panel, but opening it up from different places assigns different functions for the save/load-panel and shows and hides different buttons.