protected bool OnMove() { if (Config.Instance.showCurrentWay) { DrawWay(); } // Достигли текущей точки! if (AntMath.Distance((Vector2)_control.Position, _nextPoint) < WayMap.Current.approachRadius) { NextPoint(); } // Рулежка. UpdateAngle(); if (!AntMath.Equal(AntMath.Angle(_control.Angle), AntMath.Angle(_targetAngle), 1.0f)) { float curAng = AntMath.Angle(_control.Angle); float tarAng = AntMath.Angle(_targetAngle); if (Mathf.Abs(curAng - tarAng) > 180.0f) { if (curAng > tarAng) { tarAng += 360.0f; } else { tarAng -= 360.0f; } } if (curAng < tarAng) { _control.isLeft = true; _control.isRight = false; } else if (curAng > tarAng) { _control.isLeft = false; _control.isRight = true; } } else { _control.isLeft = false; _control.isRight = false; // Газ. if (!_isWayFinished) { _control.isForward = true; } else { _control.isForward = false; } } return(_isWayFinished); }
public override void Execute(float aDeltaTime, float aTimeScale) { // Aim on the target. if (!AntMath.Equal(AntMath.Angle(_control.towerRef.Angle), AntMath.Angle(_targetAngle), 1.0f)) { float curAng = AntMath.Angle(_control.towerRef.Angle); float tarAng = AntMath.Angle(_targetAngle); if (Mathf.Abs(curAng - tarAng) > 180.0f) { if (curAng > tarAng) { tarAng += 360.0f; } else { tarAng -= 360.0f; } } if (curAng < tarAng) { _control.RotateTower(1.0f, aDeltaTime); } else if (curAng > tarAng) { _control.RotateTower(-1.0f, aDeltaTime); } } else { Finish(); } }
public bool IsSee(Vector2 aPoint) { if (AntMath.Distance(_t.position.x, _t.position.y, aPoint.x, aPoint.y) < radius) { float angle = AntMath.Angle(AntMath.AngleDeg(_t.position.x, _t.position.y, aPoint.x, aPoint.y)); float diff = AntMath.AngleDifferenceDeg(angle, Angle); if (AntMath.InRange(diff, lowerLimit, upperLimit)) { if (Config.Instance.showVision) { AntDrawer.DrawLine(_t.position.x, _t.position.y, aPoint.x, aPoint.y, Color.yellow); } return(true); } } return(false); }
public override void Update(float aDeltaTime) { // Процесс наведения на цель. if (!AntMath.Equal(AntMath.Angle(_control.Tower.Angle), AntMath.Angle(_targetAngle), 1.0f)) { float curAng = AntMath.Angle(_control.Tower.Angle); float tarAng = AntMath.Angle(_targetAngle); if (Mathf.Abs(curAng - tarAng) > 180.0f) { if (curAng > tarAng) { tarAng += 360.0f; } else { tarAng -= 360.0f; } } if (curAng < tarAng) { _control.isTowerLeft = true; _control.isTowerRight = false; } else if (curAng > tarAng) { _control.isTowerLeft = false; _control.isTowerRight = true; } } else { _control.isTowerLeft = false; _control.isTowerRight = false; } }
public void GetConditions(AntAIAgent aAgent, AntAICondition aWorldState) { // Получаем список всех объектов которые необходимо отслеживать. if (_visualNodes == null) { _visualNodes = AntEngine.Current.GetNodes <VisualNode>(); } // 1. Обновляем информацию о себе. // ------------------------------- aWorldState.Set(aAgent.planner, "ArmedWithGun", control.Tower.HasGun); aWorldState.Set(aAgent.planner, "ArmedWithBomb", control.Tower.HasBomb); aWorldState.Set(aAgent.planner, "HasAmmo", control.Tower.HasAmmo); aWorldState.Set(aAgent.planner, "Injured", (health.HP != health.maxHP)); aWorldState.Set(aAgent.planner, "EnemyAlive", true); // Наш враг всегда жив, потому что респавнится. aWorldState.Set(aAgent.planner, "Alive", (health.HP > 0.0f)); aWorldState.Set(aAgent.planner, "HasObstacle", sensor.HasObstacle); if (sensor.HasObstacle) { sensor.HasObstacle = false; } // 2. Обрабатываем зрение. // ----------------------- // Сбрасываем состояние всех возможных значений зрения. aWorldState.Set(aAgent.planner, "NearEnemy", false); aWorldState.Set(aAgent.planner, "EnemyVisible", false); aWorldState.Set(aAgent.planner, "GunInlineOfSight", false); aWorldState.Set(aAgent.planner, "AmmoInlineOfSight", false); aWorldState.Set(aAgent.planner, "BombInlineOfSight", false); aWorldState.Set(aAgent.planner, "HealInlineOfSight", false); VisualNode visual; // Перебираем все объекты которые можно просматривать. for (int i = 0, n = _visualNodes.Count; i < n; i++) { visual = _visualNodes[i]; // Если объект из другой группы. if (vision.group != visual.Visual.group) { // Если объект попадает в область зрения. if (vision.IsSee(visual.entity.Position)) { blackboard[visual.Visual.conditionName].AsBool = true; blackboard[string.Concat(visual.Visual.conditionName, "_Pos")].AsVector2 = visual.entity.Position; // Отмечаем что видим. aWorldState.Set(aAgent.planner, visual.Visual.conditionName, true); if (vision.enemyGroup == visual.Visual.group && AntMath.Distance(control.Position, visual.entity.Position) < 1.5f) { aWorldState.Set(aAgent.planner, "NearEnemy", true); } } } } // 3. Обрабатываем наведение пушки на врага. // ----------------------------------------- aWorldState.Set(aAgent.planner, "EnemyLinedUp", false); if (aWorldState.Has(aAgent.planner, "EnemyVisible") && control.Tower.HasGun) { if (blackboard["EnemyVisible"].AsBool) { float angle = AntMath.AngleDeg((Vector2)control.Position, blackboard["EnemyVisible_Pos"].AsVector2); if (AntMath.Equal(AntMath.Angle(control.Tower.Angle), AntMath.Angle(angle), 10.0f)) { aWorldState.Set(aAgent.planner, "EnemyLinedUp", true); } } } }
private void UpdateMovement() { if (AntMath.Distance(_currentPoint, (Vector2)_t.position) < 0.5f) { // Arrived to the current way point. _pointIndex++; if (_pointIndex < _route.Count) { // Move to next one. _currentPoint = _route[_pointIndex]; } else { // This is end of the way. float dist = AntMath.Distance(_currentPoint, (Vector2)_t.position); if (dist < 0.5f) { // Enable break. _speed = AntMath.Lerp(_speed, 0.0f, 1.0f - breakCurve.Evaluate(dist / 0.5f)); _isBrake = true; } if (AntMath.Equal(_speed, 0.0f, 0.1f)) { // Absolutely arrived. StopMove(); if (EventArrived != null) { EventArrived(this); } } } _steeringTime = 0.0f; _isSteering = false; } float targetAngle = AntMath.Angle(AntMath.AngleDeg(_t.position, _currentPoint)); _debugTargetAngle = targetAngle * AntMath.RADIANS; float angleDiff = AntMath.AngleDifference(Angle, targetAngle) * AntMath.DEGREES; // If our direction incorrect. if (!AntMath.Equal(angleDiff, 0.0f, 0.01f) && !_isSteering) { // Correct our angle to the current way point. _isSteering = true; _steeringTime = 0.0f; _totalSteeringTime = totalSteeringTime * (1.0f - Mathf.Abs(angleDiff / 360.0f)); } // Acceleration! if (!_isBrake && _accelerationTime < totalAccelTime) { _accelerationTime += Time.deltaTime; _speed = AntMath.Lerp(_speed, moveSpeed, accelCurve.Evaluate(_accelerationTime / totalAccelTime)); } // Correction of the angle. if (_isSteering) { _steeringTime += Time.deltaTime; Angle = AntMath.LerpAngleDeg(Angle, targetAngle, steeringCurve.Evaluate(_steeringTime / _totalSteeringTime)); if (AntMath.Equal(angleDiff, 0.0f, 0.01f)) { _isSteering = false; _steeringTime = 0.0f; } } // Movement. float ang = Angle * AntMath.RADIANS; Velocity = new Vector2(_speed * Mathf.Cos(ang), _speed * Mathf.Sin(ang)); }
public void CollectConditions(AntAIAgent aAgent, AntAICondition aWorldState) { // 1. Remove all stored data from previous ticks. // ---------------------------------------------- ClearSensors(); // 2. Get fresh Vision and Touch data. // ----------------------------- UpdateVision(); UpdateTouch(); // 3. Update World State. // ---------------------- aWorldState.Set(TankScenario.Alive, true); aWorldState.Set(TankScenario.Injured, (_control.Health < _control.maxHealth)); aWorldState.Set(TankScenario.EnemyAlive, true); // All time is true ;) aWorldState.Set(TankScenario.HasGun, _control.Tower.IsHasGun); aWorldState.Set(TankScenario.HasAmmo, _control.Tower.IsHasAmmo); aWorldState.Set(TankScenario.HasBomb, _control.Tower.IsHasBomb); // Reset items visibility. aWorldState.Set(TankScenario.SeeGun, false); aWorldState.Set(TankScenario.SeeAmmo, false); aWorldState.Set(TankScenario.SeeBomb, false); aWorldState.Set(TankScenario.SeeRepair, false); // Update vision for items. for (int i = 0; i < SEE_ITEMS_COUNT; i++) { if (_seeItems[i] != null) { // Adds founded spawner and item to the our memory. // This data maybe will be required by bot in the near future. _blackboard.TrackSpawner(_seeItems[i].Position, _seeItems[i].kind); _blackboard.TrackItem(_seeItems[i], _seeItems[i].kind); // Update the world state. switch (_seeItems[i].kind) { case ItemKind.Gun: aWorldState.Set(TankScenario.SeeGun, true); break; case ItemKind.Ammo: aWorldState.Set(TankScenario.SeeAmmo, true); break; case ItemKind.Bomb: aWorldState.Set(TankScenario.SeeBomb, true); break; case ItemKind.Repair: aWorldState.Set(TankScenario.SeeRepair, true); break; } } } // Update vision for enemies. aWorldState.Set(TankScenario.SeeEnemy, false); for (int i = 0; i < TANKS_COUNT; i++) { if (_seeTanks[i] != null) { _blackboard.TrackTank(_seeTanks[i]); aWorldState.Set(TankScenario.SeeEnemy, true); } } // Check the enemy on line of the fire. aWorldState.Set(TankScenario.OnLineofFire, false); if (_blackboard.HasEnemy) { float angle = AntMath.AngleDeg(_control.Position, _blackboard.EnemyTank.Position); if (AntMath.Equal(AntMath.Angle(angle), AntMath.Angle(_control.Tower.Angle), 10.0f)) { aWorldState.Set(TankScenario.OnLineofFire, true); } } // Check the touching of enemy tanks. aWorldState.Set(TankScenario.NearEnemy, false); for (int i = 0; i < TANKS_COUNT; i++) { if (_touchTanks[i] != null) { aWorldState.Set(TankScenario.NearEnemy, true); break; } } }