My first post here if there's anything wrong please do highlight it :) First and foremost the problem I'm facing is practically identical to this earlier post here : Falling Blocks and complex shapes
For ease of use here is the graph used to explain the above problem:
I do have a working build that uses a similar approach to the answer suggested in the post above. However what I'm currently trying to do is move the polyominoes continuously with an independent velocity so that it accelerates as it falls.
The answer suggested in the link above only works if you assume all the shapes move at a constant velocity due to the way my game works the "ground" can be removed and blocks that were once static can start to fall again.
The problem arises when a block with a higher velocity collides with one with a lower velocity at the bottom. You could make it so that these blocks slow down as they "collide" with the slower blocks but using this approach causes a problem in cases 3 and 4 where the 2 interlocking shapes will collide endlessly with one another and just not fall.
I have tried a few ideas but they just don't seem to really work. And for anyone who wants to say it's too complex or try something simpler well I don't really have a choice in the implementation it's what someone else wants :(
Also I don't think that it really matters but I'm using Unity to build this game just in case if you wanted to know.
Again I thought it wouldn't hurt to throw this question out there rather than just bashing my head by myself.
the method that handles collisions:
protected bool handleVerticalMovement(ref Vector2 moveDelta)
{
var ySign = (int)Mathf.Sign(moveDelta.y);
var yDeltaMag = Mathf.CeilToInt(moveDelta.y * ySign);
for (int i = 0; i < _monominoes.Count; i++)
{
var x = _monominoes[i].gridPositionX;
for (int yDelta = 0; yDelta <= yDeltaMag; yDelta++)
{
var y = Mathf.CeilToInt(_monominoes[i].transform.localPosition.y * ySign + yDelta) * ySign;
// check if it has hit the boundary of the grid
if (!Board.Instance.IsValidTile(x, y))
{
var deltaToBoundary = Mathf.Clamp(y, 0, Board.Instance.height - 1) -
_monominoes[i].transform.localPosition.y;
if (moveDelta.y * ySign <= deltaToBoundary * ySign) break;
moveDelta.y = deltaToBoundary;
return false;
}
// ignore if the cell is empty or is part of this shape
if (Board.Instance.GetTileAt(x, y) == null ||
Board.Instance.GetPolyominoAt(x, y) == this) continue;
//check to see if i hit a tile that is grounded
if (Board.Instance.GetTileAt(x, y).isGrounded)
{
var detltaToGround = y - _monominoes[i].transform.localPosition.y - ySign;
if (moveDelta.y * ySign <= detltaToGround * ySign) break;
moveDelta.y = detltaToGround;
return false;
}
var deltaToTile = Board.Instance.GetTileAt(x, y).transform.localPosition.y -
_monominoes[i].transform.localPosition.y - ySign;
// if the tile is not grounded check to see the delta movement will overlap the tile if so cap the delta
if (moveDelta.y * ySign <= deltaToTile * ySign) break;
moveDelta.y = deltaToTile;
break;
}
}
return true;
}
To further elaborate my current thought process on the matter currently this method takes in a delta value iterates through the grid to see if it collides with anything. If does collide with something it will adjust the delta value and if it hits the the bounds of the grid or any shape that's grounded it will exit returning false meaning after moving this frame it will also be grounded..
The complication arises when one block hits another block that's also not grounded adjusting the delta value to slow it down it will cause the 2 blocks in case 3 and 4 to collide into each other infinitely causing them to float in mid air.
What I've tried to do is call the other block's handleVerticalMovement method to ask how far it can move and this in turn will end up a sort of recursive call to other blocks that that other block will hit. I managed to get this to work when the blocks were moving one cell at a time but it doesn't seem to work as well when the blocks are moving continuously with a pseudo gravity value causing the blocks to accelerate overtime.
I have thought about clumping the block's together and making them fall as one object this will definitely solve case case 3 and 4 but this can potentially cause problems with case 5 and 6 where if one object gets hit and becomes grounded the other "connected" block should still be able to fall a bit more.
This means if I were to make them fall as one block while they are free falling when one the "sub" blocks collides I still need some way to identify what can continue falling what blocks cannot.
Again if there's any gaping holes in my logic please do point it out.