Пример #1
0
        /// <summary>
        /// Assigns the colliding objects and their touching directions.
        /// </summary>
        /// <param name="objectA">The first object involved in the collision.</param>
        /// <param name="objectB">The second object involved in the collision.</param>
        /// <param name="touchingA">The direction that the first object is colliding in.</param>
        /// <param name="touchingB">The direction that the second object is colliding in.</param>
        public GenCollideEvent(GenObject objectA, GenObject objectB, GenObject.Direction touchingA, GenObject.Direction touchingB)
        {
            ObjectA = objectA;
            ObjectB = objectB;
            TouchingA = touchingA;
            TouchingB = touchingB;

            // TODO: Return the force of the collision as well.
        }
Пример #2
0
        /// <summary>
        /// Flags the given edge of a specific tile as open.
        /// </summary>
        /// <param name="x">The column position of the tile, starting from 0.</param>
        /// <param name="y">The row position of the tile, starting from 0.</param>
        /// <param name="edge">The direction of the edge to flag as closed.</param>
        /// <returns>True if the tile edge was flagged as open, false if not.</returns>
        public bool OpenTileEdge(int x, int y, GenObject.Direction edge)
        {
            if (Tiles[y][x] == null)
                return false;

            Tiles[y][x].OpenEdges |= edge;

            if (TileSheetTexture != null)
                GetAutoTile(x, y);

            return true;
        }
Пример #3
0
        /// <summary>
        /// Applies collision detection and response between an object and the tiles of the tilemap.
        /// Uses an object's position to efficiently find neighboring tiles to check for collision in the tiles two-dimensional array.
        /// </summary>
        /// <param name="gameObject">The object to check for collisions.</param>
        /// <param name="callback">The delegate method that will be invoked if a collision occurs.</param>
        /// <returns>True is a collision occurs, false if not.</returns>
        public bool CollideObject(GenObject gameObject, CollideEvent callback)
        {
            GetTileBounds(
                gameObject.MoveBounds.Left,
                gameObject.MoveBounds.Right,
                gameObject.MoveBounds.Top,
                gameObject.MoveBounds.Bottom);

            bool collided = false;

            for (int y = _tileBounds[2]; y <= _tileBounds[3]; y++)
            {
                for (int x = _tileBounds[0]; x <= _tileBounds[1]; x++)
                {
                    // If the tile is empty, do not check for a collision.
                     if (Tiles[y][x] != null)
                    {
                        if (GenCollide.Collide(gameObject, Tiles[y][x], callback, Tiles[y][x].OpenEdges))
                            collided = true;
                    }
                }
            }

            return collided;
        }
Пример #4
0
        /// <summary>
        /// Sets up a control scheme for moving a given object.
        /// </summary>
        /// <param name="controlObject">The object that is controlled.</param>
        /// <param name="controlMode">The type of control available to the control object.</param>
        /// <param name="movementType">How acceleration or velocity should be handled as the object moves.</param>
        /// <param name="stoppingType">How acceleration or velocity should be handled as the object stops.</param>
        /// <param name="playerIndex">The index number of the player controlling the object.</param>
        public GenControl(GenObject controlObject, ControlType controlMode = ControlType.TopDown, Movement movementType = Movement.Instant, Stopping stoppingType = Stopping.Instant, PlayerIndex playerIndex = PlayerIndex.One)
        {
            ControlMode = controlMode;
            ControlObject = controlObject;
            MovementType = movementType;
            StoppingType = stoppingType;
            PlayerIndex = playerIndex;
            _keyboardControls = new Keys[5];
            _gamePadControls = new Buttons[5];
            ButtonsSpecial = GenGamePad.ButtonsSpecial.None;
            UseInput = true;
            #if WINDOWS
            UseKeyboard = true;
            #endif
            UseGamePad = true;
            MovementSpeedX = 0;
            MovementSpeedY = 0;
            JumpSpeed = 0;
            JumpInheritVelocity = false;
            JumpCount = 1;

            // Start the jump counter at 1, since the control object spawns in the air initially.
            _jumpCounter = 1;

            Gravity = Vector2.Zero;
            _inAir = true;_state = State.Idle;
            MoveState = GenObject.Direction.None;
            IdleAnimation = null;
            MoveAnimation = null;
            JumpAnimation = null;
            FallAnimation = null;
            UseSpeedAnimation = false;
            MinAnimationFps = 0f;
            MaxAnimationFps = 12f;
            JumpCallback = null;
            LandCallback = null;

            // Set the default movement direction keyboard controls.
            SetDirectionControls(Keys.Left, Keys.Right, Keys.Up, Keys.Down);

            // Set the default jumping keyboard control.
            SetJumpControl(Keys.Space);

            // Set the default movement direction game pad controls.
            SetDirectionControls(Buttons.LeftThumbstickLeft, Buttons.LeftThumbstickRight, Buttons.LeftThumbstickUp, Buttons.LeftThumbstickDown);

            // Set the default jumping game pad control.
            SetJumpControl(Buttons.A);
        }
Пример #5
0
 /// <summary>
 /// Sets a given object as the parent of this object, using the specified parenting type.
 /// </summary>
 /// <param name="gameObject">The object to set as the parent object.</param>
 /// <param name="parentMode">The type of transformations to connect with the parent object.</param>
 public void SetParent(GenObject gameObject, ParentType parentMode)
 {
     Parent = gameObject;
     ParentMode = parentMode;
 }
Пример #6
0
        /// <summary>
        /// Override this method to add additional pre-update logic.
        /// </summary>
        public override void PreUpdate()
        {
            OldVelocity = Velocity;

            // Reset the bit fields for collision flags.
            OldTouching = Touching;
            Touching = Direction.None;

            OldPlatform = Platform;
            Platform = null;
        }
Пример #7
0
        /// <summary>
        /// A physical object that can be moved around in screen space.
        /// </summary>
        /// <param name="x">The x position of the top-left corner of the object.</param>
        /// <param name="y">The y position of the top-left corner of the object.</param>
        /// <param name="width">The width of the object.</param>
        /// <param name="height">The height of the object.</param>
        public GenObject(float x, float y, float width, float height)
        {
            _position = new Vector2(x, y);
            _oldPosition = _position;
            _hasMoved = false;
            _bounds = new GenAABB(x, y, width, height);
            _centerPosition = new Vector2(x + _bounds.HalfWidth, y + _bounds.HalfHeight);
            _origin = new Vector2(_bounds.HalfWidth, _bounds.HalfHeight);
            _originPosition = new Vector2(x + _origin.X, y + _origin.Y);
            _boundingRect = new Rectangle(0, 0, (int)width, (int)height);
            _rotation = 0f;
            RotationSpeed = 0f;
            _moveDistance = Vector2.Zero;
            _moveBounds = new GenAABB(x, y, width, height);

            Immovable = false;
            Solid = true;
            Mass = 1f;

            Velocity = Vector2.Zero;
            OldVelocity = Velocity;
            Acceleration = Vector2.Zero;
            Deceleration = Vector2.Zero;
            MaxVelocity = Vector2.Zero;

            _facing = Direction.None;
            OldTouching = Direction.None;
            Touching = Direction.None;

            Parent = null;
            ParentMode = ParentType.None;
            ParentOffset = Vector2.Zero;

            IsPlatform = false;
            Platform = null;
            OldPlatform = null;

            Path = null;
            PathNodeIndex = 0;
            PathDirection = 1;
            PathSpeed = 0f;
            PathType = GenPath.Type.Clockwise;
            PathAxis = GenMove.Axis.Both;
            PathMovement = GenPath.Movement.Instant;
        }
Пример #8
0
        /// <summary>
        /// Checks for overlaps or collisions between the given game object and objects within the node and its leaf nodes.
        /// A broad phase check is done by only checking for overlaps or collisions against objects within the leaf nodes that intersect with the given game object.
        /// </summary>
        /// <param name="gameObject">The game object to check for overlaps or collisions.</param>
        /// <param name="callback">The delegate method that will be invoked if an overlap occurs.</param>
        /// <param name="separate">A flag used to determine if objects should collide with each other.</param>
        /// <param name="collidableEdges">A bit field of flags determining which edges of the quadtree objects are collidable.</param>
        /// <returns>True if an overlap occurs, false if not.</returns>
        internal bool Overlap(GenObject gameObject, CollideEvent callback, bool separate, GenObject.Direction collidableEdges)
        {
            bool overlap = false;

            if (_nodes[0] != null)
            {
                // If the game object's movement bounds intersects with any leaf node, do overlap and collision checks against any objects in that node.
                if (gameObject.MoveBounds.Intersects(this))
                {
                    if (gameObject.MoveBounds.Top <= _midpointY)
                    {
                        if (gameObject.MoveBounds.Left <= _midpointX) // Top-left leaf node.
                        {
                            if (_nodes[0].Overlap(gameObject, callback, separate, collidableEdges))
                                overlap = true;
                        }

                        if (gameObject.MoveBounds.Right >= _midpointX) // Top-right leaf node.
                        {
                            if (_nodes[1].Overlap(gameObject, callback, separate, collidableEdges))
                                overlap = true;
                        }
                    }

                    if (gameObject.MoveBounds.Bottom >= _midpointY)
                    {
                        if (gameObject.MoveBounds.Left <= _midpointX) // Bottom-left leaf node.
                        {
                            if (_nodes[2].Overlap(gameObject, callback, separate, collidableEdges))
                                overlap = true;
                        }

                        if (gameObject.MoveBounds.Right >= _midpointX) // Bottom-right leaf node.
                        {
                            if (_nodes[3].Overlap(gameObject, callback, separate, collidableEdges))
                                overlap = true;
                        }
                    }
                }
            }

            // Check for overlaps and collisions against this node's objects.
            if (OverlapObjects(gameObject, callback, separate, collidableEdges))
                overlap = true;

            return overlap;
        }
Пример #9
0
        /// <summary>
        /// Inserts a given object by adding it to this quadtree node's objects list, and sets this node as its current location.
        /// </summary>
        /// <param name="gameObject">The <c>GenObject</c> to insert into this node.</param>
        protected void Insert(GenObject gameObject)
        {
            // If the game object is already contained within the node, do not insert the same object twice.
            _objects.Add(gameObject);

            // Set the object's location to this node.
            if (_quadtree._objectLocations.ContainsKey(gameObject))
                _quadtree._objectLocations[gameObject] = this;
            else
                _quadtree._objectLocations.Add(gameObject, this);
        }
Пример #10
0
        /// <summary>
        /// Checks for overlaps or collisions against each object within this node.
        /// </summary>
        /// <param name="gameObject">The game object to check for overlaps or collisions.</param>
        /// <param name="callback">The delegate method that will be invoked if an overlap occurs.</param>
        /// <param name="separate">A flag used to determine if objects should collide with each other.</param>
        /// <param name="collidableEdges">A bit field of flags determining which edges of the quadtree objects are collidable.</param>
        /// <returns>True if an overlap occurs, false if not.</returns>
        public bool OverlapObjects(GenObject gameObject, CollideEvent callback, bool separate, GenObject.Direction collidableEdges)
        {
            bool overlap = false;

            foreach (GenObject nodeObject in _objects)
            {
                if (separate)
                {
                    if (GenCollide.Collide(gameObject, nodeObject, callback, collidableEdges))
                        overlap = true;
                }
                else
                {
                    if (GenCollide.Overlap(gameObject, nodeObject, callback))
                        overlap = true;
                }
            }

            return overlap;
        }
Пример #11
0
        internal void Add(GenObject gameObject)
        {
            if (_nodes[0] == null)
            {
                Insert(gameObject);

                // If the node is full, attempt to add each of its objects into a leaf node.
                if ((_objects.Count >= _quadtree.MaxObjects) && (_level < _quadtree.MaxLevels))
                {
                    int nextLevel = _level + 1;

                    // Create the leaf nodes.
                    _nodes[0] = new GenQuadtreeNode(_minX, _minY, _halfWidth, _halfHeight, _quadtree, this, nextLevel);
                    _nodes[1] = new GenQuadtreeNode(_midpointX, _minY, _halfWidth, _halfHeight, _quadtree, this, nextLevel);
                    _nodes[2] = new GenQuadtreeNode(_minX, _midpointY, _halfWidth, _halfHeight, _quadtree, this, nextLevel);
                    _nodes[3] = new GenQuadtreeNode(_midpointX, _midpointY, _halfWidth, _halfHeight, _quadtree, this, nextLevel);

                    // Iterate through the objects list in reverse, attempting to add each object into a leaf node.
                    // Otherwise, leave the object in this node.
                    for (int i = _objects.Count - 1; i >= 0; i--)
                    {
                        int index = GetIndex(_objects[i].MoveBounds);

                        if (index != -1)
                        {
                            _nodes[index].Add(_objects[i]);
                            _objects.Remove(_objects[i]);
                        }
                    }
                }
            }
            else
            {
                // Since leaf nodes have already been created, attempt to add the object into a leaf node.
                // Otherwise, add the object to this node.
                int index = GetIndex(gameObject.MoveBounds);

                if (index != -1)
                    _nodes[index].Add(gameObject);
                else
                    Insert(gameObject);
            }

            _objectCount++;
        }
Пример #12
0
        public bool OverlapSelf(CollideEvent callback, bool separate, GenObject.Direction collidableEdges)
        {
            bool overlap = false;

            foreach (GenObject gameObject in _activeObjects)
            {
                GenQuadtreeNode parentNode = _objectLocations[gameObject]._parentNode;

                // Iterate up the parent nodes, and do overlap and collision checks against their objects.
                while (parentNode != null)
                {
                    if (parentNode.OverlapObjects(gameObject, callback, separate, collidableEdges))
                        overlap = true;

                    parentNode = parentNode._parentNode;
                }

                // Do overlap and collision checks against objects within its containing node and any remaining leaf nodes.
                if (_objectLocations[gameObject].Overlap(gameObject, callback, separate, collidableEdges))
                    overlap = true;
            }

            return overlap;
        }
Пример #13
0
 /// <summary>
 /// Checks for overlaps or collisions between the given game object and objects within the quadtree.
 /// A broad phase check is done by only checking for overlaps or collisions against objects within the nodes that intersect with the given game object.
 /// </summary>
 /// <param name="gameObject">The game object to check for overlaps or collisions.</param>
 /// <param name="callback">The delegate method that will be invoked if an overlap occurs.</param>
 /// <param name="separate">A flag used to determine if objects should collide with each other.</param>
 /// <param name="collidableEdges">A bit field of flags determining which edges of the quadtree objects are collidable.</param>
 /// <returns>True if an overlap occurs, false if not.</returns>
 public bool Overlap(GenObject gameObject, CollideEvent callback, bool separate, GenObject.Direction collidableEdges)
 {
     return _rootNode.Overlap(gameObject, callback, separate, collidableEdges);
 }
Пример #14
0
        /// <summary>
        /// Rotates an object around a given point.
        /// </summary>
        /// <param name="gameObject">The object to rotate around the point.</param>
        /// <param name="point">The point to rotate around.</param>
        /// <param name="angle">The angle of rotation, in degrees.</param>
        /// <param name="radius">The distance from the point that the object will be placed.</param>
        public static void RotateAroundPoint(GenObject gameObject, Vector2 point, float angle, float radius)
        {
            Vector2 rotationPosition = Vector2.Zero;

            rotationPosition = AngleToVector(angle);
            rotationPosition = point + rotationPosition * radius;

            gameObject.X = rotationPosition.X;
            gameObject.Y = rotationPosition.Y;
        }
Пример #15
0
        /// <summary>
        /// Gets a normalized vector of the x and y distances from an object to a point.
        /// Useful for calculating the distribution between horizontal and vertical speeds needed to meet an overall speed.
        /// </summary>
        /// <param name="gameObject">The object to start the distance calculation from.</param>
        /// <param name="point">The point to end the distance calculation at.</param>
        /// <param name="axis">A bit field of flags to determine which axis should be included.</param>
        /// <returns>The normalized distance vector.</returns>
        public static Vector2 GetDistanceNormal(GenObject gameObject, Vector2 point, Axis axis = Axis.Both)
        {
            Vector2 distance = Vector2.Zero;

            // Get the x and y distances between the object and the point.
            distance.X = ((axis & Axis.Horizontal) == Axis.Horizontal) ? (point.X - gameObject.Position.X) : 0f;
            distance.Y = ((axis & Axis.Vertical) == Axis.Vertical) ? (point.Y - gameObject.Position.Y) : 0f;

            // Return the normalized distance vector.
            return GenU.NormalizeVector2(distance);
        }
Пример #16
0
        /// <summary>
        /// Determines if an object will reach a specified point on the next update.
        /// Uses the current position and movement direction of the object, and a given speed.
        /// The current velocity of the object will be used if the given speed is 0.
        /// </summary>
        /// <param name="gameObject">The moving object to check.</param>
        /// <param name="point">The point needed to reach.</param>
        /// <param name="speed">The velocity to move the object at. A value of 0 will use the current velocity of the object.</param>
        /// <param name="radius">The radius extending from the point position to use as a search area.</param>
        /// <param name="axis">The movement axis to include in the check.</param>
        /// <returns>True if the object will reach the point, false if not.</returns>
        public static bool CanReachPoint(GenObject gameObject, Vector2 point, float speed = 0, float radius = 0, Axis axis = Axis.Both)
        {
            // Calculate the minimum distance that the object will need to move to reach the point.
            float minDistanceX = ((axis & Axis.Horizontal) == Axis.Horizontal) ? (gameObject.Position.X - point.X) : 0;
            float minDistanceY = ((axis & Axis.Vertical) == Axis.Vertical) ? (gameObject.Position.Y - point.Y) : 0;
            float minDistance = (float)Math.Sqrt(minDistanceX * minDistanceX + minDistanceY * minDistanceY);

            Vector2 newPosition = Vector2.Zero;

            // Calculate the next position of the object using its current direction.
            // Use the current velocity of the object if speed is 0.
            if (speed == 0)
                newPosition = Vector2.Add(gameObject.Position, gameObject.Velocity * GenG.TimeStep);
            else
                newPosition = Vector2.Add(gameObject.Position, GenU.NormalizeVector2(gameObject.Velocity) * speed * GenG.TimeStep);

            // Calculate the distance that the object will move.
            float moveDistance = Vector2.Distance(gameObject.Position, newPosition);

            return (moveDistance + radius) >= minDistance ;
        }