public Coords(CoordsType newType, Vector v)
        {
            this._type = newType;
            if (newType == CoordsType.Tile)
            {
                _X = (Int32)(v.X / Constants.TileSize);
                _Y = (Int32)(v.Y / Constants.TileSize);
                return;
            }

            _X = (Int32)Math.Floor(v.X);
            _Y = (Int32)Math.Floor(v.Y);
        }
 public double DistanceTo(Vector somewhere)
 {
     return Math.Sqrt(Math.Pow(this.X - somewhere.X, 2) + Math.Pow(this.Y - somewhere.Y, 2));
 }
예제 #3
0
        public bool RayTracerVisibilityCheckPixel(Vector c1, Vector c2)
        {
            double x0 = c1.X;
            double y0 = c1.Y;
            double x1 = c2.X;
            double y1 = c2.Y;

            double dx = Math.Abs(x1 - x0);
            double dy = Math.Abs(y1 - y0);

            int x = (int)(Math.Floor(x0));
            int y = (int)(Math.Floor(y0));

            int n = 1;
            int x_inc, y_inc;
            double error;

            if (dx == 0)
            {
                x_inc = 0;
                error = Double.PositiveInfinity;
            }
            else if (x1 > x0)
            {
                x_inc = 1;
                n += (int)(Math.Floor(x1)) - x;
                error = (Math.Floor(x0) + 1 - x0) * dy;
            }
            else
            {
                x_inc = -1;
                n += x - (int)(Math.Floor(x1));
                error = (x0 - Math.Floor(x0)) * dy;
            }

            if (dy == 0)
            {
                y_inc = 0;
                error -= Double.PositiveInfinity;
            }
            else if (y1 > y0)
            {
                y_inc = 1;
                n += (int)(Math.Floor(y1)) - y;
                error -= (Math.Floor(y0) + 1 - y0) * dx;
            }
            else
            {
                y_inc = -1;
                n += y - (int)(Math.Floor(y1));
                error -= (y0 - Math.Floor(y0)) * dx;
            }


            Coords c2Tile = new Coords(CoordsType.Tile, c2);

            for (; n > 0; --n)
            {
                Coords currentCoords = new Coords(CoordsType.Tile, x, y);

                // We ignore accrued visibility for now. Can add it later.
                if ((this._visibilityMap[currentCoords.X, currentCoords.Y] == 0) && (currentCoords != c2Tile))
                {
                    return false;
                }

                if (error > 0)
                {
                    y += y_inc;
                    error -= dx;
                }
                else
                {
                    x += x_inc;
                    error += dy;
                }
            }

            return true;
        }
예제 #4
0
        /// <summary>
        /// Performs a terrain passability check betwee two points by doing pixel validity checks at interval delta.
        /// </summary>
        public List<Creature> RayTracerPassabilityCheckRough(Creature client, Vector v1, Vector v2, double delta)
        {
            Vector difference = v2 - v1;
            Vector deltaV = difference;
            deltaV.ScaleToLength(delta);

            Vector currentPosition = v1;

            for (int i = 0; i < difference.Length() / deltaV.Length(); ++i)
            {
                Coords pixel = new Coords(CoordsType.Pixel, currentPosition);
                List<Creature> collision = _myCollider.CreatureClippingCheck(client, pixel, false);
                if (collision == null || collision.Count > 0)
                {
                    return collision;
                }
                currentPosition += deltaV;
            }

            return new List<Creature>();
        }
예제 #5
0
        /// <summary>
        /// Obtains step towards goal. Returns null if path is blocked.
        /// Returns (infinity, infinity) if goal is reached.
        /// </summary>
        /// <returns></returns>
        public Nullable<Vector> Navigate()
        {
            ++_timeTraveled;

            // Check to see if we've arrived. In that case the navigator has finished its job.
            if (_traveler.MyCollider.CollisionCheckPixelInEllipse(_goalPixel, _traveler.PositionPixel, _traveler.RadiusX, _traveler.RadiusY))
            {
                // goal attained.
                ++Constants._navigationSuccesses;
                return new Vector(Double.PositiveInfinity, Double.PositiveInfinity);
            }

            // Check to see if we have a visible goal or if we're taking too long to get to it
            if (_visiblePixelGoal == null || _timeTraveled >= _timeTraveledUpperBound)
            {
                // no goal set. check to see if a exists and whether we're on it:
                if (_routeCoarse == null || !this._putativeCurrentPosition.Equals(_traveler.PositionTile))
                {
                    // no route or we need a recalc
                    AcquireRoute();
                }
            }

            // Check to see if we've arrived to the current visible goal. If so, get new one.
            if (_traveler.MyCollider.CollisionCheckPixelInEllipse(_visiblePixelGoal.Value, _traveler.PositionPixel, _traveler.RadiusX, _traveler.RadiusY))
            {
                AcquireVisiblePixelGoal();
            }

            // We move towards current visible pixel goal.

            // Declare movement vector
            Vector principleMoveDir = new Vector(_visiblePixelGoal.Value) - _traveler.PositionDouble;
            principleMoveDir.ScaleToLength(_traveler.MoveSpeedCurrent);
            Vector startPoint = _traveler.PositionDouble;

            // Try to move in given direction. If the move fails, offset the direction angle and try again.
            // The offsets are under a full PI in either direction (so the agent doesn't get stuck in a loop).
            // Avoidance is first attempted in one direction. If it fails, the agent tries to other direction.
            // If both directions fail, the agent gives up.
            Int32 numberOfOffsetAttempts = (Int32)(Math.PI / Constants.CollisionAvoidanceRotation);

            // flags whether avoidance direction was flipped.
            bool directionFlipped = false;

            // list of creatures the agent has asked to step aside.
            List<Creature> askedToStepAside = new List<Creature>();

            while (true)
            {
                for (sbyte i = 0; i < numberOfOffsetAttempts; ++i)
                {
                    double offsetAngle = Math.Pow(-1, (sbyte)_avoidanceDirection) * i * Constants.CollisionAvoidanceRotation;
                    Vector moveDir = principleMoveDir.Rotate(offsetAngle);

                    List<Creature> checkForCollisions = _traveler.MyCollider.RayTracerPassabilityCheckPrecise(_traveler, startPoint, startPoint + moveDir);

                    if (checkForCollisions != null)
                    {
                        if (checkForCollisions.Count > 0)
                        {
                            // ask agents in the way to move
                            foreach (Creature impediment in checkForCollisions)
                            {
                                if (!askedToStepAside.Contains(impediment))
                                {
                                    Vector vectorToImpediment = impediment.PositionDouble - _traveler.PositionDouble;
                                    vectorToImpediment.ScaleToLength(1);

                                    Vector moveDirPerpendicular = directionFlipped ? moveDir.PerpendiculatRight() : moveDir.PerpendiculatLeft();
                                    moveDirPerpendicular.ScaleToLength(1);

                                    impediment.CreatureBrain.StepAsideRequest(vectorToImpediment + moveDirPerpendicular);
                                    askedToStepAside.Add(impediment);
                                }

                            }
                        }
                        else
                        {
                            // success. update creature position.
                            //_traveler.PositionDouble = startPoint + moveDir;
                            _timeWaited = 0;
                            return moveDir;
                        }
                    }
                }

                // we failed to move anywhere. the agent tries avoidance in the other direction.
                if (!directionFlipped)
                {
                    _avoidanceDirection = (AvoidanceDir)(((sbyte)_avoidanceDirection + 1) % 2);
                    directionFlipped = true;
                }
                else
                {
                    // avoidance in either direction failed. the agent gives up.
                    // NOTE: perhaps add a brief (1 second?) waiting time for the agent before giving up.
                    ++_timeWaited;

                    if (_timeWaited >= Constants.FailedCollisionAvoidanceWaitTime)
                    {
                        // give up
                        _timeWaited = 0;
                        break;
                    }
                    else
                    {
                        // pass back static moveVector
                        return new Vector(0, 0);
                    }
                }
            }

            ++Constants._navigationFailures;
            return null;

        }
예제 #6
0
        /*
        private UInt16 _sideStepTimer = 0;
        private Vector _sideStepDir;
        */

        /// <summary>
        /// Requests a move from the agent.
        /// </summary>
        /// <param name="direction">Move direction.</param>
        /// <param name="clipChecked">Whether the move has been clip-checked.</param>
        /// <param name="normalizedToSpeed">Whether the vector is normalized.</param>
        public void MoveRequest(Vector direction, bool clipChecked, bool normalizedToSpeed)
        {
            if (!normalizedToSpeed)
            {
                // Accelerate and normalize the move.
                this.Accelerate();
                direction.ScaleToLength(_owner.MoveSpeedCurrent);
            }

            _moveDir = direction;
            _moveClipChecked = clipChecked;
            _moveRequested = true;
        }
예제 #7
0
        /// <summary>
        /// Finds a route to the target.
        /// </summary>
        private void AcquireRoute()
        {
            // Line of sight check to avoid needless A* calls
            //Vector here = new Vector(_traveler.PositionPixel.X , _traveler.PositionPixel.Y);
            Vector there = new Vector(_goalPixel.X, _goalPixel.Y);

            List<Creature> clipCheck =
                _traveler.InhabitedMap.RayTracerPassabilityCheckRough(_traveler, _traveler.PositionDouble, there, _traveler.RadiusX);
            if (clipCheck != null && clipCheck.Count == 0)
            {
                _visiblePixelGoal = _goalPixel;
                _putativeCurrentPosition = _goalTile;
                EstimateTimeOfTravel();

                return;
            }

            //Coords hereCoords = _traveler.Position;
            this._routeCoarse = _traveler.MyPathfinder.PathfinderAStarCoarse(_traveler.PositionTile, _goalTile, StaticMathFunctions.DistanceBetweenTwoCoordsEucledean);

            this._putativeCurrentPosition = _traveler.PositionTile;
            AcquireVisiblePixelGoal();
        }
예제 #8
0
        // Acquires new visible pixel goal. Deletes the route entries up to that point.
        private void AcquireVisiblePixelGoal()
        {
            UInt16 i = 0;
            //Coords returnVal;
            Coords currentTile = _traveler.PositionTile;

            for (; i < _routeCoarse.Count; ++i)
            {
                Direction currentDir = _routeCoarse[_routeCoarse.Count - i - 1];
                Coords newTile = currentTile.NeighborInDirection(currentDir);

                //Vector here = new Vector(_traveler.PositionPixel.X , _traveler.PositionPixel.Y);

                Coords newTileMiddle = _traveler.InhabitedMap.GetTile(newTile).PixelMiddle();
                Vector there = new Vector(newTileMiddle.X, newTileMiddle.Y);

                List<Creature> clipCheck =
                    _traveler.InhabitedMap.RayTracerPassabilityCheckRough(_traveler, _traveler.PositionDouble, there, _traveler.RadiusX);
                if (clipCheck == null || clipCheck.Count > 0)
                {
                    // We've reached an tile, to which a direct line can't go. Set the target to the midpoint of previous tile.
                    _visiblePixelGoal = _traveler.InhabitedMap.GetTile(currentTile).PixelMiddle();
                    EstimateTimeOfTravel();

                    // remove directions from route
                    _routeCoarse.RemoveRange(_routeCoarse.Count - i, i);
                    _putativeCurrentPosition = currentTile;

                    return;
                }

                currentTile = newTile;
            }

            // we went through the loop without returning. that means the end-pixel is visible.
            _visiblePixelGoal = _goalPixel;
            EstimateTimeOfTravel();
            _putativeCurrentPosition = _goalTile;
            _routeCoarse = null;
        }
예제 #9
0
        /// <summary>
        /// Ask the agent to move aside if he can.
        /// </summary>
        public void StepAsideRequest(Vector direction)
        {
            if (_owner.MoveSpeedCurrent > 0)
            {
                //the agent is already in motion. ignore request.
                return;
            }

            // include other conditions for ignoring the request here.

            // try to step aside
            MoveRequest(direction, false, false);
        }
 /// <summary>
 /// Returns an exact pixel-by-pixel collision check.
 /// 'null' - terrain collision.
 /// empty - no collision.
 /// non-empty - creature collision.
 /// </summary>
 public List<Creature> RayTracerPassabilityCheckPrecise(Creature client, Vector v1, Vector v2)
 {
     return RayTracerPassabilityCheckPrecise(client, new Coords(CoordsType.Pixel, v1), new Coords(CoordsType.Pixel, v2));
 }
        /// <summary>
        /// Handles collisions for an agent.
        /// </summary>
        public void HandleCollisions(Creature someGuy, Vector oldPosition)
        {
            this.UpdateCreatureBoxes(someGuy, oldPosition);

            List<Creature> collisions = this.PotentialCreatureToCreatureCollision(someGuy, new Coords(CoordsType.Pixel, someGuy.PositionDouble));

            for (int i = 0; i < collisions.Count; ++i)
            {
                this.HandleCollisionBetweenTwoPlayers(someGuy, collisions[i]);
            }
        }
        /// <summary>
        /// Updates the tiles of the grid which an agent covers.
        /// </summary>
        public void UpdateCreatureBoxes(Creature someGuy, Vector oldPosition)
        {
            Coords oldCoords = new Coords((Int32)(oldPosition.X / _pixelsPerBoxX), (Int32)(oldPosition.Y / _pixelsPerBoxY));
            Coords newCoords = new Coords((Int32)(someGuy.PositionDouble.X / _pixelsPerBoxX), (Int32)(someGuy.PositionDouble.Y / _pixelsPerBoxY));

            if (oldCoords == newCoords)
            {
                // nothing to do
                return;
            }

            LinkedList<Coords> steppedOn = TilesCoveredByEllipse(new Coords(CoordsType.Pixel, someGuy.PositionDouble), someGuy.RadiusX, someGuy.RadiusY);
            foreach (Coords c in _occupiedBoxes[someGuy])
            {
                this.ClippingBoxesRemoveFrom(c, someGuy);
            }
            foreach (Coords c in steppedOn)
            {
                this.ClippingBoxesAddTo(c, someGuy);
            }

            _occupiedBoxes[someGuy] = steppedOn;
        }
        private void HandlerMouseRightClick()
        {
            Coords clicked = PixelUnderMousecursor();

            Vector averagePosition= new Vector();
            if (_selectedCreatures.Count > 0)
            {
                averagePosition = SelectedCreaturesAveragePosition();
            }
            Coords averagePositionCoords = new Coords(CoordsType.Pixel, averagePosition);

            foreach (Creature c in _selectedCreatures)
            {
                if (!c.Dead)
                {
                    Coords delta = c.PositionPixel - averagePositionCoords;
                    c.CreatureBrain.OrderMove(clicked + delta);
                }
            }
        }