void CheckPerimeter() { if (!perimeter.upToDate) { perimeter.upToDate = ResetPerimeter(); } // determine enemy heading range etc i.e disposition List <GameObject> bogieGOs = new List <GameObject>(bogies.Count); for (int i = 0; i < bogies.Count; i++) { bogieGOs[i] = bogies[i].bogieObject; } NTools.Slice enemyDisposition = NTools.AnalyseGroupDisposition( perimeter.center, perimeter.headingFloat, bogieGOs ); // Adjust perimeter heading based on enemy positions center of weight // Determine green and nongreen population of sectors // Compare population to sector importance, compute importanceMet value // if needed, add problem of type perimeter // if there exists a problem with said sector, but is not relevant anymore, remove problem }
// untested // determine sector by world coordinates, returning 401 means out of perimeter, 404 generic error private int DetermineSector(GameObject plot) { Vector3 plotBearing3D = plot.gameObject.transform.position - perimeter.center; float sqrToPlot = Vector3.SqrMagnitude(plotBearing3D); if (sqrToPlot > (perimeter.Sectors[12].distanceRange.y * perimeter.Sectors[12].distanceRange.y)) { return(404); } // if the dbogie*dbogie is farther than an outer sector farther distance*distance, return 404, i.e out of perimeter float headingToPlot = NTools.HeadingFromVector(new Vector2(plotBearing3D.x, plotBearing3D.y)); float bearing = NTools.GetBearingFromHeadings(perimeter.headingFloat, headingToPlot); if (bearing > 360 || bearing < 0) { return(404); } // Sanity check // 13 different sectors exist, loop through all, store the one where it is for (int i = 0; i <= 12; i++) { if (sqrToPlot < Mathf.Pow(perimeter.Sectors[i].headingRange.y, 2f) && sqrToPlot > Mathf.Pow(perimeter.Sectors[i].headingRange.x, 2f)) { if (perimeter.Sectors[i].headingRange.x > perimeter.Sectors[i].headingRange.y) { if (bearing < perimeter.Sectors[i].headingRange.x && bearing > perimeter.Sectors[i].headingRange.y) { return(i); // i represents the sector index from the sectors array } } else if (perimeter.Sectors[i].headingRange.x < perimeter.Sectors[i].headingRange.y) { if (bearing < perimeter.Sectors[i].headingRange.x || bearing > perimeter.Sectors[i].headingRange.y) { return(i); // i represents the sector index from the sectors array } } } } Debug.Log("Determine sector: 404"); return(404); }
// Update is called once per frame void Update() { if (Input.GetKey(KeyCode.Escape) && !LevelManager.isPaused) { levelManager.PauseGame(menuCanvas); } if (alive) { if (!LevelManager.isPaused) { switch (camSetting) { case SettingsStatic.CamSettings.player: desiredHeading += Input.GetAxis("Horizontal") * rotationSpeed; float deltaTime = Time.deltaTime; ship.Rotate(desiredHeading, deltaTime); camera.fieldOfView -= Input.GetAxis("MouseScrollWheel") * zoomSpeed; camera.fieldOfView = Mathf.Clamp(camera.fieldOfView, 30f, 80f); camera.transform.localPosition = new Vector3( 0, camera.fieldOfView * 0.1f, -30f ); break; case SettingsStatic.CamSettings.north: camera.fieldOfView -= Input.GetAxis("MouseScrollWheel") * zoomSpeed; camera.fieldOfView = Mathf.Clamp(camera.fieldOfView, 30f, 80f); camera.transform.localPosition = new Vector3( 0, camera.fieldOfView * 0.1f, -30f ); aimX -= Input.GetAxis("Horizontal"); aimY += Input.GetAxis("Vertical"); //Debug.Log("Aimx: " + aimX + " AimY: " + aimY); Vector2 aimChange = new Vector2(aimX, aimY); aimpoint += aimChange; desiredHeading = NTools.HeadingFromVector(aimpoint); ship.Rotate(desiredHeading, Time.deltaTime); //Debug.Log(Input.GetAxis("Horizontal")); aimX = 0f; aimY = 0f; break; } if (Input.GetKey(KeyCode.W)) { if (!Input.GetKey(KeyCode.LeftShift)) { ship.ThrustForward(1f); } if (Input.GetKey(KeyCode.LeftShift)) { ship.ThrustForward(2f); } } if (Input.GetKey(KeyCode.A)) { if (!Input.GetKey(KeyCode.LeftShift)) { ship.ThrustLeft(1f); } if (Input.GetKey(KeyCode.LeftShift)) { ship.ThrustLeft(2f); } } if (Input.GetKey(KeyCode.S)) { if (!Input.GetKey(KeyCode.LeftShift)) { ship.ThrustBackward(1f); } if (Input.GetKey(KeyCode.LeftShift)) { ship.ThrustBackward(2f); } } if (Input.GetKey(KeyCode.D)) { if (!Input.GetKey(KeyCode.LeftShift)) { ship.ThrustRight(1f); } if (Input.GetKey(KeyCode.LeftShift)) { ship.ThrustRight(2f); } } if (Input.GetKey(KeyCode.X)) { ship.Stop(); } if (Input.GetKeyDown(KeyCode.C)) { switch (camSetting) { case SettingsStatic.CamSettings.north: camSetting = SettingsStatic.CamSettings.player; camPlayerSet = false; break; case SettingsStatic.CamSettings.player: camSetting = SettingsStatic.CamSettings.north; break; } } if (Input.GetKeyDown(KeyCode.Tab)) { if (hintsCanvas != null) { hintsCanvas.SetActive(true); } } if (Input.GetKeyUp(KeyCode.Tab)) { if (hintsCanvas != null) { hintsCanvas.SetActive(false); } } if (Input.GetKeyDown(KeyCode.Mouse0)) { ship.FireWeapon(true); } if (Input.GetKeyUp(KeyCode.Mouse0)) { ship.FireWeapon(false); } if (Input.GetKeyDown(KeyCode.Mouse1)) { ship.SetNearestTarget(); } if (Input.GetKeyDown(KeyCode.R)) { ship.ToggleRadar(); SetRadarText(); } if (Input.GetKeyDown(KeyCode.T)) { ship.SetBoreTarget(); } if (Input.GetKeyDown(KeyCode.Y)) { ship.SetNearestTarget(); } if (Input.GetKeyDown(KeyCode.Alpha1)) { SelectWeaponByNumber(1); } if (Input.GetKeyDown(KeyCode.Alpha2)) { SelectWeaponByNumber(2); } if (Input.GetKeyDown(KeyCode.Alpha3)) { SelectWeaponByNumber(3); } if (Input.GetKeyDown(KeyCode.Alpha4)) { SelectWeaponByNumber(4); } } UpdateVelocityVector(); UpdateTargetIndicator(); UpdateLeadLine(); UpdateAimAid(); UpdateOwnLockIndicator(); UpdateIncomingLockIndicator(); UpdateCamera(); } }
// returns TRUE when CA has determined a threat and sucessfully added a WP to solve conflict // False is returned when either CA failed or no threat was found bool CollisionAvoidance() { Vector2 shipProjectedPos = gameObject.GetComponent <Rigidbody2D>().position + (wpList[wpIndex].wpCoordinates - gameObject.GetComponent <Rigidbody2D>().position).normalized * desiredSpeed; Vector2 shipPos = new Vector2(gameObject.GetComponent <Rigidbody2D>().position.x, gameObject.GetComponent <Rigidbody2D>().position.y); Vector2 headingToWP = wpList[wpIndex].wpCoordinates - shipPos; float distanceToWP = Mathf.Sqrt(Vector2.SqrMagnitude(wpList[wpIndex].wpCoordinates - gameObject.GetComponent <Rigidbody2D>().position)); Vector2 closestThreat2D = new Vector2(0f, 0f); Vector2 closestThreatVelocity2D = new Vector2(0f, 0f); Vector2 newHeadingVector = new Vector2(0f, 0f); // Variables for use in loops, to avoid repeditive declarations float timeToInterWP = 50f / desiredSpeed; float distanceToNearestThreat = 0f; float newHeadingLeft = 0f; float newHeadingRight = 0f; bool leftHeading = true; bool solutionFound = false; // Setting the travel time, by which we set the threat movement amount if (distanceToWP >= 50f) { timeToInterWP = 50f / desiredSpeed; } else { timeToInterWP = distanceToWP / desiredSpeed; } // Sorting the threats, which also fills in missing bits in the threat list SortCollisionThreats((wpList[wpIndex].wpCoordinates - gameObject.GetComponent <Rigidbody2D>().position), timeToInterWP); // parsing the POTENTIAL threats for REAL threats, the method also returns a BOOL if there are REAL threats at all NTools.CollisionThreatsSorted parsedThreats = CheckHeadingClear(shipProjectedPos, wpList[wpIndex].wpCoordinates); // If no threats are found, exit CA, else clear temporary wps from the wp list and start meaty bit of CA if (!parsedThreats.realThreatsPresent) { return(false); } // Determine distance to closest threat and its coordinates -.-- Why do I do it? else if (parsedThreats.realThreatsLeft.Count != 0 && parsedThreats.realThreatsRight.Count != 0) { ClearTemporaryWaypoints(); if (parsedThreats.realThreatsLeft[0].sqrDistance < parsedThreats.realThreatsRight[0].sqrDistance) { distanceToNearestThreat = Vector2.Distance( shipPos, parsedThreats.realThreatsLeft[0].threatCoordinates ); closestThreat2D = parsedThreats.realThreatsLeft[0].threatCoordinates; closestThreatVelocity2D = parsedThreats.realThreatsLeft[0].threatVelocity; } else { distanceToNearestThreat = Vector2.Distance( shipPos, parsedThreats.realThreatsRight[0].threatCoordinates ); closestThreat2D = parsedThreats.realThreatsRight[0].threatCoordinates; closestThreatVelocity2D = parsedThreats.realThreatsRight[0].threatVelocity; } } else if (parsedThreats.realThreatsLeft.Count == 0 && parsedThreats.realThreatsRight.Count != 0) { ClearTemporaryWaypoints(); distanceToNearestThreat = Vector2.Distance( shipPos, parsedThreats.realThreatsRight[0].threatCoordinates ); closestThreat2D = parsedThreats.realThreatsRight[0].threatCoordinates; closestThreatVelocity2D = parsedThreats.realThreatsRight[0].threatVelocity; } else if (parsedThreats.realThreatsLeft.Count != 0 && parsedThreats.realThreatsRight.Count == 0) { ClearTemporaryWaypoints(); distanceToNearestThreat = Vector2.Distance( shipPos, parsedThreats.realThreatsLeft[0].threatCoordinates ); closestThreat2D = parsedThreats.realThreatsLeft[0].threatCoordinates; closestThreatVelocity2D = parsedThreats.realThreatsLeft[0].threatVelocity; } Vector2 vectorToThreat = closestThreat2D - shipPos; // statusText.text = vectorToThreat.ToString(); // Ceck if the WP is closer than the threat, in that case, return and stop CA, return false if (distanceToWP < distanceToNearestThreat) { return(false); } headingToWP = headingToWP.normalized * distanceToNearestThreat; // parse intermittently left and right for a clear initial passage int iterations = 0; do { switch (leftHeading) { case true: newHeadingLeft -= 1; parsedThreats = CheckHeadingClear(shipPos, shipPos + NTools.RotateVector2(headingToWP, newHeadingLeft)); if (SettingsStatic.debugEnabled) { DrawDebugLine(shipPos, shipPos + NTools.RotateVector2(headingToWP, newHeadingLeft)); } leftHeading = false; iterations++; break; case false: newHeadingRight += 1; parsedThreats = CheckHeadingClear(shipPos, shipPos + NTools.RotateVector2(headingToWP, newHeadingRight)); if (SettingsStatic.debugEnabled) { DrawDebugLine(shipPos, shipPos + NTools.RotateVector2(headingToWP, newHeadingLeft).normalized); } leftHeading = true; iterations++; break; } // exit failsafes: if (newHeadingLeft < -90 || newHeadingRight > 90) { solutionFound = false; break; } } while (parsedThreats.realThreatsPresent); if (newHeadingLeft > -90 && newHeadingRight < 90) { float newHeading; if (leftHeading) { newHeading = newHeadingRight; } else { newHeading = newHeadingLeft; } solutionFound = true; //Debug.Log("Clear relative heading found: " + newHeading.ToString()); } if (!solutionFound) { Debug.Log("Heading not found in " + iterations + " iterations."); return(false); } // Determine new direction from projected ship position if (leftHeading) { newHeadingVector = NTools.RotateVector2(headingToWP, newHeadingRight); /*Debug.Log("New Heading: " + newHeadingRight); */ } else { newHeadingVector = NTools.RotateVector2(headingToWP, newHeadingLeft); /*Debug.Log("New Heading: " + newHeadingLeft); */ } float newWPDistance = 1f; do { newWPDistance += 0.1f; parsedThreats = CheckHeadingClear(shipPos + newHeadingVector * newWPDistance, wpList[wpIndex].wpCoordinates); // check to limit the possible distance of the intermittent WP to the distance of the original WP if (newWPDistance * newHeadingVector.magnitude > distanceToWP) { Debug.Log("WP solution not found."); break; } } while (parsedThreats.realThreatsPresent); if (newWPDistance < 10f) { solutionFound = true; } // This happens, when the collisionAvoidance has done its job and can add a new intermediate waypoint // also entering this loop will return true - the method has parsed successfully and added a wp if (solutionFound) { NTools.Waypoint newInbetweenWP = new NTools.Waypoint(shipPos + newHeadingVector * (newWPDistance - 0.2f), 4f, false, true); wpList.Add(newInbetweenWP); wpIndex = wpList.Count - 1; return(true); } return(false); }
public static AttackPlanF GetAttackPlanF(AttackTypeF type, Vector3 leadPos, Vector3 enemyPos, List <Vector3> nearbyFriendlies) { AttackPlanF attackPlan = new AttackPlanF(true); switch (type) { case AttackTypeF.sentry: float SQRSep = 900f; float sentryRange = 30f; float searchDegrees = 30f; Vector3 offset = (enemyPos - leadPos).normalized * sentryRange; Vector3 sentryPos = enemyPos + offset; List <Vector3> nbfSentryPos = new List <Vector3>(nearbyFriendlies.Count); foreach (Vector3 fv in nearbyFriendlies) { Vector3 fspos = enemyPos + (fv - enemyPos).normalized * sentryRange; nbfSentryPos.Add(fspos); } bool clear = true; int failsafe = 20, i = 1; while (!clear) { foreach (Vector3 fspos in nbfSentryPos) { float SQRDist = (fspos - sentryPos).sqrMagnitude; if (SQRDist < SQRSep) { clear = false; } } if (!clear) { float direction = 1f; if ((i + 1) % 2 == 0) { direction = 1; } else { direction = -1; } direction = direction * i * searchDegrees; offset = NTools.RotateVector3(offset, searchDegrees); sentryPos = enemyPos + offset; } i++; if (i >= failsafe) { clear = true; } } break; case AttackTypeF.bracket: break; case AttackTypeF.charge: break; default: break; } return(attackPlan); }
private bool ResetPerimeter() { if (objective.objectiveIsFriendly && objective.objectiveObject) { perimeter.center = objective.objectiveObject.transform.position; perimeter.heading2D = new Vector2( enemyGeneralPosition.x - perimeter.center.x, enemyGeneralPosition.y - perimeter.center.y ); perimeter.headingFloat = NTools.HeadingFromVector(perimeter.heading2D); perimeter.isMoving = objective.isMoving; } else if (!objective.objectiveIsFriendly && objective.objectiveObject) { if (capitalShips.Count != 0) { perimeter.center = NTools.GetCenterOfObjects3D(capitalShips); perimeter.center.z = 0f; perimeter.heading2D = new Vector2( enemyGeneralPosition.x - perimeter.center.x, enemyGeneralPosition.y - perimeter.center.y ); perimeter.headingFloat = NTools.HeadingFromVector(perimeter.heading2D); perimeter.isMoving = objective.isMoving; } else { //She-f*****g-nanigans List <GameObject> leads = new List <GameObject>(formations.Count); for (int i = 0; i < formations.Count; i++) { leads[i] = formations[i].Lead; } perimeter.center = NTools.GetCenterOfObjects3D(leads); perimeter.center.z = 0f; perimeter.heading2D = new Vector2( enemyGeneralPosition.x - perimeter.center.x, enemyGeneralPosition.y - perimeter.center.y ); perimeter.headingFloat = NTools.HeadingFromVector(perimeter.heading2D); } } int mood = (int)teamMood; // Adds an importance to each sector based on tabel in LFAI switch (teamState) { case TeamState.Scouting: return(AssignSectorPriorities(sectorImportancePresets.scouting[mood])); case TeamState.Attacking: return(AssignSectorPriorities(sectorImportancePresets.attacking[mood])); case TeamState.MaintainPerimeter: return(AssignSectorPriorities(sectorImportancePresets.defending[mood])); case TeamState.Regrouping: return(AssignSectorPriorities(sectorImportancePresets.regrouping[mood])); default: return(false); } }
// Used to determine for example in which direction the enemy lies and how widespread they are. // works in CCW mode public static NTools.Slice AnalyseGroupDisposition(Vector3 originPos, float originHeading, List <GameObject> objects) { NTools.Slice slice = new NTools.Slice(originPos, originHeading, 0, 0, 0, 0, new Vector3(0, 0, 0)); // sanity check, no objects means return of 000000 !!! if (objects.Count == 0) { return(slice); } float tempBear, leftBear = 0, rightBear = 0; // statistical analysis floats: float meanbearing = 0f, sumDiffFromMean = 0f; float[] bearings = new float[objects.Count]; slice.centerOfMass = NTools.GetCenterOfObjects3D(objects); for (int i = 0; i < objects.Count; i++) { // left bearing is positive, right bearing is negative, clamped between -180 to 180 tempBear = Mathf.Clamp( NTools.GetBearingFromHeadings( originHeading, NTools.HeadingFromVector(objects[i].transform.position - originPos) ), -180f, 180f); // storing for later analysis bearings[i] = tempBear; // with the first heading set both left and right bearings if (i == 0) { leftBear = tempBear; rightBear = tempBear; } else { if (tempBear > leftBear) { leftBear = tempBear; } else if (tempBear < rightBear) { rightBear = tempBear; } } } // disperison computation for (int i = 0; i < bearings.Length; i++) { meanbearing += bearings[i]; } meanbearing = meanbearing / bearings.Length; for (int i = 0; i < bearings.Length; i++) { sumDiffFromMean += bearings[i] - meanbearing; } // Filling the slice !!! slice.leftmostBearing = leftBear; slice.rightmostBearing = rightBear; slice.bearingRange = leftBear - rightBear; slice.stdDeviation = Mathf.Sqrt(Mathf.Pow(sumDiffFromMean, 2f) / (bearings.Length - 1)); return(slice); }
void CheckPerimeter() { if (!perimeter.upToDate) { perimeter.upToDate = ReassignSectorPriorities(); if (!perimeter.upToDate) { Debug.Log("Reassigning sector priorities failed."); } } List <GameObject> bogieGOs = new List <GameObject>(bogies.Capacity); NTools.Disposition enemyDisposition; // determine enemy heading range etc i.e disposition if (bogies.Count != 0) { for (int i = 0; i < bogies.Count; i++) { if (bogies[i].bogieObject != null) { bogieGOs.Add(bogies[i].bogieObject); } } enemyDisposition = NTools.AnalyseGroupDisposition( perimeter.center, perimeter.headingFloat, bogieGOs ); enemyGeneralPosition = enemyDisposition.centerOfMass; } else { enemyGeneralPosition = new Vector3(0f, 0f, 0f); } //TODO Optimize - determines perimeter anchor, heading2D and headingFloat. Is gud. if (objective.objectiveSet) { // If this happens, the game is lost or won, which will be caught by CheckObjective method if (!objective.objectiveObject) { return; } if (objective.objectiveIsFriendly) { perimeter.perimeterAnchor = objective.objectiveObject; perimeter.heading2D = new Vector2( enemyGeneralPosition.x - perimeter.perimeterAnchor.transform.position.x, enemyGeneralPosition.y - perimeter.perimeterAnchor.transform.position.y ); perimeter.headingFloat = NTools.HeadingFromVector(perimeter.heading2D); } else if (!objective.objectiveIsFriendly) { perimeter.perimeterAnchor = DeterminePerimeterAnchor(); if (perimeter.perimeterAnchor != null) { perimeter.heading2D = new Vector2( enemyGeneralPosition.x - perimeter.perimeterAnchor.transform.position.x, enemyGeneralPosition.y - perimeter.perimeterAnchor.transform.position.y ); perimeter.headingFloat = NTools.HeadingFromVector(perimeter.heading2D); } else { missionState = MissionState.lost; } } } else { perimeter.perimeterAnchor = DeterminePerimeterAnchor(); if (perimeter.perimeterAnchor != null) { perimeter.heading2D = new Vector2( enemyGeneralPosition.x - perimeter.perimeterAnchor.transform.position.x, enemyGeneralPosition.y - perimeter.perimeterAnchor.transform.position.y ); perimeter.headingFloat = NTools.HeadingFromVector(perimeter.heading2D); } else { missionState = MissionState.lost; } } }