Вопрос

This program is about driving fast and dodging the obstacles. I followed a couple of tutorials and managed to create an explosion class. Whenever a collision occurs, the explosion is meant to appear, but it doesn't.

There is no error, but I think the problem is in the Game1.cs. I created the following functions in the Game1.cs:

//list
List <Explosion> explosionList = new List<Explosion>();


//This is in the update method
    foreach (Explosion ex in explosionList)
 {
    ex.Update(gameTime);
 }


//This is a method called manage explosions

    public void ManageExplosions()
    {
        for (int i = 0; i < explosionList.Count; i++)
        {
            if (explosionList[i].isVisible)
            {
                explosionList.RemoveAt(i);
                i--;
            }
        }
    }


  //This is placed in the CheckCollision method
   explosionList.Add(new Explosion(Content.Load<Texture2D>("Images/explosion3"), new      Vector2(theHazard.Position.X, theHazard.Position.Y)));

Game1.cs

using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;

 namespace DriveFast
{

public class Game1 : Microsoft.Xna.Framework.Game
{
    GraphicsDeviceManager graphics;
    SpriteBatch spriteBatch;


    private Texture2D mCar;
    private Texture2D mBackground;
    private Texture2D mRoad;
    private Texture2D mHazard;
    private Texture2D hazardCrash;

    private KeyboardState mPreviousKeyboardState;

    private Vector2 mCarPosition = new Vector2(280, 440);
    private int mMoveCarX = 160;
    private int mVelocityY;
    private double mNextHazardAppearsIn;
    private int mCarsRemaining;
    private int mHazardsPassed;
    private int mIncreaseVelocity;
    private double mExitCountDown = 10;

    private int[] mRoadY = new int[2];
    private List<Hazard> mHazards = new List<Hazard>();

    private Random mRandom = new Random();

    private SpriteFont mFont;

    //video
    List <Explosion> explosionList = new List<Explosion>();

    private enum State
    {
        TitleScreen,
        Running,
        Crash,
        GameOver,
        Success
    }

    private State mCurrentState = State.TitleScreen;

    public Game1()
    {
        graphics = new GraphicsDeviceManager(this);
        Content.RootDirectory = "Content";

        graphics.PreferredBackBufferHeight = 600;
        graphics.PreferredBackBufferWidth = 800;
    }


    protected override void Initialize()
    {


        base.Initialize();
    }


    protected override void LoadContent()
    {
        // Create a new SpriteBatch, which can be used to draw textures.
        spriteBatch = new SpriteBatch(GraphicsDevice);

        mCar = Content.Load<Texture2D>("Images/Car");
        mBackground = Content.Load<Texture2D>("Images/Background");
        mRoad = Content.Load<Texture2D>("Images/Road");
        mHazard = Content.Load<Texture2D>("Images/Hazard");
        hazardCrash = Content.Load<Texture2D>("Images/hazardCrash");
        mFont = Content.Load<SpriteFont>("MyFont");
    }


    protected override void UnloadContent()
    {

    }

    protected void StartGame()
    {
        mRoadY[0] = 0;
        mRoadY[1] = -1 * mRoad.Height;

        mHazardsPassed = 0;
        mCarsRemaining = 3;
        mVelocityY = 3;
        mNextHazardAppearsIn = 1.5;
        mIncreaseVelocity = 5;

        mHazards.Clear();

        mCurrentState = State.Running;
    }


    protected override void Update(GameTime gameTime)
    {
        KeyboardState aCurrentKeyboardState = Keyboard.GetState();

        //Allows the game to exit
        if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed ||
            aCurrentKeyboardState.IsKeyDown(Keys.Escape) == true)
        {
            this.Exit();
        }

        switch (mCurrentState)
        {
            case State.TitleScreen:
            case State.Success:
            case State.GameOver:
                {
                    ExitCountdown(gameTime);

                    if (aCurrentKeyboardState.IsKeyDown(Keys.Space) == true && mPreviousKeyboardState.IsKeyDown(Keys.Space) == false)
                    {
                        StartGame();
                    }
                    break;
                }

            case State.Running:
                {
                    //If the user has pressed the Spacebar, then make the car switch lanes
                    if (aCurrentKeyboardState.IsKeyDown(Keys.Space) == true && mPreviousKeyboardState.IsKeyDown(Keys.Space) == false)
                    {
                        mCarPosition.X += mMoveCarX;
                        mMoveCarX *= -1;
                    }

                    ScrollRoad();

                    foreach (Hazard aHazard in mHazards)
                    {
                        if (CheckCollision(aHazard) == true)
                        {
                            //video
                            explosionList.Add(new Explosion(Content.Load<Texture2D>("Images/explosion3"), new Vector2(aHazard.Position.X, aHazard.Position.Y)));
                            break;
                        }

                        MoveHazard(aHazard);
                    }

                    UpdateHazards(gameTime);
                    break;
                }
            case State.Crash:
                {
                    //If the user has pressed the Space key, then resume driving
                    if (aCurrentKeyboardState.IsKeyDown(Keys.Space) == true && mPreviousKeyboardState.IsKeyDown(Keys.Space) == false)
                    {
                        mHazards.Clear();
                        mCurrentState = State.Running;
                    }

                    break;
                }
        }

        mPreviousKeyboardState = aCurrentKeyboardState;
        //video
        ManageExplosions();
        //
        base.Update(gameTime);
        //video
        foreach (Explosion ex in explosionList)
        {
            ex.Update(gameTime);
        }
    }


    private void ScrollRoad()
    {
        //Move the scrolling Road
        for (int aIndex = 0; aIndex < mRoadY.Length; aIndex++)
        {
            if (mRoadY[aIndex] >= this.window.ClientBounds.Height)
            {
                int aLastRoadIndex = aIndex;
                for (int aCounter = 0; aCounter < mRoadY.Length; aCounter++)
                {
                    if (mRoadY[aCounter] < mRoadY[aLastRoadIndex])
                    {
                        aLastRoadIndex = aCounter;
                    }
                }
                mRoadY[aIndex] = mRoadY[aLastRoadIndex] - mRoad.Height;
            }
        }

        for (int aIndex = 0; aIndex < mRoadY.Length; aIndex++)
        {
            mRoadY[aIndex] += mVelocityY;
        }
    }

    private void MoveHazard(Hazard theHazard)
    {
        theHazard.Position.Y += mVelocityY;
        if (theHazard.Position.Y > graphics.GraphicsDevice.Viewport.Height && theHazard.Visible == true)
        {
            theHazard.Visible = false;
            mHazardsPassed += 1;

            if (mHazardsPassed >= 100)
            {
                mCurrentState = State.Success;
                mExitCountDown = 10;
            }

            mIncreaseVelocity -= 1;
            if (mIncreaseVelocity < 0)
            {
                mIncreaseVelocity = 5;
                mVelocityY += 1;
            }
        }
    }

    private void UpdateHazards(GameTime theGameTime)
    {
        mNextHazardAppearsIn -= theGameTime.ElapsedGameTime.TotalSeconds;
        if (mNextHazardAppearsIn < 0)
        {
            int aLowerBound = 24 - (mVelocityY * 2);
            int aUpperBound = 30 - (mVelocityY * 2);

            if (mVelocityY > 10)
            {
                aLowerBound = 6;
                aUpperBound = 8;
            }

            mNextHazardAppearsIn = (double)mRandom.Next(aLowerBound, aUpperBound) / 10;
            AddHazard();
        }
    }

    private void AddHazard()
    {
        int aRoadPosition = mRandom.Next(1, 3);
        int aPosition = 275;
        if (aRoadPosition == 2)
        {
            aPosition = 440;
        }

        bool aAddNewHazard = true;
        foreach (Hazard aHazard in mHazards)
        {
            if (aHazard.Visible == false)
            {
                aAddNewHazard = false;
                aHazard.Visible = true;
                aHazard.Position = new Vector2(aPosition, -mHazard.Height);
                break;
            }
        }

        if (aAddNewHazard == true)
        {
            //Add a hazard to the left side of the Road
            Hazard aHazard = new Hazard();
            aHazard.Position = new Vector2(aPosition, -mHazard.Height);

            mHazards.Add(aHazard);
        }
    }

    private bool CheckCollision(Hazard theHazard)
    {
        BoundingBox aHazardBox = new BoundingBox(new Vector3(theHazard.Position.X, theHazard.Position.Y, 0), new Vector3(theHazard.Position.X + (mHazard.Width * .4f), theHazard.Position.Y + ((mHazard.Height - 50) * .4f), 0));
        BoundingBox aCarBox = new BoundingBox(new Vector3(mCarPosition.X, mCarPosition.Y, 0), new Vector3(mCarPosition.X + (mCar.Width * .2f), mCarPosition.Y + (mCar.Height * .2f), 0));

        if (aHazardBox.Intersects(aCarBox) == true)
        {

            //video
            explosionList.Add(new Explosion(Content.Load<Texture2D>("Images/explosion3"), new Vector2(theHazard.Position.X, theHazard.Position.Y)));
            mCurrentState = State.Crash;
            mCarsRemaining -= 1;


            if (mCarsRemaining < 0)
            {
                mCurrentState = State.GameOver;
                mExitCountDown = 10;
            }
            return true;
        }

        return false;
    }

    private void ExitCountdown(GameTime theGameTime)
    {
        mExitCountDown -= theGameTime.ElapsedGameTime.TotalSeconds;
        if (mExitCountDown < 0)
        {
            this.Exit();
        }
    }

    protected override void Draw(GameTime gameTime)
    {
        graphics.GraphicsDevice.Clear(Color.CornflowerBlue);

        spriteBatch.Begin();

        spriteBatch.Draw(mBackground, new Rectangle(graphics.GraphicsDevice.Viewport.X, graphics.GraphicsDevice.Viewport.Y, graphics.GraphicsDevice.Viewport.Width, graphics.GraphicsDevice.Viewport.Height), Color.White);

        foreach (Explosion ex in explosionList)
        {
            ex.Draw(spriteBatch);
        }

        switch (mCurrentState)
        {
            case State.TitleScreen:
                {
                    //Draw the display text for the Title screen
                    DrawTextCentered("Drive and avoid the hazards!", 200);
                    DrawTextCentered("Press 'Space' to start", 260);
                    DrawTextCentered("Exit in " + ((int)mExitCountDown).ToString(), 475);

                    break;
                }

            default:
                {
                    DrawRoad();
                    DrawHazards();

                    spriteBatch.Draw(mCar, mCarPosition, new Rectangle(0, 0, mCar.Width, mCar.Height), Color.White, 0, new Vector2(0, 0), 0.2f, SpriteEffects.None, 0);

                    spriteBatch.DrawString(mFont, "Cars:", new Vector2(28, 520), Color.Brown, 0, new Vector2(0, 0), 1.0f, SpriteEffects.None, 0);
                    for (int aCounter = 0; aCounter < mCarsRemaining; aCounter++)
                    {
                        spriteBatch.Draw(mCar, new Vector2(25 + (30 * aCounter), 550), new Rectangle(0, 0, mCar.Width, mCar.Height), Color.White, 0, new Vector2(0, 0), 0.05f, SpriteEffects.None, 0);
                    }

                    spriteBatch.DrawString(mFont, "Hazards: " + mHazardsPassed.ToString(), new Vector2(5, 25), Color.Brown, 0, new Vector2(0, 0), 1.0f, SpriteEffects.None, 0);

                    if (mCurrentState == State.Crash)
                    {

                        DrawTextDisplayArea();

                        DrawTextCentered("Crash!", 200);
                        DrawTextCentered("Press 'Space' to continue driving.", 260);
                    }
                    else if (mCurrentState == State.GameOver)
                    {
                        DrawTextDisplayArea();

                        DrawTextCentered("Game Over.", 200);
                        DrawTextCentered("Press 'Space' to re-try.", 260);
                        DrawTextCentered("Exit in " + ((int)mExitCountDown).ToString(), 400);

                    }
                    else if (mCurrentState == State.Success)
                    {
                        DrawTextDisplayArea();

                        DrawTextCentered("Well Done!", 200);
                        DrawTextCentered("Press 'Space' to play again.", 260);
                        DrawTextCentered("Exit in " + ((int)mExitCountDown).ToString(), 400);
                    }

                    break;
                }
        }
        spriteBatch.End();

        base.Draw(gameTime);
    }

    private void DrawRoad()
    {
        for (int aIndex = 0; aIndex < mRoadY.Length; aIndex++)
        {
            if (mRoadY[aIndex] > mRoad.Height * -1 && mRoadY[aIndex] <= this.window.ClientBounds.Height)
            {
                spriteBatch.Draw(mRoad, new Rectangle((int)((this.window.ClientBounds.Width - mRoad.Width) / 2 - 18), mRoadY[aIndex], mRoad.Width, mRoad.Height + 5), Color.White);
            }
        }
    }

    private void DrawHazards()
    {
        foreach (Hazard aHazard in mHazards)
        {
            if (aHazard.Visible == true)
            {
                spriteBatch.Draw(mHazard, aHazard.Position, new Rectangle(0, 0, mHazard.Width, mHazard.Height), Color.White, 0, new Vector2(0, 0), 0.4f, SpriteEffects.None, 0);
            }
        }
    }

    private void DrawTextDisplayArea()
    {
        int aPositionX = (int)((graphics.GraphicsDevice.Viewport.Width / 2) - (450 / 2));
        spriteBatch.Draw(mBackground, new Rectangle(aPositionX, 75, 450, 400), Color.White);
    }

    private void DrawTextCentered(string theDisplayText, int thePositionY)
    {
        Vector2 aSize = mFont.MeasureString(theDisplayText);
        int aPositionX = (int)((graphics.GraphicsDevice.Viewport.Width / 2) - (aSize.X / 2));

        spriteBatch.DrawString(mFont, theDisplayText, new Vector2(aPositionX, thePositionY), Color.Beige, 0, new Vector2(0, 0), 1.0f, SpriteEffects.None, 0);
        spriteBatch.DrawString(mFont, theDisplayText, new Vector2(aPositionX + 1, thePositionY + 1), Color.Brown, 0, new Vector2(0, 0), 1.0f, SpriteEffects.None, 0);
    }
    //video
    //manage explosions

    public void ManageExplosions()
    {
        for (int i = 0; i < explosionList.Count; i++)
        {
            if (explosionList[i].isVisible)
            {
                explosionList.RemoveAt(i);
                i--;
            }
        }
    }


}
}

Explosion.cs

using System;
using System.Collections.Generic;
using System.Linq;
 using Microsoft.Xna.Framework;
  using Microsoft.Xna.Framework.Audio;
  using Microsoft.Xna.Framework.Content;
  using Microsoft.Xna.Framework.GamerServices;
    using Microsoft.Xna.Framework.Graphics;
    using Microsoft.Xna.Framework.Input;
   using Microsoft.Xna.Framework.Media;

  namespace DriveFast
  {

public class Explosion 
{
    public Texture2D texture;
    public Vector2 position;
    public float timer;
    public float interval;
    public Vector2 origin;
    public int currentFrame, spriteWidth, spriteHeight;
    public Rectangle sourceRect;
    public bool isVisible;

    //Constructor
    public Explosion(Texture2D newTexture, Vector2 newPosition)
    {
        position = newPosition;
        texture = newTexture;
        timer = 0;
        interval = 20f;
        currentFrame = 1;
        spriteWidth = 128;
        spriteHeight = 128;
        isVisible = true;

    }

    //load content
    public void LoadContent(ContentManager Content)
    { 


    }

    //update
    public void Update(GameTime gameTime)
    { 
        //increase
        timer += (float)gameTime.ElapsedGameTime.TotalMilliseconds;

        if (timer > interval)
        {

            currentFrame++;
            timer = 0f;
        }

        if (currentFrame == 17) 
        {
            isVisible = false;
            currentFrame = 0;
        }

        sourceRect = new Rectangle(currentFrame * spriteWidth, 0, spriteWidth, spriteHeight);
        origin = new Vector2(sourceRect.Width / 2, sourceRect.Height / 2);
    }

    //draw
    public void Draw(SpriteBatch spriteBatch)
    {
        if (isVisible == true) 
        {

            spriteBatch.Draw(texture, position, sourceRect, Color.White, 0f, origin, 1.0f, SpriteEffects.None, 0);
        }

    }

}
}

Hazard.cs

using System;
using System.Collections.Generic;
 using System.Text;
 using Microsoft.Xna.Framework;

  namespace DriveFast
 {
 class Hazard
{
    public Vector2 Position;
    public bool Visible = true;

    public Hazard()
    {

    }
}
}
Это было полезно?

Решение

First of all you need to draw your Explosions after road, car, hazards etc. Replace next code as shown below:

DrawRoad();
DrawHazards();

spriteBatch.Draw(mCar, mCarPosition, new Rectangle(0, 0, mCar.Width, mCar.Height), Color.White, 0, new Vector2(0, 0), 0.2f, SpriteEffects.None, 0);

// place code here
foreach (Explosion ex in explosionList)
{
   ex.Draw(spriteBatch);
}
//

Into manage explosion method make !isVisible instead of isVisible:

    public void ManageExplosions()
    {
        for (int i = 0; i < explosionList.Count; i++)
        {
            if (!explosionList[i].isVisible)
            {
                explosionList.RemoveAt(i);
                i--;
            }
        }
    }

Remove line:

    foreach (Hazard aHazard in mHazards)
    {
        if (CheckCollision(aHazard) == true)
        {
            //remove next line because it is duplicate of adding Explosion which is already added inside CheckCollision(Hazard) method
            //explosionList.Add(new Explosion(Content.Load<Texture2D>("Images/explosion3"), new Vector2(aHazard.Position.X, aHazard.Position.Y)));
            break;
        }

             MoveHazard(aHazard);
    }

Change next variables:

    spriteWidth = 71;//128;
    spriteHeight = 100;//128;

    sourceRect = new Rectangle(currentFrame * spriteWidth, 0, spriteWidth, spriteHeight);
    //origin = new Vector2(sourceRect.Width / 2, sourceRect.Height / 2);
    origin = new Vector2(-(sourceRect.Width / 4), 0);

Comment next code for testing:

    if (mCurrentState == State.Crash)
    {

       //DrawTextDisplayArea();

       //DrawTextCentered("Crash!", 200);
       //DrawTextCentered("Press 'Space' to continue driving.", 260);
    }
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top