Thursday, 14 November 2019

Lighting issue

I'm working on fov and lighting as you should after 110 years of development. I have a new fov routine, but there is a problem in lighting. When each tile has independent fov and light values it will create a situation where the wall is lit from the opposite side. Imagine there is a lamp in a room and the room's door is closed. You can still see the wall lit when you are outside the room, because the lamp has to lit the "inside" walls of rooms as well. Obviously, the inside and outside walls are the same, since roguelike 2D maps usually have it that way.

I don't recall any games that have gradual lighting and how they solved it, if at all. I guess one way to try is have data for each facing of a wall, but it may get complicated. More so if the light source is on the wall itself, as some kind of wall lamp. Then things get even more complicated, unless you give the light source information about which side of the wall it is.

Whatever the solution, I have to do something about both fov and lighting finally, because in a weird way having both fov and lighting helps in dungeon design, because everything looks very different if you don't have fov on in particular.

Sunday, 13 October 2019

Progress on dungeon generation

Back in some years I ran into trouble with a large scale data-driven system developed for the dungeon generation. It seems like data-driving works best in local, isolated contex just like many other things in programming. Since then I've been breaking the data-driven system into level theme classes, using only some data-driven parts.

The good thing is that most sub-systems can be run directly from theme classes with some minor changes in the way data is passed into them.

In the past I used to think that level generation is complex, but in reality it's quite simple. As always the main point is first making a decision what the level actually contains, rather than thinking about doing it later. When you say "I'm going to do it later" you are in trouble.

Most of the building blocks are ready and about half of the themes have a basic structure. There is even a simple street generation routine for town levels where I made an observation that by storing and comparing distances from previous locations you can space the things without having to do it manually. However after all these years it's hilarious when you proceed to the next level you realize there is more to it.

I'm going to be happy if the basic structures of all themes are ready before the end of this year, because after that it's much easier to add the rest with sub-systems that mostly work by filling in the rest of the free space.

Monday, 9 September 2019

Coordinates rewrite

Each object used to store coordinate data, but for objects that don't move I thought having that data in the object itself was a waste of space. Obviously there has been complications when coordinates were removed from some object types. The way I'm storing game objects are in a list, because it's an easy way to keep them in ownership of the level. The display map is doing most of the work by having only handles to visible objects.

Since items (those items you pick up in the game) work a bit different way I have to write a unique list for them. The generic list did have some static_casts to item class for that reason and I guess it's good to remove those routines. There are some other object types that use coordinates in that context, but they are easier to fix I think.

There is also a change in the way I'm documenting issues in the source code. I used to write "note:" followed by explanation in the source code, but those seem to disappear in the code. I think it's better to create an issue list with number for each issue and then fix them the same way as bugs. That way you can see the list growing and if you don't do anything it's going to be infinitely long.

Saturday, 3 August 2019

Plan for graphics tiles

Since I got my new computer and Blender 2.80 has been released I have an idea to recreate game object tiles in 3D. It may sound like a bad idea, but I think it's not that difficult. Items will probably be the easiest, because there are lots of parts that can be modified and copied (like handles and blades of weapons etc.). Besides not many people know that I am a 3D artist/animator myself, I just didn't get jobs from that area but have been mainly working in office environment for years.

I haven't tried this before, but I know there are some things to consider. First you need to match some kind of grid with items so when you render let's say 512x512 with 32x32 tiles the items are in their own "tiles" and don't bleed to others. Then again it's quite easy to fix if that happens by moving or scaling that object. The second problem is I guess the scale, because 32x32 tiles can only have certain amount of detail. This in fact can make the whole process easier, because you don't need a lot of detail and items need large, possibly even cartoonish parts in them.

The great thing about 3D is that it's easy to rotate and scale objects if you need to change their perspective (viewed from top in the actual game) or colors (materials). And on top of that you can create matching shadows and lighting for all items in a matter of seconds. Well, the downside is that modelling is kind of difficult and slow, although I'm pretty good at it.

It would be nice to have new graphics put in the game as soon as they are made, but it requires some changes. I need to change the .wst format to a regular image format and then copy new tiles over old ones when they are made. Some object graphics can be put into one image to have less image files to handle. The new system has to be programmed for all tiles, but copying tiles from .wst to image is not a big problem, it just means I have to succeed in this 3D idea. But I think it's the right way to proceed, because drawing tiles in 2D is even harder.

Tuesday, 16 July 2019

Back to game design

After finding solutions to some technical things I've returned to creating content or more like trying to get things playable. It feels a bit weird, yet nice. At the moment I'm working on character creation which involves some RPG system design as well, with skills in particular.

The RPG system is going to focus on gear and skills, not in experience because there is none except in skills (as a limited way to advance). I never liked experience based systems myself so this is an attempt to try something different. I guess you could look at getting better gear as "experience" of sort.

I feel like the technical solutions I've reached are not going to change this time, for real. At least not in a dramatic way like before.

Sunday, 16 June 2019

What I learned about inheritance today

Working on the game object class hierarchy I was confronted with a problem that I had not been able to solve - until now. The solution is I guess kind of hack, but I think it's only fitting. So when you inherit from another branch of class(es) the "main" branch can't use the class in that other branch without virtual functions defined in the base class. These functions can use either components which is a common way to use classes when you are not sure about inheritance, or derived classes, both using function wrappers which is bad, because it can generate duplicate or similar code.

My solution is a virtual function in the base class that returns the slice of the derived class from another inheritance hierarchy. The base class obviously returns zero for non-existing slice, but any derived class can return the proper part of it simply with return this. Slicing doesn't matter when you return pointers, it just works. When the sliced class is abstract enough it doesn't cause problems with decoupling it from the host class. Real life examples are things like the opener part of an object such as door. It can have status (open, closed, etc.) and lock data as in case of this game, and another example is the actual container in objects that can contain items. Both "slices" are abstract in the sense that they don't need information about the host object when they are used. The routines that use them can have the host object pointer as well and it's the case here, because you may need to do things to base class object as well like change the graphics frame when door is opened or closed.

The reason for all this is remove "empty" virtual functions and functionality from base classes and other classes in the hierarchy that are not using some derived class functionality. With this new way to handle some aspects of game objects I can split the main hierarchy to object types that use only the functions they have and it's possible without writing multiple wrapper functions to each class, because those classes are virtual parts themselves.

Friday, 10 May 2019

Class hierarchy of game objects

The structure of game object classes is something I'm going to rewrite, maybe before source code release. The problem was that I believed the "common" knowledge that you should avoid inheritance and especially multiple inheritance in C++, and use components, not only as in component based approach but as datatypes inside the class. But if you are using classes and OOP, then what is the point of that? There is no point and not only that it has made the game object tree quite difficult to maintain.

But what about things like the dreaded diamond? It is a silly thing to dread, because any advanced programmer can't make that kind of simple mistake in inheritance. The real difficult thing is the class hierarchy itself, because you need to make independent branches that don't rely on some base class data if the class is not inherited from "main" branch.

How you split classes is part of the hierarchy problem. For example if you have fountains should they be a separate class that has water contain ability or should they be a part of some more generic container type class? The way objects behave is I think a good way to split, but even then some features are more generic than others. It's not easy to create a well behaving class hierarchy, but it's certainly not impossible or something you should avoid.

I think when people go for solutions like component based design it's a solution to problem that never existed. The way OOP works is just one way to do things, that's it. If you want to do something else, that's ok, but it's irresponsible to create assumptions about OOP that are not true.

Thursday, 2 May 2019

Descriptions

Every object in Kaduria has some kind of description of what it is. Some games have descriptions for monsters, but often not much else. I think descriptions are a nice way to clarify what the object is, because it's not always obvious. I know this myself, because I'm not a native speaker of english which is the de facto language for most roguelikes.

It's a good guess that descriptions are also a problem, because it's surprisingly hard to write good descriptions if you have a large number of objects in the game. I've mostly tackled that with kind of comical output, because it's the easiest approach in my mind. This is also something roguelikes tend to have, maybe for that same reason.

Item descriptions have been a stark reminder why it's a bad idea to create large amount of items before cementing their data structure. Kaduria doesn't have a impossible amount of items, "only" 233, but it gives plenty of work when something changes. In this case copy-pasting descriptions from C++ files to external text file. It's not even 233 copy-pastes (you can try that line by line from some random text file and get an idea) but also cleaning the source code's struct data after that. Lot's of selecting by mouse and deleting with backspace.

Some of the descriptions aren't yet written, so it's even slower than that. If there is something "technical" in the description it also has to match the game's features. Which in some cases is not yet there. Both items and monsters are a great example of overdoing and lack of planning skills. What you should do is start from a small number of items from each item/monster class and work with that before adding lots of them.

Wednesday, 3 April 2019

Game design doc

Today I learned there is something called a "design doc" and I was browsing some examples of them. Some of them are "pitch" docs which are way too simple to accurately describe a game, but there were some that were more detailed. I've never made a design doc, maybe that's why Kaduria and my other projects took so much time to finish.

Maybe I could still write a design doc for Kaduria? I just don't see that much reason for it, but it could be something to try at least. I guess it is good to know what your game is going to have in terms of places, items, monsters etc. but why not just put them in the game without a doc? Maybe I'm missing something here.

I'm in a weird kind of situation right now, because all my projects are in state where I'm not sure what to do next, in a way. Obviously there is so much to fix that I can just start doing it and worry about those more generic things later.

Working on Banana Rogue (a derived project from Advanced Rogue) has actually given me some hope for my own programming style and source code. It makes everything look much simpler, even this huge project. The source code as technical aspect doesn't have too many problems to solve, it's more like content. Well, it's almost always the content. I don't know, maybe a design doc for content or more specific for game world could help me determine how to create the entire game world, not just some level themes.

Saturday, 9 March 2019

Class enum

I knew you can put enums inside a class (like pretty much everything) but I didn't realize you can then use the class name as outside access to that enum if it's public. What this means in my case I can remove some namespaces I've created for enums. In a large project any name that is introduced increases the complexity, so using class enums is in many cases a better option, because usually enums are used inside the class and sometimes outside. As added bonus the enum will be "open" (as with namespaces) inside the class, but always closed outside (requires the access name).

There is also something called enum class, not to confuse with class enum, but it seems to be too advanced to even look at it.

Namespaces are weird. They were designed for modular style I guess, but in reality they are used to replace old school "hungarian" notation where some letter or combination is used in front of the name, like iDagger or itmDagger or itemDagger for items, and replaced with item namespace with outside access style item::Dagger. But sometimes even I'm using namespaces for modules and they are really useful to avoid name clashing problems which eventually will become reality when the project is getting bigger.

Like I said before I've backtracked too modular style, because modules should be "natural" I guess, containing stuff that's actually related and possibly even working together as a.. well, module. I think in OOP style the most important thing is a good low level or datatype class foundation and then the actual code is built using those classes, rather than writing too much "low level" code everywhere. That way the source code becomes easier to maintain, which is not the case with Kaduria.

Tuesday, 26 February 2019

Shifting paradigms

A while back I had an idea to use procedural functions in otherwise OOP code. It's not that bad idea in itself, but I went too far and now backtracking some of those routines back to classes. The other paradigm I've struggled with is the modular thing, which is much harder than I thought. Sometimes you don't want to force classes into a thematic module, because it's easier to keep it separated from others with the possibility to open the namespace in that particular file. Opening namespaces with more than one namespace is sometimes not possible without duplicate names. The distrubution of modules is the hard part in modular design, but it's better than just have tons of classes each in a separate file, because then you have endless include race going on.

I think it's going to be fine, after massive amount of work of course. A weird thing happening at the moment is Teemu's development which is in many ways doubling the amount of work, because I'm using similar kind of re-arrangement of code into more logical compositions and I can't just copy-paste between projects. In some cases I have developed things I can use in other projects, but it's quite rare. However  I do benefit from actually figuring out how to do some things, which then can be rewritten for another project. Still, I really could do without having to manage two roguelike projects at the same time.

Saturday, 16 February 2019

External data

Three most important things I'm working on at the moment are:

1. Moving some data from source code to data files. The way data is handled in this project is kind of a problem, but even you have all text data etc. in C++ files it's doable. However I'm moving plain text data to files, because I'm planning to release the source code without data files during the development process, before the first playable beta. I think it's going to be the best way to proceed, because it makes no sense to be able to run the project in this state, before there is something to play. I suspect people could just get confused and it also pretty much prevents random "release" versions leaking to the internet which is not a very likely scenario, but possible.

2. The modular design, this is one of the most important things, because it will make management of the project a little bit easier and also it will be better with less changes in the project structure for github. Maybe there will be more source files in the future, but it's ok.

3. Continue removing dumb comments from .cpp files which really has given me a new kind of idea how big this project is. While not as big as some of the major roguelike projects when counting lines of code, comparing raw lines of code is not the whole truth.

Sunday, 3 February 2019

Dumb comments

The first step in source code release is removal of "dumb" comments. It's probably the best to remove them, because unneccessary comments actually makes the source code a bit more harder to read and they don't give any meaningful clues to what the source code is trying to do. The "classic" example I guess is

int Get_Item(); //gets item

Things like that actually are in the source code as we speak and the reason is the long span of time the project has seen. Since then my programming skills have improved in some way.

Comments in C++ are sometimes needed, but often it's the matter of giving readable names to variables and functions after which comments are not required. So those are also things I'm probably fixing as I'm going through the source code. I have started with header files, because they are the easy ones to fix. I think header files should not need comments, with a big exception to classes, I think it's useful to comment in few words what the class is doing. The name of the class may tell it, but it's not always that clear.

Tuesday, 29 January 2019

Asset manager

Now that the source code is going to be released I realized it could be useful to talk about it even before release to explain my programming style and thinking. One of the newest module (I'm going to talk a lot about modules which are not a "built-in" feature in C++, yet very useful way to handle large projects) is asset manager. It's a collection of higher level routines for stuff like displaying some graphics and working with menu data etc.

The reason for asset manager is remove some of those higher level includes from "low" level modules. An example would be Add_Player_Races which, as the name says, adds playable races to a menu in character selection. This used to be in Monster Type module which is static data for creatures, but you kind of want to keep simpler modules clean from gui stuff or whatever. As clean as possible anyway.

A problem related to asset manager are procedural functions in nameplaces which in many cases belong to some type of class. So there will be a clean up of those, because I think I got a little bit too excited about "procedural" programming in some cases. It does work in generic cases though, when you create functions that can be accessed from anywhere without binding them to a specific class.