// TODO: Criar fisica do Disco /// <remarks>Source: http://gamedevelopment.tutsplus.com/tutorials/when-worlds-collide-simulating-circle-circle-collisions--gamedev-769</remarks> private static void CheckDiscCollision(BolaState state, TransformTarget target, GameContext context) { // Circle-circle collision var discRadius = context.Config.Disco.Size.Radius; var paddleRadius = context.Config.Bola.Size.Radius; var discPos = context.State.Disco.Transform.Position; var bolaPos = state.Transform.Position; var discVelocity = context.State.Disco.Heading * context.State.Disco.Speed; var paddleVelocity = target.Heading * context.Config.Bola.Size.ForwardSpeed; var discMass = context.Config.Disco.Size.Mass; var bolaMass = context.Config.Bola.Size.Mass; var dist = Vector2.Distance(discPos, bolaPos); var minDist = discRadius + paddleRadius; if (dist < minDist) { var collisionPoint = Vector2.zero; collisionPoint.x = ((discPos.x * paddleRadius) + (bolaPos.x * discRadius)) / (discRadius + paddleRadius); collisionPoint.y = ((discPos.y * paddleRadius) + (bolaPos.y * discRadius)) / (discRadius + paddleRadius); var discNormal = (collisionPoint - discPos).normalized; var bounceHeading = -Vector2.Reflect(paddleVelocity, discNormal).normalized; var newDiscVelocity = Vector2.zero; newDiscVelocity.x = (discVelocity.x * (discMass - bolaMass) + (2 * bolaMass * paddleVelocity.x)) / (discMass + bolaMass); newDiscVelocity.y = (discVelocity.y * (discMass - bolaMass) + (2 * bolaMass * paddleVelocity.y)) / (discMass + bolaMass); context.State.Disco.Heading = (newDiscVelocity + bounceHeading).normalized; context.State.Disco.Speed = Mathf.Max(context.State.Disco.Speed, newDiscVelocity.magnitude * context.Config.Bola.DiscBounceFactor); } }
private static void StepTransform(float deltaTime, GameContext context, TransformTarget target) { var state = context.State.Disco; var angleOffset = 0f; target.Heading = state.Heading; target.Distance = deltaTime * state.Speed; target.AngleOffset = angleOffset; }
public static void ResolveTarget(int playerId, GameContext context, TransformTarget target) { var state = context.State.GetBola(playerId); while (target.Distance > NearZero) { MoveToTarget(playerId, context, target); CheckDiscCollision(state, target, context); } }
public static TransformTarget StepTarget(float deltaTime, GameContext context) { var state = context.State.Disco; var target = new TransformTarget(); state.Speed *= context.Config.Disco.DragFactor; StepTransform(deltaTime, context, target); return(target); }
public static void ResolveTarget(GameContext context, TransformTarget target) { var state = context.State.Disco; while (target.Distance > NearZero) { MoveToTarget(context, target); } state.Speed = Mathf.Min(state.Speed, context.Config.Disco.MaxSpeed); }
public static TransformTarget StepTarget(float deltaTime, int playerId, GameContext context) { var state = context.State.GetBola(playerId); var target = new TransformTarget(); StepPercentOrbit(deltaTime, playerId, context); if (state.Mode == BolaState.MovementMode.Normal) { UpdateOrbitDirection(playerId, context); } UpdateOrbitOrigin(playerId, context); StepTransform(deltaTime, playerId, context, target); return(target); }
private static void MoveToTarget(int playerId, GameContext context, TransformTarget target) { var state = context.State.GetBola(playerId); var trans = state.Transform; var nextPos = trans.Position + target.Heading * target.Distance; var nextRot = trans.Rotation + target.AngleOffset; Line collisionWall; Vector2 collisionPoint; var collided = BoxPhysics.CheckPointCollision(context.Config.BolaBox, trans.Position, nextPos, out collisionWall, out collisionPoint); if (collided) { // Calculate partial position offset var collisionPosAmount = Mathf.Max(0f, Vector2.Distance(trans.Position, collisionPoint) - NearZero); var collisionPosTarget = trans.Position + target.Heading * collisionPosAmount; // Apply partial position offset target.Distance -= collisionPosAmount; trans.Position = collisionPosTarget; // Calculate partial rotation offset var bounceDistPercentage = collisionPosAmount / target.Distance; var bounceRotAmount = bounceDistPercentage * target.AngleOffset; // Reflect rotation against wall + apply partial rotation offset target.Heading = Vector2.Reflect(nextPos - trans.Position, collisionWall.Normal).Rotate(bounceRotAmount).normalized; target.AngleOffset -= bounceRotAmount; trans.Rotation = Vector2.up.SignedAngle(target.Heading); } else { target.Distance = 0f; target.AngleOffset = 0f; trans.Position = nextPos; trans.Rotation = nextRot; } }
private static void StepTransform(float deltaTime, int playerId, GameContext context, TransformTarget target) { var state = context.State.GetBola(playerId); var trans = state.Transform; var posOffset = Vector2.zero; var angleOffset = 0f; // Adicionar orbita { var orbitDist = deltaTime * context.Config.Bola.Size.OrbitSpeed * state.PercentOrbit; var orbitDegrees = MathUtility.CircleArcDistanceToAngleOffset(orbitDist, context.Config.Bola.Size.OrbitRadius); if (state.Direction == Direction.CW) { orbitDegrees *= -1; } var orbitDest = trans.Position.RotateAround(state.OrbitOrigin, orbitDegrees); var orbitPosOffset = (orbitDest - trans.Position); posOffset += orbitPosOffset; angleOffset += orbitDegrees; } // Adicionar aceleraçao { var forwardDir = MathUtility.ToHeading(trans.Rotation); var forwardDist = deltaTime * context.Config.Bola.Size.ForwardSpeed * (1 - state.PercentOrbit); var forwardPosOffset = forwardDir * forwardDist; posOffset += forwardPosOffset; } target.Heading = posOffset.normalized; target.Distance = posOffset.magnitude; target.AngleOffset = angleOffset; }
private static void MoveToTarget(GameContext context, TransformTarget target) { var state = context.State.Disco; if (state.IsInGoal) { target.Distance = 0f; return; } var trans = state.Transform; var nextPos = trans.Position + target.Heading * target.Distance; Line collisionWall = default; var collisionPoint = Vector2.zero; var collided = false; if (state.IsHeadingTowardGoal) { if (context.Config.DiscoBox.Bounds.Contains(nextPos)) { state.IsHeadingTowardGoal = false; } } // TODO:Mudar a colisao para o ObjectoController. if (!state.IsHeadingTowardGoal) { collided = BoxPhysics.CheckPointCollision(context.Config.DiscoBox, trans.Position, nextPos, out collisionWall, out collisionPoint); } if (collided && !state.IsHeadingTowardGoal) { var halfGoalSize = context.Config.Size.GoalWidth / 2 - context.Config.Disco.Size.Radius; // HACK var inGoalX = collisionPoint.x > -halfGoalSize && collisionPoint.x < halfGoalSize; if (inGoalX) { collided = false; state.IsHeadingTowardGoal = true; } } if (collided) { // Calculate partial position offset var collisionPosAmount = Mathf.Max(0f, Vector2.Distance(trans.Position, collisionPoint) - NearZero); var collisionPosTarget = trans.Position + target.Heading * collisionPosAmount; // Apply partial position offset target.Distance -= collisionPosAmount; trans.Position = collisionPosTarget; // Reflect heading against wall target.Heading = Vector2.Reflect(target.Heading, collisionWall.Normal).normalized; state.Heading = target.Heading; state.Speed *= context.Config.Disco.WallBounceFactor; } else { target.Distance = 0f; target.AngleOffset = 0f; trans.Position = nextPos; } if (state.IsHeadingTowardGoal) { var goalLineY = context.Config.DiscoBox.Bounds.max.y + context.Config.Disco.Size.Radius * 2; if (Mathf.Abs(trans.Position.y) > goalLineY) { state.IsInGoal = true; } } }