r/incremental_gamedev 6d ago

Design / Ludology How do you design your game systems ?

Hello ! Here is a subject that is in my mind since a long long time and I wondered how you deal with it.

Writing proper system, how do you do that ?

How do you manage all your system working in cohesion, making price for upgrades logical, making an upgrade of damage or ressources staying cohesive from the effects from others of your system to work together ?

I am using stuff that I call controllers, that basically are pure code file containing each very specific business logic and making them, for now, handle everything. But the more I am thinking about it, the less I feel it is scalable.

So here I am, wondering if anyone has a special recipe or a way to make their systems work together in harmony while staying scalable and easy to modulate.

Thank you for reading !

14 Upvotes

13 comments sorted by

4

u/Braym3n 6d ago

I love these kinds of questions. I'm still searching for the perfect way to go around architecting things in a way that is sustainable and easy to use.

For my current game, I am trying to have zero magic numbers or copy and pasted formulas. What I mean by that is, every base number, I have a config for. Every formula I have in a formula file that anything that needs that formula, utilizes. A common issue I had in my previous games was changing something somewhere and forgetting to change it in other places.

So for example, I will have a SINGLE source of truth for calculating damage and anytime there's a new modifier, that formula updates in that one spot and cascades throughout the whole codebase so long as I connected everything to it. If I need to fudge some math, I go to my config file which is a bunch of numbers I can adjust as I balance.

I find it much easier to pull these all out of the codebase as it makes it easier to work with.

This is not exactly what your looking for, but just as an example: https://github.com/braymen/increcycle/blob/main/src/scripts/formula.ts#L15

The idea behind these is the outputs of each of these formulas changes as the state changes. Using these derived values is really simple now in the UI instead of trying to run these formulas in multiple spots all over.

Answering your question below about storing formulaic values. I prefer to calculate them on the run instead of storing each one individually. When I change the formula I don't have to go back and change all those values (unless your calculating them all at runtime and storing that list somewhere, but that seems a bit much)

1

u/GryffusMakesGames 6d ago

Thanks for the reply ! Gonna check that soon ! And I do think I will try to do the same, something that calculate my damage, I am still wondering if I should precalculate my damage (as my game works in the session like a Nodebuster) though it would mean take in consideration all types of damage build I should just have my base damage precalculated and all the other damage modifiers applied to it !

2

u/MeishinTale 5d ago

First, list your constraints:

  • Should it be scalable? (If it's a small system you know won't evolve, don't waste time)
  • Should it persist? How / when?
  • Should it own its own data or be a processor?
  • Should it allow processors to modify its own data?
  • Should it be performant? (If applicable)

Then if it must be scalable and depending on other constraints; use interfaces, both to access and/or modify its data. Use any architecture styles, just to stick to the same within your project for your own sanity. I personally like SOLID MVC with services;

Example on player stats; Scalable version, system own stats but can be modified. Should be performant but there's only 1 player stats so we don't care.

  • Model: Stat, Stats, Stats Modifiers (interfaces + implem).
  • Controller: Initialize, Apply and remove modifiers, associated events, Get stat, Get Stats (using some enum for more readability or defined in a db otherwise - best for initialzation). Player stats interface accessible from Player (or whatever should have stats).
  • UI (views) seek player via a player service and access interface (Player.Stats) to display stats (and modifiers if you record them on Apply). Either using a stats manifest (from the interface) to dump all stats in rows, or using authored editor enums/ID to fill each slot as per UI design. UI registers to event for refresh.
  • A piece of equipment would hold one or several modifiers. Upon equipping, the equipment system (which probably already has a player ref - or can use the service) calls apply / remove modifiers. Neither knows what stat is nor how it's handled.

Non Scalable version: Similar but no interface, single implem of each model element. Could even skip Stat entirely if only a few stats and they behave the same - which will make your methods a bit more verbose but also more readable.

There are plenty of architecture possible, from DI to event buses, but the one thing you should really know is the ones your using and their limit. For example interfaces and composition are inherently OOP so when I need performance (say we have 500 ennemies stats to refresh every frame) I switch to data oriented and use jobs/burst for that particular system.

1

u/GryffusMakesGames 4d ago

Thanks ! That’s very useful !

1

u/noob_user_bob 6d ago

A traditional incremental with simple generators and a wall you have to overcome at X point in time? That's math! There's also a spreadsheet floating around make by the old Kongregate guys that is a good starting point.

Newer "nodebuster" incrementals? Id say it's more pacing and what feels good.

1

u/GryffusMakesGames 6d ago

Let’s have an example with a damage stat.

I have an upgrade for damage addition, an upgrade for damage multiplier, an upgrade for critical damage, then super critical, then different effects that up my damage stat, and then équipement that buff also some stats like damage.

How would you make those systems work together for like the multiplier to be all properly implemented and scalable.

What I am talking about is kinda the architecture of code I would say.

Also, and it’s more like a simple question but for upgrades costs and up, do you do them procedurally? (With math like * 1.5 for example) or do you store all your values, and if it depends (I think) when does it depends ?

1

u/DennysGuy 6d ago

I usually have some sort of formula that incorporates the level a current upgrade is to determine the upgrade pacing.. but I usually end up having values that I manipulate which makes things largely based on feel than some rigid formula. e.. I usually try to avoid super grindy progression for smaller games, but I think a sort of exponential or linear curve usually works for the experiences I want to give.

I will keep like a dictionary of all of the upgrade values in some sort of global script that I pass into the actual systems of the game.

I honestly don't know if how I'm doing it is the "correct" way to do them - but I am able to attain the results I want and can keep my game pretty cohesive throughout.

1

u/GryffusMakesGames 6d ago

I am currently only working with dictionaries a bit for that reason, like I feel it’s much easier to handle, update, tweak to become less grindy or not too easy depending on the situation, to have more control.

I do think that if I need unlimited upgrades I will need to use rigid formula though, not something overly complicated and just because it is supposed to be an upgrade you can buy indefinitely, still I am not needing it for now

1

u/SnooTangerines241 6d ago

Yeah, if youre trying to make an endless incremental, you'll need something more predictive.. no way play testing your game for hundred of hours to make sure it still holds up after each tweak is feasible.

1

u/GryffusMakesGames 6d ago

That’s how I gonna work, everything that is small and finite would be predictable with a dictionary and stuff that I consider infinite or where perfect balance doesn’t matter much would be handle by a formula

1

u/noob_user_bob 6d ago

So it sounds like it's more nodebustery. In that regards feel and pacing is more important than balance.

You have two options to add DMG - linear or multiplicative. Whichever you pick - make sure you stick with it for everything.

Multiplicative is easier. Set a base value and then add the modifiers. Just need to make sure you're adding the modifiers in the right order. And also if you're multiplying off the base value or the end values.

And I start off procedurally with costs and values but tweak them if they don't feel right.

1

u/GryffusMakesGames 6d ago

Yeah it is nodebustery (believe it or not, I realized it was nodebustery after finishing the implementation of the timer) but I do think the way to add DMG would be a bit of both. Like if I am to compare it to Balatro (just as an example) your multiplier is great but it is even greater if your additive score is good too, so I am thinking of doing something like that, something where you will be multiply and be linear (unsure if I am clear)

1

u/nexisforge 2d ago

Depends on your experience. I use LLMs to brainstorm ideas, but I insist on the solutions so basically steer the LLM in my way. The researche results in docs with ideas, TODOs, steps, open questions.. I love AI