mirror of
https://github.com/ClassiCube/ClassiCube.git
synced 2025-09-17 11:35:08 -04:00
Improve slab collision detection, should fix #65.
This commit is contained in:
parent
4facc54b47
commit
13c456c7c5
@ -48,5 +48,9 @@ namespace ClassicalSharp {
|
||||
public bool ZIntersects( BoundingBox box ) {
|
||||
return Max.Z >= box.Min.Z && Min.Z <= box.Max.Z;
|
||||
}
|
||||
|
||||
public override string ToString() {
|
||||
return Min + " : " + Max;
|
||||
}
|
||||
}
|
||||
}
|
@ -41,15 +41,6 @@ namespace ClassicalSharp {
|
||||
return block == 0 || info.IsSprite( block ) || info.IsLiquid( block ) || block == (byte)Block.Snow;
|
||||
}
|
||||
|
||||
bool IsFreeYForStep( Vector3 pos ) {
|
||||
// NOTE: if non whole blocks are added, use a proper AABB test.
|
||||
int x = Utils.Floor( pos.X );
|
||||
int y = Utils.Floor( pos.Y );
|
||||
int z = Utils.Floor( pos.Z );
|
||||
return CanWalkThrough( GetPhysicsBlockId( x, y + 1, z ) ) &&
|
||||
CanWalkThrough( GetPhysicsBlockId( x, y + 2, z ) );
|
||||
}
|
||||
|
||||
// TODO: test for corner cases, and refactor this.
|
||||
static State[] stateCache = new State[0];
|
||||
class StateComparer : IComparer<State> {
|
||||
@ -139,22 +130,22 @@ namespace ClassicalSharp {
|
||||
ClipY( ref size, ref entityBB, ref entityExtentBB );
|
||||
} else {
|
||||
if( finalBB.Min.X >= blockBB.Max.X ) {
|
||||
if( !DidSlide( ref blockBB, ref size, wasOn, 1, 0, ref entityBB, ref entityExtentBB ) ) {
|
||||
if( !wasOn || !DidSlide( ref blockBB, ref size, ref finalBB, ref entityBB, ref entityExtentBB ) ) {
|
||||
Position.X = blockBB.Max.X + size.X / 2 + 0.001f;
|
||||
ClipX( ref size, ref entityBB, ref entityExtentBB );
|
||||
}
|
||||
} else if( finalBB.Max.X <= blockBB.Min.X ) {
|
||||
if( !DidSlide( ref blockBB, ref size, wasOn, -1, 0, ref entityBB, ref entityExtentBB ) ) {
|
||||
if( !wasOn || !DidSlide( ref blockBB, ref size, ref finalBB, ref entityBB, ref entityExtentBB ) ) {
|
||||
Position.X = blockBB.Min.X - size.X / 2 - 0.001f;
|
||||
ClipX( ref size, ref entityBB, ref entityExtentBB );
|
||||
}
|
||||
} else if( finalBB.Min.Z >= blockBB.Max.Z ) {
|
||||
if( !DidSlide( ref blockBB, ref size, wasOn, 0, 1, ref entityBB, ref entityExtentBB ) ) {
|
||||
if( !wasOn || !DidSlide( ref blockBB, ref size, ref finalBB, ref entityBB, ref entityExtentBB ) ) {
|
||||
Position.Z = blockBB.Max.Z + size.Z / 2 + 0.001f;
|
||||
ClipZ( ref size, ref entityBB, ref entityExtentBB );
|
||||
}
|
||||
} else if( finalBB.Max.Z <= blockBB.Min.Z ) {
|
||||
if( !DidSlide( ref blockBB, ref size, wasOn, 0, -1, ref entityBB, ref entityExtentBB ) ) {
|
||||
if( !wasOn || !DidSlide( ref blockBB, ref size, ref finalBB, ref entityBB, ref entityExtentBB ) ) {
|
||||
Position.Z = blockBB.Min.Z - size.Z / 2 - 0.001f;
|
||||
ClipZ( ref size, ref entityBB, ref entityExtentBB );
|
||||
}
|
||||
@ -163,12 +154,31 @@ namespace ClassicalSharp {
|
||||
}
|
||||
}
|
||||
|
||||
bool DidSlide( ref BoundingBox blockBB, ref Vector3 size, bool wasOnGround, float x, float z,
|
||||
bool DidSlide( ref BoundingBox blockBB, ref Vector3 size, ref BoundingBox finalBB,
|
||||
ref BoundingBox entityBB, ref BoundingBox entityExtentBB ) {
|
||||
float yDist = blockBB.Max.Y - entityBB.Min.Y;
|
||||
Vector3 blockOffsetMin = blockBB.Min + new Vector3( x, 0, z );
|
||||
if( yDist > 0 && yDist <= StepSize + 0.01f && wasOnGround &&
|
||||
IsFreeYForStep( blockBB.Min ) && IsFreeYForStep( blockOffsetMin ) ) {
|
||||
if( yDist > 0 && yDist <= StepSize + 0.01f ) {
|
||||
|
||||
// Adjust entity bounding box to include the block being tested
|
||||
BoundingBox adjFinalBB = finalBB;
|
||||
adjFinalBB.Min.X = Math.Min( finalBB.Min.X, blockBB.Min.X + 0.01f );
|
||||
adjFinalBB.Max.X = Math.Max( finalBB.Max.X, blockBB.Max.X - 0.01f );
|
||||
adjFinalBB.Min.Y = (float)Math.Ceiling( blockBB.Max.Y ) + 0.01f;
|
||||
adjFinalBB.Max.Y = adjFinalBB.Min.Y + size.Y;
|
||||
adjFinalBB.Min.Z = Math.Min( finalBB.Min.Z, blockBB.Min.Z + 0.01f );
|
||||
adjFinalBB.Max.Z = Math.Max( finalBB.Max.Z, blockBB.Max.Z - 0.01f );
|
||||
|
||||
Vector3I min = Vector3I.Floor( adjFinalBB.Min );
|
||||
Vector3I max = Vector3I.Floor( adjFinalBB.Max );
|
||||
for( int x = min.X; x <= max.X; x++ ) {
|
||||
for( int y = min.Y; y <= max.Y; y++ ) {
|
||||
for( int z = min.Z; z <= max.Z; z++ ) {
|
||||
if( !CanWalkThrough( GetPhysicsBlockId( x, y, z ) ) )
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Position.Y = blockBB.Max.Y + 0.001f;
|
||||
onGround = true;
|
||||
ClipY( ref size, ref entityBB, ref entityExtentBB );
|
||||
|
Loading…
x
Reference in New Issue
Block a user