Byte Wrangler

Nov 19, 2016

As part of my attempt to get my project back on track I decided to limit the scope of each snapshot. In the past I'd planned for 6-8 week development cyles, which (due to lack of discipline) wound up overrunning and being more like 12+ weeks. This time round I tried to restrict myself to just 2 weeks. I ran into some unexpected hurdles that pushed that time out a bit, but S14 came in at just over 3 weeks. Hurrah!

What did I achieve in Snapshot 14?

About half the time was spent on refactoring and improving existing code. I've learnt a great deal about writing better code in the last year, and there's plenty of poorly thought out design in my codebase. This is a legacy of the fact that I'm a much better developer now than when I started the project 6 years ago.

I made good on my promise to start building parts of the system which are essential for the game to be releasable. Eg: the ability for the player to die.

(work in progress)

Starvation and Dehydration are now actual threats in the game. The way it works is as follows: Living creatures have health, food and water stats. Creatures will be able to consume food or drink that will instantly affect their food or water levels, but health can only be regenerated naturally.

The player's health, water and food display

While alive, creatures consume food and water. These rates are dependant on factors such as the activity level of the creature and the ambient temperature. Once the creature runs out of one of the resources, the amount consumed (plus a penalty) is instead taken from the creature's health.

I'm still tuning the rate at which it occurs, but for a player at full health its something like 2 days without water or 5 days without food before death occurs. Obviously if you're already injured and you're out of both food and water it's going to be considerably shorter.

I'm hoping to make the game less about combat and more about other interactions, such as exploration, negotiation, stealth etc. Since you can't instantly regenerate health, the way players approach combat will need to be more tactical. eg: Taking an enemy by surprise and knowing when to retreat. In addition, NPC's will be less likely to resort to deadly violence unless desperate as they value their lives and the lives of their families.

What's in store for Snapshot 15?

Next I'm going to expand the eating and drinking system to include food and water borne illnesses, such as eating uncooked meat or drinking contaminated water. Also on the agenda will be the ability to save and load the game. Most of the code is already in place to serialise and deserialise the gamestate, however its not being persisted to disk yet.

It's not a huge amount of effort, which is probably why I've put it off, but its essential for Release Ready status. As previously stated my plan is to drag the game up to a point where I can start making test builds publicly available. Its quite a way off, but at least I'm now heading in that direction!

Nov 7, 2016

So, as previously mentioned I've spent the last few weeks refactoring my codebase to remove ugly static references. I also improved the design of a few important modules, and overall I think the results are very positive. There's still a bit of work to do in this area, but the parts involved I've planned to completely rewrite in the future anyway, so I'm comfortable leaving some ugly code in there for the short to medium term. Note to future Chris: hahahahaha suck it!

What's next? Addressing the lack of focus on the important elements of a survival game. For example, being able to die. In the early game there are 3 big threats to survival ; Lack of shelter, lack of water and lack of food.

Shelter

The most critical factor is shelter. Humans can survive several days without water and a week without food, but extremes of temperature can kill you in hours. Staying cool in the heat and warm and dry in the cold will be vitally important if you expect to survive.

The easiest way to shelter from the elements will be to find a natural cave or a ruined building. In some cases you may have to clear out its existing inhabitants first. If such a shelter is not available, the player may have to construct something.

The simplest structures the player can build will be little more than a few strategically arranged tree branches. This will stop light rain and give the player some shade from the sun, but they are fragile and will be easily destroyed by moderate winds. Since they only provide partial protection from the chilling effects of wind, a campfire will be essential for surviving the night.

Once the player gains access to better materials and tools they will be able to build more permanent structures such as huts that will also keep in warmth and provide protection from other threats such as wild animals.

Clothing will also influence your ability to stay warm. Being caught in the rain or falling into water is a nuisance when you live in suburbia and can pop home to change your clothing, but in a survival situation it can be fatal. Better find somewhere to get out of the rain and get a campfire lit before the chilling effects sap your strength.

Water

Lack of water is the next most critical survival factor. Depending on the weather and exertion levels, humans need somewhere between 2 and 5 litres of water a day. Once the player has a shelter sorted out, finding (and maintaining) a source of fresh water will be the player's most pressing daily need.

In the early game the player may be scavenging water from whatever sources they can. If the player is lucky it will be a freely flowing river. If not, it may be a stagnant muddy pool with any number of pathogens lurking within.

Recognising if a source of water is safe to drink will be a vital skill. Contracting a water borne illness will only accelerate your dehydration and leave you vulnerable to other afflictions. The safest option will be to boil your drinking water, but this may not be possible if the player can't find a suitable container or a way to start a fire.

Food

Food is the final factor. There is less urgency to this one, but it cannot be ignored completely. There will be many food sources available to the player depending on their skill level. In the early game it will be edible plants and less palatable options such as insects. This will only get the player so far though. If the player wants to survive long term, fishing, hunting and trapping will provide improved sources of food if the player has the necessary skills and equipment.

As with water, food borne illness will be constant threat, so avoid spoiled food and cook things prior to eating.

Final Thoughts

In reality if you're in trouble you'll probably die from a combination of these factors.

Without food you may lack the energy to build a shelter. Without shelter your hands may become numb with cold and you're unable to start a fire. Without fire you shiver through the cold night and are unable to boil your drinking water before consumption.

Your thirst has been quenched, but you're exhausted from lack of food. You're approaching the beginnings of hypothermia and you've just started having stomch cramps, nausea, vomiting and dizziness.

Oct 9, 2016

So in my previous post I discussed how I had returned to this project after a 7 month hiatus. To get back on track I decided to do a bit of code spring-cleaning. Its actually spring here in the southern hemisphere, so it seems appropriate.

Before beginning work again on the game proper, one of the aspects I wanted to improve was the testability of the codebase and eliminate the global references that have spread through the codebase like cancer. Note: my codebase is written in C# in which global objects are defined as "static", so where I say "static", it's the same as global.

First step; make the static classes instantiable!

It turns out that I converted my EntityManager class to not be static at some point, so that was a huge advantage. However, it is created once, early in the life-cycle of the application and is stored in a global that is referenced throughout the app... bugger... about 500 times... double bugger.

Also I have a mixture of local server and client code that refers to the same references but use them in different ways, and some references that use [ThreadStatic] as a workaround to correct problems where different threads needs different versions of the same object. Truly the stuff of nightmares!

Because of that I'd written some truly horrific unit tests that had to start up most of the game engine in order to test something simple like the serialisation of a component. Seemed like an excellent place to start my clean up!

Dependencies to the rescue!

I refactored a lot of code to accept an IEntityManager instead of using the global reference, and over time my unit tests cleaned up considerably. I applied the same logic to other manager objects and eventually my unit tests became completely independent of the rest of the codebase, relying on mocked versions of the important managers, injected as dependencies.

I continued this initiative and carried it over to other globals, and I've managed to completely remove some of the references entirely. The client and server code is now safely segregated and the ThreadStatics have been removed.

The aforementioned EntityManager global still has 200 references to it, but that's a great improvement on the 500+ that were there when I started this effort. Furthermore, the AssetTemplateManager is down from over 100 to just 27 references. There's still some way to go - the target is to remove all global references..

So, lessons to be learnt here? Static/Global references are bad and once introduced to your codebase they tend to spread unchecked. I've been working on this codebase for over 5 years, and I've learnt a great deal about C# and development in general during that time. Anything in the project older than a year makes me cringe, and there's stuff still in use that was bedded down in the first few months of the project. I had no idea about dependency injection or why global references were a bad idea, and now I've seen the error of my ways.

On a side note, I've discovered that Squarepusher is great for refactoring!

Sep 23, 2016

Where to begin? Not long after my last post, development on Bulldog stalled badly. I had a few other game ideas kicking around and after some soul searching I decided to put Bulldog on the backburner for a while and start developing one of the more promising (and less ambitious!) ones. I made some good progress, and even trialled some changes to my development process.

At my day job as a developer we've been transitioning over to a Test Driven Development process. I've embraced a lot of these ideas, such as Dependency Injection and Mocking for my part-time games development. Its really shown me where I went very wrong with Bulldog's development from the outset.

Now, fast forward 6 months or so and I'm about to abandon the new project, (code-named "Collie") and switch back to Bulldog again. What the hell?!

This is for several reasons:

My design for Collie isn't really mature enough.

While working on Collie, I never stopped thinking about Bulldog, and kept coming up with cool new ideas for it, which suggests to me that my subconscious really wants to build that game, not Collie.

I've hit a bit of a wall and can't find motivation to continue on Collie at the moment. Perhaps related to #2?

So... you wasted seven months?

Not exactly. Working on a new code base, it really illustrated to me the problems I was living with in Bulldog, and as mentioned earlier, I can really see where I've gone wrong with singletons and statics all over the place.

I'm excited about getting Bulldog back on track again, and have great plans for resuming development and refactoring the codebase to correct my previous mistakes that prevent proper unit testing etc.

I've also learnt a lot about focusing on the value of new features, and developing the most crucial things first, not the coolest or hardest ones.

On this note, I came to the shocking realisation recently that Bulldog is at its core supposed to be a survival game, but after 5 years of development, I haven't coded the ability for the player to die yet! I've got procedurally generated terrain, real time shadows, pathfinding, a custom UI, status effects, loot tables etc. But if the player's health hits 0, the game locks up. What the hell?!

So yeah, I'm coming back to the project with a healthy dose of "What the hell was I thinking?", a fresh perspective, some new development skills and a renewed passion for making this game.