PieKing1215 / FallingSandSurvival

2D survival game inspired by Noita and slightly Terraria
BSD 3-Clause "New" or "Revised" License
178 stars 20 forks source link

Question on rigidbodies #19

Open ketufaispikinut opened 1 year ago

ketufaispikinut commented 1 year ago

In the current version of your engine, it appears like sand doesn't get added to rigidbodies (it can only fall off, and never start to stick to, for instance, a convenient container), based on the gifs sent here. Since you have started working on a new version, do you plan to have sand stick to rigidbodies? If yes, how will / do you do it?

PieKing1215 commented 1 year ago

I've thought about it but I haven't tried implementing yet, it seems like it'd be hard to get working consistently/stably.

But here's how I would probably approach it if I eventually try:

Say you have a sand/particle pixel moving towards a rigidbody (for this example rotated 45 degrees so "down" in the rigidbody buffer is bottom left): image

When it hits the rigidbody, move it into the rigidbody buffer (I haven't implemented this but not that hard if you have collisions already): image

Ideally what you would want to happen is for the pixels in the rigidbody to be simulated "inside" of the rigidbody so that they'd move like normal in-world sand (I don't fully do this in my new engine yet) But since the rigidbody buffer's "down" is angled you would get this, which is not ideal: image

In order to solve this, you would need to make it so your sand simulation can have any arbitrary gravity direction, since then you could simulate with rotated gravity to counteract the rigidbody's rotation: image However, arbitrary gravity goes completely against the typical "falling sand" algorithm so I have to imagine it would require a way more complicated simulation to do properly. One middle ground I can imagine (probably how I would do it) would be instead doing just 4 direction gravity, since all you'd have to change is swapping/negating x/y values when accessing pixels in the buffer. (maybe 8 direction is feasible but would be more work) Then I think you could approximate intermediate gravity directions by like switching rapidly between the two nearest ones in proportion to which one is closer (just an idea, I haven't implemented this so maybe it'd be terrible idk)

But let's say we got that working and now we try to turn the rigidbody over: image The sand inside the rigidbody simulates down until it reaches a point where there's no pixels for a while below it, so it "falls off" and becomes an in-world sand pixel

So yeah that's how I'd probably start off approaching this. It's kinda a lot, but if you set up the sand sim to be flexible enough it's definitely feasible to get vaguely working. I have to imagine that it would still be very jank without a lot more tweaking though, but I can't really say because I haven't actually tried to do it yet. Will definitely update if/when I get around to it. lmk if you have any thoughts/questions!

TL;DR: It's complicated, I haven't tried yet but doing it well probably at least requires simulating sand inside rigidbodies in rigidbody space and adding directional gravity to the sand simulation.

ketufaispikinut commented 1 year ago

Thanks a lot for the illustrations (; (and explanation) . A good way to achieve directional gravity (as I thought of it) would be by making falling pixels become particles (in a way that would end up looking similar to Powder Toy's falling sand sim). Sadly, it is not a good choice performance wise. Another, more efficient way is to simulate it using world coordinates (I believe that you already talked about this in another rigidbody-related question of this repo... ). Some last questions: How do you generate a contouring for your rigidbodies (the marching square step in the Noita dev's GDC talk). When trying to work out how to generate a line that could be accepted by the Ramer-Douglas-Pecker aglorithm, I realised that: A) It will end up looking wonky when there are holes in the rigidbody (e.g. a box with a square-shaped hole within). EDIT: Like this: rdp Red is hand-drawn line (the line connecting the exterior circle and the interior circle is just a rendering issue, and blue is RDP's simplified line showing bad behavior.

B) Marching squares doesn't generate "continuous lines" (And by that I mean that a marching square array would look like this: [ ( vec2, vec2), (vec2,vec2) ], the first vec2 being the beginning of an isoline and the second the end of it. The problem here being that segment 1 and segment 2 are unsorted, therefore making an unconnected line for RDP. How do you address this issue? Do you use a sorting algorithm based on distance?

C) And finally, how do you handle rigidbody splicing (when a rigidbody is cut off the world, such as in the presentation gifs of your repo).