Weekly Update – September 23, 2022

I threw away a big chunk of the code that I just wrote last week for Stat Modifiers. I made this decision when it became evident that maintaining a running sum of all Stat Modifiers for each Stat Type wasn’t worth the complexity. I originally chose this approach for efficiency; since the modifiers didn’t change that often, it would be more efficient to precalculate and store the values. In practice, however, the values are used infrequently enough that recalculating them every time doesn’t impact performance. The added complexity, primarily due to having to synchronize the running sums with the individual modifiers, increased the implementation effort and defect risk. In general, it’s preferable to store information in one place only.

  • Improved Inventory Panel. The number of inventory slots has expanded from 24 to 32, the panel has widened, and combat stats are now displayed.
Inventory with stats
  • Tooltips for stat bars and status effects. Hovering over the Health, Stamina, or Magic bars, or a status effect icon, now displays a tooltip with additional info.
  • Actor Debugging Panel. A new toggleable panel displays detailed info about active actors, including location, vitals, status effects, and AI state. It’s been very useful for squashing AI bugs. This is a developer-only feature; it won’t be available to players.
Actor debugger
  • Bug fixes.

Next week starts with closing out AI bugs, followed by validating combat calculations (now that Stat Modifiers are in place) and continuing to add sound effects. Also, I’m going to start on interactions between items and objects, such as scooping water into an empty vial from a fountain. 

Weekly Update – September 9, 2022

It was a highly productive week. 100% of my time went into features and fixes that are required for the initial release (not always the case).

  • Status effect icons. Enemy status effect icons now appear above the enemy. Player status effects are now represented as icons as well, located next to the health bar.
Status effect icons
  • Loading screen. New levels now display a loading screen, complete with a progress bar and text describing what is currently happening. At first, the progress bar was based on AsyncOperation.progress, which tracks the progress of an asynchronous scene load in Unity. The bar quickly got to 90% and then hung for around ten seconds. This delay was, of course, the procedural generation. Luckily, when I made the map generation visualizer last year, I had to reduce map generation into hierarchical, independent units of work – maps are generated by a series of processors, processors are composed of stages, stages are composed of substages, and substages are composed of tasks. The tasks are pre-generated and placed in a queue. This enables the map generation visualizer to display the result of one task at a time and interactively fast forward through substages, stages, and processors. It also makes it easy to calculate the progress percentage. I only had to make a slight modification to make it work with the loading screen progress bar, which was to wrap it in a coroutine and have it yield after each substage so that the UI could update the status.
Loading screen
  • Cell selection improvements. The area of effect is now highlighted and the cell indicator (not just the mouse cursor) is now shown.
  • 15 sound effects added.
  • Bug fixes.

Next week I’ll take a break from new features to shorten the bug list. Saving and loading is broken again.

Weekly Update – September 2, 2022

In last week’s update, I stated that sound effects would be the focus this week. I didn’t touch that. Instead, I wound up spending the entire week on visual improvements.

New ability icons and stat meters
  • Replaced ability icons. I was using effects and item sprites from the Oryx 16-Bit Fantasy sprite set as temporary ability icons. The images were loosely applicable at best, and too abstract to infer their purpose. They were plain and in some cases downright ugly. I didn’t want to see them anymore so I bought a giant RPG icon set from the Unity asset store to replace them. The visual style didn’t quite match the rest of the game, but that’s ok; I still plan on replacing them with original artwork eventually. I wasn’t able to use them “out of the box.” They were 32×32 pixels in size, while item/ability slots were 16×16. My solution was a compromise: I’d crop the icons to 24×24 and increase slot sizes from 16×16 to 24×24. I spent more time on this than I expected. It took a while to find the right icon for an ability, and additional time to find the right 24×24 section within the original to crop. It also required resizing slots everywhere they were used (inventory panel, ability panel, inspect panel, hotbar, quick switch slots). Since the slots use a common prefab, I only had to change the prefab rather than each individual slot, but then I needed to change panel sizes and move some UI elements around to accommodate the larger slot sizes.
  • Increased the hotbar size. This was necessitated by replacing the ability icons. I’m not thrilled about giving up more screen real estate for the hotbar, but I don’t have an alternative because I believe 24×24 is the minimum resolution for an image to portray an ability.
  • Replaced the font. The original font was an 8×8 monospaced font commonly found in early arcade and console games. The main issue with this font was space. It was difficult to read at a small size. I could have increased the resolution for text, but it wouldn’t have looked right to have pixelation at two different resolutions (one for images and one for text). Also, my aesthetic preferences have changed since then. It can be a long road to finding the right font. 80% of my time this week went into searching massive font databases and curated lists, studying screenshots from other games, and trying different fonts out in the game. I could have easily spent the entire week, and many future weeks, on this pursuit. I have a persistent problem with wanting to start with the largest space possible, explore every possibility, and narrow down to the absolute best choice. With something like fonts, there just isn’t a best choice; it’s too subjective. I decided on Merriweather because it’s a serif style but is designed specifically for screen use.
  • New status effect: Charmed. Causes an actor to fight for the caster.
  • New abilities
    • Charm. Temporarily charms an individual actor.
    • Mass Charm. Temporarily charms all actors in a 5×5 square.
  • Improved stat meter visuals. I wanted to make these look a little less plain.
  • Minor improvements
    • On the Title Screen, the Continue button now appears above the New Game button, since the former will be used more often than the latter.
    • Select cell prompt repositioned so that it doesn’t appear over the player or other UI elements.
    • Increased the number of recent log messages displayed from 4 to 8.
    • Reduced the size of tooltips.

Next week, I plan on adding a loading screen (the presently inefficient proc gen freezes the game for ~10 seconds per level), enemy status effect icons, and sound effects time if time permits. 

Weekly Update – August 26, 2022

After literally years of research, brainstorming, analysis, and procrastination, the types of resources consumed by abilities have been determined. This decision has been drawn out by many dependent questions regarding Legend’s underlying resource management design: are resources finite or infinite? Is there a hunger clock? Do health, magic, etc. regenerate? Not all of the questions have been answered. I aspired to find the perfect solution, but the model is too complex to assemble, and I no longer believe a perfect solution exists anyway. I increasingly aim for solutions that are good enough, solutions that don’t offer complete flexibility, but are flexible enough. I embrace the resulting constraints, for they shrink the answer space, and foster creativity. And thus, at the end of the ability resource design journey, I arrived not at revelation but convention, with the health/stamina/magic trinity, a staple of the PC RPG.

  • Ability resource consumption design. Abilities may consume stamina, magic, health, and/or items. Magic fuels spells, stamina powers physical feats, and items are needed for specific skills such as picking locks. Like health, stamina and magic are represented in points. The quantities of resources consumed by each ability will be fine-tuned during balancing.
  • Player magic and stamina meters. Stamina and magic meters now join the Health meter. I reduced the dimensions of the meters so that they cover up a smaller screen area.
Redesigned health/stamina/magic meters
  • New Action Step: Consume Resources. Luckily, I didn’t have to implement a new system to handle resource consumption; it fits nicely into the Action Step framework, becoming another building block for constructing actions. This was the most logical solution, since abilities essentially just invoke actions.    
  • Added Action Source to Actions. Actions are defined using the following structure: [Actor] do [Action Type] with [Item(s)] on [Target] in [Context]. For the Consume Resources Action Step to work, it needs the source of the action (the ability that invoked the action), so that it knows which resources, and how much of each resource, to consume. The action source has been added to the actor structure, making the structure now: [Actor] do [Action Type] from [Source] with [Items] on [Target] in [Context]. This required a lot of changes in the code, but was done quickly using global search and replace (which is surely an architecture smell).
  • New items
    • Magic and Stamina Potions. Self explanatory.
  • New abilities
    • Health to Magic. Recover magic at the cost of health. No class with healing abilities will be able to use this, since it would be possible to have unlimited health and magic.
    • Magic to Stamina. Recover stamina at the cost of magic.
  • Visual effects. While looking for a way to modify sprite colors at runtime (I need to display grayscale versions of sprites and make sprites appear frozen when they are hit with an Ice spell), I came across a Unity Asset, All in 1 Sprite Shader. It does far more than I need (at least currently), but it was very popular and highly rated (and on sale) so I bought it. Of all the Unity assets I’ve installed, this asset is probably the easiest to learn; simply add the component to a gameobject and, using the component’s UI, select the visual effects you want to apply. However, I don’t think I’m using it in the intended way. I didn’t want to add the component to the dozens of actor and item prefabs because I didn’t want the visual effect to be always on, and I didn’t want to maintain an extra component for actors and items. So, I just used it to make materials, and I’m applying the effects at runtime by changing the sprite material.
  • Improved random Map Element selection. Previously, all Map Elements were assigned a rarity level, which served as the weight in a weighted randomizer. The problem with this is that the rarity distribution changes depending on the number of Map Elements of each rarity level. I’ve now split the selection into two steps. The first step selects the rarity level using a fixed set of probabilities. The second step selects a Map Element from the list of Map Elements of the selected rarity level. This ensures that Map Elements are correctly chosen based on the rarity distribution.
  • Bug fixes
    • Quick Switch and Hotbar slots still interactive after the player dies
    • The action indicator cursor still appears after the player dies
    • Enemies stop moving when the player moves out of sight
  • Minor improvements
    • The Escape key now cancels the Select Cell prompt. My goal is for the game to be completely playable using a keyboard and/or mouse.
    • Ability resource consumption support
      • Preventing abilities from being used if there are insufficient resources
      • Dimming slots containing abilities that can’t be used due to lack of resources
      • Tooltips indicate why ability slots are dimmed

Next week, the major task is reassigning sound effects. I’ve purchased several collections from the Unity asset store, but I recently pulled the files out of the Unity project because they were making project snapshots huge. Now, I need to bring only the sound effects that the game is using back into the project. Beyond that, there will be more play-testing and tightening things up. 

Weekly Update – May 20, 2022

This week’s focus was on expanding Action Steps and Abilities. A big chunk of time went into solving an issue with Action Step sequencing. An action’s Action Steps are instantiated and queued when the action is instantiated. A manager class then executes the Action Steps in order. This is a problem when an Action Step depends on the outcome of a previous Action Step, for example selecting a cell. I solved this problem by passing the action to each Action Step constructor and using the common properties in every action to pass values (every action has an actor performing the action and optionally, a target entity and entity that the action is performed with). It’s an imperfect solution but I needed to move on.

I also resumed the practice of adding at least one new Map Element each week.

  • New Ability: Charge. The Charge ability causes an actor to move up to several cells in a straight line and perform a melee attack within a single turn.
  • New Action Steps: Move and Melee Attack. These Action Steps enable an action to move an entity to another cell and perform a melee attack, respectively.
  • New Map Element: Spikes. Spikes simply cause damage when an actor walks on them. The player will have different ways of dealing with these, and they can also be useful in some situations, for example pushing an enemy onto them. They’re currently placed in a random row or column within a room. 
Spikes
  • Refactoring. Redundant parameters.

Next week’s goals are undecided. I’m due for a round of bug fixing; there are a number of known issues that I’m able to work around during playtesting but must be removed before release. I also need to keep the pixel artist search moving forward by posting in a couple more places and contacting the best artists from the original post.

Weekly Update – February 11, 2022

UI finalization, which started two weeks ago, continued this week. Some questions that have been open since day one, such as available equipment slots, are getting answered because they’re dependencies for completing the UI.

  • Decided on equipment slots. This is finally done. It was one of those things that I overthought. My original philosophy was to keep things simple and have a single armor slot, and some slots for accessories like rings. My thinking changed as the depth of the game expanded. The final equipment slots are Armor, Helm, Gloves, Boots, Necklace, Rings (2), and Shield (note that weapons are handled in a different manner, to be explained in a future post). Adding the new slots to the actor inventory was easy. I had to do a little bit of rework because of the rings. The original logic assumed that there’d only be one slot per equipment type.
Equipment slots and new items
  • Updated damage absorption and evasion calculations. With multiple pieces of equipment potentially affecting damage absorption and evasion, I had to update the combat calculations. This wasn’t difficult, but balancing got more complicated. I now have to consider mixed pieces of equipment, partial equipment, and class restrictions on each equipment type.
  • New items: Leather Gloves, Leather Boots, Leather Cap, Wooden Round Shield, Wand of Magic Missile, Necklace of Protection, Ring of Invisibility. These were created to test the new equipment slots. They may or may not make it into the final game. In particular, the Ring of Invisibility, which grants invisibility as long as it’s worn, is too overpowered.
  • New map elements: Mushrooms and Crystals. Caves are in need of more variety so I added glowing mushrooms and crystals.
Crystals
  • Indefinite status effects. Previously all status effects were temporary; after a certain number of turns the effect disappeared. Now, status effects can last indefinitely. This was needed for the Ring of Invisibility and will be needed for all equipment that gives the player a status effect while worn. 

Next week, I’m implementing the quick switch slots for weapons and light sources as part of the UI finalization.

Weekly Update – February 4, 2022

It was one of those weeks where most of the time went into thinking rather than doing. Hence, there weren’t many concrete achievements. The thinking was around UI design, specifically how to quickly switch between different weapons, how to automatically use ranged weapons for distant enemies and melee weapons for nearby enemies, how to handle torches, and equipment slots. I wrote out so many different solutions. None of them were perfect; they each had pros and cons. I think I’ve chosen a solution but need to consider how the solution applies to all the possible scenarios. The solution involves an additional hotbar that lets the player quickly change melee weapons, ranged weapons, and ranged weapon ammo, and logic for when the player clicks on a cell that determines whether to use a melee or ranged weapon. It seems sound to me, but only feedback from other players will confirm whether it is intuitive and user-friendly.

I added a few new map elements, which is something I’m trying to do every week to have a wide variety by launch. As always, there were some bug fixes too.

  • Witch’s Chamber. The Witch’s Chamber map element places a cauldron, a witch, and some bookcases and tables in a room. The witch is brewing something in her cauldron, which emits a blue glow. I need to give the witch some abilities. I’m not sure what I’ll do with the cauldron.
Witch’s chamber
  • Summoning Chamber. The Summoning Chamber map element places a summoning circle, demon, and summoner in a room. The summoner has just recently summoned a powerful demon in the summoning circle. I need to build out the demon’s abilities and the summoner’s AI (the summoner lets the demon do the fighting and avoids the player).
Summoning chamber

Also, here are a few examples of the objects added last week:

Pots and varied rubble
A rug
Grass and statues

Next week I’ll implement the UI features I spent this week designing and try them out in the game. This is the next item on the critical path. 

Weekly Update – January 15, 2022

This week was spent finishing the [2022 in RoguelikeDev] post and continuing work on lighting.

Light from a brazier
Ran out of torches
Light leaking through walls (need to fix)
Illuminating a hallway (walls not showing, sort-of fixed since)

My lighting efforts alternated between two idioms: spinning my wheels and going around in circles. I learned some things at least. It became apparent that I don’t completely understand how I want lighting to work. The challenge is integrating lighting into fog of war, field of vision, and orthographic projection. On top of that, I’m still learning general lighting concepts and the Smart Lighting 2D Unity asset, which is fantastic but really lacking in documentation.

The lighting work also resurfaced another issue that I’ve yet to resolve: hiding portions of wall tiles that represent the other side of the wall and that the player shouldn’t be able to see. This is particularly an issue with the Oryx tileset because the walls have a top-down projection. Players can determine whether the tiles adjacent to a wall tile are floors or walls, even though those tiles are outside the player’s field of vision. It also makes secret doors easy to spot. The best solution I’ve come up with is to add a shadow tile map above the wall tile map that covers the quadrants of the wall tile that the player shouldn’t be able to see. But, it’s been a real struggle figuring out the logic that determines which shadow tile to choose based on the adjacent tiles.

A lesser concern, but still something that needs to be addressed, is how lighting affects the minimum hardware requirements. In many games, lighting effects are graphics options that can be turned on and off. In Legend, lighting is part of the gameplay and can’t be optional. I want to keep the hardware requirements as low as possible so that Legend can be played on older computers.

Next week, I’ll continue setting up lighting.

2021 Year in Review

2021 Retrospective

Legend has been in development for 2.3 years. It’s hard to believe that that much time has passed since I started working on the game. I don’t know if anyone else has experienced this, but how I felt at the two-year mark was in stark contrast to my feelings at the one-year mark. After the first year of development, I was thrilled with how much I had accomplished and excited for the future. At two years, panic set in. How could I possibly finish at the rate I was going? Was I wasting my time? Was this game even any good? 

Ultimately, the mid-gamedev crisis was a good thing. This was my brain telling me to reassess and correct course. That’s exactly what I did in the latter part of the year. The reality was that, at the rate Legend was progressing, it would need at least several more years to release. I don’t want to wait that long (I have more games to do!). I cut a large chunk of planned features while preserving the original vision. I forced myself to make decisions. I have a tendency to postpone decisions as long as possible to avoid limiting possibilities. It’s been a sure-fire way of keeping completion in the distant future.

Development thus far has consisted primarily of building the game system framework, and rebuilding many facets of the framework as my Unity knowledge increased and my ideas crystalized. Heading into 2022, the framework is done and development shifts to using the framework to flesh out the actual game.

What I said I was going to do in 2021:

Replacing the stock art

Completion: 0%

I’m still using Oryx. I still have some uncertainty about the exact 2D perspective that will be used. I also feel that the art doesn’t need to be replaced until the game is ready for a public release.

More content 

Completion: 5%

A handful of new enemies, items, and objects were added. Every piece of existing content was reworked in some way, for example extracting a parent class for actors and items, and moving from room-based to element-based map generation.

More polish

Completion: 30%

At the beginning of 2021, I never would have expected to accomplish as much as I did in this area. I considered polish something you do at the end of development. That largely is the case, but I’m using “polish” loosely here to refer to any visual and audio effects beyond the bare minimum, and refinement of any sort, such as fine tuning procedural generation and balancing combat. The game looked bad and felt dull whenever I did testing. Even though I knew I’d improve the look and feel before launch, I was still getting discouraged. For my own psychological benefit more than anything else, I added some game juice, including:

  • Particle effects
  • Better combat and movement animations 
  • Screen shake
  • Environmental impact: corpses, particle effect residue
  • Sound effects

Visuals | Sound Effects

This did the trick; I could finally envision other people playing the game.

Community building

Completion: 5%

I posted a weekly dev update on the website and Sharing Saturday on r/roguelikedev. I posted the link to each Sharing Saturday update on Twitter. I occasionally posted videos on Youtube. I have tiny followings on those channels. I continued to spend a minimal amount of time on community in favor of game development.

Early access release (aspirational goal)

Completion: 10%

This was nowhere close to happening, but there was movement toward this goal due to focusing on it at the end of the year. I also created a mind map visualizing features by release and a roadmap.

What else happened in 2021:

The new map generator, started in 2020, was finished in January. I built some dev tools for procedural generation analysis, tuning, and troubleshooting: an interactive map generation visualizer and a map graph visualizer. These proved to be very handy.

A map graph

I made another major change to map generation later in the year with the addition of Map Elements. These are the basic building blocks for populating a map with content after the map structure’s been created. They’re hierarchical and modular, enabling rooms to be constructed from layers of interchangeable components and reuse common components. For example, many room types can include an Abandoned Map Element that adds cobwebs and debris to give the appearance that the room is abandoned.

Maps became both more varied and more playable. Map configuration parameters, which dictate a map’s structure (number of rooms, room sizes, room distances, room themes, etc.) are now randomized. This additional layer of procedural generation increased the variety of maps while maintaining consistency within a map. Map configuration parameter ranges were fine-tuned to avoid problematic maps. Room type probability changed from a linear distribution to a weighted distribution based on rarity to give maps a more logical composition of rooms.

Significant UI work was done. New screens were added, a hotbar was added, and the main game UI was refined. 

Class selection screen
Inventory and hotbar

In action:

AI was expanded. Now, actors can have their own AI controllers and behave differently than other actors. AI controllers can be reused across multiple actor types. Actors can now track any number of other actors, enabling them to do much more than charging the player. They can attack, defend, and interact in other ways with tracked actors as dictated by their AI controller. Actors now gain awareness of events based on their vision and hearing ranges and act based on the type of event occurring. Each actor has its own inventory and the ability to pick up items and use them. When an actor dies, other actors can acquire the items it was carrying.

In light of my time constraints and the mountain of work remaining, I made a deliberate effort throughout the year to increase my productivity. The ways in which I did this include:

  • Reducing and simplifying code.
  • Moving logic from code to configuration (physical material interactions, game events).
  • Adding unit testing.
  • Adding an in-game console for spawning objects to accelerate playtesting. 
  • Adding more granular logging so that I have more information to troubleshoot.
  • Consolidating test settings into a single design-time editable object.
  • Switching my IDE from Visual Studio to Rider.
  • Reorganizing my Unity editor layout.
Reorganized Unity Editor layout

Finally, code rework occurred throughout the year. Most of it was necessary to keep the code maintainable, but I also know that I am overly eager to rework code and sometimes create more problems for myself than I solve. As the year progressed, the rework did slow down. There are two reasons for this: 1) the framework reached maturity and 2) I became more selective with when I reworked code. Before I make changes or add new features, I now consider what compromises I can make and what I can do within the existing framework to avoid rework. 

2022 Outlook

This year’s goals are essentially the same as last year’s. However, the priorities have changed. An early access release is now the primary goal. Original art, a requirement for the release, is also a top priority. Effort will be concentrated on what is absolutely necessary for public release, including tightening the game loop, balancing, and clearing the bug list. 

Weekly Update – January 8, 2022

The first week of the year is always busy work-wise and this year was no exception. Hence, progress was limited.

  • Figuring out lighting. I started to get the hang of the Smart Lighting 2D Unity asset. I set up a light source from the player and tilemap lighting so that light collides with walls.
Light colliding with walls
  • General room map element. Not every room in the dungeon can be a prison cell, summoning chamber, armory, etc. Rooms that don’t become one of these special types are referred to as “general” rooms. These rooms contain a random mix of enemy, object, and reward map elements. Adding this feature to map generation really helped fill out the dungeon in terms of use of space, challenge, interesting combat, and rewards.
  • Item rarity. Items already had a rarity attribute, but it wasn’t used. Item rarity values have been populated and rarity is now considered when placing random items.

Next week, I’ll keep working on the lighting and some miscellaneous gameplay improvements/features like reducing the player input required to shoot arrows and making the weapon hotbar functional.