I'm at the point where I can start issuing commands to units. Part of the piping work also involved a few infrastructure changes to the code but most of it was changing things into pointers to make memory management more clear (more obvious when things can be deleted and where they exist in memory). That's more of a c++ specific issue what with my awesome well-thought-out tight coupling of systems requiring me to create and pass objects between components. Code quality is dropping fast but I'll try to keep a lid on technical debt with respect to bad code.
Anyway, the general design of how to give units orders needs to be planned out. On that note, I have a general design for this.
- GameState->updateTick() calls updateTick on all factions
- Faction->updateTick() calls updateTick on all units
- Unit->updateTick() checks the top of the action stack and then performs that action, this may update their world position, may have to call react on a target and may have to broadcast location to other units nearby to check if they need to react to its presence
There are several types of actions:
- Move
- Harvest
- Attack
- Follow
And some actions are reactions:
- Flee
- AttackLimited
It might be possible to roll the reaction actions into the original set of reactions with a few member variables attached. For instance, flee might actually just be a move action. AttackLimited might just be an Attack action with information about how far a unit should pursue an enemy before giving up. Each action has certain conditions to be met before being completed and others are somewhat more complex. For instance, a harvest action will attempt to gather as much material as a unit can carry and then push a "return goods" action to the top of the stack.
Later when there are industries and other such activities, there will be more complex actions that can rest as a foundation for a unit. A blacksmith may have a "blacksmith" action and when it is reached it simply pushes several actions on top, such as a move action to get the unit to a workplace and then a build item action and so on. And then the blacksmith action is never completed, every time it is reached in the action stack, it simply pushes new actions onto the stack. This way a unit continues to be a blacksmith until it is cleared.
These actions and reactions will require a little bit of infrastructure. A unit will now have an action stack where the actions are pushed onto and popped when completed. Some actions are replaceable, it remains to be seen how complicated this may become due to the nature of the game (a Settlers style industry implies a lot of automated action scripts that may occur). For reactions, the biggest problem is reacting to the presence of an enemy. Either you flee or you attack but in both cases it requires a way to perform a distance check between all units at any given time where this condition can be met.
There are several optimisations I have thought about for this problem. The first is to have a world hash map that contains all the units bucketed by "super squares". That is, I reduced the entire map to a smaller number of squares and only perform distance checks within groupings of squares. It's sort of like an oct tree but not quite. Simpler for the purpose I have in mind. The other is to only perform a distance check between a unit that has moved (in its updateTick function) and other units "near" it as determined by those super squares. And finally, only certain units even care. That is, the world hash map only contains military units. All other unit types are simply oblivious to approaching enemies until they are attacked.
For pathfinding, I'd prefer to use A* pathfinding but beyond a certain distance threshold it may be best to use a blind greedy algorithm. Just move in a square that goes toward the target location. In later iterations of Cultura where I want infrastructure (roads are especially important), I may have to do something more fancy. As a rule of thumb in those cases, roads/waterways are preferred over self-made paths not only because they may be faster but they may also be safer. An easier way to handle it is to make the roads speed up movement enough that they are almost always preferred without any special consideration on top of that and also to use a limited A* search (only do a partial pathfind and then move on the partial path).
There's been a bit of code clean up as well. Most of it is switching things into pointers to make it more obvious when memory is/should be cleared. Later on when the first iteration of the game (the alpha version) is done I will probably then proceed to implement an event based system (or I may even wait until I make a first release of the game before making large infrastructure code improvements). The event system is the biggest improvement that could happen. I picture it to be perhaps a singleton accessible from anywhere to allow all the different components to fire an event and register to listen to events.
Finally, I've had some thoughts on what I'd want the alpha to be. Essentially I'm going to split the game into "stages". Each stage is reached by reaching the population count necessary for it. For every stage there are new problems that can happen. Those problems are all centered around three variables in your society: health, happiness and administration. Stage 0 is where you start and you have no considerations. You simply go around collect resources, craft items and grow as you see fit. Stage 1 introduces health, where you have to maintain health or people can die from disease. And then finally Stage 2 is where happiness is introduced and you could face emigration should happiness fall too low. There are more possible consequences for failing to maintain health/happiness at later stages.
The Alpha version of the game will just be Stage 0. I'll complete all the necessary components (structures, population growth, UI, actions etc) and all the polish work (loading screens, responsive UI, good user experience) and then I'll move onto working on Stage 1 and Stage 2 where I have a "complete" game and I'm simply adding features. The release candidates would be with the first three stages (0, 1, 2). Then I'd work on 3,4,5 that focus on a wider range of consequences. For instance, low happiness could result in a small revolt or low health could result in a plague outbreak whereas in the earlier stages only one person might die from illness or a small group of people would just leave your society peacefully.
The polish work will likely require the help of some friends to point out UI experience issues that I may overlook because I focus too much on implementing various features. It's important for the user to always be aware of what's important in the game, to waste as little time on trying to find buttons or information and for everything to be "obvious" but to maintain the game complexity. It should be easy to understand the complexity and be fun to play through it.
What is my current wishlist? For an alpha I'd like to have the following:
- Actions - user input and reactionary ones
- Resource piles - placing resources anywhere on the ground
- Natural Structures - caves mostly and also a resource pile with a limit inside, eventually would like to have dwarven mountains, elven tree tops, goblin bogs
- Fighting - different damage types, weapons, hp, armour, dying, dropping of equipment onto the ground, looting equipment
- Population Growth - some way of having population growth
- Loading Screen - loading screen for starting a new game or loading a game
- New Game set up - a screen for setting up a new game
- Loading and saving - serialising game objects and deserialising them for saving/loading
- Map Generation - based on some settings be able to generate a new random map that is good to play on (fair, balanced, varied landscape, sensible positioning of animals and plants)
- Update Tick - this is a more general concept, just making sure that game speed is respected, units are redrawn in the correct spot, UI elements such as selection circles appear and disappear properly
- Large Maps - get as large of a map as possible, possibly use a texture atlas and a shader that renders a texture, memory management of all the game entities see how far the limit can go
- Diplomacy - ability to speak with other groups, maintaining the faction list, ability to make treaties based on diplomatic technologies known
- AI Opponents - ability to have AI manage units, collect resources, craft items, and make diplomatic approaches with other entities, have personality, act based on relations and personality
- Wildlife - have wildlife flee upon being attacked, migrate aimlessly, seasonal migration, just look vibrant
- Vegetation Growth - be able to have regrowth of natural resources such as trees and grass, be able to record planted/dug up vegetation so that regrowth reflects environmental changes made by player
- Land Regions - have arbitrarily defined land regions for game purposes
- Maturation - have plants, animals and people have a baby to adult process, possibly a death by age process as well
These are some post-alpha ideas:
- Serialisation versioning - able to have older save games be translated into newer save games without null point exceptions and so on
- Labour skills - people can get better at particular tasks and produce higher quality goods or product them faster
- Injuries - damage sustained that requires medical technologies to heal
- Seasons - resources in random piles spoil but not in structures, health concerns if there is lack of warmth, regrowth of vegetation and wildlife in spring
- Families - death by age and children, as well as family-based resource management
- Artificial structures - structures the players builds, ability for people to understand how to use them and/or have assignments or possession of it
- Trade - permanent trade routes, festivals and trade festivals
- Health/Happiness - maintaining a calculation of health/happiness, have consequences for having low health/happiness
- Families - death by age and children, as well as family-based resource management
No comments:
Post a Comment