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.

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.

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.

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.

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.

Sunday, 6 September 2015

New Message

Yesterday I realized what to do with the Message class and messages. Previously I had passed AI id for messages, but replaced that with game object handle. That way the game object always triggers the message and selects the proper message pool with different versions of messages. Also, all visibility and other checks are in the Message class, so there is no need to check for example if the player is blind in other routines. Later messages can become more detailed depending on how far the action happens etc. but it requires more message pools.

For message pools I wrote a new class, not surprisingly named Message_Pool. It's another good example why you need to handle raw style data in a dedicated class rather than directly, because with class you can input as many similar sources as possible and then select them without using ifs or switch-case structures.

There were problems of course. I already knew I had to solve the passing of nouns and verbs to Message, because it was done for each actor first, before displaying the message. It works, but makes the game of course slower. To fix that I'm replacing direct calls with new functions that take the message id and the noun or whatever as parameters, then first check if the message itself exists and other visibility issues before copying and displaying the message. There is certainly some work to do before everything is fixed, but I had a good start in that.

The main message pool needs a clean up and the message data arranged better. It doesn't matter in what order the messages are so that's why "magic" id numbers for messages work here, they are not replaced etc.

It's not yet perfect and I'm anticipating some problems later. One of them is how individual npc names are displayed. The message data can have something like "The # hits you." but if the npc is someone you know then "The" has to be removed. It may be something simple like using another pool for "known" npcs with message data changed to "# hits you." The pool can be selected in the Message class using any kind of rule or condition, that's the nice thing about it.

Saturday, 5 September 2015

Messages

The message system of Kaduria is using a ID for each message that points to proper message buffer with versions for situations like blindness and also for other than player's messages. The message can be something like "%100The # is burnt out." where # is replaced by noun, in this case "torch" for example. This kind of system is quite nice, because it removes checks for blindess etc. in the routines that are calling messages.

It's not difficult to track messages IDs even it feels like a dumb idea to call Message(100); to display that message. The real problem with this approach is that the message list becomes large and more importantly the message data is detached from the "data type" classes. In this example I have I_Light_Item class just for items that emit light, like torches, lamps etc. This class has information about light items such as can it be re-filled with lamp oil. But it would be really useful to have also message data included in the class.

The problem at least for now is that message routines become "dumb", they need external data to determine if the message was triggered by the player and also information about blindness etc. This could be solved by some kind of generic routine that handles raw data, possibly even similar type of data to what the main message routine has.

Whatever the solution is I find messages one of the annoying parts of roguelike programming, as if there weren't plenty of them already.