Jump to content
  • Advertisement
Sign in to follow this  
rippingcorpse

SOLVED - [XNA] Game states and Sprites

This topic is 3899 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

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]

Share this post


Link to post
Share on other sites
Advertisement
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.

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites
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! :)

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites
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]

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!