コード例 #1
0
ファイル: Hitbox.cs プロジェクト: Parakoopa/RogueEssence
        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);
                }
            }
        }
コード例 #2
0
        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);
        }
コード例 #3
0
 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));
 }
コード例 #4
0
        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));
        }
コード例 #5
0
 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);
         }
     }
 }
コード例 #6
0
ファイル: Hitbox.cs プロジェクト: Parakoopa/RogueEssence
        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);
        }
コード例 #7
0
        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);
        }