Skip to content

Khemitron Industries

Amateur Game Dev, Gaming, and TTRPGs

Menu
  • Home
  • Game Dev
  • About
Menu

Refactoring the World Map

Posted on 2025-06-09

It’s been a couple of weeks since my last post. So that should mean I’ve got a lot of progress to show on my world map refactor, right?

Well, not quite. My day job suddenly became very intense, which left me with no desire to write code. That hasn’t been great, since refactoring is a very code-heavy process. On top of that, my friends persuaded me to play Marvel Rivals with them. It’s not my usual kind of game, so I was very surprised to find myself enjoying it. It’s probably because I’m only playing it with them and not random people.

Anyway, these two factors have not been conducive to refactoring the world map. But I’ve managed to carve out some time to make a start.

In this post, I’m going to talk about the choices I’ve made regarding the architecture of the world map. I’m going to analyse my experiences using the Model-View-ViewModel (MVVM) pattern that I set out in my post about the combat scene’s architecture. And I’m going to explain why I’m not using that for the world map scene.

Rebuilding the world map… again

I have already built the world map twice. Fortunately, I can afford to do so because this is a hobby project.

At this rate, I’ll probably decide I need to rebuild it another time or two by the end of the year. I hope that’s not the case though.

My first attempt was the first time I’d ever built anything in Godot, so I think it was right to discard it and try again.

My first world map used a static background image, but had no concept of map regions

In my second attempt, I built a hex map with regions. The idea here was that the regions would be used to determine:

  • What quests can spawn?
  • Which level should the spawned quests be?
  • What enemies should show up in the spawned quests?
  • How long does it take for a party to reach the quest site?
I like my second attempt and intend to keep the hex map style. All it really needs is better artwork and UI

In this, I was relatively successful. However, I ended up in a situation where many objects had references to other objects, and the game logic was incredibly entangled with these objects. Trying to follow the logic when I came back to it to start my refactor was not easy at all.

I’m sure I could have made this work. I’m also sure, however, that I would have ended up with a mess of spaghetti code that I couldn’t easily debug. That’s not good coding practice, and it would make adding new things very difficult, especially where they needed to interact with existing code.

So what am I doing this time?

Initially, I thought that I’d be rebuilding the world map using the same MVVM pattern, coupled with the observer pattern that I used in the combat scene.

With MVVM, each layer, theoretically, only communicates with the layer directly below and directly above

In this pattern, the game data, and some of the logic, lives in the Model. The ViewModel for each component then subscribes to relevant changes in the model, and tells the View to update. It seemed like a good way to decouple the logic from the UI.

However, I’ve found myself writing a lot of boilerplate code, and some of the ViewModels are nothing more than glorified functions to subscribe to events. I did achieve one of my goals though – the logic that drives the game is separate from the UI. Unfortunately, I don’t think this architecture works for my game.

So for the world map refactor, I’ve been using the Model-View-Controller (MVC) pattern.

In the MVC pattern, information flows in this cycle

The View (our UI components) passes input data to a Controller (possibly multiple controllers), which then manipulates the data in the Model. Finally, the data in the Model is used by the View to display changes. I’m also using another design pattern called the Event Bus to broadcast events across the whole system.

A quick example

This works in the following manner:

  1. The game loads up. The Model is created at this point. The UI uses the data in the model to display the game state.
  2. The UI and various other systems subscribe to relevant events on the Event Bus. This is like signing up to a specific newsletter, or following someone on social media. The parts of the UI that need to update whenever a region updates will subscribe to region events. Others might subscribe to quest events.
  3. Something changes – a timer might complete, or the player might do something like assigning a scout to a region. This change is passed into the appropriate controller.
  4. The controller uses that input to update the model. It might check whether an adventuring party has reached the quest location, or it might add a scout to a region.
  5. Once the model has been updated, the relevant event is sent via the Event Bus. This might be a QuestLocationReached event, or a ScoutAssigned event. Some events might contain information about the event, e.g. the region that the scout was assigned to, or the quest which has been reached.
  6. The components subscribed to the event then know that there’s been an update. They might check the model for new data and show it to the user, or unlock an achievement, or something else entirely.

What makes this a better architecture?

For the vast majority of software projects, there’s not one perfectly correct way to do it. There are multiple different ways to achieve the same goal, and each method has its own pros and cons.

I think this MVC with Event Bus approach (actually multiple event buses, split across multiple domains) will work well for me in this project. The pros so far are:

  • The code structure seems very logical to me. I can easily visualise how inputs and data are flowing through the game
  • The game logic is decoupled from the UI logic
  • It’s easy for new systems to hook in to existing events. E.g. if I wanted to add an achievements system, I could subscribe it to the events relevant to those achievements without needing to change any other code

However, I do need to be aware that the Event Bus pattern can be difficult to debug. With so many different systems subscribing to events, it could be easy to lose track of what code triggered a specific event. I’m hoping to mitigate this by using well-named events and a separate event bus for each domain.

What’s next?

Along with refactoring the world map code, I’ve been updating the UI to match my new snowy blue, black and silver theme. I’ve also been making sure to add saving and loading logic for everything as I’m going, as well as support for localisation.

In short, I’m doing extra work now to make sure that the whole world map is in a good place before I add in anything new.

Hopefully I’ll have a significant amount done before next week so I can show off the updated UI.

And once that’s done, I’m going to take a look at how I want to add sound effects and music into my game. Then I’ll move on to the systems surrounding adventurers – recruiting new adventurers, giving them equipment, and leveling them up.

Share on Social Media
facebook tumblr reddit emailwhatsapp

Like this:

Like Loading...

Leave a Reply Cancel reply

Your email address will not be published. Required fields are marked *

Recent Posts

  • Refactoring the World Map 2025-06-09
  • Using Themes to Enhance my Game 2025-05-19
  • Quality of Life Improvements – Nested Tooltips 2025-05-12
  • Improving Quality of Life 2025-05-05
  • Godot4.4 – Powerful Localisation with gettext 2025-04-27
©2025 Khemitron Industries | Design: Newspaperly WordPress Theme
%d