Tag: Game Design

RPG Game Dev Weekly #2

Well, so far not so great for getting weekly posts on this! It’s probably better for me to aim to do these periodically and summarize the last week or so of work. Fewer commitments that way and it’s a bit more realistic for me to achieve. With that said, let’s dive into it!

Entity Filtering in an RPG

Our RPG has had some notion of entity filtering for a long time, but to understand the current state of filtering, it’s important to understand the two major sets of entities and components we have:

  • Game Objects + Behaviors: Everything in our RPG game world is represented as a “game object” and the properties/capabilities are captured by components called “behaviors”
  • Definitions + Generator Components: The content for our game is represented by “definitions” and the “generator components” are how we transform this information into “game objects” and “behaviors”

Because I heavily focused on our loot generation system early on, the focus for filtering was really around being able to select loot from “drop tables” (which have item definitions on them and associated with enchantment definitions). Early on it was a goal to ensure that loot generation and other game systems could have extremely complex situations handled, so we needed to be able to do things like generate loot given arbitrary game state. Additionally, this system needed to be fully extensible to support any game state we wanted to add in the future.

In what might seem to be an extremely contrived example, assume we want to generate item X when:

  • The player is level 50+
  • The current weather on the map is raining
  • The current time of day in the game world is night
  • The player has completed quest A, B, and C
  • The player is holding item Y
  • We are generating loot for killing enemy N

These conditions represent a filter that we need to execute, but I never realized until recently that the implementation of this is actually something I’ve started calling “bidirectional filtering”. This means that we’re running a query with a filter over a set of drop tables, but we provide along some state and the drop tables are filtering backwards on this state. Sound complicated? It was, especially before explicitly thinking of it as bidirectional filtering!

It can be more easily digested when thinking of it this way:

Provided Game State:

  • Current weather
  • Current time of day
  • Player (level and equipment in this example)
  • Quest status

Required Filter from Game:

  • Drop table ID matching enemy N

Using the above information, we select all drop tables matching the required filter from the game. Essentially, any drop table ID for enemy N. For each of the drop tables that match this specific ID, we then run THEIR filters the opposite direction on the game state! If a drop table had no specific filters on it, it would match right away. However, if it had a weather filter on it, it would need to match the provided game state weather.

Okay so that’s bidirectional filtering in our RPG, but this is what ALREADY existed! So what did we need? We actually just needed single direction filtering. Literally just standard querying of game objects. Half the battle of what was already in place!

If you’ve played games like Path of Exile or even Last Epoch, you’ll see indicators in the game that there are tags associated with different things (like skills, items, enchantments). If in our game we want to be able to query all items in a player’s inventory that are of type “axe” or all skills associated with “fire”, we need some way to filter our entities. And in this case, there’s no need for the entities to filter backwards like in bidirectional filtering!

We expanded our filtering system to support this now, which unlocks:

  • Skills that require certain item types
  • Skill prerequisites that aren’t just a skill ID
  • Advanced skill targeting
  • Enchantments that boost skill stats (damage, levels, etc…) that match a particular filter
  • Crafting / Alchemy (i.e. filtering on ingredients)
  • Item socket patterns (this was already in game, but we can do this declaratively instead of writing custom-coded plugins)
  • Restricting applying poisons or consumables to certain item types
  • … this list goes on and on!

RPG Movement Overhaul

This block of work is what chewed up most of my RPG development time the past few days. I was frustrated with my initial and seemingly failed implementation of A* for path finding. For anyone that’s gone through popular computer science algorithms, A* is a pretty straight forward algorithm for finding shortest possible paths. It’s really popular in games because it’s extremely efficient! But my take on it just wasn’t cutting it for our RPG, and it would often report that no paths were possible (which just wasn’t true)!

Our RPG has an explore mode and a combat mode, sort of like Pokemon. However, the combat is tactical, so it’s sort of like Final Fantasy Tactics with respect to that. Being a 2D tile-based game, having tile-restricted movement makes a lot of sense. However, early on I felt that having free-form movement in the explore mode felt really fluid and fun. There was no great reason our explore mode needed to be tile restricted. However, making this movement system decision complicated all of our tile-based movement by trying to re-use the same code.

So I did a thing that I find feels counter-intuitive as a programmer normally… I duplicated a bunch of code, one for supporting tile-based movement and the other for freeform. No more “common code” for this. From here, I found I could actually start correcting each movement system and tailoring it to do the right thing. I was hitting this blockage before because these really were two fully separate implementations of class that can support movement.

From there, I worked through my path-finding issues. I built out some visuals that can determine where the player can move, and used this to validate what I believed I was seeing in my unit tests. 2D stuff is easier to understand visually! The following is an example that shows a snag that I hit where our logic to check “can we move to this position” was incorrectly calculating the distance to that point. If the player has only 3 moves to make, why does it think it can get to the tile labeled 4?

The answer? It was doing birds-eye distance checks back to where the player was standing. Not going to work for our RPG! Instead, I was able to re-use part of the A* algorithm to calculate the distance as the algorithm progresses through neighboring nodes. I also needed to update A* to report the total distance in addition to the positions on the path. The result was consistent calculations between our valid walk points and the actual pathfinding algorithm. The next snapshot shows a small update to the visuals:

And at this point, it was really just about showing/hiding/updating the valid walk highlighting at the right times! So I figured I’d whip up a little video to show progress on that:

What’s Next In Our RPG?

We’ve been making some awesome progress on our RPG. We’re starting to look into random dungeon generation, and I’ll probably try to find something more architectural to tackle. I find I burn out fast when I spend too long on things that feel strictly visual or like I’m polishing things. In this case, the movement part of combat is critical so it needed to get done. But reflecting on all of the changes there was nothing fundamentally changed in our game to accomplish this.

Additionally, I’m going to start doing a better job of adding more content. I’ll be adding in item affixes for item generation, prefixes/suffixes item name creation, and ideas for items that can drop. I don’t think we fully have the components required to define all the items I’d like to make, so I’ll start just by recording my thoughts in a consistent format.

Overall, we’re moving in the right direction! But there’s no denying making an RPG is a ton of work!


RPG Game Dev Weekly #1

As I’ve been trying to get more YouTube content put together more steadily, one of the themes I’m interested in is doing some behind-the-scenes of the role playing game (RPG) I’m making with some friends in Unity3D. I’ve found that being able to work on an RPG outside of my regular day job is a really awesome way for me to keep up on my technical skills. I love coding, and the further along I move in my career as an engineering manager, the less time I actually spend writing code myself. I pride myself in being a technical engineering manager, so for me working on this RPG is a great outlet for creativity and practice. I mentioned this in my LinkedIn post here:

Persisting Game Objects Across Maps

In this video, I focus on one of the challenges the game was facing due to how objects are materialized onto the playable map. The map that we load from disk to be shown and interacted with in the playable RPG commonly has “templates” and “spawners”. Both of these are responsible for creating objects at runtime given some criteria. As a result, uniquely placed game objects appear on the playable map for the player to interact with.

Sounds good then, right? Well the two challenges I focused on addressing were:

  1. If we leave the map and go to another one, there’s no way to persist the player across maps! That means you get a brand new character every time you transition maps. In an RPG, this is definitely not going to work out.
  2. If we return to an existing map, we expect it to be in the same state as when we were last on it. This means that the objects generated from templates or spawners must remain and NOT be respawned (which would effectively make completely new game objects).

Check out the video below:

RPG Dev Log 1 – Persist Game Objects Across Maps

Persisting Map Game Objects in a Cache

Next up was actually implementing some of the changes being discussed previously. In order to make this work in our RPG, my goal was to:

  1. Allow maps to save a lookup of the unique IDs for game objects that were generated
  2. Save the list of game objects generated into a “cache”
  3. Upon revisiting a map, tap into the “cache” to reload the existing game objects

One of my mental hurdles with this was acknowledging that we don’t yet have a solid serialization foundation for our game. I was thinking I’d want to serialize the game data to something persistent to make this work, but I was also worried writing things to disk would be overkill (and how does this mix with save game concepts?). Instead, I opted for the lightweight approach was “get something working” and I can revisit this later to extend it to persist things to disk if necessary.

Check out the video below:

RPG Dev Log 2 – Persisting Map Game Objects in a Cache

Which Domain Does This Belong To?

We’ve been trying to practice Domain Driven Design (DDD) concepts in our game. One pattern I’ve taken to an extreme is over-separating domains into very granular pieces and the result is that we have HUNDREDS of C# projects. It’s overkill, for sure. However, I feel that it’s offered some flexibility in having boundaries we can collapse later. My experience so far has told me it’s easier to collapse boundaries than it is to split.

This is all and well until we have situations where I need a class that has knowledge of two domains. That’s what this next video was about. I talk through acknowledging that I don’t know what to do and that I’ll move ahead with something best effort. I think the answer to my dilemma is that I need to translate things into a new domain for usage, but it feels like overkill. If you have thoughts on this leave a comment on this post or on the video!

Check out the video below:

RPG Dev Log 3 – Which Domain Does This Belong To?

Death Animations For All!

Finally, this last update was about something hopefully less boring… Death animations! I worked through how:

  1. I can extend our reusable sprite animation factory to create a death animation to be reused by ALL our actor sprites
  2. I can build a system that checks actor life and changes the animation as necessary to death

Unfortunately I had some hiccups the first time through recording this, but I wanted to code the whole thing live. After a Blue Screen of Death interrupted my first attempt, my second attempt I think worked pretty well! Without much code at all we could get this system fired up and it worked the first time! Well, close. I didn’t realize that our animation system already supports an animation that has an “infinite” duration final frame (in this case, the body laying on the tile). This is handled by a null value instead of a set length in seconds. I fixed it right after recording! Overall, I was incredibly happy with the result.

Check out the video below:

RPG Dev Log 4 – Death Animations For All!

Part 1 – Exploring Graphs and Trees

Graphs and Trees - Delta State Algorithm

Graphs and Trees to Start

I was chatting with my colleague about generating maps for a 2D role playing game the other day after getting super excited explaining picking ProjectXyz back up and looking into Unity3D more. He was expressing interest in algorithms for procedural generation and storing data in trees or graphs as an optimal data structure for the scenario we were going over.

It stuck with me though. I’ve been putting a lot of thought into game state management and wanting to address it by using a generic layering/stacking approach. By that, I mean that I want to find a way to take base game state, allow mods or plugins to overlay their state, allow game patches to overlay their state, and then save game data to be overlaid on top of all of that. Conceptually, I believe I can create a generic system for doing this stacking of game data, which I’ll be referring to as my Delta State Algorithm, but I’ve been struggling with a starting point.

But the trees and graph concept stuck with me because the properties of trees and graphs that my colleague was referring to seemed to line up with how I envisioned this algorithm working. A graph or a tree just might be the right structure to represent this game state and the deltas between them, so I wanted to start mocking up some ideas.

A Map is a Game Object… And so is Everything Else?

Confusing subheader? You bet. But it’s because it was an odd realization.

I’ve been re-writing the same back end for an RPG for years now. Literally, it’s probably been at least 10 years that I’ve started, progressed, and scrapped such a game. But one thing I borrowed from Unity3D development was the idea of components and component-based design. I was far too married to object hierarchies, and these would eventually result in me having to refactor a TON of code. If you couple that with the fact I wasn’t using dependency injection properly (see this little primer article), it meant my refactoring efforts got to the point where it just made sense to start over.

So I was working with loading maps from TMX or Tiled map formats, and after getting these to load I was putting some thought into how I wanted to save/load my game objects. My game objects are essentially containers of components, and the containers have no properties at all. What does that mean in practice? My Actor/NPC game object class is the exact same class as an equippable item! It’s just “GameObject”. The difference between them is the variation in the components that I attach to them. In my mind, I figured I’d need some sort of hierarchical serialization paradigm where my game object would serialize itself, then the components would serialize themselves within that process, and if I could have components with components… You get the idea. But this could sort of be represented by a tree structure.

After the discussion with my colleague about trees and graph structures for maps, I connected some dots. Really the tiles and placed objects on a map were just… game objects as well. And that means that my thought process behind hierarchical serialization aligns well with some of the properties he was referring to for maps as graphs/trees. This suggests that “world state” for a game where everything is a “GameObject” with components attached to them (where some of those components can contain other GameObjects) could be represented by a graph or tree data structure

What About Tabulated and Listed Data Sets?

So we’ve come up with a starting point for “World Data” being represented by a graph. However, if we go back to my initial goal, I want plugins/mods/patches to be able to get applied to base “Game State” data.

What’s the difference between world and game state data?

These are just my terms so I should try and clarify. The world data is the data the player sees in the playable world. It’s the status of the objects and the maps they are interacting with. Game state data is the superset of this data and all of the other lookup data for loading content into the game. So this OTHER data includes things like the possible stats players and items can have, the types of monsters that can spawn (not the instances of the spawned monsters, because that’s the world state data), the possible dialog entries, etc… This type of data is really well represented in a relational database where we can create lists of data entries.

But if we take a step back, can’t that relational database content also be represented as a graph?

Could I have:

  • A node called “Stats” as a parent to a “Life” node that is a parent to a “StatRange” node, and “LocalizedNameResource” node?
  • A node called “BaseItems” as a parent to a “Sword” node that is a parent to a “DamageRange” node, “RequiredStats” node, and “EquippableSlots” node?
  • A node called “MonsterSpawns” as a parent to a “Skeleton” node that is a parent to…

You get the idea. I generally think about this data in a relational database paradigm (and perhaps it’s much faster to edit the data this way or look it up this way). However, if I can transform this data into the same type of graph structure I want to use for world state, then it means my delta state algorithm would work on not only world state data but also ALL game state data.

So Everything in the Graph? Always?

This is an important question, and I think one that without actually explicitly thinking about was causing me some headaches and keeping me from progressing down exploring more of my delta state algorithm.

I mentioned that some of the game state data feels better represented in a relational database. It might be much faster to add/remove or look them up when the data feels like it’s just a list of records when you contrast that with a graph. But why not have multiple storage mechanisms?

The delta state algorithm serves a very important goal: Layer deltas of data on top of a base set to get a new set.

That’s it though. So once I have that final transform of data that represents the new game state, who says I can’t transform it into a different format?

Maybe the world state is still better represented as a graph. So things like maps with tiles and game objects in the world still are super efficient to work with in graph form. Maybe things like dialog entries or definitions of player stats are better represented in a relational database… I could populate a database with the necessary data based on the graph data though. And the really cool part? A save game, which is probably the delta that changes the most, probably shouldn’t have the extra game state data in it (likely just has world state deltas represented). So… if a relational database is better suited for the remaining game state data, this could get generated and cached, and then only regenerated when different mods/plugins/patches are applied!

Concluding Thoughts

To summarize some of the major thoughts discussed in this article:

  • Game objects with components can be represented by nodes in a graph just like maps with tiles on them.
  • Other game state that feels better suited for relational databases can still be transformed into nodes in a graph for working with deltas.
  • Once a final game state is calculated (based on base state + deltas for mods/plugins/patches + delta for save game), data can be transformed back into the most suitable form to work with
  • Data does NOT have to exist in only one form! We can transform it as we need to work with it more effectively.

While this article was a bit of a brain dump, this the thought process that got the ball rolling for starting to design this delta state algorithm. In my next post in this series, I want to discuss a quick look at undo/redo approaches used in applications and how they might be similar (or different) to how the delta state algorithm might work.


Delta State Algorithm Creation Series

Delta State Algorithm

Delta State Algorithm Motivation

This post will act as the table of contents for an algorithm I’m developing for calculating deltas between state for generic sets of data.

I figured this would be an interesting series to write about so I can document my thought process, trials, errors, and successes. At the end of this I plan to share working code that implements this algorithm so that you can use it in your own work.

Now that I’ve been not diving more into Unity3D development for my hobby programming, I’m getting to a point in game development where I need to manage state for data in a way that allows patches of state to be applied in a layered fashion. A couple of examples of this include:

  • Applying save game state to a base game state
  • Applying a patch to a base game state
    • Optionally allow save game state to be applied on top of this and completely override as necessary
    • Optionally allow save game state to be applied on top of this but “retroactively patch” existing save game data

I believe that I can design an algorithm that’s relatively simple that should allow the layering to work, but I have a lot of potential corner cases to figure out (especially when considering retroactively vs not for applying game patches). I’ll be exploring data structures to use and technologies to leverage for persisting this state.

It should be pretty exciting!

Delta State Algorithm Series

Just a reminder that if you’re interested in this series, you’ll want to use this page as the starting point. As I continue to add new content to this series, I’ll come back and update this page with links to the parts of the series. Ideally at the end I’ll have some working code I can share!

  • Part 1 – Exploring Graphs and Trees (TBD)
  • Part 2 – Undo/Redo Patterns (TBD)
  • Part 3 – Generic State Serialization to a Graph (TBD)
  • Part 4 –  … TBD

  • Copyright © 1996-2010 Dev Leader. All rights reserved.
    Jarrah theme by Templates Next | Powered by WordPress