Reptile Updates

Since our last post, there were a lot of concurrent systems that got resolved that came together to form what felt like some of the most productive months in a while!  On top of that, we have quite a few animations to show off — mostly centered around the Reptile.  Without further ado, let’s get into it!

Reptile

The Reptile is another one of our soldier enemies. The Reptile has very fast, unpredictable movement.  Tony Wojnar has really captured the chaotic nature of this guy and it has been fun seeing it come to life.

Reptile Walk
Reptile Walk
Reptile Run
Reptile Run
Reptile Backflip
Reptile Backflip
Reptile Breath
Reptile Breath
Reptile Balanced
Reptile Balanced

Walking / Running Weapon Animations

The next major addition from our art department is walking / running weapon animations.  Actually, this was a joint effort between programming and art!  Currently there are 12 different types of walking animations for each soldier enemy, as well as our hero.  Plus, each of the aforementioned have four run animations and four stand frames.  Multiply this for each weapon type and the number of unique animations would spiral out of control real fast.  We ended up coming up with an idea where each weapon, for each direction, has a couple of reusable still frames to choose from.  Then, programmatically, we specify the exact frame and position for our enemies / hero.  We save on the number of assets, but we do have to tediously figure this out by hand.  Luckily, this is the type of work I like to do on vacation during travel / downtime, so this worked out perfectly.  Tony concepted out a few of these, so below are what we’d see in game programmatically:

Sword Run Animation
Sword Run Animation
Sword Walk Animation
Sword Walk Animation

We did run into a problem though.  One of the big things we’ve been conveying from a gameplay standpoint is the difference between balanced and agile / heavy weapons is the fact that balanced are one-handed weapons (that can be used with a shield) and agile / heavy weapons are two handed weapons (that cannot be used with a shield).  Unfortunately all of our current walking animations assumed one-handed animations.  We tried to “cheat” with an example animation below:

Mace Walk Test
Mace Walk Test

However, it didn’t quiet feel right.  We ended up resolving this by adding two-handed stand, walk and run animations.  Luckily we could reuse a lot of the base animations and change the positions of the hands to make holding a two-handed weapon work.  Below are a few examples of all of this coming together (again, positioning programmatically, these are just references):

Spear Walk
Spear Walk
Spear Walk
Spear Walk
Orc Spear Walk
Orc Spear Walk
Orc Spear Walk
Orc Spear Walk
Reptile Spear Walk
Reptile Spear Walk
Reptile Spear Run
Reptile Spear Run
Reptile Spear Run
Reptile Spear Run

Other Notable Updates

As mentioned at the beginning of the post, we’ve made a lot of progress / resolved a lot of work on concurrent systems that have been in development for several months now.  The biggest of which was the layerDepth system.  The layerDepth system was introduced back in 2019 when we added bridges.  The simplest way to convey this system is if we are standing on a bridge, layerDepth is most likely 1, and if we are supposed to be under the bridge, layerDepth is most likely 0.  As mentioned in the linked post back as early as 2019, this system worked well for the hero, but applying this to all objects ended up reworking a lot.

Now, we didn’t just work on this system for three years (which we hope is obvious by the other posts on our blog 🙂 ), but integrating with all of the other systems took a bit of work.  Not only that, but when we discovered that the collision system we built originally was not going to handle layerDepth very optimally, we decided to update other systems (e.g. which is one of the reasons the Tile Object was introduced, to help speed up the collision system).  We’ve been talking on an off about all of these systems for a while now, but the final frontier was making all of this work with enemies, weapons, and other interactable objects.

Some interactable objects were pretty easy to update while others (like our soldier enemy) were a bit more involved.  For example, we had to update the path finding algorithm to account for different layerDepths.  This took a bit of reworking, especially around the transitions areas, which we called rampTile. RampTiles used to be single individual tiles, but we ended up merging that with our Tile Object system for optimizations.  As a reminder, RampTiles are essentially the triggers for switching an object’s layerDepth.  So, for an enemy to find a point in a different layerDepth, the enemy first needs to find the nearest ramp to toggle the enemy’s layerDepth, then the enemy needs to find the best path to that ramp, and finally, the enemy needs to compute the best path to the target.  Whew!

That was a more complicated interaction to figure out.  Below are a few other interactions we had to update and fix to make the layerDepth system work:

  • Updating an enemy’s “seeing” and “hearing” logic (i.e. enemies can normally see targets in different layerDepth, unless the target is under a bridge, for example)
  • Determining how collisions should behave with different layerDepths / trigger points / RampTiles
  • Updating the Renderable system to draw objects correctly
  • Updating the Buildingable system to determine whether an enemy is inside / outside and accounting its layerDepth
  • If an enemy / hero is using a weapon or holding something, determining how that interaction accounts for layerDepth, as well as interacting with the Buildingable system

These bullet points are not an exhaustive list either! As you can see, there were A LOT of complicated systems converging!  Of course, we’re now play testing the game again and encountering some bugs / edge cases / minor issues (which is normal with a system as complex as this).  However, we’re extremely proud of how well it all came together!

Finally, here’s a list of some other important updates we’ve completed:

  • Sound Effects / Pitching
    • We are in the beginning stages of updating our old, crusty sound effects with some new ones.  With new sound effects came the need to pitch the base sound effect randomly when needed.  Therefore, we did two things:
      • Figured out how to take Game Maker Studio’s pitch functions and use them with industry terms, such as octaves, semitones and cents.
      • Added a string definition (for easier reading, not optimally performance-wise) to indicate how we want to randomize these (e.g. snd_SlashBalanced: "semitone:-1..1;1" would take the balanced sound effect and give us three pitches relative to the base, between -1 semitone and 1 semitone (0 would be no change, so really giving us two “new” pitches)).
  • Transitions of Regions
    • As an example, the transitions from the green grasslands to the lower mountains was a pretty hard line.  Now we’ve added some softer / smoother transitions into regions.  This will be expanded on once all of the art for backgrounds has been finalized, but that will be a long ways out.  Below are a couple of screenshots:
      Transition Example
      Transition Example

      Transition Example
      Transition Example
  • Updated Long Grass Tiles
    • We also updated the art for the long grass tiles.  Below are a couple of screenshots:

      Long Grass
      Long Grass
    • When cutting the grass tiles, there was no concept of changing the neighbor tiles to visually look correct.  This was quite the undertaking to understand how auto-tile systems work.  Before we actually understood it, we were hardcoding different values with this cheat-sheet:

      Auto Tile Indexes
      Auto Tile Indexes
    • However, we soon recognized a pattern.  We’ll try to keep this brief and simple, but it does deal with binary, so hold on to your seat!
      • The first tile from the cheatsheet, 255 in binary is 11111111.  This tile has 8 neighbors, because it is a full tile.  Each of the 1 represent a neighbor.  The last tile from the cheatsheet, 0 in binary is 00000000.  This tile has 0 neighbors, because it is an empty tile.  Each of the 0 represent a neighbor.
      • So, for example, if we wanted to represent a tile visually with a left neighbor only, 8 would be that number, and could be represented by 0001000.  Here is a visual:
        000
        1 0
        000
      • So, if we wanted to represent a tile visually, with a left and right neighbor, visually it would look like:
        000
        1 1
        000
        The binary string would be 00011000, which in our normal system would be the number 24.
  • Projectiles Shot Off Cliffs
    • For a while, we’ve had the ability to shoot projectiles / throw objects over cliffs.  However, with the introduction of the z, zPseudo, we were trying to figure out how the shadow should be drawn relative to going over a cliff.  We spent a couple of weeks playing with different approaches:
      • When the object landed, continue bouncing / falling off the cliff
      • Increasing the z when moving over a cliff top and then decreasing by the same amount after moving past another cliff top of the same height
    • We ended up settling on keeping everything the same, as the fake 3/4‘s perspective didn’t seem to make it feel off in anyway.  However, we added a new construct that when a projectile lands within the cliff, if something broke from the projectile (i.e. rock breaks and a treasure came out) that this treasure will fall to the bottom of the cliff.  That way, these types of things won’t get stuck in the cliffs for the player to never be able to collect.

Leave a Reply