No luck with the compressed normal map. It just looked horrendously ugly. I'm using a standard normal map instead.
I have one other compression idea to try, but it's not orthodox and would take forever to implement.
Also, I think it's more expedient for efficiency's sake to work on eliminating general code problems instead of focusing on one specific type, for now. I feel that I must be able to eke 10 or 20 frames per second more out of the terrain code.
Progress continues apace on other fronts, however. The forest generator has been updated to use all my current models, and looks great. I had to correct some problems relating to mipmaps. Speed is ~90fps in heavily forested areas, top down; dropping to ~60 when looking side-on. This is to be expected.
I have also linked lighting to the day/night cycle. Most things now work with this cycle; the main exception being the grass, which looks out of place. My deciduous trees, unfortunately, have been nigh-impossible to get perfect. I am going to have to implement a vertex shader for them, to deny diffuse lighting to vertices that fall within a certain region of the texture map. That way, I can light the trunks but leave out the leaves.
And finally, I created a "smoke" effect. This consists of a dual-layered material, with the first layer providing color information (with a scrolling UV coordinate) and basic alpha data, and the second layer providing a constant fade over vertical space. The end result is reasonably visually pleasing, and for only twenty non-processed polygons!
Next up: Making a movement engine for all units simultaneously. Basically, this has to be as lightweight as possible; ideally no more than a couple of multiplications or additions per unit. The simpler it is, the more units I can fit on my "payroll," so to speak. I need to handle at least four hundred in real time.
I'd like to do this by a series of linked lists, representing all the units that need to move in a particular direction. Say you need to move north (y+). You add your ID to the linked list labeled "global.yplusmovers" or something like that, and keep track of your node (and your parent node) within that list. Every frame, a simple counter goes through and increments the y position of all units in that list by 1. And every eight (or however many it takes to move one cell's worth) frames, your unit can check to see where it's going next, and remove itself from any lists it's done with. (Using its kept reference to its own link!)
I can't really suss out whether this would be faster or slower than a simple if-block, though. It removes pretty much all the if statements every step, doing everything by pretty much the most simple method possible - but on the other hand, it might require two instructions per update per unit.
If I use a while loop to traverse the lists, I can easily get it down to a simple addition and variable assignment. That should be lightweight enough for anybody...
Units should do nothing unless acted on by an outside force, or unless already doing something. (Basically, Newton's first law!)
Handling user input is easy enough - it's entirely driven by the player, and is furthermore constrained in how many objects it can affect at one time.
Handling AI input is also pretty easy - set up how often the AI works (for a wild animal, say every two seconds) and let it interact with the unit's movement scripting when needed.
Handling unit-to-unit input is slightly harder. I shall need to set up some sort of fast area-effect tool so that, for instance, one antelope getting hit by a spear excites the whole herd. (And likewise, so that one unit getting attacked puts all nearby units on alert as well! This is essential to a maintenance of immersion.)
It's the "already doing something" that may prove most difficult in the end... there are an alarmingly large number of factors to take into account, from cross-map pathfinding (Always a potential speedbump, especially with A* pathfinding - although I may be able to outsource this to native C++ code), to updating the minimap (if, that is, I decide to use fog-of-war; I may be able to find a better concept!), to being aware of one's surroundings, to local pathfinding. Ideally, I'll be able to limit most of these to per-group actions (EG pathfind only once for every order the player gives, no matter how large the group), and limit the rest to occur only once every ten-plus frames, at which point I can stagger their occurance in order to handle ten times as many units at the same speed.
My hope is to get units working with an average of four operations per frame per unit. That would put large armies well within reach.
It may seem like I'm taking an awful lot of preemptive caution here. I'm not. My graphics are running on a relatively up-to-date 2005-08 era engine... but Game Maker itself is the equivalent of a turn-of-the-millenium Pentium III. It's fast to develop with, and puts big projects within the reach of the individual programmer, but it's not well-optimized. I'll be truly lucky if I can get as much happening at once as Age of Empires II managed. And that... at LEAST that... is what I intend to do.
No comments:
Post a Comment