Need some help with Drawing method

  • (3 Pages)
  • +
  • 1
  • 2
  • 3

35 Replies - 4488 Views - Last Post: 19 January 2010 - 10:40 AM

#1 ShadowsEdge19   User is offline

  • D.I.C Addict

Reputation: 142
  • View blog
  • Posts: 664
  • Joined: 16-January 10

Need some help with Drawing method

Posted 16 January 2010 - 08:32 AM

Hi, I've started a new game project that I've been slowly implementing the structure of the game and the mouse and button input handlers. However I'm having a few problems in displaying the menu elements and the buttons as the screen displays as black when I run it, yet it should show the menuBackground.png and the 3 ButtonSquare graphics plus its mouseover effects.

Once they've been displayed then I can mess around with the positioning of the buttons, the actual input handling and the button text itself.

The problems could be in the MenuScene Draw() and the ButtonHandler Draw() methods, but they might be affected by some outside method in those classes or the way in which i transfer them from the Game1 class.

Can anyone help me find the problems?

Attached File(s)



Is This A Good Question/Topic? 0
  • +

Replies To: Need some help with Drawing method

#2 lesPaul456   User is offline

  • D.I.C Addict
  • member icon

Reputation: 175
  • View blog
  • Posts: 729
  • Joined: 16-April 09

Re: Need some help with Drawing method

Posted 16 January 2010 - 10:11 AM

First off, I like to mention that you may be more likely to get a fast response if you post your code, rather than attach it.

The reason that your menu is not being drawn is because the Draw method is not being invoked.

Here's why: the MenuScene class inherits from the abstract Scenes class, which implements the DrawableGameComponent class. As I'm sure you know, the Draw method of the DrawableGameComponent class will automatically be called when it is time to draw. When you have a class that implements DrawableGameComponent, though, it must override the draw method. Scenes overrides the Draw method, but MenuScene does not. So, the MenuScene class never has its Draw method called.

It's a simple fix. Just change the signature of the Draw method in MenuScene to:

public override void Draw(GameTime gameTime)
{
    // Rest of code here.
}



Sorry if I wasn't clear enough. Let me know if I need to re-word things. :P
Hope this helps!
Was This Post Helpful? 0
  • +
  • -

#3 ShadowsEdge19   User is offline

  • D.I.C Addict

Reputation: 142
  • View blog
  • Posts: 664
  • Joined: 16-January 10

Re: Need some help with Drawing method

Posted 16 January 2010 - 11:31 AM

I've changed that and I get a problem with the line:

spriteBatch.Draw(background,new Vector2(0,0),Color.White); (This is in the Draw method of menuScene)

This is saying: "Object reference not set to an instance of an object."


I've also called this inside the Game1 Draw() method

activeScene.Draw(gameTime);
Was This Post Helpful? 0
  • +
  • -

#4 lesPaul456   User is offline

  • D.I.C Addict
  • member icon

Reputation: 175
  • View blog
  • Posts: 729
  • Joined: 16-April 09

Re: Need some help with Drawing method

Posted 16 January 2010 - 11:45 AM

Step through and find the exact line. Chances are spriteBatch hasn't been initialized.
Was This Post Helpful? 0
  • +
  • -

#5 ShadowsEdge19   User is offline

  • D.I.C Addict

Reputation: 142
  • View blog
  • Posts: 664
  • Joined: 16-January 10

Re: Need some help with Drawing method

Posted 16 January 2010 - 11:59 AM

I've declared spriteBatch at the top but that doesn't seem enough.

#region Using Statements
using System;
using System.Collections.Generic;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;
using OverTheTopGame.OverTheTop;
#endregion

namespace OverTheTopGame
{
	/// <summary>
	/// This is a game component that implements IUpdateable.
	/// </summary>
	public class MenuScene : Scenes
	{
		private SpriteBatch spriteBatch;
		private SpriteFont smallFont;
		private SpriteFont largeFont;
		private Texture2D background;
		
		//Booleans used for Mouse and Button Input
		private bool Normal; //Are we normal?
		private bool Clicking; //Are we clicking?
		private bool Hovering; //Are we hovering?
		private bool Pressed; //Have we pressed the button?
		
		//Textures and Vectors for the buttons
		private List<Button> buttons = new List<Button>(); //Our list of buttons for the game
		private List<Texture2D> buttonTextures = new List<Texture2D>(); //Our list of button textures for the menu
		private Vector2 buttonPos;
		private Texture2D normalButton;
		private Texture2D onHover;
		private Texture2D onclick;
		
		//Buttons for the menu
		private Button startButton; //An instance of Button
		private Button rulesButton; //An instance of Button
		private Button quitButton; //An instance of Button

		public MenuScene(Game game, SpriteFont smallFont, SpriteFont largeFont,
							Texture2D background, Texture2D normalButton, Texture2D onHover, Texture2D onclick)
			: base(game)
		{
			this.background = background;
			this.normalButton = normalButton;
			this.onHover = onHover;
			this.onclick = onclick;
			this.smallFont = smallFont;
			this.largeFont = largeFont;

			//Handle the button creation for the menu scene
			buttonPos = new Vector2(400, 300);
			startButton = new Button(game, buttonPos, normalButton, "Normal");

			buttonPos += new Vector2(0, 50);
			rulesButton = new Button(game, buttonPos, normalButton, "Normal");

			buttonPos += new Vector2(0, 50);
			quitButton = new Button(game, buttonPos, normalButton, "Normal");

			//Adding the buttons we recently made to the menu scene list.
			buttons.Add(startButton);
			buttons.Add(rulesButton);
			buttons.Add(quitButton);

		}

		/// <summary>
		/// Show the start scene
		/// </summary>
		public override void Show()
		{
			base.Show();
		}

		/// <summary>
		/// Hide the start scene
		/// </summary>
		public override void Hide()
		{
			base.Hide();
		}


		/// <summary>
		/// Allows the game component to update itself.
		/// </summary>
		/// <param name="gameTime">Provides a snapshot of timing values.</param>
		public override void Update(GameTime gameTime)
		{
			// TODO: Add your update code here

			base.Update(gameTime);
		}

		/// <summary>
		/// Allows the game component to draw itself.
		/// </summary>
		/// <param name="gameTime">Provides a snapshot of timing values.</param>
		public override void Draw(GameTime gameTime)
		{
			base.Draw(gameTime);
			spriteBatch.Draw(background,new Vector2(0,0),Color.White);

			//Between batch.Begin() and batch.End() we are allowed to draw.
			foreach (Button b in this.buttons) //For every button run through the code between the {}
			{
				if (Hovering) //If we are hovering
				{
					//Draw the hover sprite
					b.tex = this.onHover;
				}
				if (Clicking) //If we are clicking
				{
					//Draw the clicking sprite.
					b.tex = this.onclick;
				}
				else
				{
					//Draw the normal sprite.
					b.tex = this.normalButton;
				}
				b.Draw(gameTime);
			}

		}
	}
}

Was This Post Helpful? 0
  • +
  • -

#6 lesPaul456   User is offline

  • D.I.C Addict
  • member icon

Reputation: 175
  • View blog
  • Posts: 729
  • Joined: 16-April 09

Re: Need some help with Drawing method

Posted 16 January 2010 - 12:07 PM

Declaring a variable isn't the same as initializing it.

spriteBatch = new SpriteBatch(GraphicsDevice);

Was This Post Helpful? 0
  • +
  • -

#7 SixOfEleven   User is offline

  • Planeswalker
  • member icon

Reputation: 1055
  • View blog
  • Posts: 6,643
  • Joined: 18-October 08

Re: Need some help with Drawing method

Posted 16 January 2010 - 12:09 PM

I see where you have a SpriteBatch field but I don't see where you set it to be an instance of the SpriteBatch class. You will need to create an instance of SpriteBatch or pass an instance of SpriteBatch to your class.

*edit*
Also, would you mind posting a screen shot of what you are doing, or a little bit of code in the 52 Weeks of Code - Week 2 XNA Challenge thread. We would love to see what you are doing.
Was This Post Helpful? 0
  • +
  • -

#8 ShadowsEdge19   User is offline

  • D.I.C Addict

Reputation: 142
  • View blog
  • Posts: 664
  • Joined: 16-January 10

Re: Need some help with Drawing method

Posted 16 January 2010 - 12:29 PM

Now we're getting somewhere! I've just managed to display the menu background image:
Posted Image

Here's what I changed: In menuScene.cs

I changed the class declaration to include a spriteBatch passed on from the Game1 class

public MenuScene(Game game, SpriteBatch spriteBatch, SpriteFont smallFont, SpriteFont largeFont,
Texture2D background, Texture2D normalButton, Texture2D onHover, Texture2D onclick)

and copied it to the local copy: this.spriteBatch = spriteBatch;

Also added the pass to the menuScene creation code in Game1

menuScene = new MenuScene(this, spriteBatch, smallFont...)

I then modified the buttonHandler with the same method, changing the declarations in the menuScene to pass on the spriteBatch.

I just need to modify the size and position of the buttons and add some text to them, then work on the input handling and create the gameScene.

This post has been edited by ShadowsEdge19: 16 January 2010 - 12:30 PM

Was This Post Helpful? 0
  • +
  • -

#9 SixOfEleven   User is offline

  • Planeswalker
  • member icon

Reputation: 1055
  • View blog
  • Posts: 6,643
  • Joined: 18-October 08

Re: Need some help with Drawing method

Posted 16 January 2010 - 12:39 PM

Nice job! I'm glad that you got it to work. Good luck with the game. :)
Was This Post Helpful? 0
  • +
  • -

#10 ShadowsEdge19   User is offline

  • D.I.C Addict

Reputation: 142
  • View blog
  • Posts: 664
  • Joined: 16-January 10

Re: Need some help with Drawing method

Posted 16 January 2010 - 01:04 PM

There is however one problem that has yet to be resolved, my buttons are not changing the texture to the ButtonSquareHighlight or ButtonSquarePressed images once I move the mouse over them. This could be a problem in any number of places, a problem directly in the MouseHandler class where is determines whether the location of the mouse is within a button or not. Or could be in the If statements to determine whether it is Hovering, Clicking, Pressed or Normal. or it could be the method in which I change the textures of the buttons in menuScene Draw().

##MouseHandler##

#region
using System.Collections.Generic;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
#endregion

namespace OverTheTopGame.OverTheTop
{
	class MouseHandler : DrawableGameComponent
	{
		protected SpriteBatch spriteBatch = null;
		private Vector2 pos;
		private Texture2D tex;
		private MouseState mouseState;
		//We create variables

		public MouseHandler(Game game, Vector2 pos, Texture2D tex)
			: base(game)
		{
			this.pos = pos; //Inital pos (0,0)
			this.tex = tex; //Cursor texture
		}
		//On Update we will call this function

		/// <summary>
		/// Allows the game component to perform any initialization it needs to 
		/// before starting to run.  This is where it can query for any required
		///  services and load content.
		/// </summary>
		public override void Initialize()
		{
			// Get the current spritebatch
			spriteBatch = (SpriteBatch)Game.Services.GetService(typeof(SpriteBatch));

			base.Initialize();
		}


		public void Update()
		{
			mouseState = Mouse.GetState(); //Needed to find the most current mouse states.
			this.pos.X = mouseState.X; //Change x pos to mouseX
			this.pos.Y = mouseState.Y; //Change y pos to mouseY
		}

		//Drawing function to be called in the main Draw function.
		public void Draw(SpriteBatch spriteBatch, GameTime gameTime) //SpriteBatch to use.
		{
			base.Draw(gameTime);
			spriteBatch.Draw(this.tex, this.pos, Color.White); //Draw it using the batch.
		}

		public bool Buttonclick(Button b)
		{
			if (this.pos.X >= b.position.X // To the right of the left side
				&& this.pos.X < b.position.X + b.tex.Width //To the left of the right side
				&& this.pos.Y > b.position.Y //Below the top side
				&& this.pos.Y < b.position.Y + b.tex.Height) //Above the bottom side

				return true; //We are; return true.
			else
				return false; //We're not; return false.
		}

	}
}


##Game1##
#region Using Statements
using System;
using System.Collections.Generic;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;
using OverTheTopGame.OverTheTop;
#endregion

namespace OverTheTopGame
{
	/// <summary>
	/// This is the main type for your game
	/// </summary>
	public class Game1 : Game
	{
...

		private Texture2D normalButton; //The Normal image texture
		private Texture2D onHover; //The Hover image texture
		private Texture2D onclick; //The Click image texture

...

		private bool Normal; //Are we normal?
		private bool Clicking; //Are we clicking?
		private bool Hovering; //Are we hovering?
		private bool Pressed; //Have we pressed the button?
		private MouseState mouseState; //MouseState needed for checking the state of the mouse

...

		private String HandleMouse(Button button)
		{
			mouseState = Mouse.GetState(); //Get the current state of the mouse

			if (ourMouse.Buttonclick(button))
			{
				//If we're hovering over the mouse
				Hovering = true; //We ARE hovering
				return "Hovering";
			}
			else
				Hovering = false; //Not hovering.
			//We don't even need to use Buttonclick() again if we know if we're hovering.

			if (mouseState.LeftButton == ButtonState.Pressed && Hovering) //If we're clicking with the Left Mouse Button and we're over the button.
			{
				Clicking = true; //We ARE clicking
				return "Clicking";
			}
			else if (mouseState.LeftButton == ButtonState.Released && Hovering)
			{
				Clicking = false; //Not clicking
				Pressed = true; //We HAVE pressed the button
				return "Pressed";
			}
			else
			{
				//If the user moves the mouse off the button and releases the mouse left button
				Clicking = false; //Not clicking
				Pressed = false; //Not pressed
				Normal = true; //We ARE normal
				return "Normal";
			}

		}

		/// <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
			List<Keys> keysPressed = new List<Keys>(Keyboard.GetState().GetPressedKeys());
			if (keysPressed.Contains(Keys.Escape))
				this.Exit();

			ourMouse.Update(); //Update the mouse's position.

			foreach (Button b in menuButtonList) //For every button run through the code between the {}
			{
				//updates the states of every button in the menu
				b.state = HandleMouse(b);
			}

			
			
			base.Update(gameTime);
		}

...

		protected override void Draw(GameTime gameTime)
		{
			spriteBatch.Begin();

			//Draw the mouse.
			ourMouse.Draw(gameTime);

			//Draw the menu scene.
			activeScene.Draw(gameTime);
	  
			// Draw all Game Components..
			base.Draw(gameTime);
			
			spriteBatch.End();
		}
	}
}


MenuSecne
#region Using Statements
using System;
using System.Collections.Generic;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;
using OverTheTopGame.OverTheTop;
#endregion

namespace OverTheTopGame
{
	/// <summary>
	/// This is a game component that implements IUpdateable.
	/// </summary>
	public class MenuScene : Scenes
	{
		private SpriteBatch spriteBatch;
		private SpriteFont smallFont;
		private SpriteFont largeFont;
		private Texture2D background;
		
		//Booleans used for Mouse and Button Input
		private bool Normal; //Are we normal?
		private bool Clicking; //Are we clicking?
		private bool Hovering; //Are we hovering?
		private bool Pressed; //Have we pressed the button?
		
		//Textures and Vectors for the buttons
		private List<Button> buttons = new List<Button>(); //Our list of buttons for the game
		private List<Texture2D> buttonTextures = new List<Texture2D>(); //Our list of button textures for the menu
		private Vector2 buttonPos;
		private Texture2D normalButton;
		private Texture2D onHover;
		private Texture2D onclick;
		
		//Buttons for the menu
		private Button startButton; //An instance of Button
		private Button rulesButton; //An instance of Button
		private Button quitButton; //An instance of Button

		public MenuScene(Game game, SpriteBatch spriteBatch, SpriteFont smallFont, SpriteFont largeFont,
							Texture2D background, Texture2D normalButton, Texture2D onHover, Texture2D onclick)
			: base(game)
		{
			this.spriteBatch = spriteBatch;
			this.background = background;
			this.normalButton = normalButton;
			this.onHover = onHover;
			this.onclick = onclick;
			this.smallFont = smallFont;
			this.largeFont = largeFont;

			//Handle the button creation for the menu scene
			buttonPos = new Vector2(400, 300);
			startButton = new Button(game, spriteBatch, buttonPos, normalButton, "Normal");

			buttonPos += new Vector2(0, 50);
			rulesButton = new Button(game, spriteBatch, buttonPos, normalButton, "Normal");

			buttonPos += new Vector2(0, 50);
			quitButton = new Button(game, spriteBatch, buttonPos, normalButton, "Normal");

			//Adding the buttons we recently made to the menu scene list.
			buttons.Add(startButton);
			buttons.Add(rulesButton);
			buttons.Add(quitButton);
		}

		/// <summary>
		/// Allows the game component to update itself.
		/// </summary>
		/// <param name="gameTime">Provides a snapshot of timing values.</param>
		public override void Update(GameTime gameTime)
		{

			base.Update(gameTime);

		}

		/// <summary>
		/// Allows the game component to draw itself.
		/// </summary>
		/// <param name="gameTime">Provides a snapshot of timing values.</param>
		public override void Draw(GameTime gameTime)
		{
			base.Draw(gameTime);
			spriteBatch.Draw(background,new Vector2(0,0),Color.White);

			//Between batch.Begin() and batch.End() we are allowed to draw.
			foreach (Button b in this.buttons) //For every button run through the code between the {}
			{
				if (Hovering) //If we are hovering
				{
					//Draw the hover sprite
					b.tex = this.onHover;
				}
				if (Clicking) //If we are clicking
				{
					//Draw the clicking sprite.
					b.tex = this.onclick;
				}
				else
				{
					//Draw the normal sprite.
					b.tex = this.normalButton;
				}
				b.Draw(gameTime);
			}

		}
	}
}



and finally ButtonHandler
using System;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;


namespace OverTheTopGame.OverTheTop
{
	/// <summary>
	/// This is a game component that implements IUpdateable.
	/// </summary>
	class Button : DrawableGameComponent
	{
		protected SpriteBatch spriteBatch;
		public Vector2 position;
		public Texture2D tex;
		public String state;
		//Set up variables

		public Button(Game game, SpriteBatch spriteBatch, Vector2 position, Texture2D tex, String state)
			:base(game) //Our constructor
		{
			this.spriteBatch = spriteBatch;
			this.position = position; //Position in 2D
			this.tex = tex; //Our texture to draw
			this.state = state; //Our current state
		}

		public override void Initialize()
		{
			// Get the current spritebatch
			spriteBatch = (SpriteBatch)Game.Services.GetService(typeof(SpriteBatch));

			base.Initialize();
		}

		public void Draw(GameTime gameTime) //Draw function, same as mousehandler one.
		{
			base.Draw(gameTime);
			spriteBatch.Draw(this.tex, this.position, Color.White);
		}
	}
}

Was This Post Helpful? 0
  • +
  • -

#11 lesPaul456   User is offline

  • D.I.C Addict
  • member icon

Reputation: 175
  • View blog
  • Posts: 729
  • Joined: 16-April 09

Re: Need some help with Drawing method

Posted 16 January 2010 - 02:30 PM

Your problem is how you are handling the state of the button and really how you've designed the application.

I would suggest that any code that is specific to a button remains in the Button class. So, handle the mouse input for the button in the button class.

For example, in the button class, store all of the button's textures and its current state, override the Update method to handle mouse input for that specific button, and then draw the button according to its state. All of this should be done inside the button class and should not be spread throughout the application, as it currently is.

This post has been edited by lesPaul456: 16 January 2010 - 02:30 PM

Was This Post Helpful? 0
  • +
  • -

#12 ShadowsEdge19   User is offline

  • D.I.C Addict

Reputation: 142
  • View blog
  • Posts: 664
  • Joined: 16-January 10

Re: Need some help with Drawing method

Posted 16 January 2010 - 05:03 PM

I can't seem to use the LoadContent() method inside any class other than Game1 without it not recognizing the Content variable/object, how can I load the graphics for the button inside only the ButtonHandler class?

For example I have these inside the Game1 LoadContent() method.

normalButton = Content.Load<Texture2D>("buttonSquare"); //Sets texture to be used
onHover = Content.Load<Texture2D>("buttonSquareHighlight"); //Sets texture to be used
onclick = Content.Load<Texture2D>("buttonSquarePressed"); //Sets texture to be used



How can I store the textures to the ButtonHandler class like you propose?
Was This Post Helpful? 0
  • +
  • -

#13 SixOfEleven   User is offline

  • Planeswalker
  • member icon

Reputation: 1055
  • View blog
  • Posts: 6,643
  • Joined: 18-October 08

Re: Need some help with Drawing method

Posted 16 January 2010 - 05:19 PM

In your LoadContent method of Game1 you can add the ContentManager field Content as a Game Service.

		protected override void LoadContent()
		{
			// Create a new SpriteBatch, which can be used to draw textures.
			spriteBatch = new SpriteBatch(GraphicsDevice);
			Services.AddService(typeof(ContentManager), Content);
			// The rest of your LoadContent method would follow
		}



Then like you did here for your SpriteBatch you can do the same for ContentManager.


		ContentManager Content; // Field int he class to get the ContentManager instance

		public override void Initialize()
		{
			// Get the current spritebatch
			spriteBatch = (SpriteBatch)Game.Services.GetService(typeof(SpriteBatch));
			Content = (ContentManager)Game.Services.GetService(typeof(ContentManager));
			base.Initialize();
		}


Was This Post Helpful? 0
  • +
  • -

#14 ShadowsEdge19   User is offline

  • D.I.C Addict

Reputation: 142
  • View blog
  • Posts: 664
  • Joined: 16-January 10

Re: Need some help with Drawing method

Posted 16 January 2010 - 05:30 PM

Sorry do they both update the Game1 methods of LoadContent and Initialize?

When I add the line Services.AddService(typeof(ContentManager), Content); to the Game1 LoadContent() method I get this error:

Error 1 The type or namespace name 'ContentManager' could not be found (are you missing a using directive or an assembly reference?) C:\Users\adam\Documents\Other Programming\XNA Programming\OverTheTop\OverTheTopGame - Copy\Game1.cs 83 40 OverTheTopGame

Is it a missing using statement?

These are the ones I have for Game1:

using System;
using System.Collections.Generic;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;
using OverTheTopGame.OverTheTop;



Also when I add the declaration in Game1 I get no AutoColouration that I normally get from a defined Class:
private ContentManager Content; // Field int he class to get the ContentManager instance
Was This Post Helpful? 0
  • +
  • -

#15 SixOfEleven   User is offline

  • Planeswalker
  • member icon

Reputation: 1055
  • View blog
  • Posts: 6,643
  • Joined: 18-October 08

Re: Need some help with Drawing method

Posted 16 January 2010 - 05:34 PM

You need to add a reference to Game1 for the Content classes.

using Microsoft.Xna.Framework.Content;



Quote

Sorry do they both update the Game1 methods of LoadContent and Initialize?


No, you add Content in the Game1 class and in any class that you want to use it in you use the other code to get it.
Was This Post Helpful? 0
  • +
  • -

  • (3 Pages)
  • +
  • 1
  • 2
  • 3