Monday, December 31, 2018

battleMETAL - Why that was a bad idea, a terrible idea - Part 6 - Game Logic

A series of events;
 
    An important part of any game is level design and the game play loop of the level. One of the reasons I chose Quake / Darkplaces is because of how mod-friendly the map making process is...and how well documented it is. Back in my high school days, before learning to code, I had dabbled with making maps for Quake II. iD Tech games all generally used a tool called GTKRadiant for level creation, this was an all-in-one map maker for their games. The tool allowed users to created the full 3D spaces of a Quake level, place map objects like weapons, monsters, and player start zones. It also is where the logic of a map was created. These logic map objects were under sections called trigger_ and func_. They are responsible for making doors that move, elevators, changing maps, etc.


    There’s an old joke about iD games using the map design called a ‘monster closet.’ A monster closet is a part of the map where, behind a seemingly normal piece of wall, a monster or two is just sitting there. When the player gets close, or triggers a specific event, the wall opens up surprising the player and dropping monsters on them. This is a joke because if you look at the wall, it doesn’t look like it should logically have any space behind it and what exactly were the monsters doing behind the wall? Taking a smoke break?


    For this article, let’s focus on the how of the monster closet. The user in GTKRadiant would create a space behind the wall. They would place monster entities into that space. Next they’d turn the ‘normal’ wall piece into a door. The door, like the monsters, is another entity. Rather than relying on a specified model though, the door entity uses the map geometry its assigned as its model. Then the map designer would create another map object; trigger_once, point it to the ‘wall’. The Quake C would then say, “when the player entity touches trigger_once, open the door.” In this regard, we can say that the map file holds a lot of the game state and logic. 


    I believed that at least for map design and creation, Quake was a good move. Creating custom entities that the editor can place was fairly straightforward. GTKRadiant uses a text file to define all the possible map entities that can be placed before compiling the map into a format that Quake can read. By adding my own battleMETAL objects to this text file, I found it was easier to create maps specifically for battleMETAL - including the really cool aspects like Nav Points and Objectives ( we’ll get to those in a bit). Unlike AI which I covered previously, the map logic schema for Quake is surprisingly flexible. The map editor GTKRadiant uses a series of ‘definition’ files containing text, usually called entities.def. This file contains the definitions for entities to be placed on the map.


    The definitions must link to function names in the Quake C code. For example, the definition for an enemy AI looks like this in the .def file:
   
/*QUAKED unit_human_mech_sniper (1 0 0) (-14 -14 -20) (14 14 20) <spawn flags>
        <description text here>
    */
   
    The “QUAKED” is the head tag for an entity definition, the next piece is the function name “unit_human_mech_sniper” which should be defined in the Quake C code exactly the same wording. From what I can tell, the map compiles the entities and converts the function name either to a reference or compares the function name to all the functions in the code to find a match. Once the game finds the right function, it creates an entity and then calls this function on that entity. Whatever code is written in unit_human_mech_sniper is then run immediately.

    The next series of arguments are as follows: color in GTKRadiant, and the bounding box size. The color is for color coding the entity in the map editor, making it easier to tell entities apart from each other. As for bounding box size, that is also shown in the editor, but will also be passed to the engine when the entity is spawned. Quake C code can override the bounding boxes if it is needed. Spawnflags are an important piece of data for both the editor and the engine. Flags are a data storage concept used in general coding. They hold a series of “yes or no” sets in a single variable usually by using binary math. For our purposes here, every entity has a spawnflags field which can set up certain “yes or no” choices when the entity is created. The exact wording is up to the coder, so one entity might have DROP_TO_FLOOR for a spawnflag while another has START_INACTIVE.  The map editor will render these as checkboxes.


    Finally there’s a the descriptor section, it is here that normal text will be rendered in the map editor but has no relation to code in the game. This section is for any relevant info about creating, placing , and using a map entity. Altogether this system is fairly easy to understand and extend for modding. Debugging is nice as well, if engine can’t parse the entity from the map, it simply removes the entry and logs the result into the console.


    Now that we have context for the maps, we can do quick overview of the game logic itself. Every gameplay instance in Quake takes place on one of these maps files. The map is loaded up when the server switches to the desired map file. In Quake C this before  the Main() function is run, the main is the entry function for the Quake C. StartFrame() is any code you want to run before the engine runs all other code in that slice of server time. From here the game instance if open-ended, where the ‘end’ of a map can be determined in a few different ways. Vanilla Quake used round timers, kill counts, and map entities to end a game instance and load the next map. For battleMETAL I needed something a bit more sophisticated, seeing as how the game is descended from different DNA.


    battleMETAL is inspired by mech sims, in which part of the simulation was of more authentic military scenarios. This meant that the player is given a set number of ‘objectives’ to achieve before the scenario is ended. The objectives sometimes were destroying things, but other times it was just visiting a location on the map or protecting a base of buildings from an attacking enemy. So, to achieve a similar setup as I created some custom map objects - the Objective, and the Nav Point. I also extended the game engine to load in a text file called a “mission file.” The world map entity would have a variable that pointed to a specified mission file that was loaded to the player’s view when they connect to a map. The code I wrote also sends a unique objective ID for each objective on the map. This is linked to a list of objectives in the mission file. Together, they communicate objectives to the player both during the briefing and game play.


    Of all the things I found to be difficult with battleMETAL, this was surprisingly not one of those things. The configuration of GTKRadiant is fairly well documented and extending the functionality of making maps for my specific game turned out to not be a lovecraftian nightmare, unlike other parts of the project….well except for those 3D terrain meshes…<sigh>.

Wednesday, December 12, 2018

battleMETAL - Why that was a bad idea, a terrible idea - Part 5 - AI deux

Ah, that army...well played.

    Now that we have some context about how the Quake AI code works, we can look into why it was a no-go for battleMETAL. The first hiccup is how battleMETAL builds its AI entities. Like the player, AI entities are built using the same factory pattern code. The entity is actually a bunch of entities strung together - things like torsos, arms….legs. battleMETAL units are not animated as a complete distinct model. Because they are collection of parts, each part has its own animation. This breaks the original Quake C architecture and its reliance on the frame macros (as was explained in the last post).


    The unit piece with the most animation was the leg entity for mechs. However, the animations for the legs are not authoritative to other entity states. Therefore most code hooked up to leg frame animations is not decisive, but rather cosmetic; reacting to game events as they happen. Just having this one attached entity threw off the need for using Quake frame macros. A different solution was needed, and that was using a state machine. State machines are abstract computer designs that describe a series of ‘states’ for an arbitrary object. An AI object is a good candidate for state machines, where the state in the state machine could be a set of behavior or actions that the AI performs.


    Mind you, this was after a few other attempts to split the difference with Quake’s original AI implementation. The original code also had a set of generic AI behaviors that most monsters would invoke in about the same sequence. There existed functions like ai_walk, ai_run and so on, these were called on a per-frame basis and packed into a frame macro for the monsters. Additionally, other functions were used by the AI during gameplay to assist in calculating attacks, spotting the player, and moving around defined node entities.


    All of this existing functionality was put off to the side, to be reworked into the new AI design. Using a state machine, I broke down almost all the possible actions that an AI could take into 2 categories - states, and actions. I then declared a state to be a collection of actions. I credit my cousin Eamonn with the idea of making actions were atomic as possible ie each action as a function call would only do 1 specific thing. For example, the walk state would be the following actions:
    Scan for enemy
    Move to patrol node

 
And that would be just the walk state. If the AI spotted a valid target in Scan For Enemy, the the AI would transition to the Run state. The code marks each state with an integer, 0 = Walk, 1 = Run. Each entity then has a series of member function pointers to each state like mech.st_walk(). When the AI is created, the code tells the AI which version of of st_walk to use. In the case of mech units, they’d be assigned the mech_walk() function. 


    Then, the AI keeps track of which state it is in by having a variable called .attack_state, when the AI executes its code every frame it looks up which function to run by using its state variable. Once this paradigm was implemented, I took the idea to the next step - organizing collections of states into ‘behaviors’ or ‘unit types’. Tanks and Mechs would clearly need their own sets of state functions because of how different these units are. Using this approach I found it was easy to implement even more unit types like turrets and non-combat vehicles. Each behavior set, although using the same list of actions has their own logical flow for states, and changing the state they are on. The result is a fairly flexible and open-ended design for adding AI and its behavior.


    There are still some limits due to the foundation of this code being on Quake. A big one is AI movement. The Quake C uses an engine function to actually execute the movement of bots and no physics operations are carried out, this results in stiff movement of bots that doesn’t really look natural. This also results in bots running more slowly during gameplay, their per-frame updates are less because of how proportionally expensive it is for the game engine to move bots. In the end I’m ok with the outcome of the AI, despite its limitations I was able to add a few diverse unit types to the game. This diversity helped make the game more fun and engaging to play.


Monday, December 10, 2018

battleMETAL - Why that was a bad idea, a terrible idea - Part 4 - AI

Oh yeah? You and what army?
Another tarpit that consumed many months of dev time during this project was the AI. Quake was never known for its AI, which was only ever serviceable. The problem was thinking that the AI was extensible for the needs of battleMETAL. Quake AI is good enough for ‘basic’ FPS games. The code available allows for AI that can follow defined paths, attack and ‘fight’ with the player, and some limited hunting routines. All of this code is laid out in a few generic functions available to all AI and any monster-specific code is defined in that monster’s code file. Quake monsters are fairly capable of engaging the player in the tighter, more confined environments that Quake uses (big surprise). However I estimated that expanding level geometry size would not have had a great impact on the AI code, not realizing just how tightly engineered the AI code was.

The first wrinkle encountered was one part of how the AI code is implemented in Quake itself. Quake C functionality sits atop the C code of the engine, with limited access to engine-level code (by design). This equates to the Quake C doing the bulk of the AI work here. This means that AI execution is a tad slower due to the nature of Quake C being a parsed language versus running straight C code. I accepted these limitations due to lack of foresight and with the mistaken assumption that I could reuse a lot of the original code.

First hurdle turned out to be understanding the way the AI code was written. For example, in the m_grunt we see the following function:

                   void() army_stand1 [ $stand1, army_stand2 ] { ai_stand(); };

For me, that looked really wierd, and I had not encountered similar code in the project other than some simple animations for sprites. Let’s break this one down; what we’re looking at is a code macro. Code macros are like syntactic sugar, which is lingo for ‘shorthand’. Much like other abstract languages, such as math, have shorthand notations when writing large segments and code can also have shorthand. Most of the code shorthand is usually already baked into the language syntax itself, such as var foo = a_value. This is shorthand for the computer assigning the value a_value to the variable foo.

But what if you found yourself writing the same code many times, and would rather reduce this code to a simpler syntax? This is where macros come in. Macros can be user-defined, and customized according to the needs of the programmer. For Quake C, iD created the macro I mentioned earlier, for use with animations being synchronized to game code. Originally the animation frame rate was tied to the game’s frame rate, mostly because computing power was very limited back in 1996. It didn’t matter that the animation was tied to the game’s update rate because usually that update rate didn’t surpass 20FPS on most systems. The second part was tying game code to the animations themselves; what should happen when the Frame X of the animation is played?

So looking back to the example macro, this is what it means

        Army_stand1 is a function definition.

         The [ and ] are part of the Frame macro, this has 2 arguments, the frame number of the current frame and the next function to go to.

         $stand1 is the frame number of the first frame of the ‘stand’ animation.

         Army_stand2 is the name of the function that should be executed next after this function( army_stand1 )
 

        The { and } then define the function body for army_stand1, what code should be executed on this frame.

When dealing with models that have dozens of frames and multiple sets of animations, this is a clever way of organizing the overall flow of the entity’s animation and code. Knowing the schema for the macro, you can now read through a model’s game logic quickly and easily. There is a cost however.

The macro is more rigid than writing the code out yourself every time. What I mean by this is that the frame macro is laser-focused on solving the animation / code synchronization issue. What happens when I don’t need any code to run on a frame of animation? I still need to define the macro for that frame. This creates a problem at-scale when model animations start reaching the dozens or hundreds of frames. That was the main reason why I, once understanding what the macro does, ditched it in favor of my own approach.


I won’t go into super detail about all the attempts to bring the AI to life - there were 9 major runs of work to arrive at the solution I went with, spread across 3 distinct solutions. The 3rd solution was what ended up working, and even then I have ways it could have been improved. This topic will continue into at least a second post so I can discuss the working solution...

Monday, August 27, 2018

battleMETAL - Why that was a bad idea, a terrible idea - Part 3 - Collision Systems

About those multi-part models


Collision systems a core part of any video game engine. From the first version of Pong up to the latest games on any platform, these systems are responsible for processing impacts between game objects in the game space. In general, like most computer code, collision systems have to be built at some point because a computer does not intrinsically know when two ‘objects’ have hit each other. The complexity of these systems can vary wildly depending on how detailed the game wants to get for collisions and how complicated the game itself is. Quake’s collision system is fairly simple for a 3D FPS.

The collision system for Quake starts with a series of boxes, or specifically, axis-aligned bounding boxes (AABB). Woah there’s some jargon, AABB simply means that the collision model for a game object is a box (technically a rectangle because box proportions can be altered). The axis-aligned part means that this bounding box does not rotate. The model can change angles all it wants, but in the eyes of the collision system, it never rotates - this is an important distinction.

Here we see Quake Guy and his AABB. Whenever Quake Guy hits another entity, or is hit by entity, the game doesn’t check the Quake Guy model for this collision. Instead, the game sees if Quake Guy’s AABB was contacted; which is mathematically simpler and therefore a faster calculation. The downsides to simple AABB is the lack of detail in collision detection, this can be best seen when Quake Guy is standing on a staircase or slope. Notice how only a few corners of the AABB are touching the ground?

Let’s make one quick jump back to the previous post about models, specifically the models that make up a mech in battleMETAL. These entities use a move type called movetype_follow which tells the game to always keep the entity’s center as an offset from a code-defined center in game space. There’s one important detail here, entities with movetype_follow cannot have a collision AABB. As a restriction, this exists because the use-case for movetype_follow is for cosmetic models put on the parent entity - weapons, clothes, etc. For battleMETAL, this means that the various mech parts that are seen on-screen don’t actually have a link to the collision system. Hm, but battleMETAL requires a feature where mechs various parts can be blown off the mech.

The solution implemented is a bit obtuse to manages to satisfy the requirement and still work. The player seen on screen is a heavy composite of several code pieces and models. To start, the player doesn’t actually have a model bound to its entity structure. Rather, the visual components - the mech piece models - are all separate entities using the movetype_follow functionality to appear in the correct location during gameplay. From the perspective of the collisions system however, these pieces are ‘wrapped’ inside the player’s main AABB. When a player is struck by a weapon, the following is executed in the code:

  1. Determine the gamespace location of the hit, this is a 3D vector of X Y Z
  2. Query the gamespace location of every mech piece that the player-being-hit owns.
  3. Find the closest mech piece to the hit origin.
  4. Closest mech piece becomes the area that is ‘hit’.
More modern game engines can execute what is called Per-Poly collision where the gamepsace location of a collision between objects can be focused on the smallest parts of the models themselves. Quake is much more primitive as we have seen. The solution that battleMETAL uses is not the most precise for players, but works surprisingly well in-action. The majority of hits against a target are applied to the correct piece of the mech (if the target is a mech) and battleMETAL uses this multi-part collision detection only in very limited cases. Every weapon strike is a short loop through all the mech parts of the mech target, which can get computationally expensive if a lot of mechs are on screen.

There are some quirks to the written algorithm as well.

  1. Ignores the volume of each model piece on the mech
  2. An imprecision thats hard to detect
  3. Effects on mech design
In the end, this was deemed acceptable if it allowed players to destroy components of mech models in the game. There are several other problems with the collision system being so primitive - such as interactions between moving objects and the terrain models. The 4-point ground detection code can get a bit cagey when trying to detect collisions with a terrain piece that changes its slope too quickly- something like a really bumpy road or rocky area. This necessitated keeping terrain features more simple in their mesh complexity.

Tuesday, August 14, 2018

battleMETAL - Why that was a bad idea, a terrible idea - Part 2 - Model Mishaps

Compromises were made
Models are a good enough place to start about things that went awry. The most complicated models so far in battleMETAL are the star units themselves, the metals. The game requires that certain game units have multiple hit locations that can be destroyed before the entire unit is killed. In the case of the mechs, the locations are the center torso, left and right torsos, left and right arms, and the legs. 5 locations total for every mech unit. To better communicate damage to players, it was decided that arms and torsos should be ‘blown off’ when the health of those areas reach zero. This translates to each mech piece its own disconnect mesh, like a lego piece.

Most FPS games don’t deal with complex vehicles, they are scaled to people-sized players and monsters fighting. The models for each of this units is usually 1 solid, animated mesh. Despite complexity of the model, the fact that model is 1 contiguous piece of geometry makes working with them fairly easy. Having five sub-models that make up one complete mech model gets heavy very quickly. It increases the number of files per game unit, makes coding for game units a bit more complex. More modern game engines can handle this complication using techniques like bone-based modeling. Quake was made slightly before skeletal animation became an industry standard. Half-Life is credited with bringing skeletal animation to the mainstream and Half-Life’s engine is a heavily modified version of the Quake 1 engine.

Darkplaces does allow for skeletal animation but it comes with some severe catches. The quake c code for Darkplaces can utilize bones but only on the client-side. Now why is this a problem? I think I mentioned client-side prediction as an issue in previous posts. The snag with this approach is that the bones are only rendered on the client’s side of the game code. If the bones are only on the client then the location in game-space of those bones becomes an issue due to discrepancies between server and client game states. If Darkplaces came with out-of-the-box client-side prediction for programmers to work with, then this might be less technical debt. As it stands, client-side prediction was left up to the individual coder for some...reason...and not every programmer is up to the task of solving a such a complex issue.

The other possible option for skeletal animation is found in the Quake 3 model format called md3. This model format was made for Quake 3, itself a multiplayer-centric, fast-paced, arena FPS from late 1999. Quake 3 also made an attempt to fix client-side issues of skeletal animation but John Carmack went about it in his own unique way. MD3 models can be given little ‘tag’ triangles (a triangle being made up of 3 vertices in the model). Each ‘tag’ would then be given a unique name within the model for later reference. The technical debt of this approach is how tags are organized. When making a model, the tags have to be made, pointing in the desired direction of orientation for the mesh that will be attached there. The tags themselves are not saved when the model is exported to md3, thus any subsequent work on the mesh will require remaking the tags in their specific location.

For Quake 3 models that only ever had 1 or 2 tags per model, the ‘tag’ method was an ok solution. battleMETAL however, breaks this through complexity of the models in the game. The solution I settled on isn’t exactly performant for multiplayer gaming (thankfully battleMETAL is more a single-player game), but it does work. Remember how every model is an entity in quake c? Entities can be given specified ‘movement’ types to reflect, in the engine, how the entity is supposed to move. Player entities have MOVETYPE_WALK which is for handling player movement and physics. Darkplaces expands this functionality by adding a new MOVETYPE_FOLLOW. This movement mode is for objects that cannot collide with anything, and is for entities that, well, follow another entity.

General use-case for movetype_follow in the context of Quake is things like, having the gun model that a player is holding reflected externally by having a gun entity set to movetype_follow. Using this, battleMETAL treats all mech model pieces as separate entities with the movetype_follow. The locations of the pieces are set in relation to the controlling player’s origin point. In this way, the requirement of having hit locations, and visible damage have been satisfied without resorting to time consuming or costly programming quirks. The code uses the Factory Pattern to turn a mech data file into a mech, including the construction of the model component entities.

battleMETAL was able to use some animation for the mech models in the end. The leg models for every mech are animated in the model creation program and exported to the md3 format when animations are complete. The quake c code then controls the playback of those animations. Although this means animations are comparatively ‘stiff’ when put next to modern games, they are sufficient for the project.

Monday, August 6, 2018

battleMETAL - Quake/Darkplaces was a bad idea - Part 1

This was a terrible idea

Late again with the blog post, ach, about 2 weeks out from moving to a new location. This part is a quick overview detailing all the fun to be had pointing out why Quake / Darkplaces was a terrible choice. A feeling that I had upon reaching spring 2018, having been working on battleMETAL since July 2016, was that of exhaustion. Any strengths that the Darkplaces engine might have offered turned out to not really offset the Technical Debt that was incurred by the requirements of the game.

A great example of this situation was level creation. For original Quake, the best way to make levels is to use one of a few tools specifically dedicated to this task. Tools like GTKRadiant, QUARK, or TrenchBroom. These tools facilitate level creation by providing a means for designers to create the terrain for a level, place objects such as lights, monsters, player start point, select textures for the levels, and modify lighting. The level building tool then compiles all this information into a .bsp file that Quake loads when entering a level. Mapping for Quake is a well documented process, the advantage of being a popular and easy-to-mod game from 1996. There was just one big hitch in the process - Quake can’t really do outdoor terrain, cue the record-scratch sound.

See, in 1996 - and even well into the late 90’s and very early 2000’s, outdoor terrain was hard to achieve. Computer power was more limited despite the advances since 1993’s DooM game. Many games achieved a feeling of outdoor space through camera tricks, data storage techniques, or even art / design aesthetics. The method that Quake uses for creating level terrain is called Binary Space Partition or BSP. We’re not going to go deep into that particular set of computer programming, rather here’s the gist: the game (Quake) creates walls, floors, doors, ceilings, ramps, stairs, etc out of chunks of 3d space called brushes. When the map is compiled, the compiler takes the interior space of these brushes and compiles them into one large mesh of vertices. For computers in the 90’s, this was a level format that was easy to render without killing frame rate.

The Quake level design tools allow the user to create, reshape, change size, change textures of all brushes in a map. However, as we’ve seen with these old 90’s games, the brush-based system of level making results in very….chunky world aesthetics. There are ways to generate ‘realistic’ terrain with this brush method, but it results in map files that take several minutes or hours to compile. For battleMETAL a work around was found, by treating the terrain mesh as 3d model like any other 3d model, the game now had a way for realistic terrain. The sacrifice was that this terrain model does not show up in the map editors available, leaving the user to guess where to place other objects on the map. By requiring more accurate terrain models for the game, battleMETAL lost the ability to leverage Quake level makers which is a large trade-off indeed. This next part of the blog series will be just as the subtitle describes; why that (choosing Quake / Darkplaces ) was a bad idea.

Monday, July 16, 2018

battleMETAL - Why Quake / Darkplaces - Part 7 - Input Layer

It's a bit more tricky than one thinks 
One very important aspect of game engines is reading player input. Kind of hard to play a game if a player can’t actually control anything, right? Avoiding a more technical conversation of engine frames, processor cycles, and the like, game input is important because it needs to be timely. When picking game engines to use, input configuration is also a specific feature to compare. Quake has a few points towards itself in the area of game input, making configuration and custom behavior easy to create and maintain. Starting at the top level, Quake has multiple ways for a player to assign keys and bindings for behavior.

The 2 primary ways to change key bindings are using a console command ‘bind X key <action>’ and the second is modifying the .cfg config file. Using the bind console command, a player can change key bindings at anytime during gameplay. This is great for players and programmers. The config file is just another format of console commands, rather then being used in the console, the commands are loaded from a text file on start up or whenever the user enters the ‘reloadconfig’ command.

In the Quake C code, there exists functions to get the action bound to any given key and a way to programmatically set a keybinding. This allows the programmer to determine what keys are being used, and how, as well as make easier the task of custom key actions. Both the server and the client (remember Client-side Quake C?) can intercept key button presses for even more custom code or to consume a key press so that it does not go on to the other end of the network. A fun extension to the Quake engine provided by Darkplaces are key bindings for controllers and joysticks. Controllers and Joystick bindings aren’t a priority but if possible to implement, it’d be a welcome addition to the types of players of battleMETAL.

Custom, game-specific action code can read for player input within 2 ‘channels’ so-to-speak of input. There are impulse commands, and button commands. Impulse commands are used for one-off key presses. The engine can only read 1 impulse per frame - wait, that sounds limited? Ah ha, says the game engine, consider this: Although the game engine can only read 1 impulse per frame, the entire engine is running anywhere between 60 frames per second or higher on modern systems. This frame rate is high enough where the player will never notice that the engine is only reading 1 impulse per frame! Impulses are stored in a variable on the player’s entity under the name ‘impulse’. The engine runs the function, ImpulseCommands() on every player on the every frame. The programmer puts their custom code into that function, allowing for custom code to be bound to specific impulses.
 

The second piece are ‘buttons.’ These are slightly different than impulses. The state of a Button is not cleared every frame, whereas impulses are. So if the player is holding down the ‘forward’ button, then every frame knows the player is holding down that button. This difference is important because Buttons are used for constant-on commands such as moving forward, or jumping, or attacking. Another key difference between Buttons and impulses is that there are only a set number of ‘Buttons’ that the engine can recognize. These aren’t buttons on your keyboard, but a specific set of buttons numbered 0 to 9 internal to the engine. Quake generally uses ‘button0’ as the ‘fire weapon’ button, and this is generally bound to Mouse1 - your left mouse button.
 

In summary, Quake and by extension Darkplaces, have a tight handle on player input. Allowing for both player and programmer a level of flexibility not seen in most other engines. Out of the box, Quake’s input system is understandable by both player and programmer. Of all the parts of battleMETAL that had to be coded, the input system was one of the easiest. 

And this wraps of the 'Why' of using Quake/Darkplaces, in the next segment we will see why that was a really bad idea in the long run!

Tuesday, July 3, 2018

battleMETAL - Why Quake / Darkplaces - Part 6 - Menu Systems Layer



Click on the thingie, no wait, that thingie!

Quake was never known for its menus, in fact most iD games skip out on menus in any detail. There’s a workman-like quality to them, simple layouts and input. It also makes sense given that Quake came out in 1996, unless a game was menu-driven (like RPG’s or RTS) a game’s menu system were fairly plain. For Quake, it has all the necessary menus a player would need for an FPS. Building on DooM’s template, there are more options for graphics, and for multiplayer settings. Interestingly enough, iD did setup the code for their menu system fairly well, having console commands that can immediately bring up any particular menu.

Darkplaces however expands the capabilities. This being 2018, menus have advanced a bit since the days of 1996 and most people enjoy having a useable mouse for the menus. In Darkplaces, the source port exposes the menu entry functions to the Quake C code that modders can use. This in turn allows modders to create any and all menus they’d like to in almost any fashion they’d prefer. There are 2 layers to menus in Darkplaces, each being compiled to their own code base. The big one is called CSQC or Client-side Quake C. Original Quake, all custom code (written in Quake C) was packed into a single compiled file called progs.dat. However CSQC is packed into its own file and only used by the player’s local game of Darkplaces.

CSQC can access almost everything about the player’s game. The programmer can customize the HUD, can create their own menus, change runtime variables through the console, intercept input commands, and very importantly - define communications with the server. This last piece is helpful, this allows custom data transmission between the server and player. The coder can setup custom server-drive events, or pass specific game updates to the player for notification. Quake itself never needed to do a whole lot with this, but a mech game in 2016? Oh yes, this feature was very much needed.

The other big menu module is the specific menu layer. Quake source ports and modders never really settled on a ‘standard’ way of remaking / extending / modding Quake's original set of menus, so several options exist. One way many modders do is add the features to the CSQC described above. Another way is the menu.dat. Remember how CSQC compiles to its own file? Well its the same idea with the menu.dat code. Darkplaces looks for a menu.dat file, if it exists, Darkplaces then runs the menu code found in that file. The framework for the menu code is similar to CSQC but slightly more limited to just rendering menus and executing player input. I chose this solution for my main menus because I liked the separation of concerns that this approach offered - all the menu code is in its own folder and cleanly separated from all other code.

In summary, Darkplaces offered several flexible albeit a tad labor-intensive approaches to implementing new User Interface upgrades to the original Quake engine. I considered this sufficient at the time when selecting to go forward with Darkplaces. The available documentation on CSQC was easily found, but not the most detailed. The menu.dat code required going into the engine code to figure out how it worked. In hindsight now, despite the flexibility offered, both features actually incurred a large amount of technical debt. Newer engines handle UI systems more effectively both for the player and for the programmers.

Monday, June 25, 2018

battleMETAL - Why Quake / Darkplaces - Part 5 - Network Layer

Connecting for long distance mech mayhem
 

I will try to keep out of the deep end for this portion of the blog series. I forgot that these sections aren’t meant to be a detailed breakdown of the Quake engine or the Darkplaces source port. Rather, these posts are laying out the battleMETAL project’s discovery and assumptions before the work of battleMETAL truly began. In that spirit, these posts should be fairly short and mostly general about tech, code, architecture, etc.

At the time I was deciding whether or not to roll forward with Quake / Darkplaces for an engine, the concept of having multiplayer stood out. A mech game with some dedicated multiplayer would surely be a great game to try, and maybe even with friends. Quake’s network architecture, despite being a tad dated, is fairly robust. DooM’s network layer was peer-to-peer, where game-state was sent around to every player on the server; Quake’s networking is client-server. A main server of the game is started, and then all players connect to the server as clients. This is a server-authoritative design, where game-state is held on the server and then sent to clients. While this scales more nicely than DooM’s peer-to-peer system, the architecture wanders into sticky issues like client-side prediction and lag.

Deep diving into game networking aside, Quake had the feature set that overlapped with battleMETAL’s requirements nicely. Out-of-the-box, Quake allows any players to create their own servers, configure those servers (map, game mode, number of players, certain game rules, etc) and Quake has functionality for server-browsing. Although the menu system for Quake was rudimentary (even by late 90’s standards) it demonstrated that this functionality could be accessed by modders and programmers using custom code. The end result is customized server-browsing menus and features that have been added to battleMETAL.

In game code, Darkplaces also had mapped out functions for processing player input, data transmission between client and server, and functionality for fully customizing the player’s client-side view. Now that said, the exact knowledge for implementing these features was a bit more esoteric, but we will get into that later. Knowing that the network layer was securely placed in the engine code, vs the game code that battleMETAL would be using, Quake really had an attractive feature set for networked gameplay. One benefit of using a source port like Darkplaces is that there have been some key updates to the original Quakes network code. A little bit of client-side prediction which alleviates latency between server and client. Also increases the packet size, allowing more data to be transferred between client and server (after all, network speeds have increased since 1996.)

Further on in this series we will see that some of these initial assumptions might have been a tad generous or very much off the mark of what was actually useable. For now, let’s stick with the bright and rosy details that Quake was setup to be a multiplayer game and that therefore battleMETAL would be inheriting this functionality with little trouble.

Monday, June 18, 2018

battleMETAL - Why Quake / Darkplaces - Part 4 - The Game Loop



...and looping through it
The core of any game is the ‘main loop’. There’s a reason why we developers throw around the word ‘engine’ when talking about games. The best analogy I use is a car engine. The car burns fuel, which moves pistons that turn a camshaft. That camshaft then turns a belt called the ‘timing’ belt. The timing belt is the clock of the car engine. A game engine is very close to this. The base code is setup to run through a series of functions in a specific order, and there’s a ‘timing belt’ that keeps internal time. In Quake that ‘timing belt’ is a variable nicely called time.

Entities, remember those little guys from earlier? also form the only true ‘object’ for the Quake C language. Quake C is a cut-down version of the C language, which is powerful but does not do ‘objects’ very well. Quake C gets around this but ever so slightly. There is only 1 type of entity and all extensions to that entity are given to every entity. What this means is, if there is a custom value, such as ‘weapon type’ for an entity, every entity will now have this variable regardless if it used by that entity. This design paradigm is a blessing and a curse. The blessing is that it means creating customized entities is as simple as just assigning values to the programmer’s desired variables. The curse is that it means the code will bloat-up really fast, leaving hundreds of entities with unused values.

When a player launches a game of Quake, after going through the menu system, and launching into a desired map; the engine creates a list of entities. Almost every object on-screen is an entity. Quake organizes its entities into a list, or more specifically in-code, an array. The wonky aspects begin here. This array of entities has a fixed limit, ie how many total entities the engine can have ever. Original Quake can only handle about 640….Darkplaces however upped this cap to 32,768. Quite an improvement, eh? However there’s still a quirk remaining. The array of entities in Quake is more like a slot-system. Each of those 32,000 places in the array is a slot with a number. When the code wants to create a new entity, it finds the next available slot to place the entity...based on where the slot counter is. It is never a guarantee that the next entity the code creates is right after the current entity the code is on.

This also kinda creates a problem with removing entities. Quake never technically ‘removes’ an entity from the array. Instead, it ‘zeroes out’ the entity’s variables, removing things such as any model assigned to it, and other variables. This is was an intentional design by iD Software. Although there’s a difficulty in determining if any given entity is ‘empty’, it allows the system to ruthlessly clean up ‘unused’ entities to keep system cost down. Darkplaces keeps this paradigm in place, allowing for a fast run through of all the entities in the main array.

Entities can be invoked with the spawn() which returns an entity, usually the code will load this entity into a variable for modification: local entity foo = spawn(). From there, the programmer then must assign the variables they want to go into the entity. If the programmer wants the entity to do something in the future, they would assign a .think() function. A think() function is any code that is executed every time that entity is activated in the entity array. There are several other ‘template’ functions that can be used for various parts of entity behavior. Want to have custom code run when one entity touches another? Give that entity a .touch() function.

A programmercan also create their own child functions for the parent entity, such as entity.thisFunction(). And thanks to the code being C-like; this specific function can be whichever function the coder wants to point to. This allows for neat tricks where a set of entities can have the same function, .thisFunction() but for each entity, the actual function is completely different, like this example:

  Entity A

     .myFunction() = fireWeapon_Type_1()

  Entity B

     .myFunction() = fireWeapon_Type_2()


So when the code calls .myFunction(), if the entity is A, then fireWeapon_Type_1 is called. There’s a bunch of other C language quirks that are leveraged in Quake C, but that’s drilling down into programming language design.
Despite some of the limitations with the programming language, I liked the straightforward approach to the code design. 


I figured I could apply higher level code principles to the Quake C language to get around some of its limitations - a fine example is using the Factory Pattern for entity creation. I don’t need to rewrite the same entity customization when making, say, a missile entity. Instead, I can invoke a makeMissile function that does it all for me. Entity cleanup is a bit trickier, and checking if an entity is truly ‘empty’ or ‘null’ (in code parlance) remains a problem that has to be accounted for. Writing interfaces was sort of out of the question, but I think the entity object in Quake C qualifies as an abstract class which is super helpful.

Monday, June 11, 2018

battleMETAL - Why Quake / Darkplaces - Part 3 - 3D Rendering



Putting Stuff on-screen...


I understand that a lot of this content might be dry for readers who aren’t big into the nuts and bolts of game programming, and I’m sure that this probably doesn’t go deep enough for people who do. That said, I’m almost through this topic and I feel it needs to be typed out for context and for my own reference.

Keeping with the theme of why Quake/Darkplaces, this post will shift over to the rendering aspects of Darkplaces that merited looking into the engine. Darkplaces increases the types of 3D model file formats that can be used in-game, expanding from Quake 1’s thoroughly ancient (by 2016) .mdl format. Darkplaces can use .obj, .md2, .md3, .ase 3D model formats and their higher poly-counts. battleMETAL was never going to be a graphical powerhouse that could challenge modern games. I had the desire to make a game where graphics were clean enough that players could understand what they were looking at without being able to make super lush models.

The .md3 model format suited the project’s needs fairly well. MD3 is Quake III’s model format, which is from 1999. It's interesting to see what only 3 years of difference between Quake 1’s MDL and Quake III’s MD3 makes. MD3 can hold more detail, can something like 256 skins for a model file, and can have different textures for different models in the file. The MD3 format’s animation data is vertex based instead of bone based. MD3 was design by John Carmack for Quake III, so its footprint over a game network is incredibly low. Animations aren’t exactly a high priority (as we’ll see when I break down how I made the mech models).

Quake’s paradigm for adding models to objects is also fairly simple. Almost every object you see on the screen, in-code, is a thing called an entity. An entity is an abstract concept in game design, being a root-object of sorts from which all other objects inherit from. An entity in Quake can only ever have 1 model associated with it, which is given to the entity with the code command setmodel(). Once an entity has a model, there is functionality to affect the rendering of that model. Code can make the model partially visible, or invisible, glow with color, etc. So even if an entity has a mode, the game coder can dictate when that model should be visible. Another benefit is that an entity’s model can be changed quickly to something else entirely or removed if needed as well.

Now why does this matter? From where I sit, Quake lets the designer manage the game’s assets in their own way. Modern game design dictates that assets must be loaded into the entire development kit of the specific engine that the developer is using. There are benefits to this top-down approach, such as uniformity of design process when maintaining a project across a larger team. It also allows developers to move from project to project with familiarity of the tools. However, for battleMETAL and its one-man-army of me, I didn’t need such a heavy-handed approach. Quake allows me to manage assets as needed, adding or removing models at the code level, or even updated models in the file folders.


The last set of positives for Darkplaces is that the engine also provides tools for realtime lighting and shadows. Older game engines generally do not have this feature due to system limitations. ‘Realtime’ lighting is shorthand for saying lighting is dynamic as objects move around the game world as well as lights turning on and off. It also means lighting is more realistically represented when being projected from a source. Lighting in 3D computer graphics is its own Lovecraft-ian world that I won’t get into here, and you can find better explanations of it elsewhere. For Darkplaces, Levels can have light entities, and entities themselves can give off light. For battleMETAL, the Darkplaces lighting system is ‘good enough,’ providing enough detail to look good and allow for design aesthetics but also performant and manageable.

A neat tool that Darkplaces has is the ability to modify lights in a game level in real time using a series of built in commands. These changes are then saved to a specific file, ‘<map name>.rtlight’ which the game will load every time that map is opened. The advantage of this tool is no need to have to rebuild or recompile the map to test different lighting styles. The file is a plain text file with coordinate data, which also means the file can be copied and reapplied to other levels, or the same level. An example would be having a map transition from day to night, or a building’s lights turn on after being initially off.

The looser, bottom-up design of Darkplaces features put less emphasis on mastering a specific development environment and more on designer-based preference for their own tools. Engines like Unreal and Unity have lengthy tutorials for the various all-in-one tools they provide. For someone who doesn’t know these tools, the time required to learn them inhibits game design and the iterative testing of the project. Eventually I will give these a shot because they have their own pros and cons, but for now, I didn’t want to feel like I was fighting the tools too much….and yes we will see how I would eat this words in a buffet of hubris over this series of posts.

Tuesday, June 5, 2018

battleMETAL - Why Quake / Darkplaces - Part 2 - File management / File type loading



Files and their management; kind of important

This post was a bit late, things are getting a little busy around here.

One aspect about game coding that I like to pay attention to is file loading and management. Now this may seem like an obvious thing for any application, but one could be surprised at the variety of management strategies. Some games will hardcode data files to be loaded in a certain order. Other games may keep all their files compiled into the game itself. Quake uses what is called a Virtual File System, it sounds complicated but it boils down to this: When the game Quake runs, it treats its home folder like, say Windows, treats a folder. Quake knows how to dive into folders to get files, create new files. It has a set of file types that it can read and has loose preset folder structure.

Darkplaces really just extends the file types that Quake can load, mostly for modernization, but this also has an impact on other game aspects like graphics. Darkplaces allows for higher resolution images to be used, higher-poly models, and cleaner sound formats. Quake’s organizes these files pretty much for the programmer. Yes a programmer can extend the folder structure to their heart’s content, but that should only really be a last resort. An example of this automatic organization would be loading menu graphics.

/Quake/id1/gfx/

If we break this down, we see that id1 contains all of the game files that Quake needs to run, and that the menu graphics are then packed into the /gfx/ folder. This paradigm is also used for models with the /progs/ folder. An interesting note about the /id1/ folder, this is just for Quake’s game files. Modders wanting to make their own games and mods, can easily make their own separate folder such as /battleMETAL/ and then Quake / Darkplaces can switch between the two folders during runtime. This allows users to seamlessly switch between their favorite mods without too much interruption of gameplay. The caveat for my game, battleMETAL, however is that it's a total conversion which precludes compatibility between Quake’s settings and battleMETAL’s. So for my game, I stash everything in the id1 folder with the assertion that a user should not try to run both Quake and battleMETAL in the same install.

Why does this stuff matter? It makes management of dozens of game files easier and reduces to the amount of file loading that the programmer has to write themselves. Most game assets for Quake are loaded in the game code through the following functions precache_sound, precache_model, precache_pic. Even better, the textures for models are precached when their parent model object is, thus reducing the number of precache calls. This makes adding new content super easy as well. The built-in file loading code of Darkplaces knows how to process any of the files that are added through a precache call.

The final piece of this good feature is, we have all these files, how do we package them nicely for a release? Once again, Quake and Darkplaces have an easy answer. Within the game’s asset folder, Darkplaces can read and open .pk3 files. ‘Pak’ files are just a .zip file that has been renamed. This allows the developer to keep the release version of the asset folder clean. By naming pk3 files in successive numbers - PAK0.pk3, PAK1.pk3, the developer can actually split up game assets. Now, why would anyone want this? Think about it this way, if the developer splits game models into PAK1 and sound effects into PAK2, the developer can then patch the models by simply releasing a ‘new’ version of PAK1 with the new models. This siloing of resources is incredibly handy.

In conclusion, Quake / Darkplaces file-folder system implementation is clean and performant. It is useful at-scale, during development and is savvy in its organization for release. This is a strong reason to use Darkplaces as a game engine for simpler game making.

Wednesday, May 30, 2018

battleMETAL - Why Quake / Darkplaces - Part 1 - The Devil you thought you knew well enough



The Devil you thought you knew well enough


Now we begin to get a bit more technical about why picking Darkplaces was a good idea. First let us begin with the software concept called a source port. This example, Darkplaces is a source port of Quake 1. Source ports allow software to be run on systems that are different than the original specs. In video games, most source ports merely allow the specific game to played on a newer system - like Quake 1 (circa 1996) to be played natively on Windows 10. However, Darkplaces is also a library of modifications to the Quake 1 software that expands functionality.

Darkplaces was developed by a user by the handle LordHavoc and you can find more about that over here. The biggest things that
Darkplaces accomplished was a modernization of sorts for the Quake engine. Updates to the rendering software allows Darkplaces to draw higher resolution textures, real time lighting, higer polygon-count models, smoother animations. Not just rendering, Darkplaces also allows for higher quality sound effects and music. Finally, a big update was raising the memory capacity of the engine to handle large quantities of monsters, bullets, players, and other game objects in a level and even increasing the size of potential levels. In essence, the Quake 1 engine is a Virtual Machine geared towards running Quake, so upping memory capacity is a huge plus if one is looking to expand the Quake engine to be more than running Quake.

All of these features fit well enough into my understanding of modding Quake 1 and Quake 2 engines. The requirements of the engine, relative to more modern engines, is incredibly modest, and the engine runs well on almost anything. Actually modifying the engine is generally accomplished by changing the game code. Game code is in a ‘bastardized’ version of the C coding language. A lot of functionality has been stripped out or pared back to concerns only of the game engine. Plenty of tutorials and tutorial sites are at one’s fingertips as well, making question-answering fairly quick and easy. This is a benefit to an older game engine, a lot of the most basic questions have been answered somewhere and a lot of other people have tried something similar to what you are trying to do.

By choosing a Quake derivative like
Darkplaces , I was also subscribing to Quake’s template of game creation. Most game engines define how to add levels, link levels together, manage player inventory, etc. Even if a game allows a ton of modding, it doesn’t make a whole lot of sense to rip out a game’s functionality completely and try to bash in something that doesn’t conceptually jive with the game. I knew battleMETAL would be an FPS, a mech FPS, but it still was an FPS, thus Quake aligned conceptually with that goal. I also knew that battleMETAL levels don’t need to be super complex or scripted, and again Quake aligns with this concept. So, I talked myself into downloading Darkplaces and took a look under the hood.

Monday, May 21, 2018

battleMETAL - The Dare - Part 2


(this one is a bit lengthy, some paragraphs are skippable :P)
How it all started
I had been doing the exercise of designing games since 2008, but those early efforts were plagued with poor planning and lack of knowledge. I give 2012 as a starting point because that was the year I sat down and said “I am going to make a video game.” No, this game wasn’t battleMETAL. This was Project Redshift, what became known as the game Zond. Zond is a top-down, Asteroids-like game built in Java. The player commanded any one of the classic Space Race era spacecraft in combat missions. I never really finished the game and you can learn more about it by going here.

Zond fizzled out for various reasons, both technical and non-technical, however I learned a lot about the process of game making. The project wasn’t large enough to bury a one-man team, but its features challenged me as a programmer. It also gave me a crash course into core game code design and some of the paradigms used commonly in game coding. After Zond, I cast about for a few years making other attempts at video games, most work was exploratory and mired in technical debt. It wasn’t until 2016 that I thought about making another ‘serious’ go of ‘it’.

When you are the Devil’s Advocate in a case against yourself

So here comes 2016, and I’ve been wondering what game to make. A long time ago I remember reading a quote that has stuck with me - “Make the games you want to play.” I can’t remember who said it, but it has become a mantra that I believe in. Make the games, you want to play, ignore the gaming zeitgeist and make what you want. What games do I like to play? Simulators….but not just any….mech simulators. Ever since I fired up Mechwarrior 2 back in the ancient past of 1996, Mech Games have been one of my all time favorite genres of game. There’s nothing cooler than stomping forward, deflecting a hail storm of cannon fire, in your armored leviathan. An avatar of war, a walking tank. To fight another mech is to engage in a knightly duel of old, or like two Aces in WW1 biplanes, or two prize fighters in boxing. I love the motifs of mech games, the themes, the spectacle. Sadly by 2016 the gaming zeitgeist had declared mech games to be very dead.

See, by 2016, Simulators are a kinda dead genre. No large company is really making them, for whatever reasons (I could get into that but its heavily opinionated salt). My only options as a gamer to get some mech action in the style of Mechwarrior was really only Mechwarrior: Online and that in my opinion is super depressing. Mechwarrior: Online is a pale shadow of what mech games can be and what Mechwarrior games used to be. That previous sentence was opinion, if you weren’t sure, but it's important to know that because that leads into the impetus for making battleMETAL. So I ask myself - what is stopping me from finally making a mech game? I’ve been kicking around ideas for a few years, along with talks with close friends about concepts and design for mech games.

The initial stopping point was technology. I tried working with Unreal 4 but at the time in 2015, I found the UI overwhelming for a single developer to really get traction. I thought about Unity but it looked like I’d face the same uphill challenges as Unreal, at the time, remember - hindsight is everything. Thinking about my options, I dredged up an idea from the past - what about Quake? To make a side story short, I was familiar with making Quake II maps back in 2002 / 2003 or so, and had read about a few source ports of the Quake 1 engine, namely Darkplaces. Quake 1 also had its own specific C-style language that was purpose built for modding Quake.

It sounded like Darkplaces was a good ‘my first 3d engine’ to really dive into, it felt approachable. Functionality was literal, not hidden behind splashy UI. Here’s an example: to get texture effects like light-reflection and bump mapping? Simply add 2 files - <your texture>_bump.tga, <your texture>_gloss.tga. Darkplaces had a built-in file system for loading and caching game files. Rendering was secondary, I’m not a graphical artist by trade so I was prepared to make a game that looked ‘ok’. Another plus for Darkplaces was that it had a network-layer built into the game as well as entity management. There’s a power to game engines where you can just start coding the fun stuff...and a danger.

Then came July 4th, 2016. Having just finished a barbecue with friends at our apartment, I sat down to do some really dumb tests with Darkplaces. In one evening, I replaced the Player model with an old mech model I had made in 2015, and I changed the weapon model to a cockpit mesh I made sometime in 2013 / 2014. Here were the results:

 These screen shots are Quake but I replaced the Player model with my own mech model and replaced the First-Person gun model with a cockpit.


And that was one evening! My head exploded with ideas, drawn in with a “well this doesn’t look so hard” mentality. As we’ll see over the next 1.5 years, that was the definition of short-term success hiding long-term pain. Eventually I fought through the ‘necro-tech’, realizing just how obsolete a game engine Darkplaces really is. Through it all, it still is one hell of an adventure into game design. battleMETAL is a case where I played Devil’s Advocate for myself, why not a mech game right now? Why not just ‘get it done? The mantra I’d end up using throughout the entire project as the months wore on became:


Perfect, is the enemy of good.

Monday, May 14, 2018

battleMETAL - The Dare - Part 1

Who am I
To be super brief - just some 30-something guy from New England, in the United States.

To be a bit more specific? Programmer, artist, historian, painter of miniatures, and game designer. I’m not going to try and recount my life story here but merely try and give some context to the person behind this entire project.

The threads winding their way through my life to get to this point would be longer than socially bearable to recount. Two events in my childhood, looking back now, I think, are what would end up altering my career path. These are more clear in hindsight, about 20 years later, but at the time and even into college I didn’t really think about it.

The first event was joining the ‘Computer Club’ in 5th grade. Now to be clear, this was a normal public school, in 1997, in more-rural-esque Connecticut. So, if you expected a guided experience with some old sweat coder….you are quite wrong. It was run by a well-meaning if a bit misguided teacher who wasn’t so great with computers. The club was mostly about using macs and the program called Hyperstudio to create super simple ‘programs.’ hilarious outdated link. Most of the things we made in that club could be charitably called ‘interactive Power Point presentations.’

The roots of the idea was there, though. The program showed how to create menus, do limited animation and sound. It was a ‘first’ step towards coding and computer game design for me if there ever was one. Up until this point I thought I wanted to go into Marine Biology.

I’ve wanted to be a game designer / maker since 8th grade. The reason I can remember it so clearly is because of the TI-86 graphing calculator ( https://en.wikipedia.org/wiki/TI-86 ). Every student at the time was required to get one in my school as we entered 8th grade in 2000. One of the discoveries we, students, made was that not only was the TI-86 super handy actual math...but it could also run games. In 2000, seven years before iPhones and ubiquitous mobile devices, being able to play games anywhere was still a bit of a luxury. Sure the GameBoy was around but you couldn’t exactly play that in class without getting it taken away at some point. The TI-86? Perfect camouflage.

By 9th grade, the start of high school, I had found you could indeed code your own games onto the calculator...and into the internet of the early 2000’s I went. I scrounged around for tutorials, how-to’s, anything I could get my hands on. I read up on printing characters to the screen using an X/Y coordinate system. I learned about interpreting user input, and the keycode number for every key on the calculator. I played around with writing simple little menus for my games.

 Early attempts were clones of projects I found online, printing out reams of code on paper for later reference. Although many of these projects existed on my family computer (I did buy the pc / calculator cable so that I could code on the pc), sadly all were lost in the subsequent years of hard drive failures. After this point, things were reliably on track for me through high school and into college.

Those early habits of scouring any and all knowledge for help in my own efforts has stayed with me. In a quirky twist, these skills also ignited a love of History that still burns today. As to how this relates to battleMETAL? In the coming posts you will see how the self-confidence of that young programmer would be challenged and reforged. How learning to sift through and collate disparate fonts of information would help in completing a (so-far) arduous task.

Wednesday, May 9, 2018

The cold rise from sleep...

5 years and a what feels like a life time...

I'm going to attempt to start this blog up again mostly to document the video game battleMETAL that I have been working since mid-2016. I had planned on doing a retrospective when the game was finished but decided a weekly or bi-weekly blog would make the task less daunting. 

Posts are going to range from general discussion of the development of battleMETAL to focusing on specific challenges or features of the project. 

<fumbles in pocket, pulling out wrinkled napkin>
 
I do have a rough outline for this series of posts, and I'll try to stay on-script as best I can. I will also try to make sure the posts happen in a regular fashion, as blog posting is not a habit of mine and for the longest time I personally felt it took time away from working on the actual project.


Some of these posts will also get a bit technical when discussing in-depth topics, if you find yourself struggling - feel free to skip that post, but I do encourage trying to muddle through.


The Dare 
  •     Who am I
  •     How it all started - when you are the Devil’s Advocate in a case against yourself

Why Quake / Darkplaces

  •      Reasons for
  •      The Devil you thought you knew well enough
  •      File management
  •      File type loading
  •      3d renderer
  •      Game loop
  •      Networking layer
  •      Menu layer
  •      Input layer

Why that was a bad idea, a terrible idea

  •      Everything discovered
  •      Map pipeline
  •      Model issues
  •      AI
  •      Collison system
  •      Game Logic

And Yet, somehow, it works

  •      Sanity is preserved in the console logging functions
  •      Eventual map pipeline
  •      Game Data systems
  •      Flexible, but built in systems
  •      Mech model implementation
  •      AI implementation 1
  •      AI implementation 2
  •      The Mech Hud
  •      Hud Impl 1
    •    Sorta generic, entity based
  •      Hud Impl 2
    •     Generics, generics, generics
  •      The CSQC Menu System
  •      Overall design
  •      Briefing menu
  •      Text wrap
  •      Mech hangar / arming
  •      Deployment menu
  •      The Menu.dat
  •      Entities, callbacks, swtich cases, textfields, dragon drops
  •      File Loading and folder layout
  •      Animatic System