Example #1
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;
        }
Example #2
0
        public override void Update()
        {
            base.Update();

            // Do collision checking first.
            //GenG.Collide(Player, Text);

            // Cache the HitCave delegate to avoid creating garbage for each collision check.
            if (HitCaveCache == null)
            {
                HitCaveCache = HitCave;
            }

            GenG.Collide(Cave, Player, HitCaveCache);
            GenG.Collide(Cave, Boxes);

            //GenG.Collide(Chain, Player);
            //GenG.Collide(Warthog4, Warthog5);
            //GenG.Collide(Cave, Chain);
            //GenG.Collide(Cave, Warthog3);
            //GenG.Collide(Player, Warthog3);
            //GenG.Collide(Player, Warthog4);
            GenG.Collide(Cave, Emitter);
            //GenG.Collide(Emitter, Emitter);
            GenG.Collide(Player, Boxes);
            GenG.Collide(Boxes, Boxes);
            //GenG.Collide(Boxes, Emitter);

            //Text.Y = GenU.SineWave(200, 2, 10);
            //Text.Rotation = GenU.SineWave(0, 3, 10);

            if (GenG.GamePads[(int)PlayerIndex.One].JustPressed(Buttons.X))
                GenG.IsDebug = !GenG.IsDebug;
            #if WINDOWS
            if (GenG.Keyboards[(int)PlayerIndex.One].JustPressed(Keys.R))
                GenG.ResetState(new LoadingState());

            if (GenG.Keyboards[(int)PlayerIndex.One].IsPressed(Keys.Z))
                GenG.TimeScale = 0.2f;
            else if (GenG.Keyboards[(int)PlayerIndex.One].IsPressed(Keys.X))
                GenG.TimeScale = 2f;
            else
                GenG.TimeScale = 1f;

            if (GenG.Keyboards[(int)PlayerIndex.One].JustPressed(Keys.A))
                GenG.Paused = !GenG.Paused;

            if (GenG.Keyboards[(int)PlayerIndex.One].JustPressed(Keys.Escape))
                GenG.Game.Exit();
            #endif
            if (GenG.GamePads[(int)PlayerIndex.One].JustPressed(Buttons.Y))
                GenG.ResetState(new LoadingState());

            /*if (GenG.GamePads[(int)PlayerIndex.One].IsPressed(Buttons.LeftTrigger))
                GenG.TimeScale = 0.2f;
            else if (GenG.GamePads[(int)PlayerIndex.One].IsPressed(Buttons.RightTrigger))
                GenG.TimeScale = 2f;
            else
                GenG.TimeScale = 1f;*/

            if (GenG.GamePads[(int)PlayerIndex.One].JustPressed(Buttons.LeftTrigger))
                Camera.Flash(0.5f, 0.1f, Color.CornflowerBlue);

            if (GenG.GamePads[(int)PlayerIndex.One].JustPressed(Buttons.Start))
                GenG.Paused = !GenG.Paused;

            if (GenG.GamePads[(int)PlayerIndex.One].JustPressed(Buttons.Back))
                GenG.Game.Exit();

            //((GenObject)Chain.Members[0]).X = Player.X;
            //((GenObject)Chain.Members[0]).Y = Player.Y;

            if (!GenG.Paused)
            {
                //GenMove.AccelerateToPoint(Boxes, Player.CenterPosition, 200);
                GenMove.AccelerateToPoint(Emitter, Player.CenterPosition, 500, 100);
                //GenMove.AccelerateToPoint(Cloth, Player.CenterPosition, Player.Velocity.Length() * 3, 70);
            }

            Warthog4.Velocity.X = GenU.SineWave(0, 2, 200);
            //Warthog4.Color = new Color(1, GenU.SineWave(0.5f, 10, 0.5f), GenU.CosineWave(0.5f, 10, 0.5f));

            //Warthog3.Rotation = GenMove.VectortoAngle(Warthog3.CenterPosition, Player.CenterPosition);
            //GenMove.AccelerateAtAngle(Warthog3, Warthog3.Rotation, 500);

            if (Warthog5.Parent != null)
                Warthog5.Rotation = Warthog5.Parent.Rotation;

            //Chain.LineColor = GenU.RandomColor();

            //Player.Rotation++;
            if (Player.Velocity.Y < 0)
            {
                Player.Scale.X = MathHelper.Clamp(Math.Abs((Player.Velocity.Y) / Player.MaxVelocity.Y) + 1, 1f, 1.2f);
                Player.Scale.Y = 1 - (Player.Scale.X - 1);
            }
            else if (Player.Velocity.Y > 0)
            {
                Player.Scale.X = MathHelper.Clamp(1 - Math.Abs((Player.Velocity.Y) / Player.MaxVelocity.Y), 0.8f, 1f);
                Player.Scale.Y = 1 + (1 - Player.Scale.X);
            }
            else
            {
                Player.Scale.X = GenU.CosineWave(1, 8, 0.1f);
                Player.Scale.Y = GenU.SineWave(1, 8, 0.1f);
            }

            ProgressBar.Scale.Y = GenU.SineWave(1, 8, 0.2f);
            ProgressBar.Value = GenU.SineWave(50, 2, 51);

            //Cloth.LineColor = new Color(0.5f, (float)MathHelper.Lerp(0, 1, GenU.SineWave(0.5f, 10f, 0.5f)), 0.5f);

            //Player.Alpha = GenU.SineWave(0.5f, 2f, 0.5f);

            /*if (Player.IsTouching(GenObject.Direction.Down))
                Player.Rotation = 0;
            else if (Player.IsTouching(GenObject.Direction.Right))
                Player.Rotation = 270;
            else if (Player.IsTouching(GenObject.Direction.Left))
                Player.Rotation = 90;
            else if (Player.IsTouching(GenObject.Direction.Up))
                Player.Rotation = 180;
            else if (!Player.IsTouching(GenObject.Direction.Any))
                Player.RotationSpeed = Player.Velocity.X * 4;*/

            //if (GenG.Keyboards[(int)PlayerIndex.One].JustPressed(Keys.Space))
            //    Cave.AddTile((int)(Player.OriginPosition.X / Cave.TileWidth), (int)(Player.OriginPosition.Y / Cave.TileHeight), false);

            if (Warthog5.X < -2000)
            {
                Warthog5.X = 5000;
            }
        }
Example #3
0
        /// <summary>
        /// Applies collision detection and response between an object or group of objects 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="objectOrGroup">The object or group 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 Collide(GenBasic objectOrGroup, CollideEvent callback)
        {
            if (objectOrGroup is GenObject)
                return CollideObject(objectOrGroup as GenObject, callback);

            if (objectOrGroup is GenGroup)
            {
                bool collided = false;

                foreach (GenBasic basic in (objectOrGroup as GenGroup).Members)
                {
                    if (CollideObject(basic as GenObject, callback))
                        collided = true;
                }

                return collided;
            }

            return false;
        }
Example #4
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;
        }
Example #5
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;
        }
Example #6
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;
        }
Example #7
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);
 }
Example #8
0
 public virtual void OnCollide(T col)
 {
     CollideEvent?.Invoke(col);
 }
Example #9
0
        /// <summary>
        /// Applies collision detection and response against two objects that may overlap.
        /// </summary>
        /// <param name="objectA">The first object to check for a collision.</param>
        /// <param name="objectB">The second object to check for a collision.</param>
        /// <param name="callback">The delegate method that will be invoked if a collision occurs.</param>
        /// <param name="collidableEdges">A bit field of flags determining which edges of the second object are collidable.</param>
        /// <returns>True if a collision occurs, false if not.</returns>
        public static bool Collide(GenObject objectA, GenObject objectB, CollideEvent callback, GenObject.Direction collidableEdges = GenObject.Direction.Any)
        {
            // Do not check for collisions if the objects are the same.
            if (objectA == objectB)
                return false;

            // Do not check for collisions if either object is not solid, or if both objects are immovable.
            if ((!objectA.Solid || !objectB.Solid) || (objectA.Immovable && objectB.Immovable))
                return false;

            // If the movement bounding boxes of each object are overlapping, check for a collision.
            if (Overlap(objectA, objectB, callback))
            {
                // Get the normal direction of the collision from bounding box A to B along the least penetrating axis.
                // Return no collision if the surface normal is projected towards a non-collidable edge of bounding box B.
                _distance = objectA.Bounds.GetDistanceAABB(objectB.Bounds);

                // The greatest absolute distance value between the two bounding boxes is along the axis of least penetration.
                if (_distance.X > _distance.Y)
                {
                    if (objectA.Bounds.MidpointX > objectB.Bounds.MidpointX)
                    {
                        // The collision normal is pointing from the left edge of bounding box A.
                        _collisionNormal.X = -1f;
                        _collisionNormal.Y = 0f;

                        if ((collidableEdges & GenObject.Direction.Right) == 0)
                            return false;
                    }
                    else
                    {
                        // The collision normal is pointing from the right edge of bounding box A.
                        _collisionNormal.X = 1f;
                        _collisionNormal.Y = 0f;

                        if ((collidableEdges & GenObject.Direction.Left) == 0)
                            return false;
                    }
                }
                else
                {
                    if (objectA.Bounds.MidpointY > objectB.Bounds.MidpointY)
                    {
                        // The collision normal is pointing from the top edge of bounding box A.
                        _collisionNormal.X = 0f;
                        _collisionNormal.Y = -1f;

                        if ((collidableEdges & GenObject.Direction.Down) == 0)
                            return false;
                    }
                    else
                    {
                        // The collision normal is pointing from the bottom edge of bounding box A.
                        _collisionNormal.X = 0f;
                        _collisionNormal.Y = 1f;

                        if ((collidableEdges & GenObject.Direction.Up) == 0)
                            return false;
                    }
                }

                float distance = Math.Max(_distance.X, _distance.Y);
                float remove;

                // Apply an alternative collision response against tiles for pixel-perfect accuracy.
                if (objectB is GenTile)
                {
                    // Get the amount of normal velocity to remove from the object so that it just touches along the collision surface of the tile.
                    remove = Vector2.Dot(-objectA.Velocity, _collisionNormal) + Math.Max(distance, 0f) * GenG.InverseTimeStep;

                    // If the amount of velocity to remove is positive, the object will separate itself from the tile.
                    if (remove >= 0)
                        return false;

                    if (_collisionNormal.X != 0)
                    {
                        objectA.X = (_collisionNormal.X == 1) ? objectB.X - objectA.Bounds.Width : objectB.Bounds.Right;
                        objectA.Velocity.X = 0f;
                    }
                    else
                    {
                        objectA.Y = (_collisionNormal.Y == 1) ? objectB.Y - objectA.Bounds.Height : objectB.Bounds.Bottom;
                        objectA.Velocity.Y = 0f;
                    }
                }
                else
                {
                    // Get the relative velocity along the collision normal.
                    float relativeNormalVelocity = Vector2.Dot(objectB.Velocity - objectA.Velocity, _collisionNormal);

                    // Get the amount of relative normal velocity to remove so that the bounding boxes are just touching along the collision surface.
                    remove = relativeNormalVelocity + distance * GenG.InverseTimeStep;

                    // If the amount of velocity to remove is positive, the objects will separate themselves.
                    if (remove >= 0)
                        return false;

                    float impulse = remove / (objectA.InverseMass + objectB.InverseMass);

                    if (!objectA.Immovable)
                        objectA.Velocity += impulse * _collisionNormal * objectA.InverseMass;

                    if (!objectB.Immovable)
                        objectB.Velocity -= impulse * _collisionNormal * objectB.InverseMass;
                }

                // Use a bit field of flags to provide the direction that each object is colliding in during the current collision.
                GenObject.Direction touchingA = GenObject.Direction.None;
                GenObject.Direction touchingB = GenObject.Direction.None;

                if (_collisionNormal.X != 0)
                {
                    if (_collisionNormal.X == 1)
                    {
                        objectA.Touching |= GenObject.Direction.Right;
                        objectB.Touching |= GenObject.Direction.Left;

                        touchingA |= GenObject.Direction.Right;
                        touchingB |= GenObject.Direction.Left;
                    }
                    else
                    {
                        objectA.Touching |= GenObject.Direction.Left;
                        objectB.Touching |= GenObject.Direction.Right;

                        touchingA |= GenObject.Direction.Left;
                        touchingB |= GenObject.Direction.Right;
                    }
                }
                else
                {
                    if (_collisionNormal.Y == 1)
                    {
                        objectA.Touching |= GenObject.Direction.Down;
                        objectB.Touching |= GenObject.Direction.Up;

                        touchingA |= GenObject.Direction.Down;
                        touchingB |= GenObject.Direction.Up;

                        if (objectB.IsPlatform)
                        {
                            if (objectA.Acceleration.X == 0)
                                objectA.Platform = objectB;
                        }
                    }
                    else
                    {
                        objectA.Touching |= GenObject.Direction.Up;
                        objectB.Touching |= GenObject.Direction.Down;

                        touchingA |= GenObject.Direction.Up;
                        touchingB |= GenObject.Direction.Down;

                        if (objectA.IsPlatform)
                        {
                            if (objectB.Acceleration.X == 0)
                                objectB.Platform = objectA;
                        }
                    }
                }

                if (callback != null)
                {
                    _collideEventArgs.ObjectA = objectA;
                    _collideEventArgs.ObjectB = objectB;
                    _collideEventArgs.TouchingA = touchingA;
                    _collideEventArgs.TouchingB = touchingB;

                    callback(_collideEventArgs);
                }

                return true;
            }

            return false;
        }
Example #10
0
        /// <summary>
        /// Checks for overlap between the movements bounds of two objects.
        /// </summary>
        /// <param name="objectA">The first object to check for an overlap.</param>
        /// <param name="objectB">The second object to check for an overlap.</param>
        /// <param name="callback">The delegate method that will be invoked if an overlap occurs.</param>
        /// <returns>True if an overlap occurs, false if not.</returns>
        public static bool Overlap(GenObject objectA, GenObject objectB, CollideEvent callback)
        {
            // Check if both objects are alive to avoid unwanted overlap checks that may be called by a quadtree.
            if ((objectA.Exists && objectA.Active) && (objectB.Exists && objectB.Active))
            {
                if (objectA.MoveBounds.Intersects(objectB.MoveBounds))
                {
                    if (callback != null)
                    {
                        _collideEventArgs.ObjectA = objectA;
                        _collideEventArgs.ObjectB = objectB;
                        _collideEventArgs.TouchingA = GenObject.Direction.None;
                        _collideEventArgs.TouchingB = GenObject.Direction.None;

                        callback(_collideEventArgs);
                    }

                    return true;
                }
            }

            return false;
        }