Most things in a game can be thought of standing up, with a base dimension and a height. For example a treasure box, it might have a 2x1 and be 1.5 high. These things are essentially "block like", they have effectively a 2-dimensional base. Since they have a 2-dimensional base, they can stand on their own.
@p
Imagine putting a box inside another box. If the base of the smaller box is bigger than the outer box, it won't fit. Objects in Texas only turn in 1/4 turn increments, so we could try reorienting it one way but generally, it's an easy check.
@p
Other things are small, for instance a coin. This is more like an object with a 0-dimensional base. We could think of putting infinitely many of these things into a containing box. They take up such a small amount of space, they can fit in any shape as long as it's 2-dimensional; it will never "not fit" and never fill it up.
@p
Of course, you might notice we've skipped a dimension. And in fact, that's right! Some things can be thought of as having a 1-dimensional base. These are "stick like" objects.
@p
The trick with stick-like objects is their unique topology when it comes to fitting into other things. Imagine a flower in a vase. The vase has a 2D base, and the flower has a 1D base. We can fit infinitely many flowers into the vase, as long as we tilt it up. Once it's tilted up, it has effectively a point or 0D base and so it will fit. But if it's on it's side, it has a 1D base and we can't even fit one in.
@p
Now imagine a sword. We can put a sword into the vase, as well, as long as we stand it up. So a sword might be most interesting if we model it as a 1D object.
@p
1D objects are also special in how they interact with the terrain and building surfaces. Mainly, sometimes they might lay down and sometimes they might lean on things. A sword looks quite natural leaning against a wall, as does a shovel, pitchfork. It depends on how long it is, how close it is to a wall, etc., as to whether it should lean against the wall or just lay flat on the ground.
@p
We want to implement sticklike mechanics, for now. Boxes and containers with 2D bases will, for now, only contain 0D and 1D things. 1D things will stand up, and only fit if they aren't too tall for the container (i.e., they would tip out: imagine putting a really tall pitchfork into a vase-- it would tip it over)
@p
This is the easiest part. The harder part is when they drop on the ground. What we want to do is calculate an appropriate "leaning" slope for each dropping direction. So they will have a position where they are dropped, but they will lean in one of four directions depending on the slope of the terrain/building.
@p
Imagine a pitchfork. Call the fork end the top, and the other end the bottom. The bottom point, end of the handle, corresponds to where the pitchfork is dropped. Since it has a 0D base (as it's a 2D object) it will fall one of four directions. The algorithm for placing it could therefore look like:
@p
1. Pick a random direction to fall.
@p
2. Calculate the fall mechanic.
@p
Step 2, to calculate the fall mechanic, will depend on how long it is. But basically, we would start with a slope = 0 (i.e., laying flat) and iterate per-block over the length of the pitchfork. Each block we encounter that we'd be intersecting (i.e., if it fell in the direction of a wall or a table) we would re-calculate a larger slope, and start over. We start over because the slope will affect how many blocks we need to iterate; when the slope is 0, we iterate the most number of blocks; if it were possible to be standing perfectly straight (slope inf) then we would not iterate any.
@p
Once we can iterate the whole length of the pitchfork, we have the final slope. This doesn't take into account center-of-gravity issues, but for now, let's ignore that. We'll just assume there is a lot of friction at the bottom end of the pitchfork, so that if it leans against even a short box, it will still have the bottom end touching the ground (versus tipping over the box). We could, however, probably take that into account without *too* much difficulty, by changing the initial Z position that we iterate from.
@p
Once we have this algorithm, we can choose a "resting slope" for the pitchfork, and it will appear to rest on the ground naturally where we dropped it.
@p
One more thing remains, which is we can make Step 1. a bit smarter. Instead of choosing randomly, calculate the resting slopes for all four possible fall directions. Let's assume the player is a bit smart. He knows in advance how the pitchfork will rest, just as you or I would, before he sets it down. By default, he wants it to be standing up, since it's tidier and easier to reach in the future. So if there is a resting angle that is "standing up", i.e., high enough slope, then choose it.
@p
Otherwise, he doesn't want it to be resting in a way that, as per our final note on Step 1, would result in in with a weird center of gravity issue (e.g., he's not going to lean it against a short box since he knows it will slide off). So if that's the situation, choose whatever direction has the flattest slope.
@p
One final note. What if we drop it while standing on a short box, or something? Well in this case, it's fine, the slope will be negative but the general rules still apply, more or less. In this case, there won't be a way to "stand it up" at all; so choose the flattest (minimum of absolute value of slope) slope to place it. We just end up with a negative resting slope.
@p
In fact, a negative resting slope will cause us to appear to poke through whatever we're resting on, but we can fix that by incrementing our position artificially by whatever direction we chose to fall in, * 0.5 blocks.
@p
VOILA! This is kind of complicated, but something I've been wrestling with for awhile, and today it sort of came to me how to solve it. So I wanted to write it up before it was lost.
2009-06-05