Jawab’s Ancient Temple and Sawmill

Given that it’s been a bit longer since our last post, this post will be a part one of two, since the amount of content that has happened since our May post is more than usual.  In this first part, we focus on our progress on the first dungeon of the game.  If you couldn’t tell by the title, this dungeon’s theme is an ancient temple that was abandoned.  Over time this temple was renovated into a sawmill.  Then, as monsters began emerging, the sawmill became abandoned as it was overrun.  There is some interesting lore here that we can’t get into quite yet, but we’re hoping it’s enough to keep you interested.  Let’s get into it!

Pixel Art

These past few months have been mostly focused on the Velarian Soldier / Dojo Master / Ancient Guard sprites.  However, before we get to those, Tony also finished up the Skeleton animations during the latter part of May.  Below are some of those remaining animations:

Skeleton Appear
Skeleton Appear
Skeleton Disappear
Skeleton Disappear

We decided to showcase a little fight with the skeletons out in the wild:

We also worked on a few compasses and icons.  Below are some of those sprites:

Heart Piece Compass
Heart Piece Compass
Bad Enemy Compass
Bad Enemy Compass
Bad Enemy Icon
Bad Enemy Icon
Fort Icon
Fort Icon
Heart Piece Icon
Heart Piece Icon
Weapon Shop Icon
Weapon Shop Icon
Chest Icon
Chest Icon

Now the aforementioned Velarian Soldier / Dojo Master / Ancient Guard sprites:

Solider Balanced Swing Down
Solider Balanced Swing Down
Solider Agile Thrust Left
Solider Agile Thrust Left
Solider Heavy Swing Right
Solider Heavy Swing Right
Soldier Shield Bash Down
Soldier Shield Bash Down
Soldier Back Roll Up
Soldier Back Roll Up
Soldier Back Roll Left
Soldier Back Roll Left
Soldier Bow Pull Down
Soldier Bow Pull Down
Soldier Stun Left
Soldier Stun Left
Soldier Death Down
Soldier Death Down
Soldier Death Up
Soldier Death Up

The Knights have taken up the majority of June and July.  Tony did a great job on all of these animations, and we’re sure he’s ready to move on to other pixel art!  Speaking of other pixel art…

Jawab’s Ancient Temple and Sawmill

The month of June I (Dan) mostly worked on the Forest Dungeon concept.  There was a lot of code updates so that we could build dungeon rooms and other dungeon concepts out much faster down the road.

One of our major updates was to our sequence system.  We added an abort_sequence function, that would stop a sequence from running entirely.  For example, let’s say we stepped on a switch and the pillar starts moving down.  However, this switch must have some weight on it in order for the pillar to stay down.  Typical games stop the players movement while a sequence is panning the camera to show the result of stepping on the switch.  However, in The Violets of Amicus™, the player is still free to move while the camera is panning.  Because of this, the player could theoretically step off of the switch while the pillar moving down and sneak through it before the animation begins of the pillar moving up.  Therefore, it was important to add something that would trigger the stopping of the animation of the pillar to prevent the player from “sequence breaking”.  Hence, why abort_sequence was necessary.

The good news is this can be reused for other sequences as well.  For example, perhaps we want to “skip” cutscenes outright.  This function gives us the possibility of doing so.

As mentioned, there were several other updates that happened as a result of the Forest Dungeon.  However, we won’t go into all of the details, and a screenshot will have to suffice:

Screenshot
Screenshot

Finally, without further ado, let’s show off some screenshots of our Forest Dungeon concept:

Forest Dungeon Concept
Forest Dungeon Concept
Forest Dungeon Concept
Forest Dungeon Concept
Forest Dungeon Concept
Forest Dungeon Concept
Forest Dungeon Concept
Forest Dungeon Concept
Forest Dungeon Concept
Forest Dungeon Concept
Forest Dungeon Concept
Forest Dungeon Concept

Some of the art in the screenshots are still a little rough around the edges, but it should convey the concept of an abandoned ancient temple, renovated into a sawmill, then became abandoned as it was overrun with monsters.  We have the general structure / puzzles mostly figured out.  However, the details and layout will change as we add more art and get some play testing in.  We’re happy with the results so far!

Below is a short clip of the Dungeon in action:

One other item we’ve worked on is a second floor (2F) concept.  This is still an early prototype, but we’d thought we’d share the progress thus far:

2F Prototype
2F Prototype

If Asteric were to go off the tile pattern, he would “slip” and fall into the 1F.  Therefore, we added a concept that would make an interactable object fall to a lower floor.  This will obviously add some old school puzzle elements to our dungeons.

Ancient Guard Boss Fight

Finally, here’s a video that combines the two main elements so far — an Ancient Guard boss fight in our Forest Dungeon:

We wanted to include this in our previous section with the Knight, but it also spoiled the Dungeon aesthetic before it was introduced, so we decided to wait until now in our post.

The Ancient Guard is proficient in defense, being able to parry offensive attacks, or dodge threatening blows. The Ancient Guard is also a melee specialist, skilled with Balanced, Agile and Heavy weapons.  The Ancient Guard understands that Heavy Weapons > Balanced Weapons > Agile Weapons > Heavy Weapons …, and therefore switches out the melee weapon based on what its enemy is holding.  This makes for a great combat challenge, testing the player’s mastery in one of the central mechanics of the game: switching weapons.

Title Screen

If June’s task was working on a Dungeon concept, then July’s task was working on the Title Screen.  One might think “a whole month to work on a title screen?”  And one would normally be right.  However, it is a little more involved.

The main problem is that before the addition of the title screen, the game would simply boot into the world.  This meant that all of the sprites, enemies, tiles, walls, etc. were loaded and then parsed into their appropriate sections.  This would take a few seconds to thirty seconds, depending on the room size and how fast the computer playing the game is.  If we add a title screen, we don’t want to wait to load all of the aforementioned assets, especially down the road where the player could choose to begin a new game or load a previous save.  It would be a lot of waiting to then rewait again.  Therefore, we want to put a title screen before all of this loading.

This is where the problem begins.  If we put the loading screen before everything, that means we need to figure out a way to only load the absolute necessary elements to “boot” a title screen.  Therefore, this means a lot of gutting, rearranging, and refactoring — especially around assets that are used in both the title screen and the game world.  For example, our SoundBoard object, which is responsible for playing music and sound effects, would be needed for both the title screen and the game world.  So, we need to figure out a way to move that into a boot function that would be required by both.

As we were building out the functionality that abstracts our instances to load after our title screen, we recognized that this could be abstracted out even further, that would meet the goal of a post-Kickstarter task — only load sections surrounding the section we are in, and then unload the sections not needed.  Right now, we are loading all of the sections into memory.  This is fine, for now, as the demo will only have about nine sections.  However, the real game will have 81 sections, and this would simply be too much.  Nine sections at any time is about the maximum we’d want loaded into memory.  Therefore, we decided to take our abstraction a step further.  We decided to save the section instances to a file, so that could be “streamed” later.  Right now we are still loading / streaming all of the instances (as previously mentioned nine sections isn’t hurting anything).  However, with the instances loaded to a file, we could easily down the road set this up to stream from a “section” file, instead of everything at once.

There were several other problems that needed addressed, but we’ll simply bullet point them here, for the sake of interest:

  • When creating instances in our game rooms, Game Maker Studio creates a constant that can be referenced in game code, to uniquely do something with that particular instance.  We are making use of this in several place.  With instances being loaded from a file, this constant is no longer the same reference.  However, we got around this problem by writing a mapper.
  • Many of our global objects were being referenced by its object identifier instead of its instance identifier.  Either works, but the instance identifier is faster.  Since our global objects are being referenced thousands of times per frame, referencing our instance identifiers through global has increased performance.
  • We moved elements of obj_Camera into _SuperGlobal, which in a way acts as a display manager now.  This was necessary since we don’t need a camera on the title screen.
  • Our “No Controller Dialog” was needed in the title screen, since we can be in a state where the controller is not recognized on the title screen.  We ended up moving this text renderer in our obj_HumanInput object, so we didn’t have to maintain two different objects.
    • As an aside, we now automatically pause the game if the controller gets lost during gameplay
  • Our ugly options page in game also needed to be utilized in the title screen.  Therefore, we overhauled our options page, and make it functional in both the title screen and the pause screen:

    Options Screenshot
    Options Screenshot

With all of that out of the way, we were able to implement our title screen, which can be seen in this video clip below:

There’s a few elements (e.g. the buttons and logo) still to polish up and after the Kickstarter, we plan to add some sort of eye-catching animation.  But it is functional and has a good foundation to build off of later.

You may have noticed a ticker at the bottom.  Our idea here is those who back the project at $30 (actual value TBD) will get their name on the title screen!  Those who back the project at $60 (actual value TBD) will have their name at the start of the list (i.e. their name shown first).  These lists will be randomized so every time the game boots up, it won’t be the same list each time.

Other Notable Updates

Believe it or not, this section also contains quite a bit of content!  We’ll try to keep it brief and concise though (and sprinkle in a picture here and there).

Playback Input / Recorder Fixes

As you may recall, we have implemented a input recorder / playback system that records a players inputs and then afterwards, can play them back exactly.  This makes debugging easier, as we get can get to an exact state if a game crashes, as well as simply watch a players gameplay session.  However, we were encountering some errors.

After a good solid week, we realized our problem.  The numbers that our RNG creates uses Game Make Studio’s real number, which are double for those who are computer science geeks (for those who are not, it can loosely means double precision with the amount of decimal points than that of a float).  I (Dan) think this must have changed in the update to removing 32bit support in Game Maker because these numbers used to be float.  Anyway, long story short, we were storing these numbers as float instead of double.  This generally works fine, but after a while, the loss of precision of these numbers would eventually cause unexpected behaviors and crash.  Storing as double seemed to fix the issue and the random (no pun intended) crashes we were getting!

Mac OSX Epsilon Issues

Another related floating point issue!  Different architectures handle decimal points slightly differently.  Because of this, to support “identical” behavior between platforms, Game Maker Studio has this thing called Epsilon, which when comparing if two numbers are equal, it actually loosely compares them behind the scenes, and if they are within the epsilon range, then they are equal.

We had an issue where we were getting an infinite loop on the Mac platform.  This is because the Mac was incorrectly calculating arctan due to some rounding issues.  Therefore, we set the value of epsilon to be a bit bigger, which fixed our issue.

Map Screen Polishes

We also updated our map screen to be a bit more polished.  Below is a screenshot:

Map Screenshot
Map Screenshot

This uses some of the updated interface items / layout from our UI / UX project mentioned back in our March post.  There’s still a bit of room to add more things, such as objectives or maybe even floor markers for our dungeons!

Bullet Points

  • Our can_hear_it system was crashing randomly and predictably.
    • The predictable one was easy (since it was, well reproducible) — we forgot to check if a property existed on a mass object, like obj_LongGrass (which can produce sound when cut).
    • The random issue ended up being found because of our fixed input recorder playing back to the exact frame it crashed.  It ended up being from an enemy taking damage twice which resulted in death.  For example, let’s say an enemy took damage from a stuck arrow, while also taking damage by removing the arrow.  The first damage would destroy the enemy and cancel any sound effects that would result from the enemy.  The second, however, would add a null owner to the sound effect.  When another enemy was trying to “hear it”, it couldn’t find the already dead enemy.  We fixed it by not adding sound effects to already destroyed objects.
  • We made some text revisions to our intro cutscene.

    Intro Cutscene Updates
    Intro Cutscene Updates
  • A bit lower level, but we are now using sprite names for our sprite layer tiles instead of indexes.  Whenever we added / removed a sprite from our library, these numbers would get all out of whack, and would return gibberish tiles the next time it was loaded.  We are now storing the names of the sprites (since these don’t change) instead of their indexes.
  • Another lower level item, but also important for performance!  We found a few places that were not cleaning up dynamic resources, such as mass sprites from fromTile walls, obj_RampTileMass and obj_WaterTileMass.  We also weren’t removing the audio after using audio_create_stream for our music tracks.
  • When using the Quick Switch menu, when the joystick would snapback, it would cause missinputs.  We alleviated the snapback issues by only checking for inputs every other frame.
  • We buffed the water rod in rain, as well as added some other buffs and nerfs for elements.
  • We added an NPC Sitting concept.  There currently isn’t any animation, this was more to fix the functional problem.  We set the NPC that are supposed to be sitting in-between a chair and the table.  If an object gets stuck in a wall, it will try to push it out.  Well, since the chair and table are both considered walls, on one frame the NPC gets pushed up by the chair and the next frame the NPC gets pushed down by the table, causing an endless jittery look.  Consequently, by fixing this, this also fixed an abundance of memory getting used as well!
  • Finally, we tried to update to the latest version of Game Maker Studio, 2024.4 and then 2024.6.  However, 2024.4 had a bunch of collision issues introduced to it, that got resolved in 2024.6, but then 2024.6 introduced a problem with loading instances from our stored file explained in the title screen abstraction section.

Conclusion

We know that was a lot of material to go through!  If you stuck with it until the end, thank you!  Part two will be a bit lighter on the reading, and will hopefully be out by the end of the month!

 

Leave a Reply