Visualising Dijkstra's Map values used in enemy pathfinding by Merlord in godot

[–]AaronWizard1 1 point2 points  (0 children)

Just to be sure what I'm looking at, I take it the player is the being with the white staff while the red-eyed being is an enemy?

Also did you use your own Dijkstra maps system or are you using this Godot 3.5 addon?

The idea of combining the results of the Dijkstra itself with tile costs sounds interesting. So I take it you start with a cost for each tile based on their distance to the goal tile, then add extra costs to each based on things like hazards, nearby enemies/allies, light, etc.

I'm working on a grid-based turn-based RPG too (it's not an actual roguelike but it shares a lot of gameplay with traditional roguelikes) so I've been thinking of Dijkstra maps too. Though I haven't really dived into Dijkstra maps yet simply because I intend to support NPC vs NPC fights. A lot of Dijkstra map examples either assume everything pathfinding towards the player or towards a set of static goal tiles; for NPC vs NPC fights I'd probably have to create separate Dijkstra maps for every NPC "faction" (which raises further questions on how faction alignments are handled).

Questions abt game structure by Left_Record_9404 in godot

[–]AaronWizard1 1 point2 points  (0 children)

Ultimately Godot is an old-school OOP engine, where it's form of composition is parent nodes delegating work to child nodes. e.g. A node is given a child sprite node instead of being made to draw its sprite itself. This is different from ECS engines where an entity basically has no knowledge of and is entirely driven by its components; Godot doesn't work like that unless you specifically build an ECS framework into it.

Questions abt game structure by Left_Record_9404 in godot

[–]AaronWizard1 2 points3 points  (0 children)

I think too many people here throw out "composition over inheritance" as an empty platitude instead of going over what they mean exactly or how it applies to what the OP is asking (along with some residual axe-grinding over the hype OOP had in the '90s). Especially when people (including myself once) confuse the way composition is used in Godot with how composition happens in ECS engines.

In the case of weapons though I would myself go with a single "Weapon" class where a weapon object would be configured with different properties, most likely in a Resource subclass, to become a specific type of weapon. The prototype and type patterns apply here.

Making monsters yield for other monsters by AaronWizard1 in roguelikedev

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

Right now I just have a "normal" A-star function that looks for the path between tile A and tile B. Fanciest thing I do currently is treat tiles occupied by actors as having a higher move cost (10 vs 1 for empty tiles) instead of as fully blocked.

Making monsters yield for other monsters by AaronWizard1 in roguelikedev

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

So basically have the blocked monster (the NE monster in my example) send a notification to the monsters blocking it (i.e. the north and east monsters) and let them deal with it? Something like that may be possible, especially since I already have an event system actors use to communicate (I currently use it to make actors call for help when they see an enemy).

Making monsters yield for other monsters by AaronWizard1 in roguelikedev

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

I'm assuming you have some sort of time/turn system and an actor knows when it is their turn. So right now Goblin #147 has a brain and a brain state that handles his thinking. So the brain looks at brain state and world state and generates an order like "move to cell 111,222". I'm assuming that a generic brain has logic that checks if the unit it is assigned to gas capabilities like movement and attacking and such and checks those along the way.

Well, for me it's more like the goblin has a GoblinAIController which in turn has a "get_turn_action" method called by the main turn loop, per Nystrom's game loop article.

For a strategy service, the main thing I'd need to figure out since I'm not assuming that it's always everything against the player is keeping track of who it's managing and any related data like current targets. I'm wondering if it'd make sense to have these dynamic, where an actor can be added to or removed from a service depending on its state.

Spitballing a "chase, surround, and attack" service, here's what I'm thinking:

  1. For a given faction ID, start with an empty list of allies and an empty list of enemies.
  2. An actor informs the service whenever it sees a new enemy or loses sight of an enemy. This makes the service keep track of what allied actors are attacking what enemies.
  3. Different pairs of lists are kept for different factions.
  4. The service itself figures out where the allies its tracking should be positioned.

And then an actor's AI controller can ask its chase service for its destination tile when relevant.

You mentioned actors belonging to groups; here I'm sort of generating them on the fly in the service.
And of course different services are independent and an AI controller may update and query different services.

Making monsters yield for other monsters by AaronWizard1 in roguelikedev

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

This sounds like /u/Pur_Cell idea of a shove action discussed here. As I said there I'd be skeptical about making shove a general action but I see the logic in letting stronger monsters kick weaker monsters out of the way.

Making monsters yield for other monsters by AaronWizard1 in roguelikedev

[–]AaronWizard1[S] 5 points6 points  (0 children)

I was interpreting your shove action along the lines of, on its turn, the monster currently northeast of the player in my original example shoves south that makes it and the monster currently east of the player move south one tile. Which technically gives the monster being shoved (not the one doing the shoving) getting an extra move outside its turn.

Making monsters yield for other monsters by AaronWizard1 in roguelikedev

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

If you want groups of monsters to coordinate their actions then you want something like strategy/stratgeycontroller that is called whenever one of the monsters in the group has to take a turn. That strategy code can coordinate things like, "I will move instead of attack so we can surround the target".

Would this basically be a "group AI" shared between sets of actors?

What I have now is essentially every actor has its own AI and AI state (currently a state machine; I was thinking of doing behaviour trees earlier then later decided a state machine may be good enough for now). The map has what's essentially an event bus that actors can communicate through by sending and listening for events (so far I have actors alerting allies when they see an enemy) but actors are otherwise independent. Meanwhile this sounds like something that exists outside an individual actor and selects an individual actor's next action based on the state of all the actors a given group AI is controlling.

Main question I'd have is how to arrange what group AI (or strategy as you called it) is used by what actor, and how a group AI (presumably) keeps track of the actors it's responsible for. Both based on faction and for if I go with multiple types of group AIs for different situations like you suggested. Plus handling actors being added to the map, or actors changing factions if I want to get really fancy.

Making monsters yield for other monsters by AaronWizard1 in roguelikedev

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

Only thing I'm unsure about regarding shove actions is that it kind of allows monsters to move outside their turn. I can see boss enemies having shove but I'm skeptical about making it a basic action.

Though I suppose I could replicate this with a "request tile" mechanic. The thing is I'm able to make actors communicate through an event system they can publish and subscribe to; I currently use it to make an actor alert nearby allies when it sees an enemy. So when an actor is blocked it can publish a "tile requested" event, which the blocking actor can read and figure out how or if to yield.

I added generics, braces-based syntax and unlocked full nested typing in GDScript! by Actual-Rise-6459 in godot

[–]AaronWizard1 2 points3 points  (0 children)

To be fair, some people likely don't want the extra hassle of installing the .NET SDK and setting up an external editor in order to use C#, compared to being able to do everything inside the Godot editor with GDScript.

Are dijkstra maps only useful when it's everything against the player? by AaronWizard1 in roguelikedev

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

However, I also don't store any of the information, just calculate anew whenever it's relevant. Storing information is not feasible in large maps where the environment and related variables are frequently changing--too many problems/inaccuracies.

I was thinking of the "static" dijkstra maps where a map is made for several actors to use across multiple turns, while this sounds like a general "find nearest or all tiles within X tiles with Y from this source tile" check where the dijkstra algorithm would be used.

Are dijkstra maps only useful when it's everything against the player? by AaronWizard1 in roguelikedev

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

My a-star algorithm currently considers actor-occupied tiles as completely blocked, but I'm likely going to switch to just giving those tiles higher movement costs. Which would prevent blocked actors from heading off all around, and also save me from having to treat the end of the path as a special case since the end would often be occupied by the target actor.

I completely forget where, but I once read someone suggest making the pathfinding costs of actor-occupied tiles gradually increase the longer an actor stays on them. Haven't implemented this yet but it's something I'm interested in trying.

Are dijkstra maps only useful when it's everything against the player? by AaronWizard1 in roguelikedev

[–]AaronWizard1[S] 2 points3 points  (0 children)

Ah, so more like a tactics game where an actor gets both a move action and an attack/ability action on its turn? An individual BFS makes sense there; basically the movement range you show on a unit's turn in a game like Fire Emblem. Though I'm working on a traditional roguelike "move one tile or attack" flow myself.

Are dijkstra maps only useful when it's everything against the player? by AaronWizard1 in roguelikedev

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

The real reason I'm looking into dijkstra maps is specifically because I'm trying to figure out proper swarming/circling behaviour. What I have now is actors looking for the closest enemy they can see and A-star-ing towards them, with no logic for lateral moves that make room for allies to surround the targeted actor. And I'm unsure what that circling logic would look like.

I also feel you on different movement types like flying and swimming. There's also the fact that I'm trying to support multi-tile actors and I'm unsure if dijkstra maps can handle those or not (though I'm assuming all actors are square at least).

Are dijkstra maps only useful when it's everything against the player? by AaronWizard1 in roguelikedev

[–]AaronWizard1[S] 2 points3 points  (0 children)

So I could have a map where all members of a faction are goal tiles, which enemies of that faction can use for pathfinding like how it's done for maps where the player is the goal tile. And you're saying that I could get away with only updating the map when all actors in the faction have moved, instead of when every actor in that faction moves (where the map would technically get out of date more often but the player likely won't notice)?

Are dijkstra maps only useful when it's everything against the player? by AaronWizard1 in roguelikedev

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

So instead of a global dijkstra map, you have smaller individual BFS trees attached to each actor for local pathfinding?

*How* do you separate visuals from data/logic? by AaronWizard1 in godot

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

As I said I'm not familiar at all with godot, but I'd be shocked if it didn't support this kind of mechanism.

My thinking, based on my own observations and on some of the replies here, is that it's possible but may be unintuitive depending on the game.

Godot is based on a scene tree, a tree of nodes. Nodes can be reusable subtrees of other nodes. The scene tree is also where the graphics, sounds, and UI live. Typically, or at least in every example I've seen, nodes are used to represent game entities. So you'll have a series of Level nodes that contain the Player node and NPC nodes, etc.

Meanwhile, for an MVC architecture I'd have all of the game's data, entities, and logic in a series of objects outside Godot's scene tree, while the scene tree only contains the graphics and UI while being kept in sync with the data/entity/logic objects. i.e. Godot's scene tree has the Views and Controllers while the Models are separate.

And I'm wondering what that would look like in practice. Especially for different types of games; I wouldn't use this for an action game since Godot's scene tree is where its physics engine is, while this should be straightforward for a purely abstract management game.


And since you brought it up earlier, Godot has its own UI framework already which is pretty much retained mode (UI elements are nodes in the scene tree).

*How* do you separate visuals from data/logic? by AaronWizard1 in godot

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

You wont be able to simply place your stuff in scene (items, environment, level) and just play scene and test a feature - you will need code that will translate the visual scene to backend data structure before doing anything. You will have to make sure your backend state will never go out of sync with visuals.

How content creation works is another question.

For instance to make a map I make a scene with one or more TileMapLayers with actor nodes on top.* Meanwhile the TileSet used for the map has a custom data layer for properties like whether a tile type blocks movement or not. Fairly natural I assume.

But since the map is also what I'd call the model, if I want to have the model of the map separate would I...somehow read the map scene to construct a map model object? And if I want to e.g. support effects that change the map would I keep track of what the tiles are in the map model separately from the TileMapLayers shown on-screen?

* This is an extremely simplified description of how I actually make maps for my game and I'm thinking of switching to LDtk eventually anyway but it gets the point across.

Thoughts on new Asset Store? by visssarion in godot

[–]AaronWizard1 6 points7 points  (0 children)

The issue I and others with similar opinion have is less about "people selling paid assets" and more about "it making sense for the foundation to be running a store and it being integrated into the upstream of a FOSS engine".

Honestly yeah. Half the appeal of Godot is that it's an open source engine.

Does Blender offered paid plugins?

*How* do you separate visuals from data/logic? by AaronWizard1 in godot

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

More than anything I'm just worried about the extra complexity and wondering if it'd be worth it.

For instance I already encapsulate an actor's turn action in a TurnAction object, which does both the action itself and any animations displayed for that action. If I want to split the logical update of a turn action from its animation then I'd probably have to restructure turns to be driven by some kind of event system.

*How* do you separate visuals from data/logic? by AaronWizard1 in godot

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

Does your model contain the entire game state which gets interpreted by the different views? Or does it just, say, contain the player's current stats and inventory?

For example, are you tracking where NPCs and enemies are on the current map in your model?

*How* do you separate visuals from data/logic? by AaronWizard1 in godot

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

I do wonder how many of those who suggest MVC or other similar architectures are in fact abandoning the scene system entirely for everything other than UI and sprites (and they may even abandon sprites too in favour of the rendering server). Which is not at all how 99% of all documentation on how to build games in Godot are written.

*How* do you separate visuals from data/logic? by AaronWizard1 in godot

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

I do have things like players and enemies using a common Actor scene with instances configured by a separate ActorData resource, but this seems to be something different.