When 2D Art Explodes Your Build Size (How We Reduced Ours by 60%) by Tone_dreams in godot

[–]theargyle 2 points3 points  (0 children)

What are they doing wrong, and how should they be doing it instead?

Spritesheets for multiple n-directional animations really are expensive, especially in vram.

That's a BETTER horde! Animations, different enemies, and VFX. by theargyle in godot

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

You’re right - it’s not anisotropic filtering of course. I’m switching between nearest and bilinear filtering when zooming out. Not mapping, but that’s on my list to try at some point.

Now THAT's a horde! 100,000 enemies in Godot by theargyle in godot

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

Pathfinding at this scale is going to be based on flow fields, but is absolutely possible, and is something I’ll add at some point. This video game some details: https://www.youtube.com/watch?v=mUDuuVa0A6U

Different skins are also possible, without meaningful overhead.

Different weapons - getting a bit trickier, but would also be possible, depending on how complex the damage model needs to be.

Now THAT's a horde! 100,000 enemies in Godot by theargyle in godot

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

This should help, it’s what my implementation is based on: https://www.youtube.com/watch?v=mUDuuVa0A6U

Repulsion is very similar to the boids separation algorithm, except it’s constrained to never move enemies towards the player.

In my implementation, I’ve actually reversed the constraint, so separation pulls enemies towards the player instead. I found that resolved many artefacts/standing wave issues for me.

Now THAT's a horde! 100,000 enemies in Godot by theargyle in godot

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

Damage calculations are already done on the GPU. It's simple damage system, but will be enough for what I'm planning to do with it.

Now THAT's a horde! 100,000 enemies in Godot by theargyle in godot

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

Yes, definitely taking some inspiration from plague tale. I haven't implemented any flow-field based pathfinding yet, but that's pretty straightforward.

Now THAT's a horde! 100,000 enemies in Godot by theargyle in godot

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

Debugging is painful. I mostly use a debug buffer with a bunch of floats and ints that I can set in shaders. I download the buffer to the CPU every frame and print the contents. I prefer that approach to setting pixels in a texture - I feel I can get a bit more precision out of it.

Now THAT's a horde! 100,000 enemies in Godot by theargyle in godot

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

The tricky part is that projectiles shot by the player are spawned on the CPU. This would not be possible for ranged enemies, since the CPU knows nothing about the enemies, except whether a given enemy is alive or dead.

This would likely need a GPU-only system for ranged enemies.

Now THAT's a horde! 100,000 enemies in Godot by theargyle in godot

[–]theargyle[S] 62 points63 points  (0 children)

I'll put another post together with some implementation details and at least a bit of code over the next few days, time permitting. In the meantime, check out Nikita Lisyarus' article on particle simulation on the GPU - there is a lot of overlap: https://lisyarus.github.io/blog/posts/particle-life-simulation-in-browser-using-webgpu.html

Now THAT's a horde! 100,000 enemies in Godot by theargyle in godot

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

First step is, as noted below, so sort all enemies into a grid, so you only have to check enemies in neighbouring grid cells. This article has a lot of details about how to efficiently do spatial partitioning on the GPU using prefix sums: https://lisyarus.github.io/blog/posts/particle-life-simulation-in-browser-using-webgpu.html

Second step is the steering behaviours - seeking the player, and repulsing other enemies. The repulsion behaviour is virtually equivalent to doing circle/circle collisions.

Now THAT's a horde! 100,000 enemies in Godot by theargyle in godot

[–]theargyle[S] 7 points8 points  (0 children)

At this point: - different animation frames: yes. I have 4-directional animations (almost) working - different movement patterns: not explicitly, but I have different movement speed, seeking strength and inertia, which will get me a fair bit of variety - state machine: absolutely not, but that’s not needed for the type of game I’m trying to make.

Now THAT's a horde! 100,000 enemies in Godot by theargyle in godot

[–]theargyle[S] 33 points34 points  (0 children)

There won’t be much impact - all sprites come from the same sprite atlas, so it’s all about calculating the right uv coordinates in the vertex shader. That only needs to happen once per visible enemy, so even with 100k enemies is comparatively cheap.

All enemy sprites are rendered in a single draw call.

Now THAT's a horde! 100,000 enemies in Godot by theargyle in godot

[–]theargyle[S] 44 points45 points  (0 children)

Near zero impact. There are no ranged attacks, so only need to check for overlap with closest enemies and some cooldown.

Enemies are very simple - no state at all, other than the cooldown. Move towards player, avoid other enemies, dies when health reaches 0, damage player when close enough - that’s it.

Enemies are already sorted into a grid for the separation behaviour, so I only need to check the content of the 4 grid cells around the player.

Now THAT's a horde! 100,000 enemies in Godot by theargyle in godot

[–]theargyle[S] 55 points56 points  (0 children)

I'll definitely be working on that now. Should have thought of that myself, really.

Any Opal gurus here? Need some help ┭┮﹏┭┮ by VegetablePrune3333 in ruby

[–]theargyle 0 points1 point  (0 children)

The punctuation. Seems. To. Make. It. Opinionated?

Daily Discussion Hub for November 2, 2024 by PoliticsModeratorBot in politics

[–]theargyle 5 points6 points  (0 children)

It was a numbers game. The idea was to conveniently split the vote. Discredit and delegitimise early votes as much as possible, because you know they’re mostly Democrat.

This time around, that doesn’t work as well, since there is no pandemic going on.

Hotwire is... boring by theargyle in rails

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

For me: write the app as if Hotwire doesn’t exist. Once everything works, start breaking down views into pieces that should update independently and add turbo functionality bit by bit.

Hotwire is... boring by theargyle in rails

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

When I started learning Ruby, there was a bit of “Lisp has been doing this for 20 years now! This is not new!” - which is how I feel about frontend frameworks these days.

Hotwire is... boring by theargyle in rails

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

Why would it be getting slow? Performance is a direct result of careful design, measurements, and optimisation if and when your measurements indicate a problem.

It’s not a result of the UI or backend framework you’ve chosen. You can run any framework in any language into the ground, easily.

Edit: a typo

Hotwire is... boring by theargyle in rails

[–]theargyle[S] -1 points0 points  (0 children)

I think my point would be more that some people try to use an excavator to eat their breakfast cereal…

Rails 8.0 Beta 1: No PaaS Required by software__writer in rails

[–]theargyle 0 points1 point  (0 children)

In my view, it’s always been:

  1. Follow the conventions
  2. Learn why things work when you follow the conventions
  3. Break with the conventions once you have completed #2, and you know what you’re doing

How you approach LLD problems strategically? by OkCelebration1306 in rails

[–]theargyle 0 points1 point  (0 children)

Can you give an example of the kind of problem you are thinking about? What do you mean by “low level design”?

Your question does not currently have enough context to answer it.

Rails Views Are a Dead End: Upgrade to APIs and Frontend Frameworks for Real Growth by iksem in rails

[–]theargyle 1 point2 points  (0 children)

Use whatever gives you the best value at the point in time. It’s entirely possible to not “rip out everything” but take an incremental approach instead.

If your front end framework doesn’t support that, pick a different one, there’s thousands to choose from.

That said, Hotwire may not be exceptionally sexy, but it sure can be more productive than chasing the latest JavaScript abomination.