public void UpdateWorldMatrixBall() { List <Vector3> verticesSoup = game.maze.VertList; Vector3 tableCenter = game.table.Position; Vector2 velocity = physics.CurrentVelocity(delta, externalAcceleration); externalAcceleration = Vector2.Zero; Vector3 prevPosition = position; COLLISION collision = COLLISION.NoHit; Vector2 distance = physics.Collision(new BoundingSphere(position, Globals.config.ballRadius), verticesSoup, velocity, ref collision); switch (collision) { case COLLISION.HitXY: physics.PreVelocityX = -reflectionIndex * velocity.X; physics.PreVelocityY = -reflectionIndex * velocity.Y; position.X -= physics.PreVelocityX * Globals.config.gFrameTime; position.Z -= physics.PreVelocityY * Globals.config.gFrameTime; break; case COLLISION.HitX: if (Math.Abs(physics.PreVelocityX) > 1) { physics.PreVelocityX = -reflectionIndex * velocity.X; physics.PreVelocityY = velocity.Y; position.X -= physics.PreVelocityX * Globals.config.gFrameTime; position.Z -= physics.PreVelocityY * Globals.config.gFrameTime; } else { physics.PreVelocityY = velocity.Y; physics.PreVelocityX = 0; position.Z -= velocity.Y * Globals.config.gFrameTime; } break; case COLLISION.HitY: if (Math.Abs(physics.PreVelocityY) > 1) { physics.PreVelocityX = velocity.X; physics.PreVelocityY = -reflectionIndex * velocity.Y; position.X -= physics.PreVelocityX * Globals.config.gFrameTime; position.Z -= physics.PreVelocityY * Globals.config.gFrameTime; } else { physics.PreVelocityX = velocity.X; physics.PreVelocityY = 0; position.X -= velocity.X * Globals.config.gFrameTime; } break; case COLLISION.HitEdgeX: if (Math.Abs(physics.PreVelocityX) > 10) { physics.PreVelocityX = -reflectionIndex * velocity.X; physics.PreVelocityY = velocity.Y; position.X -= physics.PreVelocityX * Globals.config.gFrameTime; position.Z -= physics.PreVelocityY * Globals.config.gFrameTime; } else { physics.PreVelocityY = velocity.Y; physics.PreVelocityX = 0; position.Z -= velocity.Y * Globals.config.gFrameTime; } break; case COLLISION.HitEdgeY: if (Math.Abs(physics.PreVelocityY) > 10) { physics.PreVelocityX = velocity.X; physics.PreVelocityY = -reflectionIndex * velocity.Y; position.X -= physics.PreVelocityX * Globals.config.gFrameTime; position.Z -= physics.PreVelocityY * Globals.config.gFrameTime; } else { physics.PreVelocityX = velocity.X; physics.PreVelocityY = 0; position.X -= velocity.X * Globals.config.gFrameTime; } break; case COLLISION.NoMove: physics.PreVelocity = Vector2.Zero; break; default: position.X -= velocity.X * Globals.config.gFrameTime; position.Z -= velocity.Y * Globals.config.gFrameTime; physics.PreVelocityX = velocity.X; physics.PreVelocityY = velocity.Y; break; } world = Matrix.Identity; world *= Matrix.CreateTranslation(0f, -tableCenter.Y, 0f); world *= Matrix.CreateFromAxisAngle(Vector3.Normalize(new Vector3(0f, 0, 1f)), delta.X); world *= Matrix.CreateFromAxisAngle(Vector3.Normalize(new Vector3(1f, 0f, 0f)), delta.Y); world *= Matrix.CreateTranslation(0f, tableCenter.Y, 0f); Vector4 deltaPos = Vector4.Transform(position, world); world = Matrix.CreateTranslation(deltaPos.X, deltaPos.Y, deltaPos.Z); }
public void UpdateWorldMatrixBall() { List <Vector3> verticesSoup = game.maze.VertList; Vector3 tableCenter = game.table.Position; Vector2 velocity = physics.CurrentVelocity(delta, externalAcceleration); externalAcceleration = Vector2.Zero; Vector3 prevPosition = position; COLLISION collision = COLLISION.NoHit; Vector2 distance = physics.Collision(new BoundingSphere(position, Globals.config.ballRadius), verticesSoup, velocity, ref collision); switch (collision) { case COLLISION.HitXY: if (Math.Abs(physics.PreVelocityX) > 1 || Math.Abs(physics.PreVelocityY) > 1) { float vol = (float)((Math.Max(Math.Abs(velocity.X), Math.Abs(velocity.Y)))) / 200; sound2Instance.Volume = vol > 1 ? 1 : vol; sound2Instance.Play(); physics.PreVelocityX = -reflectionIndex * velocity.X; position.X -= physics.PreVelocityX * Globals.config.gFrameTime; physics.PreVelocityY = -reflectionIndex * velocity.Y; position.Z -= physics.PreVelocityY * Globals.config.gFrameTime; } else { sound1Instance.Stop(); physics.PreVelocityX = 0; physics.PreVelocityY = 0; } break; case COLLISION.HitX: if (Math.Abs(physics.PreVelocityX) > 1) { float vol = (float)(Math.Abs(velocity.X)) / 200; sound2Instance.Volume = vol > 1 ? 1 : vol; sound2Instance.Play(); physics.PreVelocityX = -reflectionIndex * velocity.X; physics.PreVelocityY = velocity.Y; position.X -= physics.PreVelocityX * Globals.config.gFrameTime; position.Z -= physics.PreVelocityY * Globals.config.gFrameTime; } else { if (physics.PreVelocity != Vector2.Zero) { float velocityMagnitude = (float)(Math.Sqrt(Math.Pow(velocity.X, 2) + Math.Pow(velocity.Y, 2))) / 200 - 1; sound1Instance.Pitch = velocityMagnitude > 1 ? 1 : velocityMagnitude; sound1Instance.Play(); } else { sound1Instance.Stop(); } physics.PreVelocityY = velocity.Y; physics.PreVelocityX = 0; position.Z -= velocity.Y * Globals.config.gFrameTime; } break; case COLLISION.HitY: if (Math.Abs(physics.PreVelocityY) > 1) { float vol = (float)(Math.Abs(velocity.Y)) / 200; sound2Instance.Volume = vol > 1 ? 1 : vol; sound2Instance.Play(); physics.PreVelocityX = velocity.X; physics.PreVelocityY = -reflectionIndex * velocity.Y; position.X -= physics.PreVelocityX * Globals.config.gFrameTime; position.Z -= physics.PreVelocityY * Globals.config.gFrameTime; } else { if (physics.PreVelocity != Vector2.Zero) { float velocityMagnitude = (float)(Math.Sqrt(Math.Pow(velocity.X, 2) + Math.Pow(velocity.Y, 2))) / 200 - 1; sound1Instance.Pitch = velocityMagnitude > 1 ? 1 : velocityMagnitude; sound1Instance.Play(); } else { sound1Instance.Stop(); } physics.PreVelocityX = velocity.X; physics.PreVelocityY = 0; position.X -= velocity.X * Globals.config.gFrameTime; } break; case COLLISION.HitEdgeX: if (Math.Abs(physics.PreVelocityX) > 1) { float vol = (float)(Math.Abs(velocity.X)) / 200; sound2Instance.Volume = vol > 1 ? 1 : vol; sound2Instance.Play(); physics.PreVelocityX = -reflectionIndex * velocity.X; physics.PreVelocityY = velocity.Y; position.X -= physics.PreVelocityX * Globals.config.gFrameTime; position.Z -= physics.PreVelocityY * Globals.config.gFrameTime; } else { if (physics.PreVelocity != Vector2.Zero) { float velocityMagnitude = (float)(Math.Sqrt(Math.Pow(velocity.X, 2) + Math.Pow(velocity.Y, 2))) / 200 - 1; sound1Instance.Pitch = velocityMagnitude > 1 ? 1 : velocityMagnitude; sound1Instance.Play(); } else { sound1Instance.Stop(); } physics.PreVelocityY = velocity.Y; physics.PreVelocityX = 0; position.Z -= velocity.Y * Globals.config.gFrameTime; } break; case COLLISION.HitEdgeY: if (Math.Abs(physics.PreVelocityY) > 1) { float vol = (float)(Math.Abs(velocity.Y)) / 200; sound2Instance.Volume = vol > 1 ? 1 : vol; sound2Instance.Play(); physics.PreVelocityX = velocity.X; physics.PreVelocityY = -reflectionIndex * velocity.Y; position.X -= physics.PreVelocityX * Globals.config.gFrameTime; position.Z -= physics.PreVelocityY * Globals.config.gFrameTime; } else { if (physics.PreVelocity != Vector2.Zero) { float velocityMagnitude = (float)(Math.Sqrt(Math.Pow(velocity.X, 2) + Math.Pow(velocity.Y, 2))) / 200 - 1; sound1Instance.Pitch = velocityMagnitude > 1 ? 1 : velocityMagnitude; sound1Instance.Play(); } else { sound1Instance.Stop(); } physics.PreVelocityX = velocity.X; physics.PreVelocityY = 0; position.X -= velocity.X * Globals.config.gFrameTime; } break; case COLLISION.NoMove: if (physics.PreVelocity != Vector2.Zero) { float vol = (float)(Math.Sqrt(Math.Pow(velocity.X, 2) + Math.Pow(velocity.Y, 2))) / 200; sound2Instance.Volume = vol > 1 ? 1 : vol; sound2Instance.Play(); } sound1Instance.Stop(); physics.PreVelocity = Vector2.Zero; break; default: if (physics.PreVelocity != Vector2.Zero) { float velocityMagnitude = (float)(Math.Sqrt(Math.Pow(velocity.X, 2) + Math.Pow(velocity.Y, 2))) / 200 - 1; sound1Instance.Pitch = velocityMagnitude > 1 ? 1 : velocityMagnitude; sound1Instance.Play(); } else { sound1Instance.Stop(); } position.X -= velocity.X * Globals.config.gFrameTime; position.Z -= velocity.Y * Globals.config.gFrameTime; physics.PreVelocityX = velocity.X; physics.PreVelocityY = velocity.Y; break; } world = Matrix.Identity; world *= Matrix.CreateTranslation(0f, -tableCenter.Y, 0f); world *= Matrix.CreateFromAxisAngle(Vector3.Normalize(new Vector3(0f, 0, 1f)), delta.X); world *= Matrix.CreateFromAxisAngle(Vector3.Normalize(new Vector3(1f, 0f, 0f)), delta.Y); world *= Matrix.CreateTranslation(0f, tableCenter.Y, 0f); Vector4 deltaPos = Vector4.Transform(position, world); world = Matrix.CreateTranslation(deltaPos.X, deltaPos.Y, deltaPos.Z); }
public Vector2 Collision(BoundingSphere sphere, List <Vector3> vertices, Vector2 velocity, ref COLLISION collision) { Ray[] ray = new Ray[3]; ray[0].Position = sphere.Center; ray[0].Direction = Vector3.Normalize(new Vector3(-velocity.X, 0, 0)); ray[1].Position = sphere.Center; ray[1].Direction = Vector3.Normalize(new Vector3(0, 0, -velocity.Y)); Vector2 distance = Vector2.One * float.MaxValue; Vector3 Edge = Vector3.Zero; float? distanceEdge = float.MaxValue; for (int i = 0; i < vertices.Count; i += 3) { Vector2 tmpDistance; tmpDistance.X = RayTriangleIntersects(ray[0], vertices[i], vertices[i + 1], vertices[i + 2]); tmpDistance.Y = RayTriangleIntersects(ray[1], vertices[i], vertices[i + 1], vertices[i + 2]); if (tmpDistance.X < distance.X) { distance.X = tmpDistance.X; } if (tmpDistance.Y < distance.Y) { distance.Y = tmpDistance.Y; } if (vertices[i].Y != vertices[i + 1].Y && vertices[i].X == vertices[i + 1].X && vertices[i + 1].Z == vertices[i + 1].Z) { ray[2].Position = new Vector3(vertices[i].X, (vertices[i].Y + vertices[i + 1].Y) / 2, vertices[i].Z); ray[2].Direction = Vector3.Normalize(new Vector3(velocity.X, 0, velocity.Y)); float?tmp = sphere.Intersects(ray[2]); if (tmp == null) { tmp = float.MaxValue; } if (tmp < distanceEdge) { Edge = ray[2].Position; distanceEdge = tmp; } } } if (!(distance.X != float.MaxValue && distance.X > 0 && (distance.X <= Globals.config.ballRadius || distance.X <= Math.Abs(velocity.X * Globals.config.gFrameTime) + Globals.config.ballRadius))) //|| distance <= Math.Abs(velocity.Y * Globals.config.gFrameTime) + Globals.config.ballRadius)) { distance.X = float.MaxValue; } if (!(distance.Y != float.MaxValue && distance.Y > 0 && (distance.Y <= Globals.config.ballRadius || distance.Y <= Math.Abs(velocity.Y * Globals.config.gFrameTime) + Globals.config.ballRadius))) //|| distance <= Math.Abs(velocity.Y * Globals.config.gFrameTime) + Globals.config.ballRadius)) { distance.Y = float.MaxValue; } if (!(distanceEdge != float.MaxValue && distanceEdge > 0 && (distanceEdge <= Math.Sqrt(Math.Pow(velocity.X, 2) + Math.Pow(velocity.Y, 2)) * Globals.config.gFrameTime))) { distanceEdge = float.MaxValue; } if (distance.X != float.MaxValue && distance.Y != float.MaxValue && distance.X - Globals.config.ballRadius < distanceEdge / 2 && distance.Y - Globals.config.ballRadius < distanceEdge / 2) { collision = COLLISION.HitXY; } else if (distance.X != float.MaxValue && distance.X - Globals.config.ballRadius < distanceEdge / 2) { collision = COLLISION.HitX; } else if (distance.Y != float.MaxValue && distance.Y - Globals.config.ballRadius < distanceEdge / 2) { collision = COLLISION.HitY; } else if (distanceEdge != float.MaxValue) { float angleBefore = (float)(Math.Atan2(sphere.Center.Z - Edge.Z, sphere.Center.X - Edge.X)); if (angleBefore != -MathHelper.PiOver2) { collision = COLLISION.NoHit; } if (angleBefore > 0 && angleBefore < MathHelper.PiOver2) { if (velocity.X <= 0 && velocity.Y >= 0) { collision = COLLISION.HitEdgeY; } else if (velocity.X >= 0 && velocity.Y <= 0) { collision = COLLISION.HitEdgeX; } else { collision = COLLISION.NoMove; } } else if (angleBefore > MathHelper.PiOver2 && angleBefore < MathHelper.Pi) { if (velocity.X >= 0 && velocity.Y >= 0) { collision = COLLISION.HitEdgeY; } else if (velocity.X <= 0 && velocity.Y <= 0) { collision = COLLISION.HitEdgeX; } else { collision = COLLISION.NoMove; } } else if (angleBefore < -MathHelper.PiOver2 && angleBefore > -MathHelper.Pi) { if (velocity.X >= 0 && velocity.Y <= 0) { collision = COLLISION.HitEdgeY; } else if (velocity.X <= 0 && velocity.Y >= 0) { collision = COLLISION.HitEdgeX; } else { collision = COLLISION.NoMove; } } else if (angleBefore < 0 && angleBefore > -MathHelper.PiOver2) { if (velocity.X <= 0 && velocity.Y <= 0) { collision = COLLISION.HitEdgeY; } else if (velocity.X >= 0 && velocity.Y >= 0) { collision = COLLISION.HitEdgeX; } else { collision = COLLISION.NoMove; } } else if (angleBefore == 0 || angleBefore == -MathHelper.Pi || angleBefore == MathHelper.Pi) { collision = COLLISION.HitEdgeX; } else if (angleBefore == MathHelper.PiOver2 || angleBefore == -MathHelper.PiOver2) { collision = COLLISION.HitEdgeY; } } return(distance); }