Terrain refactoring is done for now, but some stuff will be changed later. The speed problem was caused by Visual Studio's debug mode. When the .exe is run outside the IDE it's fast. It's still kind of problem in everyday testing and can't be solved easily.
Much bigger problem are messages, because even the number of calls to old message routines are not that many, each rewriting seems to take the time. But you have to be positive, because this time it's done properly. I hope...
Saturday, 24 October 2015
Tuesday, 20 October 2015
Speed problem of terrain objects
Now the terrain tiles are objects and everything is fine, right? No. The map displaying is somewhat slower from average 5-10ms up to 40ms per step (in small rooms it's under 5ms though). It's not that bad I guess and optimizing gives more speed.
Then I noticed something strange. When I quit the game there is a noticeably long pause. And it becomes worse when you visit more levels. For some reason deleting objects from maps is incredibly slow. I guess it can be, because there are 10 000 tile objects in a 100 x 100 map. Still it's surprisingly slow, taking several seconds with just 4-5 maps. Imagine you visit all levels in the game and wait for 5 minutes for it to delete the objects when you leave the program.
Is delete really that slow or am I doing something wrong? There isn't a big difference in std::vector compared to raw array of pointers (which is easy to test, because the syntax is the same). Raw array seems to be a little bit faster, but not in a way that would make a real difference.
So, what you can do in a situation like this? Should I return to the model where only one level is stored in the memory at a time, loading the level data from files when changing the level? Maybe, if nothing else works. The class hierarchy for game objects is quite heavy, at least now when Tile object of a map could in fact own/contain many of the static object types which don't move. That would remove the "double" pointers for objects, one in the list and other in a form of quick pointer in a Tile. The entire model could be switched from list to a type where Tile owns all objects.
The base class for objects could be also simplified and some functionality moved forward in the inheritance level possibly to intermediate classes (which then would make the class hierarchy more complex and who knows what happens then).
The map itself could contain Tile objects only in the visible areas and empty pointers in solid rock areas of the level.
Or maybe this problem will go away by itself in 10 years when computers become faster.
Then I noticed something strange. When I quit the game there is a noticeably long pause. And it becomes worse when you visit more levels. For some reason deleting objects from maps is incredibly slow. I guess it can be, because there are 10 000 tile objects in a 100 x 100 map. Still it's surprisingly slow, taking several seconds with just 4-5 maps. Imagine you visit all levels in the game and wait for 5 minutes for it to delete the objects when you leave the program.
Is delete really that slow or am I doing something wrong? There isn't a big difference in std::vector compared to raw array of pointers (which is easy to test, because the syntax is the same). Raw array seems to be a little bit faster, but not in a way that would make a real difference.
So, what you can do in a situation like this? Should I return to the model where only one level is stored in the memory at a time, loading the level data from files when changing the level? Maybe, if nothing else works. The class hierarchy for game objects is quite heavy, at least now when Tile object of a map could in fact own/contain many of the static object types which don't move. That would remove the "double" pointers for objects, one in the list and other in a form of quick pointer in a Tile. The entire model could be switched from list to a type where Tile owns all objects.
The base class for objects could be also simplified and some functionality moved forward in the inheritance level possibly to intermediate classes (which then would make the class hierarchy more complex and who knows what happens then).
The map itself could contain Tile objects only in the visible areas and empty pointers in solid rock areas of the level.
Or maybe this problem will go away by itself in 10 years when computers become faster.
Sunday, 18 October 2015
Terrain as object - part 2
The refactoring of terrain from int to a game object is about half done. No big surprises, but the entire structure of Level and map is a bit complicated. I guess it's supposed to be, because it's not a simple thing.
The call hierarchy to the actual terrain object is in most cases Level - Level_Map - Tile - U_Terrain (the last class is the terrain object instance). Not only that, the U_Terrain also includes the static data class for terrain, named K_Terrain_Type. In most cases Tile is using most of static data information so to avoid some wrapper functions I made U_Terrain the friend of Tile in which case getting information from static data looks like this:
bool w=terrain->type.Is_Wall();
It's always a problem in class programming to decide the structure of functions that handle something. In ideal case you can avoid simple getters, but in real life.. well, they do happen once a while. I think it's important not to care too much about "bad" structure, rather than concentrate on making things that work in gameplay level. No one cares how bad the source code is if the game is great. Also, I think in most cases it's a matter of preference where the action happens. If you want to limit the action to a low level class then you have to pass more information in that class. Or the other way is get more information in smaller pieces using getters.
This refactoring has been a lot easier than I thought, mainly because Tile class was already there and the "only" thing to change is simply add terrain object to Tile instead of int type. Of course it's not that simple if you want to make bigger changes in the concept of terrain as just another object type.
There is also a kind of struggle with other game objects. At the moment objects are stored in lists, but they could also be owned by the Tile itself as the terrain object is now. Tile is using only object pointers for easier access to object in that tile, but it could also own the objects, now that terrain is owned by it.
The call hierarchy to the actual terrain object is in most cases Level - Level_Map - Tile - U_Terrain (the last class is the terrain object instance). Not only that, the U_Terrain also includes the static data class for terrain, named K_Terrain_Type. In most cases Tile is using most of static data information so to avoid some wrapper functions I made U_Terrain the friend of Tile in which case getting information from static data looks like this:
bool w=terrain->type.Is_Wall();
It's always a problem in class programming to decide the structure of functions that handle something. In ideal case you can avoid simple getters, but in real life.. well, they do happen once a while. I think it's important not to care too much about "bad" structure, rather than concentrate on making things that work in gameplay level. No one cares how bad the source code is if the game is great. Also, I think in most cases it's a matter of preference where the action happens. If you want to limit the action to a low level class then you have to pass more information in that class. Or the other way is get more information in smaller pieces using getters.
This refactoring has been a lot easier than I thought, mainly because Tile class was already there and the "only" thing to change is simply add terrain object to Tile instead of int type. Of course it's not that simple if you want to make bigger changes in the concept of terrain as just another object type.
There is also a kind of struggle with other game objects. At the moment objects are stored in lists, but they could also be owned by the Tile itself as the terrain object is now. Tile is using only object pointers for easier access to object in that tile, but it could also own the objects, now that terrain is owned by it.
Wednesday, 14 October 2015
Terrain tiles as objects
When refactoring message routines I realized that terrain tiles are not game objects. It makes rather difficult to handle messages since it's clearly designed for object handles. I could have added special cases to message routine to get stuff like direct char pointer to terrain's name.
Changing terrain tiles from a simple int in map data to actual game object is difficult, sure. But it would not only solve this message thing, but many other problems related to terrain. For example when terrain tiles are objects they can have individual data for stuff like damage and so on.
This question of terrain tiles as objects has been kind of "debate" in roguelike development for a long time. They certainly spend more memory than simple tile maps, but in modern computers it's not a problem anymore. And it's about the only downside in them. My advice for developers who are thinking this question is that make them objects. You wont regret it later when more advanced terrain operations are needed.
What this means as a refactoring work is.. well.. I don't actually know the exact answer. The map system is already changed so that there is Tile object for each map tile, where the terrain tile is. Since the Tile is the owner of the terrain it becomes important not to override the existing terrain object, but that's quite easy to do. Most refactoring is spent in replacing the current system where "regular" game objects and the terrain is handled with different routines and style. When terrain becomes a game object it's possible to handle them using same routines as with other objects.
This change has been long overdue, because I knew the problem about the terrain much earlier, but was still reluctant to start the refactoring since it was working for the purpose at the time.
Changing terrain tiles from a simple int in map data to actual game object is difficult, sure. But it would not only solve this message thing, but many other problems related to terrain. For example when terrain tiles are objects they can have individual data for stuff like damage and so on.
This question of terrain tiles as objects has been kind of "debate" in roguelike development for a long time. They certainly spend more memory than simple tile maps, but in modern computers it's not a problem anymore. And it's about the only downside in them. My advice for developers who are thinking this question is that make them objects. You wont regret it later when more advanced terrain operations are needed.
What this means as a refactoring work is.. well.. I don't actually know the exact answer. The map system is already changed so that there is Tile object for each map tile, where the terrain tile is. Since the Tile is the owner of the terrain it becomes important not to override the existing terrain object, but that's quite easy to do. Most refactoring is spent in replacing the current system where "regular" game objects and the terrain is handled with different routines and style. When terrain becomes a game object it's possible to handle them using same routines as with other objects.
This change has been long overdue, because I knew the problem about the terrain much earlier, but was still reluctant to start the refactoring since it was working for the purpose at the time.
Sunday, 11 October 2015
Actor message model
There is a similar kind of refactoring need for messages as in Teemu. I'm still wondering why it took this long to realize how the messages should be handled, but anyway... This time however I'm going to build a new message system on top of the existing one and rewrite everything with small steps. That way I can check if everything is working properly.
The new message system is not just replacing the old, it's more than that. The new style hopefully requires less inheritance in the game object classes and maybe even more dramatic change is moving the "action" closer to data (in data type classes). It's good I think, because then the data and messages (and actions) are more modular than before.
It's lot of work, but has to be done and it means moving on to the next level in this project.
The new message system is not just replacing the old, it's more than that. The new style hopefully requires less inheritance in the game object classes and maybe even more dramatic change is moving the "action" closer to data (in data type classes). It's good I think, because then the data and messages (and actions) are more modular than before.
It's lot of work, but has to be done and it means moving on to the next level in this project.
Wednesday, 7 October 2015
Themes for GUI elements
Windows and menus have now color themes which are versions of graphics replaced by color of that theme. It's such a simple idea, but something I should have done much earlier. The nice thing about it is not only that you can adjust colors to match them better with other graphics etc. but the way things like highlight bars and background erasing is using colors of the theme. When it's automatic you don't have to set up those colors somewhere else, just to notice when you change the color of window you have to change those colors as well.
Font colors are not defined in the theme (at least not yet) except for title fonts which now also have theme colors. Usually the text is simply displayed over the window graphics, it's not a part of the window, but in menus the text is in a list of items and in that color could be used for text as well. I'm probably not going to create a rigid theme based font colors, because it's easy enough to do that manually and also you are not limited to color set of the theme which may be a good thing sometimes.
Lately I've been working quite long days which is quite different than it used to be. I don't know what happened to me, but now I have to limit the amount of time for programming, because it may be too much, at least in the long run.
Font colors are not defined in the theme (at least not yet) except for title fonts which now also have theme colors. Usually the text is simply displayed over the window graphics, it's not a part of the window, but in menus the text is in a list of items and in that color could be used for text as well. I'm probably not going to create a rigid theme based font colors, because it's easy enough to do that manually and also you are not limited to color set of the theme which may be a good thing sometimes.
Lately I've been working quite long days which is quite different than it used to be. I don't know what happened to me, but now I have to limit the amount of time for programming, because it may be too much, at least in the long run.
Sunday, 4 October 2015
Procedural GUI graphics
I'm planning to create some kind of "procedural" system for GUI graphics which in Kaduria's case are mainly window and gameview graphics. There isn't many graphical elements which is fine, because I try to change them to procedural versions rather than loading them from image data.
There are two ways to do this, easy and hard. In easy version you have some kind of graphical template which has colors you then replace with the actual color palette. In hard version you create the graphics by programming it.
It's possible to use both styles and that's something I'm probably going to do. For windows it could be easy to use the existing glyph data as a template and only create new versions for each color. If there were different kind of fonts then it would be better to create windows graphics that can scale to the font size, but in Kaduria the font is (hopefully) going to stay the same size to the release.
The procedural part in this case is mainly color. It's then easy to adjust colors to create better looking graphics, because color is important especially in GUI. Later it can be also possible to create different kind of color themes and even give the players an option to change colors as they wish.
I think my main goal for this month could be the GUI, because some things are still unfinished and when you have the GUI ready it's one less thing to worry about.
There are two ways to do this, easy and hard. In easy version you have some kind of graphical template which has colors you then replace with the actual color palette. In hard version you create the graphics by programming it.
It's possible to use both styles and that's something I'm probably going to do. For windows it could be easy to use the existing glyph data as a template and only create new versions for each color. If there were different kind of fonts then it would be better to create windows graphics that can scale to the font size, but in Kaduria the font is (hopefully) going to stay the same size to the release.
The procedural part in this case is mainly color. It's then easy to adjust colors to create better looking graphics, because color is important especially in GUI. Later it can be also possible to create different kind of color themes and even give the players an option to change colors as they wish.
I think my main goal for this month could be the GUI, because some things are still unfinished and when you have the GUI ready it's one less thing to worry about.
Subscribe to:
Posts (Atom)