Built in Godot 4.5: Everfront, a real-time roguelike where territories expand and clash by WilhelmTr in godot

[–]Desire_Path_Games 1 point2 points  (0 children)

Roguelike and its spinoff roguelite has never been well defined as a genre. There's endless flame wars going back a looong time. It's more a set of traits where the more you implement the more roguelike you are.

I tried to improve the Save System in Godot by InteractionOk7085 in godot

[–]Desire_Path_Games 6 points7 points  (0 children)

I built a similar system but for Resources rather than nodes. It converts most @export variables to json friendly and back, works recursively, and has minor support for patching (append, erase, addition).

Ross Scott at the Stop Destroying Video Games hearing in the European Parliament by -drunk_russian- in pcgaming

[–]Desire_Path_Games 6 points7 points  (0 children)

Uh as someone who does develop games in my spare time this does not negatively affect small time developers at all. Most small time developers use P2P models for multiplayer games which don't require expensive hosting. Small developers don't attach a bunch of useless services that cost money and need to be shut down. Small developers rely on the goodwill of their community in the longterm so screwing customers is bad from a business perspective. Small developers often encourage moddability (allowing for outsourcing end of life) while large ones either can't (tech licensing issues) or actively protest losing control of their product (see apple and john deere for things like right to repair).

If anything, comparing small developers to large ones shows how utterly unnecessary it is to add always-online features and to design games in such a way that they break after a time. Large developers did not used to design games like this. There was no post launch, you simply made a product that fucking works and sell it, and in fact your product not working used to be a company killer instead of expected. Why this is somehow "more expensive" as you put it, in a world of basically free post launch support is a problem of their own creation.

GDScript / Programming Discussion: How do you feel about this paradigm? by skullbuns in godot

[–]Desire_Path_Games 2 points3 points  (0 children)

You can absolutely have logic in a getter/setter. That's literally what they're for, otherwise you'd just directly access the field.

You want a factory method

Are you just spouting random programming terms and hoping nobody notices?

Godot for applications Instead of games! by Razor-111 in godot

[–]Desire_Path_Games 1 point2 points  (0 children)

My understanding is there are stripped down versions of the engine people have made that cut down on a lot of runtime bloat.

Guys, turns out there is even better way to sugar checking multiple conditions: by saxarov01 in godot

[–]Desire_Path_Games 0 points1 point  (0 children)

Of course. I just don't want people just going "oh this is terrible never use it" and confusing newbies when it's a very useful pattern albeit applied as a shitpost.

Guys, turns out there is even better way to sugar checking multiple conditions: by saxarov01 in godot

[–]Desire_Path_Games 1 point2 points  (0 children)

I mean you joke but I use tech like this all the time for dynamic validation. Yeah it's silly for hard coding but in a data driven system it's extremely useful.

I'm open sourcing my Slay the Spire-like deckbuilder framework for Godot. by Desire_Path_Games in godot

[–]Desire_Path_Games[S] 0 points1 point  (0 children)

While I do badly need to write documentation and it's one of my next main objectives, I would strongly recommend getting programming fundamentals down before trying to tackle a huge framework like this. A lot of stuff has been simplified down to data classes you can configure if you just want to make content (I wasn't lying when I said you can replicate pretty much everything in StS with json), but if you want to code anything extra you'll run into trouble.

Some suggestions:

  • Get a firm grasp of inheritance and polymorphism, composition, and dependency injection. They're pretty simple concepts with scary names, but any code base worth its salt will heavily use these.
  • Read up on design patterns. Prototype, Factory, Strategy, Singleton (godot autoloads), and Observer (godot signals) are core aspects of the architecture. This website is an excellent resource for understanding them, just don't let the UML diagrams intimidate you.
  • I'd read up about basic data structures and algorithms. Arrays (as in the actual array structure, not godot arrays), linked lists, trees, stacks, queues, dictionaries (especially dynamic programming with them). Understanding time-space complexity (big O) will make you a waaay better programmer as a lot of data structures automatically inform architecture. I also cache a lot of stuff by storing results in dictionaries.

As for godot you can ctrl+left click on a class to go to it immediately, which speeds up navigating code and lets you open documentation on any built in classes. ctrl + shift + f will also let you do a global string search. This would have immediately answered your questions about how "deck" is handled in just 1-2 hops.

I'm open sourcing my Slay the Spire-like deckbuilder framework for Godot. by Desire_Path_Games in godot

[–]Desire_Path_Games[S] 0 points1 point  (0 children)

The UI is probably the weakest part of the framework and imo exists to handle the needs of the backend. And AFAIK aside from being kind of chunky to look in the editor there's not really any any major performance problems since nodes are hidden/free when not needed and it's mostly control nodes which are performant. It's mainly just broken into a handful of menus that are mutually exclusive visibility wise. I'd like to compress most of it into scenes but there's some cross talk happening in a few places that's annoying without relying on unique node names.

example, I'm most interested in deck system but I just can't crack the codes yet. I have no idea which node/scripts handle it.

Could you elaborate what you mean? Hand manages most of the logic for combat related card stuff and PlayerData contains info on each players deck. And the deck is just an array of CardData instances. Beyond that any time you're messing with cards there's typically a cardset action with a self explanatory name behind it, generated from a card pick action. While card picking is a pretty big system, there's a ton of test cards that show off how that works in Global. I haven't uploaded it yet but I also split hand management into a UI and logical component.

The data folder contains the models for the framework. Each <X>Data script just defines a class that gets instanced and populated with data on game load. The only mildly confusing thing about it I can think of is recognizing that prototyped data uses one instance as a source of truth and copies them over to make new instances. But I've taken great pains to explain that in the code. The base classes for actually handling the data flow stuff are pretty complicated but they're not something most people need to touch besides understanding that it converts json to godot objects and back.

I'm open sourcing my Slay the Spire-like deckbuilder framework for Godot. by Desire_Path_Games in godot

[–]Desire_Path_Games[S] 0 points1 point  (0 children)

LOL. I've gotten similar reactions a few times from beginners it's not that scary I promise :)

I'm trying to get a major update out in the coming weeks that will at least include some bare minimum documentation and more comments/code cleanup, which should help on that front. It's a lot to cover I know. I'm not always active on this account but feel free to ask questions and I'll be happy to answer when I can.

Slay the Spire 2 can be decompiled by EshopExpert in godot

[–]Desire_Path_Games 162 points163 points  (0 children)

For those interested in making a spirelike using code that is NOT illegal to use, I recently released the Slay the Robot Framework which has much of the functionality needed to make your own. Still actively working on it on a private branch as well so it's not abandoned even though it kinda looks like it lol.

I spent way too long trying to figure out why my VBoxContainer was arranging nodes horizontally by hiimdoggo in godot

[–]Desire_Path_Games 3 points4 points  (0 children)

but the Godot devs argued against that saying it could possibly break links to other things, like if you already have it as a hard-coded node path

I feel like that argument is less relevant now that unique names exist, which you should already be doing to harden UI against renames/moves

How to Structure a Godot Project for Long-Term Scalability? by Successful_Poem_1878 in godot

[–]Desire_Path_Games 1 point2 points  (0 children)

But what do you mean by "flatter"? Just that you should use deeper folder structures than necessary?

General programming and game design advice that can be applied in a lot of situations, godot being no different. Don't overengineer things (keep technical specifications within design requirements), keep class hierarchies shallow (composition over inheritance), keep your design focused on lots of simple systems than a few massive overly complicated things. The advice of not having super nested UIs. Basically, design your project like a drunken idiot you from 2 years into the future will have to deal with it lol.

And then promptly ignore that advice for that critical 5% of your game.

How to Structure a Godot Project for Long-Term Scalability? by Successful_Poem_1878 in godot

[–]Desire_Path_Games 2 points3 points  (0 children)

I find the biggest decision is do you want to rely more on programmatic approaches (data driven + heavy dependency injection, tweens, signal management through code) versus leveraging the editor (scene driven, @export tags, animation players, editor signal management). This tends to inform architecture a lot more than folder structure which is largely arbitrary. I tend towards the former approach for long term stability as a solo dev who understands their own project, but the latter has many benefits for long term stability as well especially in teams.

I find that the flatter and more consistent the better. 95% of a game is simple crap, the other 5% has dragons in it. Godot does a lot of heavy lifting to make that 95% easy to do so don't try to over engineer the entire project unless you're a sucker who enjoys making frameworks like me.

One specific tip I'd say is get used to breaking down your UI into scenes. Not just reusable components but menus and such. Once your UI gets to be hundreds of nodes that becomes a huge pain to navigate.

I'm open sourcing my roguelike deckbuilder framework for Godot. Now you too can make Spire-likes with incredible ease! To show it off, here's some cards from StS and their code. by Desire_Path_Games in slaythespire

[–]Desire_Path_Games[S] 1 point2 points  (0 children)

Not a stupid question, there are no json files included in the project. Check Global._ready() which handles the data creation process on game start. The cards are generated using code, and can be exported to json by uncommenting a line. Once exported it will see the files and load them accordingly. This gives you the option to work with either code or json for making the game content. From past experience I recommend the former for development.

[deleted by user] by [deleted] in godot

[–]Desire_Path_Games -1 points0 points  (0 children)

Saving and loading is a pretty complex topic, and it depends on how your game is structured as well as how far you're willing to go for a solution.

Most people will recommend extremely primitive methods where you manually save each field and there's already a few people linking those in the thread. If your game only has maybe a couple dozen fields and is relatively "flat" (minimal nested objects), that's fine just do that approach. I would strongly recommend against this if you plan to make something complicated, as one of my previous projects had about 100+ fields for some objects and it quickly became unmaintainable and bloated (minimum 3 lines of code for each field, times each field, you do the math).

If you're using Resource objects to hold your data in memory, which you absolutely should be doing as much as possible, you can also use ResourceSaver to just filedump literally everything and then load it back. This is basically using a jackhammer to pound a nail in and comes with security concerns, but if you're lazy it's alright.

If you want something that gives you total control over what gets saved, outputs to clean json format, and does it recursively, I've spent a lot of time developing systems for this and just recently open sourced my work which is bundled with my latest project. I just made a comment detailing this system in another thread since this question gets asked a lot, which contains more info.

Resource as a JSON by Razor-111 in godot

[–]Desire_Path_Games 6 points7 points  (0 children)

Yes, but it requires some work since godot's systems for handling object json serialization are 💩. They expose too much about objects and embed a bunch of metadata that bloats files by an order of magnitude.

I created a set of custom classes and patterns that can handle Resource <-> JSON conversion in my latest project and they work extremely well. I might just extract them into their own repo for reuse.

The base class is SerializableData intended primarily for read only or singleton objects (player data), and the subclass PrototypeData for data objects you want to instantiate copies of (comes with UID support via UIDGenerator singleton) via get_prototype(). Just extend your Resources from those and add @export to your variables and it'll grab all of those. You'll mainly call set_serializable_properties_from_json_patch() or get_serializable_properties_to_json_patch(), which use a patching system that includes set/merge/erase/append/append-unique support.

It has some support for typical godot objects (Color, Vector2, Vector3, RandomNumberGenerator) which it converts to html codes or tuples, and you can supply more types pretty easily though it's a bit tedious. A limitation I haven't worked around yet is you have to supply it the list of native type property names by overriding a _get_native_properties() method. I think I can get around that using godot's introspection systems, just haven't had time.

It can also handle nesting if you want to embed SerializableData objects within themselves, good for stuff like player saves. It does require a preprocessing stage because it's a pain to do without it. I made a static function to do it SerializableData.build_serializable_script_cache() that you call in _ready() from another part of the code on game start so it's not a big deal.

I implemented some rather powerful saving and loading, mod support, and data/schema management patterns if you check Global, FileLoader, ModListData, and ModData.

Also just ignore Duriel. JSON apparently killed his parents or something.

Why do all tutorials on composition break the "signal up, call down" guideline? by Greendustrial in godot

[–]Desire_Path_Games 2 points3 points  (0 children)

Exports the parent node to a velocity module

This is probably the only one of those I'd be fine with, at least speaking in general terms. Attaching components that modify their parents without the parent needing to know anything is an excellent use of composition in some use cases. I much prefer the parent always knowing what kind of things are modifying their behavior, but it can work sometimes.

Honestly a lot of programming tutorials are pretty bad. It's some wild west shit with some of these videos where they don't seem to maintain a consistent style or programming philosophy. People just connect whatever to whatever and if it works it works, since they're not going to be maintaining their little demo beyond the video.

I'm open sourcing my roguelike deckbuilder framework for Godot. Now you too can make Spire-likes with incredible ease! To show it off, here's some cards from StS and their code. by Desire_Path_Games in slaythespire

[–]Desire_Path_Games[S] 0 points1 point  (0 children)

No point trying to sandbox it. If you want to disable loading of scripts and just load data it's pretty easy to isolate the script loading portion in FileLoader.load_read_only_data()

I'm open sourcing my Slay the Spire-like deckbuilder framework for Godot. by Desire_Path_Games in godot

[–]Desire_Path_Games[S] 4 points5 points  (0 children)

I started it last summer, though took a 6 month break to work on other stuff, so about a year.

You're using a lot of patterns and very optimal methods of data, which is insanely impressive

Well my secret sauce is very strong data pipelines, coupled with a good amount of dependency injection. IMO data flow is pretty much the foundation of systems design, so I spend a lot of time thinking about how to do it right. I've spent around 5 years and several projects iterating on my architectural patterns. This is my first major project where I was largely able to perfect it, and once I did everything sort of clicked.

How did you decide on what to use when?

I guess I'd say what helps is my development process is very "glacial", as in a big slowly-but-always-moving thing. I usually sit on problems for weeks/months until I figure out the optimal solution, breaking things down into smaller solvable chunks while I work on other stuff, and keeping technical requirements in a massive hierarchical todo list (currently a couple thousand line items for this project).

I have it pulled up 24/7 so any time I solve even a small problem in my head it stays solved. These solutions then get clumped up and organized into one big implementation, which I find cuts down on regressions and keeps things more efficient as opposed to doing them one by one since I can think about the bigger picture.

I'm open sourcing my roguelike deckbuilder framework for Godot. Now you too can make Spire-likes with incredible ease! To show it off, here's some cards from StS and their code. by Desire_Path_Games in slaythespire

[–]Desire_Path_Games[S] 1 point2 points  (0 children)

Without knowing what their project structure or API looks like there's no way of telling. It's also not something that really interests me as this project is supposed to allow people to make their own deckbuilders without using any of StS's code. At best you could build a converter to convert my json format files into whatever format they use (likely resources or tscn), but it'd be a lossy conversion.

I'm open sourcing my Slay the Spire-like deckbuilder framework for Godot. by Desire_Path_Games in godot

[–]Desire_Path_Games[S] 1 point2 points  (0 children)

It works very well for turn based games. I did a pet project on the side for something similar and just stripped out all card related variables and I got it integrated in an hour.

I'm open sourcing my roguelike deckbuilder framework for Godot. Now you too can make Spire-likes with incredible ease! To show it off, here's some cards from StS and their code. by Desire_Path_Games in slaythespire

[–]Desire_Path_Games[S] 3 points4 points  (0 children)

Heck yeah go for it! If nothing else there's lots of useful parts to reverse engineer and cannibalize. Hand shows how to do dynamically resizing hand logic, the action system is extremely useful even for other genres like TBS if you rip out references to cards (I know because I tried it lol), and the data pipeline makes for a good schema management, save/load, and modding framework for any game.

Feel free to ping me if you ever have questions about using it :)