public void AirWallRecovery(GameState gamestate, BotCalculations botCalculations) { if (gamestate.myCar.player.Physics.Rotation.Roll > .5) { botCalculations.controller.Steer = 1; botCalculations.controller.Roll = -1; } else if (gamestate.myCar.player.Physics.Rotation.Roll < -.5) { botCalculations.controller.Steer = -1; botCalculations.controller.Roll = 1; } if (!gamestate.myCar.player.HasWheelContact) { if (gamestate.myCar.player.Physics.Rotation.Pitch > .5) { botCalculations.controller.Pitch = -1; } else if (gamestate.myCar.player.Physics.Rotation.Pitch < -.5) { botCalculations.controller.Pitch = 1; } float angle = Utils.AngleBetween(Vector3.Zero, gamestate.myCar.player.Physics.Rotation, gamestate.myCar.player.Physics.Velocity); angle = Utils.Clamp(angle, -1, 1); botCalculations.controller.Yaw = angle; } }
public void ContactBall(GameState gamestate, BotCalculations botCalculations) { // Simple Jump. // Find where the ball is relative to us. Vector3 ballLocation = gamestate.ballPhysics.Location; Vector3 ballRelativeLocation = Orientation.RelativeLocation(gamestate.myCar.player.Physics.Location, ballLocation, gamestate.myCar.player.Physics.Rotation); if (Math.Abs(ballRelativeLocation.X) < 400 && Math.Abs(ballRelativeLocation.Y) < 150 && ballLocation.Z > 100 && ballLocation.Z < 300) { botCalculations.controller.Jump = true; } }
public Tactic ChooseTactic(GameState gameState, BotCalculations botCalculations) { Vector3 meToBallDirection = Vector3.Normalize(gameState.ballPhysics.Location - gameState.myCar.player.Physics.Location); Vector3 meToOwnGoalDirection = Vector3.Normalize(gameState.fieldState.ownGoalLocation - gameState.myCar.player.Physics.Location); if (Vector3.Dot(meToBallDirection, meToOwnGoalDirection) > .95f) { return(new Defend()); } else if (botCalculations.predictedBallLocation.Z > 300) { return(new Patience()); } else { return(new Attack()); } }
public override void DoWork(GameState gameState, BotCalculations botCalculations) { // Drive towards safest post. Vector3 directionToBall = Vector3.Normalize(gameState.ballPhysics.Location - gameState.myCar.player.Physics.Location); float YDistanceFromGoal = gameState.fieldState.ownGoalLocation.Y - gameState.myCar.player.Physics.Location.Y; float distanceFactor = YDistanceFromGoal / directionToBall.Y; Vector3 OwnWallIntersection = directionToBall * distanceFactor; Vector3 safePosition = gameState.fieldState.ownGoalLocation; if (OwnWallIntersection.X > 0) { safePosition.X -= Utils.GoalPostOffset; } else { safePosition.X += Utils.GoalPostOffset; } float angleToSafePosition = Utils.AngleBetween(gameState.myCar.player.Physics.Location, gameState.myCar.player.Physics.Rotation, safePosition); botCalculations.primaryTarget = safePosition; botCalculations.primaryAngle = angleToSafePosition; if (Math.Abs(angleToSafePosition) < 0.2f) { // TODO: don't boost when unnecessary. Both for worthless hits, and lack of urgency? botCalculations.controller.Boost = true; } // Turn to safe position. botCalculations.controller.Throttle = 1; botCalculations.controller.Steer = Utils.Clamp(angleToSafePosition * 6.0f, -1, 1); // Fixups. AirWallRecovery(gameState, botCalculations); // Jump. ContactBall(gameState, botCalculations); }
public override void DoWork(GameState gameState, BotCalculations botCalculations) { Vector3 safePosition = Utils.ProjectLocationTowardsTarget(gameState.fieldState.ownGoalLocation, gameState.fieldState.oppGoalLocation, 150); float angleToSafePosition = Utils.AngleBetween(gameState.myCar.player.Physics.Location, gameState.myCar.player.Physics.Rotation, safePosition); botCalculations.primaryTarget = safePosition; botCalculations.primaryAngle = angleToSafePosition; if (Math.Abs(angleToSafePosition) > Math.PI * 0.5f) { // Reverse to safe position. botCalculations.controller.Throttle = -1; float reverseAngle; if (angleToSafePosition > 0) { reverseAngle = (float)Math.PI - angleToSafePosition; } else { reverseAngle = -(float)Math.PI + angleToSafePosition; } botCalculations.controller.Steer = Utils.Clamp(reverseAngle, -1, 1); } else { // Turn to safe position. botCalculations.controller.Throttle = 0.2f; botCalculations.controller.Steer = Utils.Clamp(angleToSafePosition, -1, 1); } // Fixups. AirWallRecovery(gameState, botCalculations); // Jump. ContactBall(gameState, botCalculations); }
public override Controller GetOutput(rlbot.flat.GameTickPacket gameTickPacket) { // Convert the current frame data into our own structures and helpers. GameState gameState = InitializeGameState(gameTickPacket); if (gameState == null) { return(new Controller()); } BotCalculations botCalculations = new BotCalculations { controller = new Controller() }; botCalculations.predictedBallLocation = gameState.GetPredictionLocation(); botCalculations.primaryMechanic = currentMechanic; // Decide on a tactic and run it. if (currentMechanic == null) { currentTactic = ChooseTactic(gameState, botCalculations); } currentTactic.DoWork(gameState, botCalculations); currentMechanic = botCalculations.primaryMechanic; // Examples of rendering in the game Renderer.DrawString3D("Ball", Colors.Black, botCalculations.predictedBallLocation, 3, 3); if (botCalculations.controller.Steer != 0) { Renderer.DrawString3D(botCalculations.controller.Steer > 0 ? "Right" : "Left", Colors.Aqua, gameState.myCar.player.Physics.Location, 3, 3); } if (botCalculations.controller.Jump) { Renderer.DrawString3D("Jump", Colors.Green, gameState.myCar.player.Physics.Location, 3, 3); } Color tacticColor = Colors.Red; switch (currentTactic.tacticType) { case TacticType.Attack: tacticColor = Colors.Magenta; break; case TacticType.Defend: tacticColor = Colors.Purple; break; case TacticType.Patience: tacticColor = Colors.DarkGreen; break; } Renderer.DrawLine3D(tacticColor, gameState.myCar.player.Physics.Location, botCalculations.primaryTarget); Renderer.DrawCenteredRectangle3D(tacticColor, botCalculations.primaryTarget, 50, 50, false); Renderer.DrawCenteredRectangle3D(Colors.LimeGreen, botCalculations.predictedBallLocation, 20, 20, false); Renderer.DrawString2D(currentTactic.tacticType.ToString(), Colors.WhiteSmoke, new Vector2(), 5, 5); return(botCalculations.controller); }
public override void DoWork(GameState gameState, BotCalculations botCalculations) { // Get the data required to drive to the ball. Vector3 ballActualLocation = gameState.ballPhysics.Location; Vector3 carLocation = gameState.myCar.player.Physics.Location; Orientation carRotation = gameState.myCar.player.Physics.Rotation; Vector3 ballLocation = gameState.GetPredictionLocation(); botCalculations.predictedBallLocation = ballLocation; // Target the side of the ball to shoot at their goal. Vector3 ballEdgeLocation = Utils.ProjectLocationTowardsTarget(ballLocation, gameState.fieldState.oppGoalLocation, -Utils.BallRadius * 1.25f); float distanceToBall = Utils.DistanceBetween(carLocation, ballEdgeLocation); // How far away from the ball should we be aiming? float glidepathAimAmount = Math.Min(.25f * distanceToBall * distanceToBall / 1000.0f, 800); float distanceToBallToAim = Utils.BallRadius + glidepathAimAmount; Vector3 targetLocation = Utils.ProjectLocationTowardsTarget(ballLocation, gameState.fieldState.oppGoalLocation, -distanceToBallToAim); targetLocation = Utils.ClampToField(targetLocation); botCalculations.primaryTarget = targetLocation; // Check the angle to the ball and steer that way. float angleToBallTarget = Utils.AngleBetween(carLocation, carRotation, targetLocation); botCalculations.primaryAngle = angleToBallTarget; // Specify steer strength as less when ball is far. (unnecessary?) const float minTurnEasingDistance = 300; const float maxTurnEasingDistance = 1000; float distanceFactor = Utils.Clamp(distanceToBall, minTurnEasingDistance, maxTurnEasingDistance); float steerStrength = Utils.Lerp(6.0f, 10, (maxTurnEasingDistance - distanceFactor) / (maxTurnEasingDistance - minTurnEasingDistance)); // Steer stronger when moving fast. if (gameState.myCar.player.Physics.Velocity.Length() > 1000) { steerStrength *= 2; } botCalculations.controller.Steer = Utils.Clamp(angleToBallTarget * steerStrength, -1, 1); if (Math.Abs(angleToBallTarget) < 0.2f) { // TODO: don't boost when unnecessary. Both for worthless hits, and lack of urgency? botCalculations.controller.Boost = true; } botCalculations.controller.Throttle = 1; if (Math.Abs(angleToBallTarget) > 1.6f) { botCalculations.controller.Handbrake = true; } // TODO: Pass the direction to the ball instead of using steer. bool shouldDodge = distanceToBall < 400 && ballLocation.Z < 200; // && Math.Abs(angleToBallTarget) < 0.5f; if (shouldDodge || botCalculations.primaryMechanic != null) // fixup { if (botCalculations.primaryMechanic == null) { botCalculations.primaryMechanic = new ForwardDodge(); } bool hasWork = botCalculations.primaryMechanic.Update(gameState, botCalculations.primaryAngle, ref botCalculations.controller); if (!hasWork) { botCalculations.primaryMechanic = null; } } else { // Fixups. AirWallRecovery(gameState, botCalculations); // Jump. ContactBall(gameState, botCalculations); } }
public abstract void DoWork(GameState gameState, BotCalculations botCalculations);