コード例 #1
0
        /// <summary>
        /// Allows the game to run logic such as updating the world,
        /// checking for collisions, gathering input, and playing audio.
        /// </summary>
        /// <param name="gameTime">Provides a snapshot of timing values.</param>
        protected override void Update(GameTime gameTime)
        {
            // Allows the game to exit
            // Allows user to exit the game by using Escape Button
            if (Keyboard.GetState().IsKeyDown(Keys.Escape))
            {
                this.Exit();
            }

            // TODO: Add your update logic here

            // Making "GOKU" character following the mouse state
            MouseState mouse = Mouse.GetState();

            goku.Update(gameTime, mouse);

            // Update every objects in the game every milisecond
            foreach (Superman superfat in supermen)
            {
                superfat.Update(gameTime);
            }
            foreach (Weapon weapon in weapons)
            {
                weapon.Update(gameTime);
            }
            foreach (Explosion explosion in explosions)
            {
                explosion.Update(gameTime);
            }

            // Check and Update the collisions between enemies
            for (int i = 0; i < supermen.Count; i++)
            {
                for (int j = i + 1; j < supermen.Count; j++)
                {
                    if (supermen[i].Alive && supermen[j].Alive)
                    {
                        EnemiesCollisionInfor collis = CollisionUtils.CheckCollision(
                            gameTime.ElapsedGameTime.Milliseconds,
                            GameVariables.SCREEN_WIDTH,
                            GameVariables.SCREEN_WIDTH,
                            supermen[i].sVelocity,
                            supermen[i].sRectangle,
                            supermen[j].sVelocity,
                            supermen[j].sRectangle);
                        if (collis != null)
                        {
                            if (collis.firstOutBounds)
                            {
                                supermen[i].Alive = false;
                            }
                            else
                            {
                                supermen[i].sVelocity  = collis.getFirstVelocity;
                                supermen[i].sRectangle = collis.getFirstRectangle;
                            }

                            if (collis.firstOutBounds)
                            {
                                supermen[j].Alive = false;
                            }
                            else
                            {
                                supermen[j].sVelocity  = collis.getSecondVelocity;
                                supermen[j].sRectangle = collis.getSecondRectangle;
                            }
                        }
                    }
                }
            }

            // Check and Update what happen if the Goku's fire hits a superman
            foreach (Superman superfat in supermen)
            {
                foreach (Weapon weapon in weapons)
                {
                    if (weapon.Type == WeaponType.GokuWeapon &&
                        weapon.Active && superfat.Alive && superfat.getRectangle.Intersects(weapon.wRectangle))
                    {
                        weapon.Active  = false;
                        superfat.Alive = false;
                        score         += GameVariables.KILLED_SUPERMAN_AWARD;
                        // Make a new Explosion when the superfat is not Alive
                        Explosion newExplode = new Explosion(explosionSprite, superfat.currentLocation.X,
                                                             superfat.currentLocation.Y);

                        newExplode.Sound = explosion;
                        // Add the Explosion to the Array List
                        explosions.Add(newExplode);

                        //play sound
                        if (!Game1.IsLosing)
                        {
                            newExplode.Sound.Play();
                        }
                    }
                }
            }

            // Check if Goku gets hit by touching the superman
            foreach (Superman superfat in supermen)
            {
                if (superfat.Alive && goku.getRectangle.Intersects(superfat.sRectangle))
                {
                    goku.health   -= GameVariables.SUPERMAN_DAMAGES_HIMSELF;
                    superfat.Alive = false;
                    score         += GameVariables.KILLED_SUPERMAN_AWARD;
                    explosions.Add(new Explosion(explosionSprite, superfat.currentLocation.X, superfat.currentLocation.Y));
                    if (!Game1.IsLosing)
                    {
                        GokuGetHit.Play();
                        explosion.Play();
                    }
                }
            }

            // Check if Goku gets hit by touch the superman's fires
            foreach (Weapon weapon in weapons)
            {
                if (weapon.Type == WeaponType.SupermanWeapon && weapon.wRectangle.Intersects(goku.getRectangle))
                {
                    weapon.Active = false;
                    goku.health  -= GameVariables.SUPERMAN_SHOOTING_DAMAGES;
                    if (!Game1.IsLosing)
                    {
                        GokuGetHit.Play();
                    }
                }
            }

            // Clean out the superman objects which has the Aclive status is false
            for (int i = supermen.Count - 1; i >= 0; i--) // remove from the back of the list
            {
                if (!supermen[i].Alive)
                {
                    supermen.RemoveAt(i);
                }
            }

            while (supermen.Count < GameVariables.MAX_NUM_SUPERMEN)
            {
                SpawnSuperman();
            }

            // Clean out the weapon objects which has the Aclive status is false
            for (int i = weapons.Count - 1; i >= 0; i--) // remove from the back of the list
            {
                if (!weapons[i].Active)
                {
                    weapons.RemoveAt(i);
                }
            }

            // Clean out the explosion when it finishes
            for (int i = explosions.Count - 1; i >= 0; i--) // remove from the back of the list
            {
                if (explosions[i].Finish)
                {
                    explosions.RemoveAt(i);
                }
            }

            // display current score and health
            healthString = GameVariables.HEALTH + goku.health;
            scoreString  = GameVariables.SCORE + score;

            // Always check if we are losing or not
            IsLostAlready();

            base.Update(gameTime);
        }
コード例 #2
0
        /// <summary>
        /// Check where and which direction should the enemies collide to
        /// </summary>
        /// <param name="timeStep"></param>
        /// <param name="screenWidth"></param>
        /// <param name="screenHeight"></param>
        /// <param name="firstObjectVelocity"></param>
        /// <param name="secondObjectVelocity"></param>
        /// <param name="firstObjectRectangle"></param>
        /// <param name="secondObjectRectangle"></param>
        /// <returns></returns>
        public static EnemiesCollisionInfor CheckCollisions(int timeStep, int screenWidth, int screenHeight,
                                                            Vector2 firstObjectVelocity, Vector2 secondObjectVelocity,
                                                            Rectangle firstObjectRectangle, Rectangle secondObjectRectangle)
        {
            Rectangle initialFirstObject;
            Rectangle initialSecondObject;
            Rectangle finalfirstObject;
            Rectangle finalSecondObject;
            Rectangle collisionRectangle;

            //checking if they are overlap
            bool detectedCollision = firstObjectRectangle.Intersects(secondObjectRectangle);

            if (detectedCollision)
            {
                // getting the same size of the rectangle
                finalfirstObject.Width   = firstObjectRectangle.Width;
                finalfirstObject.Height  = firstObjectRectangle.Height;
                finalSecondObject.Width  = secondObjectRectangle.Width;
                finalSecondObject.Height = secondObjectRectangle.Height;

                // Getting the information right at the moment they overlap
                float firstXSpeed = (firstObjectVelocity.X * timeStep);
                float firstYSpeed = (firstObjectVelocity.Y * timeStep);
                initialFirstObject.X      = (int)(firstObjectRectangle.X - firstXSpeed);
                initialFirstObject.Y      = (int)(firstObjectRectangle.Y - firstYSpeed);
                initialFirstObject.Width  = firstObjectRectangle.Width;
                initialFirstObject.Height = firstObjectRectangle.Height;

                float secondXSpeed = (secondObjectRectangle.X * timeStep);
                float secondYSpeed = (secondObjectRectangle.Y * timeStep);
                initialSecondObject.X      = (int)(secondObjectRectangle.X - secondXSpeed);
                initialSecondObject.Y      = (int)(secondObjectRectangle.Y - secondYSpeed);
                initialSecondObject.Width  = secondObjectRectangle.Width;
                initialSecondObject.Height = secondObjectRectangle.Height;

                // Constantly, the time step is 60 frames per second, time will increament by the power of 2
                int timeIncrement   = timeStep / 2;
                int collisionDeltaT = timeStep;      // rate of change of time
                int DeltaT          = timeIncrement; // rate of change of time at a certain moment

                while (timeIncrement > 0)
                {
                    // Move the objects
                    firstXSpeed  = firstObjectVelocity.X * DeltaT;
                    firstYSpeed  = firstObjectVelocity.Y * DeltaT;
                    secondXSpeed = secondObjectVelocity.X * DeltaT;
                    secondYSpeed = secondObjectVelocity.Y * DeltaT;

                    // Updating current Location for the objects
                    finalfirstObject.X  = (int)(initialFirstObject.X + firstXSpeed);
                    finalfirstObject.Y  = (int)(initialFirstObject.Y + firstYSpeed);
                    finalSecondObject.X = (int)(initialSecondObject.X + secondXSpeed);
                    finalSecondObject.Y = (int)(initialSecondObject.Y + secondYSpeed);

                    // decreasing the time increament
                    timeIncrement /= 2;

                    // check if they bound again or not
                    detectedCollision = finalfirstObject.Intersects(finalSecondObject);

                    if (detectedCollision)
                    {   // if the collision happens again
                        collisionDeltaT = DeltaT;
                        DeltaT         -= timeIncrement;

                        Rectangle.Intersect(ref finalfirstObject, ref finalSecondObject, out collisionRectangle);
                    }
                    else
                    {
                        DeltaT += timeIncrement;
                    }
                }

                // Start the Collision
                int collisionStartTime = collisionDeltaT;
                firstXSpeed  = firstObjectVelocity.X * collisionStartTime;
                firstYSpeed  = firstObjectVelocity.Y * collisionStartTime;
                secondXSpeed = secondObjectVelocity.X * collisionStartTime;
                secondYSpeed = secondObjectVelocity.Y * collisionStartTime;

                finalfirstObject.X  = (int)(initialFirstObject.X + firstXSpeed);
                finalfirstObject.Y  = (int)(initialFirstObject.Y + firstYSpeed);
                finalSecondObject.X = (int)(initialSecondObject.X + secondXSpeed);
                finalSecondObject.Y = (int)(initialSecondObject.Y + secondYSpeed);

                // Check the side of the collision
                Rectangle            collisionIntersection = Rectangle.Intersect(finalfirstObject, finalSecondObject);
                EnemiesCollisionSide possibleSide          = checkCollisionSide(finalSecondObject, collisionIntersection,
                                                                                firstObjectVelocity, secondObjectVelocity);

                // Let the object move over the time Step
                int preCollisionTime  = collisionStartTime - 1;
                int postCollisionTime = timeStep - preCollisionTime;

                EnemiesCollisionInfor enemiesBounce = getBounceObjects(firstObjectVelocity, initialFirstObject,
                                                                       secondObjectVelocity, initialSecondObject,
                                                                       preCollisionTime, postCollisionTime, possibleSide);
                enemiesBounce.firstOutBounds  = IsOutOfBounds(firstObjectRectangle, screenWidth, screenHeight);
                enemiesBounce.SecondOutBounds = IsOutOfBounds(secondObjectRectangle, screenWidth, screenHeight);

                return(enemiesBounce);
            }
            else
            {
                // no collision happens -> no enemiesCollisionInfor
                return(null);
            }
        }
コード例 #3
0
        /// <summary>
        /// Returns the collision resolution info object associated with a detected collision or null if no collision
        /// is detected
        ///
        /// Ref: David M. Bourg, Physics for Game Developers, pages 207 and 209
        /// </summary>
        /// <param name="timeStep">the time step, in milliseconds</param>
        /// <param name="windowWidth">the width of the game window</param>
        /// <param name="windowHeight">the height of the game window</param>
        /// <param name="firstVelocity">the velocity of the first object</param>
        /// <param name="firstDrawRectangle">the draw rectangle of the first object</param>
        /// <param name="secondVelocity">the velocity of the second object</param>
        /// <param name="secondDrawRectangle">the draw rectangle of the second object</param>
        /// <returns>the collision resolution info object for a detected collision or null if no collision is detected</returns>
        public static EnemiesCollisionInfor CheckCollision(int timeStep, int windowWidth, int windowHeight,
                                                           Vector2 firstVelocity, Rectangle firstDrawRectangle,
                                                           Vector2 secondVelocity, Rectangle secondDrawRectangle)
        {
            Rectangle initialFirstAabr;
            Rectangle initialSecondAabr;
            Rectangle currentFirstAabr;
            Rectangle currentSecondAabr;
            Rectangle collisionRectangle;

            // overlap test
            bool collisionDetected = firstDrawRectangle.Intersects(secondDrawRectangle);

            if (collisionDetected)
            {
                // initialize non-changing properties
                currentFirstAabr.Width   = firstDrawRectangle.Width;
                currentFirstAabr.Height  = firstDrawRectangle.Height;
                currentSecondAabr.Width  = secondDrawRectangle.Width;
                currentSecondAabr.Height = secondDrawRectangle.Height;

                // back up both objects to their locations before the time step
                float firstDx = (firstVelocity.X * timeStep);
                float firstDy = (firstVelocity.Y * timeStep);
                initialFirstAabr.X      = (int)(firstDrawRectangle.X - firstDx);
                initialFirstAabr.Y      = (int)(firstDrawRectangle.Y - firstDy);
                initialFirstAabr.Width  = firstDrawRectangle.Width;
                initialFirstAabr.Height = firstDrawRectangle.Height;

                float secondDx = (secondVelocity.X * timeStep);
                float secondDy = (secondVelocity.Y * timeStep);
                initialSecondAabr.X      = (int)(secondDrawRectangle.X - secondDx);
                initialSecondAabr.Y      = (int)(secondDrawRectangle.Y - secondDy);
                initialSecondAabr.Width  = secondDrawRectangle.Width;
                initialSecondAabr.Height = secondDrawRectangle.Height;

                // at fixed time step of 60 fps, time increment can only be 8, 4, 2, or 1
                int timeIncrement = timeStep / 2;
                int collisionDt   = timeStep;  // we know we have a collision or we wouldn't be here
                int dt            = timeIncrement;
                while (timeIncrement > 0)
                {
                    // move both objects forward by dt from their initial positions
                    firstDx  = firstVelocity.X * dt;
                    firstDy  = firstVelocity.Y * dt;
                    secondDx = secondVelocity.X * dt;
                    secondDy = secondVelocity.Y * dt;

                    // update axis-aligned bounding rectangles
                    currentFirstAabr.X  = (int)(initialFirstAabr.X + firstDx);
                    currentFirstAabr.Y  = (int)(initialFirstAabr.Y + firstDy);
                    currentSecondAabr.X = (int)(initialSecondAabr.X + secondDx);
                    currentSecondAabr.Y = (int)(initialSecondAabr.Y + secondDy);

                    // cut time increment in half as we search for the time of collision
                    timeIncrement /= 2;

                    collisionDetected = currentFirstAabr.Intersects(currentSecondAabr);
                    if (collisionDetected)
                    {
                        // collision detected, so save collision dt and reduce dt to make it earlier
                        collisionDt = dt;
                        dt         -= timeIncrement;

                        // save the collision rectangle in case we don't find any other collisions
                        Rectangle.Intersect(ref currentFirstAabr, ref currentSecondAabr, out collisionRectangle);
                    }
                    else
                    {
                        // no collision detected, so increase dt to make it later
                        dt += timeIncrement;
                    }
                }

                // get rectangle locations at start of collision
                int collisionStartTime = collisionDt;
                firstDx  = firstVelocity.X * collisionStartTime;
                firstDy  = firstVelocity.Y * collisionStartTime;
                secondDx = secondVelocity.X * collisionStartTime;
                secondDy = secondVelocity.Y * collisionStartTime;

                currentFirstAabr.X  = (int)(initialFirstAabr.X + firstDx);
                currentFirstAabr.Y  = (int)(initialFirstAabr.Y + firstDy);
                currentSecondAabr.X = (int)(initialSecondAabr.X + secondDx);
                currentSecondAabr.Y = (int)(initialSecondAabr.Y + secondDy);

                // use square collision normals
                Rectangle            intersection  = Rectangle.Intersect(currentFirstAabr, currentSecondAabr);
                EnemiesCollisionSide collisionSide = GetCollisionSide(currentSecondAabr,
                                                                      intersection, firstVelocity, secondVelocity);

                // move objects through complete time step
                int preCollisionDuration       = collisionStartTime - 1;
                int postCollisionDuration      = timeStep - collisionStartTime + 1;
                EnemiesCollisionInfor colInfor = BounceObjects(firstVelocity, initialFirstAabr,
                                                               secondVelocity, initialSecondAabr, preCollisionDuration, postCollisionDuration,
                                                               collisionSide);

                // check out of bounds and return
                colInfor.firstOutBounds  = OutOfBounds(firstDrawRectangle, windowWidth, windowHeight);
                colInfor.SecondOutBounds = OutOfBounds(secondDrawRectangle, windowWidth, windowHeight);
                return(colInfor);
            }
            else
            {
                // no collision
                return(null);
            }
        }