I will have to add mouse scrolling. This implies that I detect the mouse position and if it is near the edge then I scroll, otherwise I do not. I’m not sure if the usual method is to detect mouse position in the window or to set a bool when the mouse moves to the edge and then set it to false when it is away from it. My concern is that since I’m going to debug in non-full-screen, detecting position of the mouse could be superior to avoid “perma-lock scrolling”.
Finally, for the camera controller, I need for the GameState to inject the map size to the CameraManager after it is finished loading. The GameState will inform the AppStateManager who then informs the InputManager who then informs the CameraManager.
I will just say that situation is not ideal. Later I will likely implement an eventHandler or eventManager, shove it into the GameEngine and then pass a pointer of it down to every class who can then register to listen to events and also send out events. It’ll be cleaner. That way I instantiate all the different game components and they can talk without knowing each other.
***
At this point I can start making a high level design of the CGameState object which holds information for the current state of the game (the position of all units, resources, animals, health and everything else).
My initial thoughts are to use lots of memory for very quick access and performance. I’m willing to sacrifice optimising on the memory end primarily because most of the data will be integers and other such primitives and basically not worth optimising over runtime performance. So on that end I was thinking that
Terrain
- Water, Grass, Bushes, Trees will all be a gigantic 2d array of respective classes CWater, CGrass.. etc
- Each class is an instantiation of water, grass and so on, to keep track of the current condition of it (
- hopefully not overly expensive, but for a 100x100 map, it would imply 10 000s objects, for a memory use of maybe say 40 000 objects and each object is say 10 integers, so maybe 40 000 * 10 * 4 bytes = 400 kb of memory, it would scale linearly, so for a mega large map of 5000x5000 then you could have 25 000 000 * 4 * 10 * 4 bytes = 4 000 000 000 bytes, which is 4 000 MB, which is 4 gigs... so at that point I’d have to do something fancy :P
Game
- Faction
- Units, Structures
- Each unit is an instantiation of a specific type of object
- Position on map
- Pointer to Ogre::entity if exists or null, update this during updateTick
- Units have action stack and need update method
- AI State variables
- Relationship with each known faction
- Expectation levels
- Trade expectation (whether you give favourable trade deals)
- Aid expectation (how much he thinks you’ll help if asked)
- Perceived reputation of target
- Current relationship strength
- Threat factor (a number to represent a likelihood of attack)
- military threat modifier (the ability of this faction to utilise its military power in a superior fashion)
Spaghetti Flying Monster Thoughts...
Currently, there is no event system manager. That’s on my wish list of to-do infrastructure features with the code. The earlier I do it, likely the less “regression” required. I’d like to first get to the point of being able to play the game (that is, mouse clicking, resource, actions for a unit etc.) before I move onto events. The reason is primarily due to my lack of thought on an overall design but I have an idea on it.
The map size when loaded needs to be fed into the camera system right now. This allows the camera manager to know whether or not you’ve reached the edge of the map and then stop scrolling. Right now, the GameState will have to somehow return that value back to the AppStateManager who then can shove it back down into the InputManager where the CameraManager lives. If I had events, this could be part of the GAME_MAP_LOADING_COMPLETE event or some such thing (I’ve read a recommendation to use GUIDs rather than an enum list so that the different game system pieces don’t need to be recompiled when a new event is added).
Performance Thoughts...
So, the update loop in the main code will eventually tell CGameState to call its updateTick functionality. It will then go through each unit to update them (depending on their current action they will do whatever it is they need to do, and if they have a target that target may change their current action). A large number of units in the game (maybe >1000? I’d have to do stress testing later) could slow down a tick below 60 updates per second. That’d make the game rather jittery and unplayable.
Now, I could definitely reduce updates to below 60 updates per second, although I think 60 is the lower bound, to ensure your eye doesn’t catch any “jumpiness”.
First thought is to try to skip units without actions which implies the ability to queue and dequeue units from a “hasAction” list that is cheap. In that case a linked list would be good, since enqueuing and dequeuing are O(1) actions. I wouldn’t need random access to the linkedlist of unitsWithActions so the O(n) constraint there doesn’t matter (and I don’t need to do anything complicated about it).
As always I’m not going to bother until it’s a problem. The first iterations of Cultura are going to be strictly set in early stone age and the first version won’t have reproduction at all.
My expectation is that graphics will take a constant amount of memory. I won’t have “graphics settings”. They’ll just be well tuned for 60 FPS on my box which is five years old, so hopefully it will be a good baseline for everyone (it also uses an ATI card just to be sure I don’t use any nVidia specific driver stuff and cause a blue screen on ATI computers... or it could be because an ATI card is half the price and uses a quarter the electricity... hurr!).
Game-wise, I think that each square of map implies roughly 160 bytes of memory and interesting this bounds the rest of the game object memory because they would be limited by the lack of in-game resources (no land, no food!). Let’s say it’s like 5 objects worth of stuff, each around 10 integers worth of data, so 5 * 10 * 4 = 200 bytes. So each square of land is like 360 bytes.
Let’s keep map sizes below the need for performance magic for now. We’ll say I want to keep this amount of memory use to be at ~500 Mb. So that means 1 388 889 squares and that means a square map of about 1179 x 1179. So let’s keep a map at 1000 x 1000. I’m concerned about the load-time on that but let’s ignore that for now. Actually, if it turns out the load time is too slow for such a large map, then I will reduce map size to compensate.
Later on when the game is in a very excellent state (resource management, technological research, reproduction, AI, interacting with other societies), I will start performance stints to allow for larger maps and more people. Yay.
No comments:
Post a Comment