private void preCalculateCoverage(StablePriorityQueue <int, Loc> tilesToHit, int delay) { Loc leftDiff, rightDiff; if (Dir.IsDiagonal()) { leftDiff = DirExt.AddAngles(Dir, Dir8.UpRight).GetLoc(); rightDiff = DirExt.AddAngles(Dir, Dir8.UpLeft).GetLoc(); } else { leftDiff = DirExt.AddAngles(Dir, Dir8.Right).GetLoc(); rightDiff = DirExt.AddAngles(Dir, Dir8.Left).GetLoc(); } Loc candTile = StartPoint; for (int ii = 0; ii < MaxDistance; ii++) { candTile += Dir.GetLoc(); tilesToHit.Enqueue(calculateTimeToHit(StartPoint, candTile) + delay, candTile); if (Wide) { tilesToHit.Enqueue(calculateTimeToHit(StartPoint + leftDiff, candTile + leftDiff) + delay, candTile + leftDiff); tilesToHit.Enqueue(calculateTimeToHit(StartPoint + rightDiff, candTile + rightDiff) + delay, candTile + rightDiff); } } }
public static bool IsDirBlocked(Loc loc, Dir8 dir, LocTest checkBlock, LocTest checkDiagBlock, int distance) { if (checkBlock == null) { throw new ArgumentNullException(nameof(checkBlock)); } if (checkDiagBlock == null) { throw new ArgumentNullException(nameof(checkDiagBlock)); } if (!dir.Validate()) { throw new ArgumentException("Invalid value to check."); } else if (dir == Dir8.None) { return(false); } for (int ii = 0; ii < distance; ii++) { if (dir.IsDiagonal()) { dir.Separate(out DirH horiz, out DirV vert); Loc diagLoc = loc + horiz.GetLoc(); if (checkDiagBlock(diagLoc)) { return(true); } diagLoc = loc + vert.GetLoc(); if (checkDiagBlock(diagLoc)) { return(true); } } loc += dir.GetLoc(); if (checkBlock(loc)) { return(true); } } return(false); }
public static IEnumerable <Point> EnumeratePointsAtChebyshevDistance( this Point source, int distance, bool clockwise, bool orderByEuclideanDistance, Dir8 startDir = Dir8.N) { if (distance < 0) { throw new ArgumentException("distance must be nonnegative"); } if (!startDir.IsValid(false)) { throw new ArgumentException("startDir must be an orthogonal or diagonal"); } if (orderByEuclideanDistance && startDir.IsDiagonal()) { // If ordering by Euclidean distance, we'll be starting at an orthogonal direction anyway: startDir = startDir.Rotate(clockwise); } return(source.PointsAtChebyshevDistanceInternal(distance, clockwise, orderByEuclideanDistance, startDir)); }
public void DrawBeam(SpriteBatch spriteBatch, Vector2 pos, int frame, Dir8 dir, int offset, int length, Color color) { Loc dirLoc = dir.GetLoc(); Loc diff = dirLoc * (length + offset); Rectangle body = getBeamFrame(BeamFrame.Body, frame); Draw(spriteBatch, new Vector2(pos.X + diff.X, pos.Y + diff.Y), body, new Vector2(body.Width / 2, body.Height), color, new Vector2(1, dir.IsDiagonal() ? (float)(length * 1.4142136 + 1) : length), (float)((int)dir * Math.PI / 4)); diff = dirLoc * offset; Rectangle tail = getBeamFrame(BeamFrame.Tail, frame); Draw(spriteBatch, new Vector2(pos.X + diff.X, pos.Y + diff.Y), tail, color, new Vector2(1), (float)((int)dir * Math.PI / 4)); diff = dirLoc * (length + offset - 1); Rectangle head = getBeamFrame(BeamFrame.Head, frame); Draw(spriteBatch, new Vector2(pos.X + diff.X, pos.Y + diff.Y), head, color, new Vector2(1), (float)((int)dir * Math.PI / 4)); }
public static IEnumerable <Point> EnumeratePointsByChebyshevDistance( this Point source, bool clockwise, bool orderByEuclideanDistance, Dir8 startDir = Dir8.N) { if (!startDir.IsValid(false)) { throw new ArgumentException("startDir must be an orthogonal or diagonal"); } if (orderByEuclideanDistance && startDir.IsDiagonal()) { // If ordering by Euclidean distance, we'll be starting at an orthogonal direction anyway: startDir = startDir.Rotate(clockwise); } for (int distance = 0; ; ++distance) { foreach (Point p in source.PointsAtChebyshevDistanceInternal(distance, clockwise, orderByEuclideanDistance, startDir)) { yield return(p); } } }
public static bool IsInSquareHitbox(Loc loc, Loc origin, int squareRadius, AreaLimit limit, Dir8 dir) { if (loc.X < origin.X - squareRadius || loc.X > origin.X + squareRadius) { return(false); } if (loc.Y < origin.Y - squareRadius || loc.Y > origin.Y + squareRadius) { return(false); } if (limit == AreaLimit.Cone) { //check if it's inside the cone //get line diff Loc diff = loc - origin; //get cone vectors Dir8 cone1 = DirExt.AddAngles(dir, Dir8.DownRight); Dir8 cone2 = DirExt.AddAngles(dir, Dir8.DownLeft); //get vector orthogonal1 to first cone line (aka, -second cone line) Loc ortho1 = cone2.GetLoc() * -1; //get vector orthogonal2 to second cone line ( aka, first cone line) Loc ortho2 = cone1.GetLoc(); //get dot product of diff to orthogonal1; must be less than or equal to 0 int dot1 = Loc.Dot(diff, ortho1); //get dot product of diff to orthogonal2; must be greater than or equal to 0 int dot2 = Loc.Dot(diff, ortho2); if (dot1 > 0 || dot2 < 0) { return(false); } } else if (limit == AreaLimit.Sides) { Loc diff = loc - origin; if (dir.IsDiagonal()) { //get cone vectors Dir8 cone1 = DirExt.AddAngles(dir.Reverse(), Dir8.DownRight); Dir8 cone2 = DirExt.AddAngles(dir.Reverse(), Dir8.DownLeft); //get vector orthogonal1 to first cone line (aka, -second cone line) Loc ortho1 = cone2.GetLoc() * -1; //get vector orthogonal2 to second cone line ( aka, first cone line) Loc ortho2 = cone1.GetLoc(); //get dot product of diff to orthogonal1; must be less than or equal to 0 int dot1 = Loc.Dot(diff, ortho1); //get dot product of diff to orthogonal2; must be greater than or equal to 0 int dot2 = Loc.Dot(diff, ortho2); if (dot1 > 0 || dot2 < 0) { return(false); } //additionally, both dot products cannot be a nonzero if (dot1 != 0 && dot2 != 0) { return(false); } } else { //check if it's inside the sides int dot = Loc.Dot(diff, dir.GetLoc()); //check if the other point is EXACTLY perpendicular if (dot != 0) { return(false); } } } return(true); }
public override GameAction Think(Character controlledChar, bool preThink, IRandom rand) { if (controlledChar.CantWalk) { return(null); } List <Character> seenCharacters = new List <Character>(); bool seeLeader = false; foreach (Character testChar in controlledChar.MemberTeam.IterateByRank()) { if (testChar == controlledChar) { if (preThink)//follow only leaders in pre-thinking { break; } else//settle for other partners in action { if (seeLeader) { continue; } else { return(null); } } } else if (controlledChar.IsInSightBounds(testChar.CharLoc)) { seenCharacters.Add(testChar); seeLeader = true; } } //gravitate to the CLOSEST ally. //iterate in increasing character indices GameAction result = null; foreach (Character targetChar in seenCharacters) { //get the direction to that character //use A* to get this first direction? check only walls? List <Loc>[] paths = GetPaths(controlledChar, new Loc[1] { targetChar.CharLoc }, true, false); List <Loc> path = paths[0]; Dir8 dirToChar = DirExt.GetDir(controlledChar.CharLoc, targetChar.CharLoc); if (path.Count > 1) { dirToChar = DirExt.GetDir(path[path.Count - 1], path[path.Count - 2]); } //is it possible to move in that direction? //if so, use it result = tryDir(controlledChar, targetChar, dirToChar, !preThink); if (result != null) { return(result); } if (dirToChar.IsDiagonal()) { Loc diff = controlledChar.CharLoc - targetChar.CharLoc; DirH horiz; DirV vert; dirToChar.Separate(out horiz, out vert); //start with the one that covers the most distance if (Math.Abs(diff.X) < Math.Abs(diff.Y)) { result = tryDir(controlledChar, targetChar, vert.ToDir8(), !preThink); if (result != null) { return(result); } result = tryDir(controlledChar, targetChar, horiz.ToDir8(), !preThink); if (result != null) { return(result); } } else { result = tryDir(controlledChar, targetChar, horiz.ToDir8(), !preThink); if (result != null) { return(result); } result = tryDir(controlledChar, targetChar, vert.ToDir8(), !preThink); if (result != null) { return(result); } } } else { result = tryDir(controlledChar, targetChar, DirExt.AddAngles(dirToChar, Dir8.DownLeft), !preThink); if (result != null) { return(result); } result = tryDir(controlledChar, targetChar, DirExt.AddAngles(dirToChar, Dir8.DownRight), !preThink); if (result != null) { return(result); } } } //if a path can't be found to anyone, return false return(null); }