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(); } }
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); }
private int FindVertex(Vector2 aPoint) { for (int i = 0, n = _self.vertices.Count; i < n; i++) { if (AntMath.Equal(_self.vertices[i], aPoint)) { return(i); } } return(-1); }
public int FindEdge(Vector2 aA, Vector2 aB) { for (int i = 0, n = _self.edges.Count; i < n; i++) { if (AntMath.Equal(_self.vertices[_self.edges[i].a], aA) && AntMath.Equal(_self.vertices[_self.edges[i].b], aB)) { return(i); } } return(-1); }
public override void Drag(Vector2 aDelta) { var oldPos = rect.position; base.Drag(aDelta); if (!AntMath.Equal(oldPos.x, rect.position.x) || !AntMath.Equal(oldPos.y, rect.position.y)) { _action.position = rect.position; EditorUtility.SetDirty(_scenario); } }
private void AddPointToList(ref List <Vector2> aList, Vector2 aPoint) { for (int i = 0, n = aList.Count; i < n; i++) { if (AntMath.Equal(aList[i], aPoint)) { // This point already exists in the list, skip. return; } } aList.Add(aPoint); }
public void Reset(AntEmitter aEmitter) { IsActive = Preset.scale.animateScale; _endScale = Preset.scale.endScale; _startScale = Vector2.zero; _startScale.x = Preset.scale.startScale.x + AntMath.RandomRangeFloat(Preset.scale.rndToScaleX); _startScale.y = Preset.scale.startScale.y + AntMath.RandomRangeFloat(Preset.scale.rndToScaleY); _curveX = Preset.scale.scaleCurveX; _curveY = Preset.scale.scaleCurveY; _useChild = Preset.scale.useChildSprite; _proportional = Preset.scale.proportional; if (Preset.scale.effectLifeTime && !AntMath.Equal(_particle.Effect.lifeTime, 0.0f)) { _delta = _particle.Effect.Duration / _particle.Effect.TotalDuration; _delta = AntMath.TrimToRange(_delta, 0.0f, 1.0f); _startScale.x = AntMath.Lerp(_startScale.x, Preset.scale.endScale.x, _curveX.Evaluate(_delta)); _startScale.y = AntMath.Lerp(_startScale.y, Preset.scale.endScale.y, _curveY.Evaluate(_delta)); } if (Preset.scale.useChildSprite) { _childTransform.localScale = new Vector3( _startScale.x, (Preset.scale.proportional) ? _startScale.x : _startScale.y, 1.0f ); } else { _transform.localScale = new Vector3( _startScale.x, (Preset.scale.proportional) ? _startScale.x : _startScale.y, 1.0f ); } }
private void MergeNodes() { // _notFoundEdges.Clear(); for (int i = 0, n = _from.Count; i < n; i++) { if (!AntMath.Equal(_to[i], _from[i])) { int fromNode = _self.FindNodeByPoint(_from[i]); int toNode = _self.FindNodeByPoint(_to[i]); if (toNode > -1) { var edges = new int[2]; var center = _self.GetNodeCenter(toNode); if (IsPossibleMergeTriangles(_from[i], center, ref edges)) { var a = _self.vertices[_self.edges[edges[0]].a]; var b = _self.vertices[_self.edges[edges[0]].b]; var c = _self.vertices[_self.edges[edges[1]].a]; var d = _self.vertices[_self.edges[edges[1]].b]; if (!MergeEdgesIfNotCrossing(a, c, b, d, fromNode, toNode)) { if (!MergeEdgesIfNotCrossing(b, c, a, d, fromNode, toNode)) { if (!MergeEdgesIfNotCrossing(b, d, a, c, fromNode, toNode)) { MergeEdgesIfNotCrossing(a, d, b, c, fromNode, toNode); } } } } } } _to[i] = _from[i]; } }
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)); }
private void OnSceneGUI() { bool isDirty = false; // bool isRemovePressed = ((Event.current.modifiers & (EventModifiers.Command | EventModifiers.Control)) != 0); bool isLinkPressed = ((Event.current.modifiers & EventModifiers.Command) != 0); bool isRemovePressed = ((Event.current.modifiers & EventModifiers.Control) != 0); bool isAddPressed = ((Event.current.modifiers & EventModifiers.Shift) != 0); // DEBUG POINTS. // ------------- // From Point. Handles.color = Color.blue; var delta_d = DotHandle(_self.fromPoint) - _self.fromPoint; if (delta_d != Vector2.zero) { _self.fromPoint += delta_d; } // To Point. Handles.color = Color.red; delta_d = DotHandle(_self.toPoint) - _self.toPoint; if (delta_d != Vector2.zero) { _self.toPoint += delta_d; } // Merge nodes. // ------------ if (Event.current.type == EventType.MouseUp && Event.current.button == 0) { MergeNodes(); } Handles.matrix = _self.transform.localToWorldMatrix; DrawMesh(); if (!_self.editMesh) { return; } // Is pressed hotkey for linking nodes (command key). // -------------------------------------------------- if (isLinkPressed) { if (_from.Count != _self.nodes.Count) { _from.Clear(); _to.Clear(); for (int i = 0, n = _self.nodes.Count; i < n; i++) { _from.Add(_self.GetNodeCenter(i)); _to.Add(_from[_from.Count - 1]); } } Handles.color = Color.yellow; for (int i = 0, n = _to.Count; i < n; i++) { var p = _to[i]; var delta = DotHandle(p) - p; if (delta != Vector2.zero) { _to[i] = p + delta; } if (!AntMath.Equal(_to[i], _from[i])) { Handles.DrawLine(_from[i], _to[i]); int nodeIndex = _self.FindNodeByPoint(_to[i]); if (nodeIndex > -1) { var edges = new int[2]; var center = _self.GetNodeCenter(nodeIndex); DrawLinks(nodeIndex); if (IsPossibleMergeTriangles(_from[i], center, ref edges)) { Handles.color = Color.green; var a = _self.vertices[_self.edges[edges[0]].a]; var b = _self.vertices[_self.edges[edges[0]].b]; var c = _self.vertices[_self.edges[edges[1]].a]; var d = _self.vertices[_self.edges[edges[1]].b]; if (!DrawEdgesIfNotCrossing(a, c, b, d)) { if (!DrawEdgesIfNotCrossing(b, c, a, d)) { if (!DrawEdgesIfNotCrossing(b, d, a, c)) { DrawEdgesIfNotCrossing(a, d, b, c); } } } Handles.color = Color.yellow; } } } } } // If pressed hotkey for removing nodes (triangles). // ------------------------------------------------- else if (isRemovePressed) { Handles.color = Color.red; Vector2 center; for (int i = 0, n = _self.nodes.Count; i < n; i++) { center = _self.GetNodeCenter(i); if (Handles.Button(center, Quaternion.identity, 0.05f, 0.05f, Handles.DotHandleCap)) { RemoveNode(i); isDirty = true; break; } } } // Pressed hotkey for adding new nodes (triangles). // ------------------------------------------------ else if (isAddPressed) { var mouse = HandleUtility.GUIPointToWorldRay(Event.current.mousePosition).origin; var p = _self.transform.InverseTransformPoint(mouse); // var pos = (Vector2) _self.transform.position; Handles.color = Color.white; int nearEdge = _self.GetNearEdge(p); if (nearEdge > -1) { Handles.DrawDottedLine(_self.vertices[_self.edges[nearEdge].a], p, 1.0f); Handles.DrawDottedLine(_self.vertices[_self.edges[nearEdge].b], p, 1.0f); if (Handles.Button(p, Quaternion.identity, 0.05f, 0.05f, Handles.DotHandleCap)) { var newVertex = AddVertex(p.x, p.y); var edges = new int[2]; edges[0] = AddEdge(_self.edges[nearEdge].a, newVertex); edges[1] = AddEdge(newVertex, _self.edges[nearEdge].b); var newNode = AddNode(nearEdge, edges[0], edges[1]); var e = _self.edges[nearEdge]; e.AddNeighbor(newNode); _self.edges[nearEdge] = e; isDirty = true; } // Handles.color = Color.white; // float s = HandleUtility.GetHandleSize(p) * 0.05f; // for (int i = 0, n = _self.vertices.Count; i < n; i++) // { // Handles.DotHandleCap(0, _self.vertices[i], Quaternion.identity, s, EventType.DragUpdated); // } } } // Simple editing the NavMesh. // --------------------------- else { Handles.color = Color.white; for (int i = 0, n = _self.vertices.Count; i < n; i++) { var p = _self.vertices[i]; var delta = DotHandle(p) - p; if (delta != Vector2.zero) { _self.vertices[i] = p + delta; isDirty = true; } } // float dist; // float ang; // Vector2 pa, pb; // Vector2 center = Vector2.zero; // Handles.color = Color.green; // for (int i = 0, n = _self.edges.Count; i < n; i++) // { // // if (_self.edges[i].hasNeigbors) // // continue; // pa = _self.vertices[_self.edges[i].a]; // pb = _self.vertices[_self.edges[i].b]; // dist = AntMath.Distance(pa, pb) * 0.5f; // ang = AntMath.AngleRad(pa, pb) - 90.0f * Mathf.Deg2Rad; // center = new Vector2((pa.x + pb.x) * 0.5f, (pa.y + pb.y) * 0.5f); // if (Handles.Button(center, Quaternion.identity, 0.05f, 0.05f, Handles.DotHandleCap)) // { // // AntGeo.ExpandSegment(pa, pb, ref _c, ref _d, 100.0f); // // AntLog.Trace(_self.edges[i].nodeA, _self.edges[i].nodeB, _self.edges[i].HasNeigbors); // var newVertex = _self.AddVertex( // center.x + dist * Mathf.Cos(ang), // center.y + dist * Mathf.Sin(ang) // ); // var edges = new int[2]; // edges[0] = _self.AddEdge(_self.edges[i].a, newVertex); // edges[1] = _self.AddEdge(newVertex, _self.edges[i].b); // var newNode = _self.AddNode(i, edges[0], edges[1]); // var e = _self.edges[i]; // e.AddNeighbor(newNode); // _self.edges[i] = e; // // var edge = _self.edges[i]; // // _self.edges[i] = edge; // isDirty = true; // } // } } if (isDirty) { EditorUtility.SetDirty(target); } }
private bool MergeEdgesIfNotCrossing(Vector2 aA, Vector2 aB, Vector2 aC, Vector2 aD, int aFrom, int aTo) { // Link two nodes only. (?) // if ((AntMath.Equal(aA, aC) && AntMath.Equal(aB, aD)) || // (AntMath.Equal(aA, aD) && AntMath.Equal(aB, aC))) // { // AntLog.Trace("Merge two edges!"); // return true; // } // Create one new node. // -------------------- var v = new Vector2[] { aA, aB, aC, aD }; for (int i = 0; i < 4; i++) { for (int j = 0; j < 4; j++) { if (i != j && AntMath.Equal(v[i], v[j])) { // Remove shared vertex. AntArray.RemoveAt <Vector2>(ref v, i); var edges = new int[3]; edges[0] = GetEdge(v[0], v[1]); edges[1] = GetEdge(v[1], v[2]); edges[2] = GetEdge(v[2], v[0]); var node = AddNode(edges[0], edges[1], edges[2]); LinkNodes(aFrom, node); LinkNodes(node, aTo); var center = _self.GetNodeCenter(node); var testNode = _self.FindNodeByPoint(center); if (testNode != node) { // The triangle turned inside out, recreate. RemoveNode(node); edges[0] = GetEdge(v[0], v[2]); edges[1] = GetEdge(v[2], v[1]); edges[2] = GetEdge(v[1], v[0]); node = AddNode(edges[0], edges[1], edges[2]); LinkNodes(aFrom, node); LinkNodes(node, aTo); center = _self.GetNodeCenter(node); testNode = _self.FindNodeByPoint(center); if (testNode != node) { // The triangle turned inside out, recreate. RemoveNode(node); edges[0] = GetEdge(v[1], v[2]); edges[1] = GetEdge(v[2], v[0]); edges[2] = GetEdge(v[0], v[1]); node = AddNode(edges[0], edges[1], edges[2]); LinkNodes(aFrom, node); LinkNodes(node, aTo); center = _self.GetNodeCenter(node); testNode = _self.FindNodeByPoint(center); if (testNode != node) { A.Warning("Wrong triangle! ({0})", node); } } } return(true); } } } // Create two new nodes. // --------------------- if (!AntGeo.LinesCross(aA, aB, aC, aD)) { var edges = new int[5]; edges[0] = GetEdge(aA, aB); edges[1] = GetEdge(aB, aD); edges[2] = GetEdge(aD, aA); edges[3] = GetEdge(aA, aC); edges[4] = GetEdge(aC, aD); var nodeA = AddNode(edges[0], edges[1], edges[2]); var nodeB = AddNode(edges[3], edges[4], edges[2]); LinkNodes(aFrom, nodeA); LinkNodes(nodeA, nodeB); LinkNodes(nodeB, aTo); return(true); } return(false); }
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; } } }
public List <Vector2> FindWay(WayPoint aCurrent, WayPoint aGoal) { List <WayPoint> opened = new List <WayPoint>(); List <WayPoint> closed = new List <WayPoint>(); aCurrent.parent = null; aCurrent.cost = 0.0f; aCurrent.heuristic = aCurrent.Heuristic(aGoal); aCurrent.sum = aCurrent.heuristic; opened.Add(aCurrent); WayPoint current; while (opened.Count > 0) { current = opened[0]; for (int i = 1, n = opened.Count; i < n; i++) { if (opened[i].sum < current.sum) { current = opened[i]; } } opened.Remove(current); if (AntMath.Equal(current.position, aGoal.position)) { return(GetPath(current)); } closed.Add(current); WayPoint neighbor; int openedIndex = -1; int closedIndex = -1; float cost = 0.0f; for (int i = 0, n = current.neighbors.Count; i < n; i++) { cost = current.cost + current.neighbors[i].cost; neighbor = current.neighbors[i]; openedIndex = opened.IndexOf(neighbor); closedIndex = closed.IndexOf(neighbor); if (openedIndex > -1 && cost < opened[openedIndex].cost) { opened.RemoveAt(openedIndex); openedIndex = -1; } if (closedIndex > -1 && cost < closed[closedIndex].cost) { closed.RemoveAt(closedIndex); closedIndex = -1; } if (openedIndex == -1 && closedIndex == -1) { neighbor.cost = cost; neighbor.heuristic = neighbor.Heuristic(aGoal); neighbor.sum = cost + neighbor.heuristic; neighbor.parent = current; opened.Add(neighbor); } } } return(null); }