XNA Sprite Class using Game Component and IDrawable - c#

I am working on my Sprite and Actor class for a game and I have 2 different types of enemies, a pumpkin and a bat. What I wanted to do was to make them both updatable so the pumpkin will fall straight down from its spawn and the bat will follow the player until the player's death or its destruction. But right now I am trying to create their Actor class and I am kind of new to XNA and Stack-Overflow.
Sprite Class:
public class Sprite : Microsoft.Xna.Framework.GameComponent, IDrawable
{
public Texture2D texture;
public Vector2 position;
public Vector2 moveSpeed;
public Vector2 scale;
public Color tint;
public bool active;
public Rectangle rect
{
get { return new Rectangle((int)position.X, (int)position.Y, Width, Height); }
}
public int Height
{
get { return (int)(texture.Height * scale.Y); }
}
public int Width
{
get { return (int)(texture.Width * scale.X);}
}
public Sprite(Game game, String tex)
: base(game)
{
// TODO: Construct any child components here
texture = game.Content.Load<Texture2D>(tex);
}
/// <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()
{
// TODO: Add your initialization code here
base.Initialize();
position = Vector2.Zero;
tint = Color.White;
active = true;
}
/// <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);
}
public void Draw(GameTime gameTime)
{
((Game1)Game).spriteBatch.Begin();
((Game1)Game).spriteBatch.Draw(texture,rect,tint);
((Game1)Game).spriteBatch.End();
}
public int DrawOrder
{
get { return 1; }
}
public event EventHandler<EventArgs> DrawOrderChanged;
public bool Visible
{
get { return active; }
}
public event EventHandler<EventArgs> VisibleChanged;
}
Actor Class:
public class Actor : Microsoft.Xna.Framework.GameComponent
{
public Sprite sprite; //Call Instance of Sprite class
public String tag; //String for the texture
public float health; //Health of the sprite
public int value; //The enemies will need a score
public Actor(Game game, String tex)
: base(game)
{
// TODO: Construct any child components here
sprite = new Sprite(game, tex);
game.Components.Add(this);
}
/// <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()
{
// TODO: Add your initialization code here
base.Initialize();
health = 100.0f; //Initialize the health of Enemy
value = 10; //Initialize the value of enemy destruction
}
/// <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
if(sprite.rect.Intersects(sprite.rect))
{
health -= 100;
sprite.active = false;
}
base.Update(gameTime);
}
}

Related

C# XNA -Trying to randomize movement of list of objects. All but one move the same

I am trying to get a list of sprite objects to move randomly across the screen in short linear movements (up, down , left, right). The sprites move randomly, but they all move the same as each other (e.g all move left, all move right, etc), apart from one which moves separately. I want them all to move independently to each other. Code below -
namespace game2
{
/// <summary>
/// This is the main type for your game
/// </summary>
public class Game1 : Microsoft.Xna.Framework.Game
{
GraphicsDeviceManager graphics;
SpriteBatch spriteBatch;
/// <summary>
/// Sprite
/// </summary>
List<Sprite> spriteList;
Sprite tempSprite;
private int spriteNum;
/// <summary>
/// General
/// </summary>
Random random;
int randomNum;
Rectangle viewPort;
public Game1()
{
graphics = new GraphicsDeviceManager(this);
Content.RootDirectory = "Content";
}
/// <summary>
/// Allows the game to perform any initialization it needs to before starting to run.
/// This is where it can query for any required services and load any non-graphic
/// related content. Calling base.Initialize will enumerate through any components
/// and initialize them as well.
/// </summary>
protected override void Initialize()
{
// TODO: Add your initialization logic here
//Initialize Sprites
spriteList = new List<Sprite>();
spriteNum = 4;
for (int i = 0; i < spriteNum; i++) //Load in as many sprites as spriteNum specifies
{
tempSprite = new Sprite();
spriteList.Add(tempSprite); //add in sprites to list
}
//initialise random
random = new Random();
//initialise viewport
viewPort = new Rectangle(0, 0, GraphicsDevice.Viewport.Width, GraphicsDevice.Viewport.Height);
base.Initialize();
}
/// <summary>
/// LoadContent will be called once per game and is the place to load
/// all of your content.
/// </summary>
protected override void LoadContent()
{
// Create a new SpriteBatch, which can be used to draw textures.
spriteBatch = new SpriteBatch(GraphicsDevice);
foreach (Sprite s in spriteList) //for each sprite in spriteList, load content by passing in Game1's content
{
s.LoadContent(this.Content, viewPort, "square");
s.Position = new Vector2(random.Next(0, viewPort.Width), random.Next(0, viewPort.Height));
}
// TODO: use this.Content to load your game content here
}
/// <summary>
/// UnloadContent will be called once per game and is the place to unload
/// all content.
/// </summary>
protected override void UnloadContent()
{
// TODO: Unload any non ContentManager content here
}
/// <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
if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed)
this.Exit();
//update sprites
foreach (Sprite s in spriteList)
{
s.Update(gameTime);
}
// TODO: Add your update logic here
base.Update(gameTime);
}
/// <summary>
/// This is called when the game should draw itself.
/// </summary>
/// <param name="gameTime">Provides a snapshot of timing values.</param>
protected override void Draw(GameTime gameTime)
{
GraphicsDevice.Clear(Color.CornflowerBlue);
spriteBatch.Begin();
foreach (Sprite s in spriteList)
{
s.Draw(this.spriteBatch);
}
spriteBatch.End();
// TODO: Add your drawing code here
base.Draw(gameTime);
}
}
}
And here is the sprite class -
namespace game2
{
class Sprite
{
//Movement
public Vector2 Position = new Vector2(0,0);
private float counter = 0f;
private float range = 100f;
private Random random;
public int randomNum;
//Properties
private Texture2D mSpriteTexture;
//General
private Rectangle viewPort;
public void LoadContent(ContentManager theContentManager, Rectangle tempViewport, string asset)
{
random = new Random();
viewPort = tempViewport;
mSpriteTexture = theContentManager.Load<Texture2D>(asset);
}
public void Update(GameTime gameTime)
{
if (randomNum == 0)
{
if (Position.X + mSpriteTexture.Width < viewPort.Width && counter <= range)
{
Position.X++;
counter++;
}
else
{
randomNum = random.Next(0, 4);
counter = 0;
}
}
if (randomNum == 1)
{
if (Position.X > viewPort.X && counter <= range)
{
Position.X--;
counter++;
}
else
{
randomNum = random.Next(0, 4);
counter = 0;
}
}
if (randomNum == 2)
{
if (counter <= range)
{
Position.Y++;
counter++;
}
else
{
randomNum = random.Next(0, 4);
counter = 0;
}
}
if (randomNum == 3)
{
if (counter <= range)
{
Position.Y--;
counter++;
}
else
{
randomNum = random.Next(0, 4);
counter = 0;
}
}
}
public void Draw(SpriteBatch theSpriteBatch)
{
theSpriteBatch.Draw(mSpriteTexture, Position, Color.White);
}
}
}
You are loading all the sprites very quickly in LoadContent normally, this isn't a problem, but each one has its own Random class.
Because of this, many are getting identical seeds (similar to the problem you see when instantiating Random in a for or while loop). RNGs with the same seed will produce the same sequence of values, thus causing the behavior you are seeing.
Passing a single Random instance to all objects that use it should cause your problem to go away.

XNA An object reference is required for the non-static field, method, or property error

I've done some research around the internet including this site but I am still confused about what to do with this error. I have 2 classes I'm using MainSkeleton which is the Game1 class and it has the move method while I also made a class InputSkeleton that handles user inputs. When I try calling the move method I'm getting the error even though I called the class.
MainSkeleton
/// <summary>
/// This is the main type for your game
/// </summary>
public class MainSkeleton: Microsoft.Xna.Framework.Game
{
GraphicsDeviceManager graphics;
InputSkeleton input;
SpriteBatch spriteBatch;
Color backColor = Color.CornflowerBlue;
public MainSkeleton()
{
input = new InputSkeleton(1);
graphics = new GraphicsDeviceManager(this);
Content.RootDirectory = "Content";
}
/// <summary>
/// Allows the game to perform any initialization it needs to before starting to run.
/// This is where it can query for any required services and load any non-graphic
/// related content. Calling base.Initialize will enumerate through any components
/// and initialize them as well.
/// </summary>
protected override void Initialize()
{
// TODO: Add your initialization logic here
base.Initialize();
}
/// <summary>
/// LoadContent will be called once per game and is the place to load
/// all of your content.
/// </summary>
// This is a texture we can render.
Texture2D myTexture;
// Set the coordinates to draw the sprite at.
Vector2 spritePosition = Vector2.Zero;
// Store some information about the sprite's motion.
Vector2 spriteSpeed = new Vector2(50.0f, 50.0f);
protected override void LoadContent()
{
// Create a new SpriteBatch, which can be used to draw textures.
spriteBatch = new SpriteBatch(GraphicsDevice);
myTexture = Content.Load<Texture2D>("Person");
// TODO: use this.Content to load your game content here
}
/// <summary>
/// UnloadContent will be called once per game and is the place to unload
/// all content.
/// </summary>
protected override void UnloadContent()
{
// TODO: Unload any non ContentManager content here
}
/// <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
if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed)
this.Exit();
// TODO: Add your update logic here
input.Update();
base.Update(gameTime);
}
/// <summary>
/// This is called when the game should draw itself.
/// </summary>
/// <param name="gameTime">Provides a snapshot of timing values.</param>
protected override void Draw(GameTime gameTime)
{
GraphicsDevice.Clear(Color.CornflowerBlue);
// Draw the sprite.
spriteBatch.Begin(SpriteSortMode.BackToFront, BlendState.AlphaBlend);
spriteBatch.Draw(myTexture, spritePosition, Color.White);
spriteBatch.End();
base.Draw(gameTime);
}
public void Move(String direction)
{
int MaxX = graphics.GraphicsDevice.Viewport.Width - myTexture.Width;
int MinX = 0;
int MaxY = graphics.GraphicsDevice.Viewport.Height - myTexture.Height;
int MinY = 0;
if (direction.Equals("up"))
{
if (spritePosition.Y > MinY)
{
spritePosition.Y = spritePosition.Y - 1;
}
else
{
spritePosition.Y = MinY;
}
}
if (direction.Equals("down"))
{
if (spritePosition.Y < MaxY)
{
spritePosition.Y = spritePosition.Y + 1;
}
else
{
spritePosition.Y = MaxY;
}
}
if (direction.Equals("left"))
{
if (spritePosition.X > MinX)
{
spritePosition.X = spritePosition.X - 1;
}
else
{
spritePosition.X = MinX;
}
}
if (direction.Equals("right"))
{
if (spritePosition.X < MaxX)
{
spritePosition.X = spritePosition.X + 1;
}
else
{
spritePosition.X = MinX;
}
}
}
}
InputSkeleton
public class InputSkeleton
{
public KeyboardState newKState;
public KeyboardState oldKState;
public MouseState newMState;
public MouseState oldMState;
public Boolean menuState;
public Boolean gameRun;
public int player;
public InputSkeleton(int p)
{
player = p;
}
public void Update()
{
if (menuState == true && gameRun == false)
{
MenuInput();
}
else if (menuState == false && gameRun == true)
{
PlayerInput();
}
}
public void MenuInput()
{
}
public void PlayerInput()
{
newKState = Keyboard.GetState();
if (newKState.IsKeyDown(Keys.Up))
{
MainSkeleton.Move("up");
}
if (newKState.IsKeyDown(Keys.Down))
{
MainSkeleton.Move("down");
}
if (newKState.IsKeyDown(Keys.Left))
{
MainSkeleton.Move("left");
}
if (newKState.IsKeyDown(Keys.Right))
{
MainSkeleton.Move("right");
}
oldKState = newKState;
}
}
A static method can be called on a class, while a non static method needs to be called on an object. You're trying to call a non static method on a class;
MainSkeleton.Move("up");
Either you need to make the Move() method a static method (which in this case is not an option since you want to call the method on the same object every time), or you need to somehow get to the original MainSkeleton object and call the method on that.
A simple way to get to the original object is to pass it in to the InputObject constructor which you call from MainSkeleton;
input = new InputSkeleton(1, this); // Pass in myself
...and take the object in the constructor;
MainSkeleton mainSkeleton;
public InputSkeleton(int p, MainSkeleton m)
{
player = p;
mainSkeleton = m;
}
...and finally call move() on the object instead;
mainSkeleton.Move("up");
Problem is you are calling the class without creating an instance.
You need to first create an instance to call a non-static method in a class.
Example;
private MainSkeleton _MainSkeleton = new MainSkeleton();
private void Update()
{
// The below is calling a method and telling what object is calling that method.
_MainSkeleton.Move("right");
// The below calls a method but does not link to any object. The below is only able to call non-static methods.
MainSkeleton.Move("right");
}
You should look up more about static vs non-static methods to see what the difference is.

Detecting history of keystrokes in c#

So currently, I am a newb starting coding in c#. I started making a space game akin to space invaders and ran into an issue, in the draw method, I set it to draw my bullet and head upward on the string as soon as i hit space. But the problem was as soon as I let go of space, my bullet disappeared. I made a work around where as soon as the bullet left the screen it would teleport to the ship. Is there anyway to make the game check if the button has been pressed in the past and make the bullet keep moving until i want it to disappear.
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 Spaceteroids
{
/// <summary>
/// This is the main type for your game
/// </summary>
public class Game1 : Microsoft.Xna.Framework.Game
{
Texture2D spriteSheet;
Texture2D laser;
Texture2D Enemyship;
spriteAnimation loading;
GraphicsDeviceManager graphics;
SpriteBatch spriteBatch;
KeyboardState currentKeyboard;
KeyboardState oldKeyboard;
PlayerShip character;
Rectangle characterRectangle;
Bullet bullet;
Bullet bullet2;
bool heightCheck;
public Game1()
{
graphics = new GraphicsDeviceManager(this);
Content.RootDirectory = "Content";
}
/// <summary>
/// Allows the game to perform any initialization it needs to before starting to run.
/// This is where it can query for any required services and load any non-graphic
/// related content. Calling base.Initialize will enumerate through any components
/// and initialize them as well.
/// </summary>
protected override void Initialize()
{
// TODO: Add your initialization logic here
currentKeyboard = new KeyboardState();
oldKeyboard = new KeyboardState();
//characterRectangle = new Rectangle((int)character.Position.X,(int)character.Position.Y, spriteSheet.Width / 4, spriteSheet.Height);
character = new PlayerShip(new Vector2(GraphicsDevice.Viewport.Width / 2, GraphicsDevice.Viewport.Height - 40));
bullet = new Bullet(new Vector2(character.Position.X, character.Position.Y - 20));
base.Initialize();
}
void Movement()
{
if (IsHeld(Keys.A))
{
character.xSpeed = -6;
}
else if (IsHeld(Keys.D))
{
character.xSpeed = 6;
}
else
{
character.xSpeed = 0;
}
}
void Collision()
{
if (character.Position.X < 0)
{
character.Position.X = 0;
}
else if (character.Position.X + (spriteSheet.Width/4) > graphics.GraphicsDevice.Viewport.Width)
{
character.Position.X = graphics.GraphicsDevice.Viewport.Width - (spriteSheet.Width/4) ;
}
}
/// <summary>
/// LoadContent will be called once per game and is the place to load
/// all of your content.
/// </summary>
protected override void LoadContent()
{
laser = Content.Load<Texture2D>("Laser");
Enemyship = Content.Load<Texture2D>("EnemyShip");
spriteSheet = Content.Load<Texture2D>("shipSpriteSheet");
spriteBatch = new SpriteBatch(GraphicsDevice);
loading = new spriteAnimation(Content.Load<Texture2D>("shipSpriteSheet"), 4);
loading.Position = new Vector2(character.Position.X);
loading.IsLooping = true;
loading.FramesPerSecond = 30;
// TODO: use this.Content to load your game content here
}
/// <summary>
/// UnloadContent will be called once per game and is the place to unload
/// all content.
/// </summary>
protected override void UnloadContent()
{
// TODO: Unload any non ContentManager content here
}
/// <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)
{
bullet.Position.X = character.Position.X;
currentKeyboard = Keyboard.GetState();
oldKeyboard = currentKeyboard;
loading.Update(gameTime, character);
bullet.ySpeed = -10;
bullet.UpdateBullet();
Collision();
Movement();
if (NotPressed(Keys.Space))
{
bullet.Position.Y = character.Position.Y - 15;
}
if (bullet.Position.Y < 0)
{
bullet.Position.Y = character.Position.Y - 15;
}
character.UpdateShip();
// TODO: Add your update logic here
base.Update(gameTime);
}
/// <summary>
/// This is called when the game should draw itself.
/// </summary>
/// <param name="gameTime">Provides a snapshot of timing values.</param>
protected override void Draw(GameTime gameTime)
{
GraphicsDevice.Clear(Color.Black);
spriteBatch.Begin();
spriteBatch.Draw(laser, new Vector2(bullet.Position.X, bullet.Position.Y), Color.White);
loading.Draw(spriteBatch);
spriteBatch.End();
base.Draw(gameTime);
}
public bool IsHeld(Keys key)
{
if (currentKeyboard.IsKeyDown(key))
{
return true;
}
else
{
return false;
}
}
public bool IsReleased(Keys key)
{
if (currentKeyboard.IsKeyUp(key) && oldKeyboard.IsKeyDown(key))
{
return true;
}
else
{
return false;
}
}
public bool JustPressed(Keys key)
{
if (currentKeyboard.IsKeyDown(key) && oldKeyboard.IsKeyUp(key))
{
return true;
}
else
{
return false;
}
}
public bool NotPressed(Keys key)
{
if (IsHeld(key) != true)
{
return true;
}
else
{
return false;
}
}
public bool HasBeenPressed(Keys key)
{
if (oldKeyboard.IsKeyDown(key))
{
return true;
}
else return false;
}
}
}
If you need any other information, feel free to ask.
No, there is nothing in XNA to track keystroke history (or anywhere else either). You have to do it yourself.
The usual solution to your problem is to maintain state on an object that represents the bullet. The keystroke may go away, but the object remains and keeps the bullet visible and moving until it is destroyed. You appear to have that state in your bullet object, so the likelihood is you just have logic errors in when to update it.
The problem is not instantly obvious from a quick read but your handling of keyboard state seems overly complex. All you need is key down and key up. All the rest you should track for yourself.

Error with constructor when inheriting using a base class

Hey im new to c# and XNA. My goal is to inherit from a Sprite class and make classes such as pongSprite, paddleSprite etc... Im getting an error on my constructor. I have extended the sprite class and i have put the variables and objects from the Sprite class into the :base()
Here is my code:
**
Sprite.cs
**
namespace SimplePong
{
/// <summary>
/// This is a game component that implements IUpdateable.
/// </summary>
public class Sprite : DrawableGameComponent
{
protected string id;
protected Texture2D texture;
//bounding box
//protected Rectangle sourceRectangle;
protected Rectangle destinationRectangle;
protected Color color;
protected Main game;
private Sprite pongBall;
public Sprite(Main game, string id, Texture2D texture,
Rectangle destinationRectangle, Color color)
: base(game)
{
this.game = game;
this.id = id;
this.texture = texture;
this.destinationRectangle = destinationRectangle;
this.color = color;
}
/// <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()
{
// TODO: Add your initialization code here
base.Initialize();
}
/// <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);
}
public override void Draw(GameTime gameTime)
{
game.spriteBatch.Begin();
game.spriteBatch.Draw(texture, destinationRectangle, color);
game.spriteBatch.End();
base.Draw(gameTime);
}
}
}
**
ballSprite.cs
**
using Microsoft.Xna.Framework;
namespace SimplePong
{
public class BallSprite : Sprite
{
// public Main game;
public Sprite pongBall;
public BallSprite()
: base(Main game, string id, Texture2D texture,
Rectangle destinationRectangle, Color color)
{
}
public override void Initialize()
{
base.Initialize();
}
public override void Update(GameTime gameTime)
{
destinationRectangle.X += 2;
destinationRectangle.Y += 2;
base.Update(gameTime);
}
public override void Draw(GameTime gameTime)
{
base.Draw(gameTime);
}
}
}
The syntax of the constructor your inherited class is wrong. I suspect you want:
public BallSprite(Main game, string id, Texture2D texture,
Rectangle destinationRectangle, Color color)
: base(game, id, texture, destinationRectangle, color)
{
}
If you want a parameterless constructor then you're going to have to come up with the values for the parameters yourself (or not call the base constructor).

Sound Buttons don't play sound

I'm making a program where one clicks buttons to create sound, like those instant button apps. But when I click the button, it won't play any sound. I don't know why either.
All my "Build" debugs are succeeding too.
These are my classes:
Game1.cs:
public class Game1 : Microsoft.Xna.Framework.Game
{
GraphicsDeviceManager graphics;
SpriteBatch spriteBatch;
Texture2D Background;
Button button;
public Game1()
{
graphics = new GraphicsDeviceManager(this);
Content.RootDirectory = "Content";
this.Window.Title = "Bengt Slår På Knappar";
graphics.PreferredBackBufferHeight = 720;
graphics.PreferredBackBufferWidth = 1280;
IsMouseVisible = true;
}
/// <summary>
/// Allows the game to perform any initialization it needs to before starting to run.
/// This is where it can query for any required services and load any non-graphic
/// related content. Calling base.Initialize will enumerate through any components
/// and initialize them as well.
/// </summary>
protected override void Initialize()
{
// TODO: Add your initialization logic here
base.Initialize();
}
/// <summary>
/// LoadContent will be called once per game and is the place to load
/// all of your content.
/// </summary>
protected override void LoadContent()
{
Background = Content.Load<Texture2D>("bengtbakgrund");
Texture2D Btexture = Content.Load<Texture2D>("Button");
SoundEffect dundundun = Content.Load<SoundEffect>("DUN DUN DUN");
button = new Button(dundundun, Btexture);
spriteBatch = new SpriteBatch(GraphicsDevice);
}
/// <summary>
/// UnloadContent will be called once per game and is the place to unload
/// all content.
/// </summary>
protected override void UnloadContent()
{
// TODO: Unload any non ContentManager content here
}
/// <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
if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed)
this.Exit();
Rectangle mouseRect = new Rectangle(Mouse.GetState().X, Mouse.GetState().Y, 10, 10);
MouseState mouseState = Mouse.GetState();
if (mouseRect.Intersects(button.rect) && mouseState.LeftButton == ButtonState.Pressed)
{
button.MySound.Play();
}
base.Update(gameTime);
}
protected override void Draw(GameTime gameTime)
{
GraphicsDevice.Clear(Color.CornflowerBlue);
spriteBatch.Begin();
spriteBatch.Draw(Background, new Vector2(0,0), Color.White);
button.Draw(spriteBatch, new Vector2(300, 300));
spriteBatch.End();
base.Draw(gameTime);
}
}
Button.cs:
public class Button
{
Texture2D Texture { get; set; }
public SoundEffect MySound { get; set; }
public Rectangle rect;
public Button(SoundEffect mySound, Texture2D texture)
{
MySound = mySound;
Texture = texture;
}
public void LoadContent(ContentManager Content)
{
}
public void Update(GameTime gameTime)
{
}
public void Draw(SpriteBatch spriteBatch, Vector2 location)
{
Rectangle rect = new Rectangle((int)0, (int)0, Texture.Width, Texture.Height);
spriteBatch.Draw(Texture, location, Color.White);
}
}
What I'm trying to do is have one base button class, so if you want to add a new button with a sound, you just write: button = new Button(//sound effect, //texture);
But I can't get it to work. Any help would be appreciated.
The way you are handling your buttons position is incorrect, and I am not sure how it compiles. In your draw method you define a local variable rect that already exists. And even if it did, you are not taking into account the actual position of the button.
I think you could also move your button update logic into the class, so I will propose what I think you need to do.
public class Button
{
//Properties
private Texture2D Texture { get; set; }
private SoundEffect Sound { get; set; }
private Rectangle Rectangle { get; set; }
public Button(SoundEffect sound, Texture2D texture, Rectangle position)
{
Sound = sound;
Texture = texture;
Rectangle = position;
}
public void Update(GameTime gameTime, MouseState mouseState)
{
//If mouse is down and the rectangle contains the mouse point (Better for points than Intersect())
if (mouseState.LeftButton == ButtonState.Pressed && Rectangle.Contains(new Point(mouseState.X,mouseState.Y))
{
Sound.Play()
}
}
public void Draw(SpriteBatch spriteBatch)
{
spriteBatch.Draw(Texture, rectangle, Color.White);
}
}
You can then just do button.Update(Mouse.GetState()) (Or use another MouseState if you have one already)
It appears there was some confusion with the drawing position, vs the actual position of the button (in the draw method)
You need to make sure the button is aware of its position on the screen, as well as it's width and height.
button = new Button(dundundun, Btexture, new Rectangle(300, 300, Btexture.Width, Btexture.Height);
That will make the button at 300,500 and be the default size for the texture, now your sound button is done done done :)
I would also recommend learning and using event handlers, so you can add events for the button such as button.Click += //Do something easily

Categories