/// <summary> /// Calculate the value of total force exherted at the location by the gravity points. /// </summary> /// <param name="location">The current location.</param> /// <param name="gravityPoints">Points representing gravity/anti-gravity sources</param> /// <returns></returns> private Force GetNetForce(Point location, List<GravityPoint> gravityPoints) { var netForce = new Force() { X = 0.0, Y = 0.0 }; foreach (var gravityPoint in gravityPoints) { var distance = Point.Distance(gravityPoint.Location, location); var force = gravityPoint.Power / Math.Pow(distance, gravityPoint.DistanceDecay); var angle = Utils.NormalAbsoluteAngle(Math.Atan2(gravityPoint.Location.X - location.X, gravityPoint.Location.Y - location.Y)); netForce.X += Math.Sin(angle) * force; netForce.Y += Math.Cos(angle) * force; } return netForce; }
/// <summary> /// Gets the gravity/anti-gravity force working on the robot. /// For more information, see Anti-Gravity Movement. /// </summary> /// <param name="currentLocation">The current location.</param> /// <param name="enemyLocations">Enemy locations.</param> /// <param name="enemyBullets">Predicted enemy bullets.</param> /// <param name="time">The time.</param> /// <param name="fieldWidth">Width of the field.</param> /// <param name="fieldHeight">Height of the field.</param> /// <returns></returns> private Force GetAntiGravityForce(Point currentLocation, List<Point> enemyLocations, List<WaveBullet> enemyBullets, long time, double fieldWidth, double fieldHeight) { var enemyGravityPoints = new List<GravityPoint>(); var fieldGravityPoints = new List<GravityPoint>(); var powerPerEnemy = -3000 / this.Others; // gravity points from enemies enemyGravityPoints.AddRange(enemyLocations.Select(point => new GravityPoint() { Location = point, Power = powerPerEnemy, DistanceDecay = 2 })); // gravity points from walls (should minimise the risk of hitting them under normal circumstances) fieldGravityPoints.AddRange(new List<GravityPoint>() { new GravityPoint() { Location = new Point() { X = 0, Y = currentLocation.Y }, Power = -5000, DistanceDecay = 3 }, new GravityPoint() { Location = new Point() { X = fieldWidth, Y = currentLocation.Y }, Power = -5000, DistanceDecay = 3 }, new GravityPoint() { Location = new Point() { X = currentLocation.X, Y = 0 }, Power = -5000, DistanceDecay = 3 }, new GravityPoint() { Location = new Point() { X =currentLocation.X, Y = fieldHeight }, Power = -5000, DistanceDecay = 3 }, }); // meant to add a perpendicular force from predicted enemy bullets that would push the robot aside, allowing to dodge them // never got around to get it to work though var enemyBulletGravityPoints = new List<GravityPoint>(); if (this.Others <= 2) { var bulletsToTerminate = new List<WaveBullet>(); foreach (var bullet in enemyBullets) { double guessFactor = 0; if (bullet.CheckHit(this.Name, currentLocation, this.Time + 10, out guessFactor)) { enemyBulletGravityPoints.Add(new GravityPoint() { Power = 3000, DistanceDecay = 0, Location = bullet.StartPoint }); bulletsToTerminate.Add(bullet); } if (this.Time - bullet.Time > 100) { bulletsToTerminate.Add(bullet); } } foreach (var bullet in bulletsToTerminate) { enemyBullets.Remove(bullet); } } var forceFromEnemies = GetNetForce(currentLocation, enemyGravityPoints); var forceFromField = GetNetForce(currentLocation, fieldGravityPoints); var forceFromEnemyBullets = GetNetForce(currentLocation, enemyBulletGravityPoints); // a dodge direction that would fluctuate with time var perpendicularDirection = ((this.Time / 20) % 2 == 0) ? 1 : -1; forceFromEnemyBullets = new Force() { X = perpendicularDirection * forceFromEnemyBullets.X, Y = -perpendicularDirection * forceFromEnemyBullets.Y }; return new Force() { X = forceFromEnemies.X + forceFromField.X + forceFromEnemyBullets.X, Y = forceFromEnemies.Y + forceFromField.Y + forceFromEnemyBullets.Y }; }