Pagina's

Wednesday, 31 July 2019

Between dinner and Casa de Papel

So holiday has ended a couple of days ago  and I'm writing this blog from the bus again. On my way to that thing we call the office. As I probably said before,  I have a full time job as programmer making office applications for customers. And by the fact I write my corpus of blogposts in the bus for a part, I  need to travel every day.

This means that I am home quite late and that doesn't afford me much time to work on my game. Holiday is over indeed.

Having said that,  I'm glad I was able to lay some groundwork for things I could implement in the hours and half hours of the evening,  between dinner and Casa de Papel that me and my wife just started watching.

With the placeholder GUI in placeholder place, the coming time will mostly be about object interaction, about unit AI and the like, but only in following orders. Letting the enemies control their units is for later. For now, I'll be focussing on making sure that when a decision is made,  the objects know what to do.

Things I am planning to do soon include:

  • Changing a dead object or a dead and resourceless object to look and behave differently.  For instance,  when you kill a goat, it'll fall over and you can harvest the food. When the food is gone, it looks the same, but you can't interact with it anymore.  I want this to be clearer. Maybe turn the goat into a skeleton and have it vanish over time.
  • Right now, resources can be dropped at any building.  I'd like to change that. You shouldn't be able to drop wood at the barracks. I'll probably build granaries, storage buildings and the like for that.
  • When you attack a unit and it runs, following it is very simple. Have the unit close in and if it's close enough, continue attacking. I'd like the attacker to have to face the defender before fighting.  Besides,  I don't want the following to go infinitely.  That could be a tricky thing later when players discover luring enemy units.
  • If you gather resources,  you return to a building. That works. But if gathering or returning is interrupted, there's no way to just drop the stuff at the building  and be done with it.  To drop something now, you need to first send the unit to the resource to have it return. I'd like to trigger returning directly.
I don't think that these points are very big, so these should be fine for the evenings. Besides,  I really like the small successes that such things make. They are really motivating. 

Tuesday, 30 July 2019

Just GoThere(place)

Yesterday evening I found and fixed the bug that was haunting me for a couple of days  and it was one of those bugs I'll probably see return every now and then, because that's the kind of programmer I am. I overused a method that did more than I intended.

You see, units are supposed to be able to go places and for that, they have a navmesh agent that moves once a destination is set and the destination is not their current position. So far so good.  Can't have that fail (well, we can, but I won't bother you with that right now).

The other main part of the unit script is a  finite state machine AI system. In short, units have a state and a task. The state says what the unit is doing and the task what its objective is.  So when we want to cut a tree over there, clicking the tree will cause the unit to have Cut as task, the tree as target and Moving as state. The moving state will find out if the unit is near enough to the target to change the state to Fighting. Etc.

Now the problem with the bug was that the task was no longer to Cut. The unit went to the tree and that was it. It turned to the Idle state with Nothing on its mind. Actually, that was easy, because I made the mistake of messing with the Moving state. It had a simple statement to set the destination and I,  thinking that it would be smart,  replaced that by a GoThere method.

And that method set the destination,  so the guy did go to the tree. That was good. It also set the state to Moving, which is fine. But is ALSO set the task to Move. That was the problem.

The unit made its way to the tree and stopped near it. That was good. Then the Moving state wondered what to do next,  so it asked the script. The script said. If you're moving and the task is to move, then once you reach your destination, you're done and you can run SetIdle(), whatever that may mean. No cutting the tree.

Now, dear rubber duck, this is a clash of principles.  We have the DRY-principle (Don't Repeat Yourself) that will stop you from writing the same code multiple times. I try to live by this principle as much as possible.

Then there is this programming thing to keep things small. I wrongly assumed that the GoThere method would just set the destination even though I just added the messing up code for another aim. I wanted to make things consistent, but did not think about it enough. Because some things should be different from other things.

Lesson learned,  but by no means expecting not to make the mistake again.  I do think it should now be easier to detect.

Sunday, 28 July 2019

Mondays after the holiday

Mondays and most particularly this Monday...

Holiday is over and I'm in the bus to the office again. Santorini was great and back home we had record heat with temperatures over 40 degrees in the shade, so that was tough and I did not work on Holocene as much as I would have liked. Now it'll be evenings and weekends anyway, but that's just the way it is.

In my sweaty state, I did make progress in the unit mechanics. There was some refactoring in the way we deal with targets for the units, making is unnecessary to have different targets for resources, units, incomplete buildings and the like. This should make further progress easier.

The main thing is that I started the skeleton of a combat system.  When I have a unit selected and I click on some attackable object, the unit will move there and start dealing damage until the object dies. Then, depending on the type of object it's attacking, it might start gathering resources or find other objects to attack.  That works fine now.

I think I'll have to switch some of the mechanics to another class once I start implementing enemy AI and behaviour that does not depend on user input. I have some ideas about that, but not fleshed out yet. For now, I'm pretty pleased how it's all going and it's not been as difficult as I might have expected... YET.

Wednesday, 24 July 2019

Cutting the trees, blacksmithies and trebuchets

Right, today was the hottest day ever in the Netherlands and tomorrow, they expect another record, so what did I do? I only worked on Holocene in the morning and now, in the middle of the night, right before going to bed, here's what I made.

Most of the stuff I've been working on is work in progress, except for turning trees into animals, like I announced yesterday. Turning trees into animals allows easier implementation of changing states. Trees will yield wood as resources, but only after cutting them. So first we're looking at a stationary unit and when it dies, it'll change into a resource object that has an animation and all the stuff we expect from resources. This is how it now looks.


The other thing I've been working on is trying to have the guy to the left have any say in the fall of the tree. The aim is to allow the unit to interact with the tree and then cut it. There are some different kinds of objects to interact with which will all need slightly different ways to do so. for instance, there's the ground and if you right click there with a unit selected, you order the unit to go there. If you right click on a building you own, you move the guy to the edge of the building and see if the building has any interaction of its own, like healing the unit or fortifying the building. If you right click on an enemy unit, you run to it and attack it. And if you right click an tree, you go towards it and start dealing damage.

In theory, this all works fine, but somehow I experience problems having the BigBookBasic script  find out what kind of object it is. Apart from the ground, all clickable objects derive from a WorldObject class, for now in this way:
  • Building
  • IncompleteBuildings
  • Units
  • Resources
All of these could have different members. A Barracks and a Wall are both buildings, A Worker and a Warrior are units and Rocks and Berry Bushes are resources. Further, Units could be animals too. BigBookBasic will need to find out what kind of object we're looking at a a certain moment. Well, that does not yet work. I'm sure I'll figure it our, but not today and I'm also sure that I need to figure it out soon, because it's central to give units the information they need to decide what to do with an order. In other words, I think this part of the program is what will turn it into a game. 

When I get this to work, there'll be some refactoring needed, because I have some scripts, like the gather script, that do work, but it a roundabout way and I have different variables to track target unit, building, resource and "object" for units. I want them in one variable. For that I made a small class to store both the object itself and some information on it. This class will be the main focus in interactions between objects.

In short, the trees do fall and turn into resources. I cheated, because you see the health bar decrease, but that's just because I added some testing code. Sneak preview perhaps, or will I delete it later?


    protected override void Update()
    {
        if (Input.GetKeyDown(KeyCode.T))
        {
            DamageHealth(10);
        }
        base.Update();
    }

Tuesday, 23 July 2019

G.O.A.T. of goats

Ha! Did you get the pun? The goat. Greatest Of All Time. I just needed to make that joke. It's not Lionel Messi or Cristiano Ronaldo or even Kanye West or whatever he needs to be called nowadays.  The goat is either Peter Sagan or my goat objects.

Last post I told you that I wanted my goat script to have an overhaul and I did do that this morning while my wife was still asleep. I made a new class, an Animal class. Animals are objects that start as some sort of unit and turn into a resource once they die. Probably, I'll turn trees into animals too, because you first need to cut them before they bring resources. Biologists, don't worry, because I know that trees are plants and not animals.

Anyway goats are now animals.  It's official.  They run around randomly,  being just a bit slower than the humans. I have a piece of code that I'll delete later. When I press M, all goats get 10 damage. Biologists should know that goats has 50 hit points, so after 5 times,  it's gone.

Once the goat has gone where we can't follow, it's replaced by a  "dead goat" object, just like we all will have that happen to us.  A dead goat is a resources for food.

Workers will be able to gather that, but be quick,  because I added a rot timer to resources.  A rock will not quickly deplete on its own, but the weather is great here, so animals will. Every 5 seconds,  one piece of food will vanish from the dead goat.

Well, that works. I'm now sitting in the back yard again, soaking up the sun. I'll be working on the game again soon, probably turning trees into animals. I think I'll have the combat system soon.

Saturday, 20 July 2019

The action and the goat

So, back from my two weeks holiday to Santorini with my wife and back to programming in another week of before the office seems to need me again. I made two things in Holocene work. One is a UI thing and the other is a game mechanic.

The UI thing is about getting tooltips for when the mouse cursor hovers over an object or a UI element. For now I wanted two kinds of tooltips to be possible: Object tooltips and action tooltips. Object tooltips are actually pretty straightforward and they were easy to implement. Whenever the mouse hovers over an object, I use the same system that helps me detect objects to be able to select them by clicking. That system will trigger a little GUI panel with some information about the object.

The second thing was more difficult. Actions are not physical things, just GUI elements. This means that I could not use the system I use for detecting objects. I tried to use events on the button for running the actions, but that did not work, because the buttons are rebuilt all the time, making the tooltip flash on and off, because it detects there's nothing that we point to. This took some time to fix, because I needed to work with an unfamiliar concept: a graphics raycast. How could I know that existed?

With a graphics raycast, I detect there is a couple of UI elements below the mouse pointer. In that list, I find the relevant one (a panel with action information). That element contains a script that controle the contents anyway. All I have to do is show that action on the tooltip and reset a counter. This counter is to make sure that the tooltip will only vanish when no panel has been detected for at least 0.5 seconds. No flashing then.


The gameplay thing is more interesting, I think. A worldobject in Holocene can be an incomplete building, a building, a unit or a resource. I wanted to have composite ones. For that, I made a goat, because you need goats. A goat is a unit, controlled by a non-human player, "Environment". It has some behaviour, running around from random place to random place. When it dies, it turns into a resource to be gathered. Gathering goat resources (food) will work exactly the same as gathering wood. Now, I'm writing this thing down and explaining it to my miniature greek helmet doubling as a rubber duck, I think I need some more thought here...


I think I'll make a new Animal class to inherit from Unit and that adds a slot for a prefab for a new Resource for once it dies. Animals always die to become a resource, at least that's the idea. I'll have to give some information to the player for the tooltip and selected object bar to show how much resources the animal will yield. That sounds better than my current disabling of components in the same object. Dead animals will look and behave different anyway, so why not make a better one.  Sorry if this does not make sense, but right now, I know what I mean!

Thursday, 4 July 2019

Builders gonna build

Here we are again, in the bus to the office. Time to discuss the progress of Holocene. I did not have too much time for development because I was busy with all kinds of things, but yesterday I had a full evening to spend.

I spent it on some unplanned refactoring and work on the building mechanics. What I wanted to achieve was:

  • Buildings get built by workers interacting with them.
  • More workers mean quicker building.
  • The worker performing the initial building placement action will start building it immediately after placing the object.
  • Once the building is finished,  involved workers will look for another project to work on in their vicinity. 
This all looks quite straightforward, but it brought to light a thinking error in the planning of classes and inheritance. What I have is a structure of WorldObjects. A worldobject is a unit, a  building,  an incomplete building or a resource. These things all inherited from worldobject  because they share a lot, like name, sprite, UI etc.

Now the thinking error occurs one level deeper. Units. There are many kinds of units planned. What I tried to do is make a class for gatherers,  inheriting from Unit. Another one would be builder. This would work, under one condition: it should be either-or. 

That did not turn out to be like this. With a worker being both a gatherer and a builder, it ended up with two names, healths, sprites etc. I haven't seen it causing  problems yet, but I like my objects well-structured, so I started working on my temporary solution.

I now have a worker class, deriving from Unit. That does the job. I do want to replace it by a sort of component system. All building mechanics will go to a dedicated class, so I can have other kinds of unitshelp building without having to copy code. I did not implement it yet, because of time constraints,  but I'll go that way.

Back to the mechanics.  With the extended worker script in place, I got the above aims working. I did not yet test the searching for nearby incomplete buildings yet, but that'll be ok. I can now have builders build.

Three more issues I found:
  • When a building is placed, it did not update the nav mesh. I fixed that by a navmesh obstacle component with Carve turned on.
  • When I drag the building around the screen before placing it, it'll wipe away objects like units. I'll need the collider of the object be trigger so I can prevent that while still getting collision detection to work. We do not need buildings on top of other objects besides the ground.
  • There's a thing with selection when the incomplete building is finally replaced by the complete one. I'll have to look at that one.
Now, the bus is almost there. My last office day before going off to Greece after the weekend. Have a nice day!

Tuesday, 2 July 2019

Gamification of the world

No game development for me today. Usually my wife gets to watch tv while I have the computer, but tonight is different. Next week, we'll be in Santorini for our two week holiday and my wife likes the pre-fun of finding out what fun there is on that island, so she's at the computer and I am writing this post on my phone.

Now that the US beat England in womens football and the dutch will face Sweden tomorrow (and NAC had an exhibition game today) I'm just sitting on our sofa overthinking the last couple of days. While there's a lot that I will not bother you with, there's some gamedev related stuff that might be interesting.

A couple of days ago, someone on Twitter asked me if he should turn game developer full time at the age of 16 and I think he should not.  Now I am biased because my passion is for history over game development.  The thing is, though, it's not a zero sum game between seeing things and making games. In fact, I think a broader education and set of experiences will inevitably make you a better game maker.

History is my thing, so that'll always be a main focus for me. And history is a very potent source of storytelling and ideation for games.  For instance, build a game where you are a senator in Rome and you try to survive the dog-eat-dog world. Or you are a general facing the nazis. You're Genghis Khan and your sons are rebelling. Endless opportunities.

I'm not an expert so don't take my word for it,  but I think turning a narrative person helps getting ideas and as a solo indie developer, ideas are important.  All of us can program or are well on our way and most of us can find an art style to suit our needs,  but ideas, cheap as they often are, do make us better game makers in the broader sense.  The best way to get ideas, I think,  is to tap the systems in everything around you, past, present and future.

It does not have to be anything big. It does not have to be profound.  Funny thing is that almost everything can turn into a game idea if you look. Talk about gamification of the world!