public override void handleCollision(Q3BSPLevel level, GameTime gameTime) { if (!active) { return; } //Simple collision detection against level Q3BSPCollisionData collision = level.TraceBox(position, newPosition, minPoint, maxPoint); position = collision.collisionPoint; }
public override void handleCollision(Q3BSPLevel level, GameTime gameTime) { // if noclipping is enabled, do not check for collisions if (!m_settings.clipping) { position = newPosition; } // otherwise, check for collisions else { Q3BSPCollisionData collision = level.TraceBox(position, newPosition, minPoint, maxPoint); Vector3 point = collision.collisionPoint; if (collision.collisionPoint != collision.endPosition) { Vector3 start = collision.startPosition; Vector3 col = collision.collisionPoint; Vector3 end = collision.endPosition; //Wall Detection: Not Working //point = slopeCollision(level, start, col, end, m_left, 75); //Ramp Detection point = slopeCollision(level, start, col, end, new Vector3(0, 0.5f, 0), maxClimb); } position = point; //Gravity //Check if on floor collision = level.TraceBox(position, position - new Vector3(0, 1, 0), minPoint, maxPoint); if (collision.collisionPoint == collision.endPosition || isJumping) { //Not on floor so check gravity updateGravity(gameTime); collision = level.TraceBox(position, newPosition, minPoint, maxPoint); if (collision.collisionPoint != collision.endPosition) { resetGravity(); } position = collision.collisionPoint; } else { //On floor don't do gravity, but reset it resetGravity(); } } }
private Vector3 slopeCollision(Q3BSPLevel level, Vector3 start, Vector3 collision, Vector3 end, Vector3 offset, float angle) { start += offset; end += offset; // check the slope of a collision face Q3BSPCollisionData slopetest = level.TraceBox(start, end, minPoint, maxPoint); // get the angle of the collision face, and check to see that it is not too steep for the player to climb, then return the appropriate collision point if (slopetest.collisionPoint != collision + offset) { float opp = offset.Length(); float adj = (end - start).Length(); float theta = MathHelper.ToDegrees((float)Math.Atan(opp / adj)); if (theta < angle) { return(slopetest.collisionPoint); } } return(collision); }
public Q3BSPCollisionData Trace(Vector3 startPosition, Vector3 endPosition) { Q3BSPCollisionData cd = new Q3BSPCollisionData(); cd.startOutside = true; cd.inSolid = false; cd.ratio = 1.0f; cd.startPosition = startPosition; cd.endPosition = endPosition; cd.collisionPoint = startPosition; WalkNode(0, 0.0f, 1.0f, startPosition, endPosition, ref cd); if (1.0f == cd.ratio) { cd.collisionPoint = endPosition; } else { cd.collisionPoint = startPosition + cd.ratio * (endPosition - startPosition); } return(cd); }
//Custom Collision Detection public override void handleCollision(XNAQ3Lib.Q3BSP.Q3BSPLevel level, GameTime gameTime) { base.handleCollision(level, gameTime); //Gravity //Check if on floor Q3BSPCollisionData collision = level.TraceBox(position, position - new Vector3(0, 1, 0), minPoint, maxPoint); if (collision.collisionPoint == collision.endPosition || isJumping) { //Not on floor so check gravity updateGravity(gameTime); collision = level.TraceBox(position, newPosition, minPoint, maxPoint); if (collision.collisionPoint != collision.endPosition) { resetGravity(); } position = collision.collisionPoint; } else { //On floor don't do gravity, but reset it resetGravity(); } }
private void CheckBrush(ref Q3BSPBrush brush, ref Q3BSPCollisionData cd) { float startFraction = -1.0f; float endFraction = 1.0f; bool startsOut = false; bool endsOut = false; for (int i = 0; i < brush.BrushSideCount; i++) { Q3BSPBrushSide brushSide = brushSides[brush.StartBrushSide + i]; Plane plane = planes[brushSide.PlaneIndex]; float startDistance = Vector3.Dot(cd.startPosition, plane.Normal) - plane.D; float endDistance = Vector3.Dot(cd.endPosition, plane.Normal) - plane.D; if (startDistance > 0) { startsOut = true; } if (endDistance > 0) { endsOut = true; } if (startDistance > 0 && endDistance > 0) { return; } if (startDistance <= 0 && endDistance <= 0) { continue; } if (startDistance > endDistance) { float fraction = (startDistance - Q3BSPConstants.epsilon) / (startDistance - endDistance); if (fraction > startFraction) { startFraction = fraction; } } else { float fraction = (startDistance + Q3BSPConstants.epsilon) / (startDistance - endDistance); if (fraction < endFraction) { endFraction = fraction; } } } if (false == startsOut) { cd.startOutside = false; if (false == endsOut) { cd.inSolid = true; } return; } if (startFraction < endFraction) { if (startFraction > -1.0f && startFraction < cd.ratio) { if (startFraction < 0) { startFraction = 0; } cd.ratio = startFraction; } } }
private void WalkNode(int nodeIndex, float startRatio, float endRatio, Vector3 startPosition, Vector3 endPosition, ref Q3BSPCollisionData cd) { // Is this a leaf? if (0 > nodeIndex) { Q3BSPLeaf leaf = leafs[-(nodeIndex + 1)]; for (int i = 0; i < leaf.LeafBrushCount; i++) { Q3BSPBrush brush = brushes[leafBrushes[leaf.StartLeafBrush + i]]; if (0 < brush.BrushSideCount && 1 == (textureData[brush.TextureIndex].Contents & 1)) { CheckBrush(ref brush, ref cd); } } return; } // This is a node Q3BSPNode thisNode = nodes[nodeIndex]; Plane thisPlane = planes[thisNode.Plane]; float startDistance = Vector3.Dot(startPosition, thisPlane.Normal) - thisPlane.D; float endDistance = Vector3.Dot(endPosition, thisPlane.Normal) - thisPlane.D; if (startDistance >= 0 && endDistance >= 0) { // Both points are in front WalkNode(thisNode.Left, startRatio, endRatio, startPosition, endPosition, ref cd); } else if (startDistance < 0 && endDistance < 0) { WalkNode(thisNode.Right, startRatio, endRatio, startPosition, endPosition, ref cd); } else { // The line spans the splitting plane int side = 0; float fraction1 = 0.0f; float fraction2 = 0.0f; float middleFraction = 0.0f; Vector3 middlePosition = new Vector3(); if (startDistance < endDistance) { side = 1; float inverseDistance = 1.0f / (startDistance - endDistance); fraction1 = (startDistance + Q3BSPConstants.epsilon) * inverseDistance; fraction2 = (startDistance + Q3BSPConstants.epsilon) * inverseDistance; } else if (endDistance < startDistance) { side = 0; float inverseDistance = 1.0f / (startDistance - endDistance); fraction1 = (startDistance + Q3BSPConstants.epsilon) * inverseDistance; fraction2 = (startDistance - Q3BSPConstants.epsilon) * inverseDistance; } else { side = 0; fraction1 = 1.0f; fraction2 = 0.0f; } if (fraction1 < 0.0f) { fraction1 = 0.0f; } else if (fraction1 > 1.0f) { fraction1 = 1.0f; } if (fraction2 < 0.0f) { fraction2 = 0.0f; } else if (fraction2 > 1.0f) { fraction2 = 1.0f; } middleFraction = startRatio + (endRatio - startRatio) * fraction1; middlePosition = startPosition + fraction1 * (endPosition - startPosition); int side1; int side2; if (0 == side) { side1 = thisNode.Left; side2 = thisNode.Right; } else { side1 = thisNode.Right; side2 = thisNode.Left; } WalkNode(side1, startRatio, middleFraction, startPosition, middlePosition, ref cd); middleFraction = startRatio + (endRatio - startRatio) * fraction2; middlePosition = startPosition + fraction2 * (endPosition - startPosition); WalkNode(side2, middleFraction, endRatio, middlePosition, endPosition, ref cd); } }