Still Reading

Progress on QubeKwest stalled a little bit here recently due to a lot of reading and an otherwise busy schedule. I got really amped up working on the core game engine concepts, and then started to get a little worried that I may be making a horrible decision somewhere in the process. This resulted in still more reading. This time, the book du jour is an absolute monster of a tome called Game Engine Architecture: Third Edition by Jason Gregory. I already own, but only made a cursory pass at reading, the Second Edition of the same book. When I noticed there was a new one I picked it up because I wanted to make sure my efforts at reading a book of this magnitude were spent on the most up to date information possible.

In case I haven’t made it obvious yet, this book is gigantic. The introduction actually states that it is designed to be the textbook for a series of three college courses about game architecture. I’m plugging my way through it and getting a bit twitchy that I’m not actually coding, but in this case, I figure it’s a good idea to make sure my decisions are well informed since it is extremely likely to be devastating to the project to have to fundamentally change some large part of the core game engine thanks to a poor choice.

I’ve been reading it for a bit, I’ve got a long way to go, and I thankfully haven’t found any choices I’ve made to be bad. This is good news and may lead me to finally writing the Vulkan boilerplate initialization code.

Historical Detour

As I’ve been up to my eyeballs in engine coding for QubeKwest I began to wax nostalgic. This led to conversations with people about old game engines, which in turn led to the purchase of a series of interrelated books, which in turn led to reading them. Really nothing about this pattern is especially odd, but it is rather impressively distracting. I think I was primed and ready for a distraction that prevented me from writing over 1000 lines of Vulkan boilerplate setup code and these books provided that perfectly.

The journey through history started with the Game Engine Black Book: Wolfenstein 3D by Fabien Sanglard. This book was very hard for me to put down as I grew up with the computers that were described in the book (386 CPUs running DOS on practically no RAM) and Wolfenstein 3D was the first FPS I’d ever played. All told this book only took me about 3 day to plow through cover to cover. There’s a fair bit of code, a lot of helpful diagrams, and tons of screenshots. (In other words, I recommend getting the paper version of this book instead of a digital form.)

Once I was done with that game engine, I was on to the next one made by the same guys at id software. The Doom engine was my personal favorite growing up. It was so immersive and killing hordes of demons was more varied and entertaining than killing enemy soldiers. This led me directly into the Game Engine Black Book: Doom also by Fabien Sanglard. This one was about other computers I had growing up (486 CPUs, still running DOS, and barely more RAM) and the guts of how a BSP (binary space partition) based game engine works. There was a ton of interesting information in this one about porting Doom to other platforms too. Most should never have had a port of Doom, but it was interesting none-the-less. This one was a bit longer and took me about a week to read through.

Having now become completely fascinated with the guys that started id Software and the game engines they created, I took a step further back in time and picked up Masters of Doom: How Two Guys Created an Empire and Transformed Pop Culture by David Kushner, which drops the coding side of the story in favor of the story of the people that created it. This book is far older than either of the earlier two I mentioned, and it’s an inspiring read of how a couple of scrappy kids eventually went on to make a ton of money and mostly have fun doing it. I’m still reading my way through this one, and the guys (as I’ve come to refer to them) have put out Commander Keen, Wolfenstein 3D, and Spear of Destiny and are just getting ramped up on making Doom.

All this reading spun off a temporary side project to see if I could write my own version of the Wolfenstein 3D engine from scratch in JavaScript. After a weekend of working on it, I had the ability to walk around in a place with texture mapped walls. I was proud of what I’d done, so I took a bit of time to add a 2D overhead map that updates with what the rays looked like that were cast to produce the 3D view and tracked the player as they wandered around. Next I tried to make objects (like lamps and tables and bowls of dog food) and while I did manage to get my raycasting method to work as a recursive algorithm to allow mostly transparent objects, I never did quite get them to show up properly. I also never tried to make doors, elevator switches, or secret push blocks, but I considered what I’d made in a weekend as “good enough” for a distraction and called it as done as I was likely to make it. At least for the time being.

With a lot of reading and a side project mostly behind me at this point, I’m back to where I get to climb that mountain of Vulkan boilerplate setup code. I’m not sure how much fun it’ll be to write, but it is definitely all new to me, so there’s something to be said for that.

Graphics Engine

I’m writing my graphics engine, again. I was probably supposed to be writing tests for my on-going code audit, but they are boring and I don’t want to right now. (So there.) The alternative path I’m following is to start over with my graphics engine coding. This has resulted in a handful of changes.

First, the entire previous attempt at an OpenGL based graphics engine has been balled up and thrown into the temporary package com.qubekwest.graphics.old so I can use it for reference, but where it doesn’t get confusingly mixed in with the new stuff I’m writing. Second, I have switched entirely to Vulkan (from OpenGL) for my graphics library of choice. That decision comes with some serious baggage.

Vulkan offers a lot of cool things that make it better (in my opinion) than OpenGL. Some of these things make it faster and more powerful. Such as the all new way of telling the video card what to do from a multithreaded environment. This lets you use as many CPUs as your computer can throw at it without them getting in each other’s way. Another thing makes it vastly harder to learn. To give developers more control over how things work in Vulkan, they well, gave developers more control over how things work. To accomplish this, they make most of the things you want to do take way more steps than they used to. Finally, Vulkan comes with some fun things that make it require newer hardware (and/or newer drivers) than OpenGL. This one means Raspberry Pi is just not a valid development target anymore. At least not models 1B through 3B+, maybe the 4 will have Vulkan capable hardware.

I’m trying to build the concept of a graphics engine as cleanly as possible and in a way that would let me implement a second one in OpenGL in the future if I want. There are some decisions I’m trying to make as I go that I’m almost positive will be just flat wrong because I made them before I understood enough of what I was trying to do for real. Thus is the side effect of the learning curve I figure.

There are lots of semi-related things that go with this, such as the management of the main game loop and of accepting user input. Admittedly they are mostly only related because GLFW (Graphics Library Framework) includes stuff for creating windows, accepting input, and managing the game loop. I am likely to use all of those things, but I haven’t figured out if I’m going to call them all part of the “Graphics Engine” I’m building or treat them as separate entities glued together into a “Game Engine” or something. I guess we’ll see.

Code Audit (Round 2)

The code base has come a long way since my last code audit, and worse, I got lazy and never really finished the last one properly.  There are more sub-packages in the data package than there used to be, there are more classes in the math package, and in general just more.  Since the last time, Google Sheets finally added support for making text in a cell conveniently crooked, that’s helped too.  Now I get to track my progress in a spreadsheet instead of on hand labeled sheets of graph paper in my notebook.

This is actually a bit handy since I haven’t touched the code in nearly a year and I really need to relearn what I was doing in the code before I stopped.  I’m actually almost completely done with the code portion of the audit (added around 3500 lines of code) and I’ll be moving on to auditing the tests and coverage next.  I’m not going to lie, this process is tedious and boring, but I’m still feeling rather motivated to do it as I gear up for another big graphics push toward getting a cube on the screen.

Calendar Adjustments

As I ramp up my work on the project again, I am reading over and relearning a lot of code.  Today I got to the GameCalendar class and remembered that I had a bunch of changes I wanted to make before I’d stopped work on QubeKwest.  What I wasn’t sure of exactly, was what changes I wanted to make.  After a bit of consideration followed by a bunch of coding, here’s the things I’ve changed.

Tracking game ticks was a pointless complexity for the calendar system.  Thus it was removed and that of course means that the math ticks added into the calendar was removed too.  This makes several parts of the calendar easier to calculate and it also means that the internal workings of advancing the time for the calendar now only needs to happen roughly 1/53rd as often.  It’s not a lot of overhead, but I’ll take it.

Days were too short.  My brother and I have played a bit of Minecraft lately and been repeatedly frustrated by how short the days are.  While I’d already build days to be longer than they were in Minecraft, I decided I wanted to make them even longer, and a bit more asymmetrical in favor of daylight.  This table demonstrates what I’m talking about:

Part of Day   Minecraft   QK (Old)   QK (New)
-------------------------------------------------
Day            10 min     16 min     40 min      
Dusk          1.5 min      3 min      4 min
Night           7 min     10 min     12 min
Dawn          1.5 min      3 min      4 min
-------------------------------------------------
Total          20 min     32 min     60 min

This change adjusted how the game represents the current “wall clock time.”  In simple terms, the math is different for deciding what time of day it is.  The game will still represent the clock as a 24 hour clock of 60 minutes in each hour.  The length of a minute in the game has just increased.  (Now 2.5 seconds each.)

Seasons were too short.  Due to the length of months (16 days) it seemed incorrect to have seasons be only 2 months long.  Thus, I’ve changed to a 16 month calendar.  Now each of the 4 seasons is 4 months long.  I haven’t come up with names for any of the months, and I’m not even sure if I’m going to bother.

Moon phases still line up in the months the same way they did before.  This is because neither the length of a month nor the number of moon phases there are have been changed.  It doesn’t sound like a lot, but I was thankful for this break in the sweeping changes I was making.

Due to the collected changes, the timestamp format was adjusted to have a second digit for the day of the month. The resulting format is:

hh:mm YYYY-MM-DD

Calculating this was simplified by the removal of game ticks from the calendar, but it was an almost total rewrite for this method to accommodate that adjustment.  The best part is that the wall clock time and the timestamp are no longer only approximate values.  Since I now only track down to the minute level, the number of minutes involved is always exactly known.  No rounding errors any more.

Last but not least, the collection of constants used by the calendar were updated in both name and value to make using them a little cleaner.  It’s been a fun day that involved drawing in my notebook, coding, and correcting tests that I blew up with all these changes, but I’m also glad it’s all set now.