SOLVED - [XNA] Game states and Sprites

Started by
16 comments, last by Dave Hunt 16 years, 3 months ago
This question is a long shot, but has anyone here used the following game state sample?: http://creators.xna.com/Headlines/developmentaspx/archive/2007/01/01/Game-State-Management-Sample.aspx I'm having troubles displaying a class-based sprite during the gameplay state. I know how to display a sprite in the main class but in this example I am stuck. If I display the sprite in the main class' draw method, it only displays during the load segment. If there is no chance that this will be answered, could you offer a suggestion? Thanks in advance [Edited by - rippingcorpse on January 19, 2008 11:50:28 AM]
Advertisement
You put your gameplay state's drawing code in the gameplay state's Draw method. ;)
Quote:Original post by Dave Hunt
You put your gameplay state's drawing code in the gameplay state's Draw method. ;)


Its not that quite simple, sir. I'm not sure where to place the necessary code aside from the draw method. I can't just leave it in the main class and I can't seem to put it in the gameplay class.
I'm afraid we'll need to see some of your code to understand what you are saying. You say you can't seem to put it in the gameplay class. What do you mean? Do you get an error? Does it not work?

P.S. If my previous reply offended you, I apologize. It was not my intention.
Quote:Original post by Dave Hunt
I'm afraid we'll need to see some of your code to understand what you are saying. You say you can't seem to put it in the gameplay class. What do you mean? Do you get an error? Does it not work?

P.S. If my previous reply offended you, I apologize. It was not my intention.


It wasn't offensive, no need to apologize.

I'll be much easier to understand if you have the code sample but I could copy segments if you wish. I would have to copy about four classes worth of code since they're all linked, so there is no use copying it all if you are willing to get the sample.
I'm quite familiar with the sample, so you can just show the relevent parts of your code and where they fit in the sample. I should be able to follow it from there.
Quote:Original post by Dave Hunt
I'm quite familiar with the sample, so you can just show the relevent parts of your code and where they fit in the sample. I should be able to follow it from there.


namespace Game{// The main class, the "engine" class    public class Engine : Microsoft.Xna.Framework.Game    {                #region Fields        public bool ToggleScreenOne;        public bool ToggleScreenTwo;        GraphicsDeviceManager graphics;        ScreenManager screenManager;        // Audio API components.        private SoundEngine _soundEngine;        //The object used for drawing the sprites to the screen        SpriteBatch mSpriteBatch;        //The Wizard object        Wizard mWizard;        #region Framerate        // Framerate private field members        public float fps;        public float updateInterval = 1.0f;        public float timeSinceLastUpdate = 0.0f;        public float framecount = 0;        #endregion        #endregion        #region Initialization        #region Initialize        public Engine()        {            graphics = new GraphicsDeviceManager(this);            graphics.PreferredBackBufferWidth = 802;            graphics.PreferredBackBufferHeight = 625;            // Create the screen manager component.            screenManager = new ScreenManager(this);            Components.Add(screenManager);            // Activate the first screens.            screenManager.AddScreen(new BackgroundScreen());            screenManager.AddScreen(new MainMenuScreen());        }        protected override void Initialize()        {            // create sound engine            _soundEngine = new SoundEngine();            //Create the SpriteBatch object used for drawing the srprites            mSpriteBatch = new SpriteBatch(this.graphics.GraphicsDevice);            ContentManager aLoader = new ContentManager(Services);            //Instantiate a new instance of the Wizard object            mWizard = new Wizard(this.graphics.GraphicsDevice, aLoader);            base.Initialize();            // play background sound            _soundEngine.Play("Robots");        }        #endregion        #endregion        #region Load Graphics Content        protected override void LoadGraphicsContent(bool loadAllContent)        {            if (loadAllContent)            {                LoadResources();            }            // TODO: Load any ResourceManagementMode.Manual content        }        #endregion        #region Load Resources        void LoadResources()        {            //Load the image into the texture object            ContentManager aLoader = new ContentManager(Services);        }        #endregion        #region Update Game        protected override void Update(GameTime gameTime)        {            //Get the current state of the keyboard            KeyboardState aKeyboard = Keyboard.GetState();            // TODO: Add your drawing code here            float elapsed = (float)gameTime.ElapsedRealTime.TotalSeconds;            float elapsedTime = (float)gameTime.ElapsedRealTime.TotalSeconds;            //Framerate draw            framecount++;            //Update the Wizard            mWizard.Update(gameTime.ElapsedGameTime.TotalSeconds);        #region Draw Game        protected override void Draw(GameTime gameTime)        {            graphics.GraphicsDevice.Clear(Color.Black);            // TODO: Add your drawing code here            // TODO: Add your drawing code here            //graphics.GraphicsDevice.Clear(Color.Black);            //Draw the Wizard            //mWizard.Draw(mSpriteBatch);            // The real drawing happens inside the screen manager component.            base.Draw(gameTime);        }        #endregion        public OptionsMenuScreen myOptions = new OptionsMenuScreen();                #region Entry Point            /// <summary>    /// The main entry point for the application.    /// </summary>    static class Program    {        static void Main()        {            using (Engine game = new Engine())            {                game.Run();            }        }    }    #endregion}    }


namespace Game{// The gameplay screen class    public class GameplayScreen : GameScreen     {        #region Fields        ContentManager content;        SpriteFont gameFont;        Vector2 playerPosition = new Vector2(100, 100);        Vector2 enemyPosition = new Vector2(100, 100);        Random random = new Random();        //The object used for drawing the sprites to the screen        SpriteBatch mSpriteBatch;        //The Wizard object        Wizard mWizard;        #endregion        #region Initialization                       /// <summary>        /// Constructor.        /// </summary>        public GameplayScreen()        {            TransitionOnTime = TimeSpan.FromSeconds(1.5);            TransitionOffTime = TimeSpan.FromSeconds(0.5);        }        /// <summary>        /// Load graphics content for the game.        /// </summary>        public override void LoadGraphicsContent(bool loadAllContent)        {            if (loadAllContent)            {                if (content == null)                    content = new ContentManager(ScreenManager.Game.Services);                gameFont = content.Load<SpriteFont>("Content/gamefont");                Thread.Sleep(1000);            }        }        /// <summary>        /// Unload graphics content used by the game.        /// </summary>        public override void UnloadGraphicsContent(bool unloadAllContent)        {            if (unloadAllContent)                content.Unload();        }        #endregion        #region Update and Draw        public override void Update(GameTime gameTime, bool otherScreenHasFocus,                                                       bool coveredByOtherScreen)        {            base.Update(gameTime, otherScreenHasFocus, coveredByOtherScreen);            if (IsActive)            {               }        }        public override void HandleInput(InputState input)        {            if (input == null)                throw new ArgumentNullException("input");            if (input.PauseGame)            {                // If they pressed pause, bring up the pause menu screen.                ScreenManager.AddScreen(new PauseMenuScreen());            }            else            {            }        }        /// <summary>        /// Draws the gameplay screen.        /// </summary>        public override void Draw(GameTime gameTime)        {            // The game has a black background.            ScreenManager.GraphicsDevice.Clear(ClearOptions.Target,                                               Color.Black, 0, 0);            //HERE IS WHERE I'M HAVING TROUBLE LOADING THE WIZARD SPRITE.            // If the game is transitioning on or off, fade it out to black.            if (TransitionPosition > 0)            {                ScreenManager.FadeBackBufferToBlack(255 - TransitionAlpha);            }        }       public Engine myEngine = new Engine();        #endregion    }}


namespace Game{//The ScreenManager class in its original entirety.    public class ScreenManager : DrawableGameComponent    {        #region Fields        List<GameScreen> screens = new List<GameScreen>();        List<GameScreen> screensToUpdate = new List<GameScreen>();        InputState input = new InputState();        IGraphicsDeviceService graphicsDeviceService;        ContentManager content;        SpriteBatch spriteBatch;        SpriteFont font;        Texture2D blankTexture;        Texture2D mWizard;        SpriteBatch mWizardSpriteBatch;        bool traceEnabled;        #endregion        #region Properties        /// <summary>        /// Expose access to our Game instance (this is protected in the        /// default GameComponent, but we want to make it public).        /// </summary>        new public Game Game        {            get { return base.Game; }        }        /// <summary>        /// Expose access to our graphics device (this is protected in the        /// default DrawableGameComponent, but we want to make it public).        /// </summary>        new public GraphicsDevice GraphicsDevice        {            get { return base.GraphicsDevice; }        }        /// <summary>        /// A content manager used to load data that is shared between multiple        /// screens. This is never unloaded, so if a screen requires a large amount        /// of temporary data, it should create a local content manager instead.        /// </summary>        public ContentManager Content        {            get { return content; }        }        /// <summary>        /// A default SpriteBatch shared by all the screens. This saves        /// each screen having to bother creating their own local instance.        /// </summary>        public SpriteBatch SpriteBatch        {            get { return spriteBatch; }        }        /// <summary>        /// A default font shared by all the screens. This saves        /// each screen having to bother loading their own local copy.        /// </summary>        public SpriteFont Font        {            get { return font; }        }        /// <summary>        /// If true, the manager prints out a list of all the screens        /// each time it is updated. This can be useful for making sure        /// everything is being added and removed at the right times.        /// </summary>        public bool TraceEnabled        {            get { return traceEnabled; }            set { traceEnabled = value; }        }        #endregion        #region Initialization        /// <summary>        /// Constructs a new screen manager component.        /// </summary>        public ScreenManager(Game game)            : base(game)        {            content = new ContentManager(game.Services);            graphicsDeviceService = (IGraphicsDeviceService)game.Services.GetService(                                                        typeof(IGraphicsDeviceService));            if (graphicsDeviceService == null)                throw new InvalidOperationException("No graphics device service.");        }        /// <summary>        /// Load your graphics content.        /// </summary>        protected override void LoadGraphicsContent(bool loadAllContent)        {            // Load content belonging to the screen manager.            if (loadAllContent)            {                mWizardSpriteBatch = new SpriteBatch(GraphicsDevice);                spriteBatch = new SpriteBatch(GraphicsDevice);                font = content.Load<SpriteFont>("Content/menufont");                blankTexture = content.Load<Texture2D>("Content/blank");                mWizard = content.Load<Texture2D>("Images/WizardSheet");            }            // Tell each of the screens to load their content.            foreach (GameScreen screen in screens)            {                screen.LoadGraphicsContent(loadAllContent);            }        }        /// <summary>        /// Unload your graphics content.        /// </summary>        protected override void UnloadGraphicsContent(bool unloadAllContent)        {            // Unload content belonging to the screen manager.            if (unloadAllContent)            {                content.Unload();            }            // Tell each of the screens to unload their content.            foreach (GameScreen screen in screens)            {                screen.UnloadGraphicsContent(unloadAllContent);            }        }        #endregion        #region Update and Draw        /// <summary>        /// Allows each screen to run logic.        /// </summary>        public override void Update(GameTime gameTime)        {            // Read the keyboard and gamepad.            input.Update();            // Make a copy of the master screen list, to avoid confusion if            // the process of updating one screen adds or removes others.            screensToUpdate.Clear();            foreach (GameScreen screen in screens)                screensToUpdate.Add(screen);            bool otherScreenHasFocus = !Game.IsActive;            bool coveredByOtherScreen = false;            // Loop as long as there are screens waiting to be updated.            while (screensToUpdate.Count > 0)            {                // Pop the topmost screen off the waiting list.                GameScreen screen = screensToUpdate[screensToUpdate.Count - 1];                screensToUpdate.RemoveAt(screensToUpdate.Count - 1);                // Update the screen.                screen.Update(gameTime, otherScreenHasFocus, coveredByOtherScreen);                if (screen.ScreenState == ScreenState.TransitionOn ||                    screen.ScreenState == ScreenState.Active)                {                    // If this is the first active screen we came across,                    // give it a chance to handle input.                    if (!otherScreenHasFocus)                    {                        screen.HandleInput(input);                        otherScreenHasFocus = true;                    }                    // If this is an active non-popup, inform any subsequent                    // screens that they are covered by it.                    if (!screen.IsPopup)                        coveredByOtherScreen = true;                }            }            // Print debug trace?            if (traceEnabled)                TraceScreens();        }        /// <summary>        /// Prints a list of all the screens, for debugging.        /// </summary>        void TraceScreens()        {            List<string> screenNames = new List<string>();            foreach (GameScreen screen in screens)                screenNames.Add(screen.GetType().Name);            Trace.WriteLine(string.Join(", ", screenNames.ToArray()));        }        /// <summary>        /// Tells each screen to draw itself.        /// </summary>        public override void Draw(GameTime gameTime)        {            foreach (GameScreen screen in screens)            {                if (screen.ScreenState == ScreenState.Hidden)                    continue;                screen.Draw(gameTime);                            }        }        private OptionsMenuScreen myOptions = new OptionsMenuScreen();        #endregion        #region Public Methods        /// <summary>        /// Adds a new screen to the screen manager.        /// </summary>        public void AddScreen(GameScreen screen)        {            screen.ScreenManager = this;            // If we have a graphics device, tell the screen to load content.            if ((graphicsDeviceService != null) &&                (graphicsDeviceService.GraphicsDevice != null))            {                screen.LoadGraphicsContent(true);            }            screens.Add(screen);        }        /// <summary>        /// Removes a screen from the screen manager. You should normally        /// use GameScreen.ExitScreen instead of calling this directly, so        /// the screen can gradually transition off rather than just being        /// instantly removed.        /// </summary>        public void RemoveScreen(GameScreen screen)        {            // If we have a graphics device, tell the screen to unload content.            if ((graphicsDeviceService != null) &&                (graphicsDeviceService.GraphicsDevice != null))            {                screen.UnloadGraphicsContent(true);            }            screens.Remove(screen);            screensToUpdate.Remove(screen);        }        /// <summary>        /// Expose an array holding all the screens. We return a copy rather        /// than the real master list, because screens should only ever be added        /// or removed using the AddScreen and RemoveScreen methods.        /// </summary>        public GameScreen[] GetScreens()        {            return screens.ToArray();        }        /// <summary>        /// Helper draws a translucent black fullscreen sprite, used for fading        /// screens in and out, and for darkening the background behind popups.        /// </summary>        public void FadeBackBufferToBlack(int alpha)        {            Viewport viewport = GraphicsDevice.Viewport;            spriteBatch.Begin();            spriteBatch.Draw(blankTexture,                             new Rectangle(0, 0, viewport.Width, viewport.Height),                             new Color(0, 0, 0, (byte)alpha));            spriteBatch.End();        }        #endregion    }}


If you need more, let me know. Also, some sections from the original gamestate sample may be left over that are unneeded, so just ignore these sections.

Thanks again! :)
Ok, now I think I see the problem. I assume the sprite you are wanting to draw is the Wizard? If that's the case then here is the problem. You've declared and created the Wizard object in your Game class and are updating it in the Update method (but not drawing it in the Draw method). However, in your GamePlayScreen class, you've declared another Wizard object but never created it, nor are you doing anything with it.

You need to move the code that creates and updates the Wizard object into your GamePlayScreen class. Then, just add a call to the Wizard's Draw method in your GamePlayScreen's Draw method right where you've indicated you're having trouble.

Also, you've declared a SpriteBatch object in your GamePlayScreen class, but you haven't created it. You don't really need that since the ScreenManager has a public property to get a reference to it's SpriteBatch object. Use that reference when calling your Wizard's Draw method.

Give that a shot and let me know if you're still having trouble or couldn't follow what I was trying to say.
Quote:Original post by Dave Hunt
Ok, now I think I see the problem. I assume the sprite you are wanting to draw is the Wizard? If that's the case then here is the problem. You've declared and created the Wizard object in your Game class and are updating it in the Update method (but not drawing it in the Draw method). However, in your GamePlayScreen class, you've declared another Wizard object but never created it, nor are you doing anything with it.

You need to move the code that creates and updates the Wizard object into your GamePlayScreen class. Then, just add a call to the Wizard's Draw method in your GamePlayScreen's Draw method right where you've indicated you're having trouble.

Also, you've declared a SpriteBatch object in your GamePlayScreen class, but you haven't created it. You don't really need that since the ScreenManager has a public property to get a reference to it's SpriteBatch object. Use that reference when calling your Wizard's Draw method.

Give that a shot and let me know if you're still having trouble or couldn't follow what I was trying to say.



Yes, I'm drawing the Wizard. I originally had it drawn in the Engine class. Here is the original code that I had in the Engine class' draw method:

        #region Draw Game        protected override void Draw(GameTime gameTime)        {            graphics.GraphicsDevice.Clear(Color.Black);            // TODO: Add your drawing code here            // TODO: Add your drawing code here            mSpriteBatch.Begin(SpriteBlendMode.AlphaBlend);            //Draw Wizard            mWizard.Draw(mSpriteBatch);            mSpriteBatch.End();            base.Draw(gameTime);        }        #endregion 


I need to know how to move this to the GameplayScreen class.

Quote:Original post by Dave Hunt
Then, just add a call to the Wizard's Draw method in your GamePlayScreen's Draw method right where you've indicated you're having trouble.


How do I do this?

Quote:Original post by Dave Hunt
"Also, you've declared a SpriteBatch object in your GamePlayScreen class, but you haven't created it. You don't really need that since the ScreenManager has a public property to get a reference to it's SpriteBatch object. Use that reference when calling your Wizard's Draw method."


And how do I do this?

I got rid of the GameplayScreen Wizard declaration, I just had some scrap code lying around from previous failed attempts.

Thanks again

[Edited by - rippingcorpse on January 19, 2008 9:47:15 AM]
Well, you can't access any variables declared in the Game class from your GamePlayScreen class unless you expose them as public properties in the Game class. Unless you really need to use the wizard in the main game class, you need to move ALL code referencing your wizard to your GamePlayScreen class.

In the section where you declare your variables in the GamePlayScreen class:
        ...        //The object used for drawing the sprites to the screen        SpriteBatch mSpriteBatch;        //The Wizard object        Wizard mWizard;        #region Framerate        // Framerate private field members        ...


In your GamePlayScreen's LoadGraphicsContent method:
        public override void LoadGraphicsContent(bool loadAllContent)        {            if (loadAllContent)            {                if (content == null)                    content = new ContentManager(ScreenManager.Game.Services);                gameFont = content.Load<SpriteFont>("Content/gamefont");                //Instantiate a new instance of the Wizard object                mWizard = new Wizard(ScreenManager.Game.GraphicsDevice, content);                Thread.Sleep(1000);            }        }


In your GamePlayScreen's Update method:
        public override void Update(GameTime gameTime, bool otherScreenHasFocus,                                                       bool coveredByOtherScreen)        {            base.Update(gameTime, otherScreenHasFocus, coveredByOtherScreen);            if (IsActive)            {                 mWizard.Update(gameTime.ElapsedGameTime.TotalSeconds)            }        }


In your GamePlayScreen's Draw method:
        public override void Draw(GameTime gameTime)        {            // The game has a black background.            ScreenManager.GraphicsDevice.Clear(ClearOptions.Target,                                               Color.Black, 0, 0);            mWizard.Draw(ScreenManager.SpriteBatch);            // If the game is transitioning on or off, fade it out to black.            if (TransitionPosition > 0)            {                ScreenManager.FadeBackBufferToBlack(255 - TransitionAlpha);            }        }


Then remove EVERYTHING referencing the wizard object from your main Game class.

Keep in mind that I may have mixed some 1.0 and 2.0 functionality (I notice you're still using 1.0), so you may need to tweak it a little bit. I would strongly recommend that you update to 2.0 anyway. The game state sample has been updated for 2.0, so you wouldn't have to worry about that.

This topic is closed to new replies.

Advertisement