Reputation: 25
I'm making a 2D spaceshooter in my spare time to get some practice in c# before University starts. However, I have run into an issue that I can't seem to figure out. For the menu I followed a Youtube tutorial on how to make the menu but the button is not getting displayed. I have spent the last few days trying to figure it out but with no luck therefore, any help would be greatly appreciated. I apologize if the code is confusing I am still learning. When I run the game I get no errors I just get a blank blue screen with no button displayed.
Button Class
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Game1
{
class Button : Game1
{
Texture2D texture;
Vector2 position;
Rectangle rectangle;
Color colour = new Color(255, 255, 255, 255);
public Vector2 size;
bool down;
public bool isClicked;
public Button(Texture2D newText, GraphicsDevice graphics)
{
texture = newText;
size = new Vector2(graphics.Viewport.Width / 20, graphics.Viewport.Height / 10);
}
public void Update(MouseState mouse)
{
rectangle = new Rectangle((int)position.X, (int)position.Y,
(int)size.X, (int)size.Y);
Rectangle mouseRect = new Rectangle(mouse.X, mouse.Y, 1, 1);
if (mouseRect.Intersects(rectangle))
{
if (colour.A == 255) // if only one thing is in an if statement curly braces aren't needed
down = false;
if (colour.A == 0)
down = true;
if (down) colour.A += 3;
else colour.A -= 3;
if (mouse.LeftButton == ButtonState.Pressed)
isClicked = true;
}
// Once the mouse cursor has moved away from the button, the opacity will begin to increase.
else if (colour.A < 255)
{
colour.A += 3;
isClicked = false;
}
}
public void setPosition(Vector2 newPosition)
{
position = newPosition;
}
public void Draw(SpriteBatch spriteBatch)
{
spriteBatch.Draw(texture, rectangle, colour);
}
}`
}
relevant Game1.CS code:
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 System;
using System.Collections.Generic;
namespace Game1
{
/// <summary>
/// This is the main type for your game.
/// </summary>
public class Game1 : Game
{
GraphicsDeviceManager graphics;
SpriteBatch spriteBatch;
public Texture2D mTexture;
public Vector2 mPosition = new Vector2(400, 0);
Sprite enemyShip;
public Vector2 Position;
player mPlayer;
player p;
MouseState previousMouseState;
public List<enemies> enemies = new List<enemies>();
Random random = new Random();
float spawn = 0; // delcaring the spawn variable as 0;
SpriteFont livesFont;
public float lives = 5;
SpriteFont scoreFont;
SpriteFont ammoFont;
public int ammoCount = 30;
Button playButton;
KeyboardState previousKeyboardState;
enum GameState
{
startMenu,
Loading,
Playing,
Paused,
}
// GameState gameState = new GameState();
GameState gameState = GameState.startMenu; // this is the state that it will load first.
enum MusicState
{
musicPause,
musicPlay,
}
MusicState musicState = MusicState.musicPlay;
public Game1()
{
graphics = new GraphicsDeviceManager(this);
Content.RootDirectory = "Content";
}
protected override void Initialize()
{
previousKeyboardState = Keyboard.GetState();
mPlayer = new player();
enemyShip = new Sprite();
p = new player();
IsMouseVisible = true; // this allows the mouse to be visible within the game.
base.Initialize();
}
protected override void LoadContent()
{
spriteBatch = new SpriteBatch(GraphicsDevice);
playButton = new Button(Content.Load<Texture2D>("startButton"), graphics.GraphicsDevice);
playButton.setPosition(new Vector2(300, 200)); // setting position of the playButton.
mPlayer.LoadContent(this.Content);
mPlayer.bulletText = Content.Load<Texture2D>("bullet1"); // can load the texture this way, similiar to the line of code above.
mPlayer.LoadContent(this.Content, "spaceship");
enemyShip.LoadContent(this.Content, "enemyShip");
// loading SpriteFonts
scoreFont = Content.Load<SpriteFont>("NewSpriteFont");
livesFont = Content.Load<SpriteFont>("NewSpriteFont");
ammoFont = Content.Load<SpriteFont>("NewSpriteFont");
}
protected override void UnloadContent()
{
}
/// <param name="theGameTime">Provides a snapshot of timing values.</param>
protected override void Update(GameTime theGameTime)
{
// keyboard and mouseStates
KeyboardState currentKeyboardState = Keyboard.GetState();
MouseState mouseState = Mouse.GetState();
previousMouseState = mouseState;
// switch case for gameStates
switch (gameState)
{
case GameState.startMenu:
if (playButton.isClicked == true)
{
gameState = GameState.Playing;
playButton.Update(mouseState);
}
break;
case GameState.Playing:
break;
}
// Pausing and playing the game and music
if (gameState == GameState.Playing)
{
if (currentKeyboardState.IsKeyDown(Keys.P) && previousKeyboardState.IsKeyUp(Keys.P))
{
gameState = GameState.Paused;
}
}
else if (gameState == GameState.Paused)
{
if (currentKeyboardState.IsKeyDown(Keys.P) && previousKeyboardState.IsKeyUp(Keys.P))
{
gameState = GameState.Playing;
}
}
if (musicState == MusicState.musicPlay)
{
if (currentKeyboardState.IsKeyDown(Keys.M) && previousKeyboardState.IsKeyUp(Keys.M))
{
MediaPlayer.Pause();
musicState = MusicState.musicPause;
}
}
else if (musicState == MusicState.musicPause)
{
if (currentKeyboardState.IsKeyDown(Keys.M)&& previousKeyboardState.IsKeyUp(Keys.M))
{
MediaPlayer.Play(song);
musicState = MusicState.musicPlay;
}
}
previousKeyboardState = currentKeyboardState;
colliitionDetection();
respawn();
loadEnemies(); // loads enemies through update.
spawn += (float)theGameTime.ElapsedGameTime.TotalSeconds;
foreach (enemies enemy in enemies) // foreach loop
enemy.Update(graphics.GraphicsDevice); // updating the enemy.
foreach (enemies enemy in enemies)
{
for (int b = 0; b < p.mbullets.Count; b++)
{
if (enemy.boundingBoxEnemy.Intersects(p.mbullets[b].boundingBoxBullet))
{
Console.WriteLine("please fucking work");
enemy.isVisible = false;
}
}
}
Vector2 aDirection = new Vector2(-1, 0); //aDirection - as the sprites are moving to the left we are decreasing the X direction.
Vector2 aSpeed = new Vector2(100, 0);
mPlayer.Update(theGameTime); // updating the player through here.
}
public void colliitionDetection()
{
for (int i = 0; i < enemies.Count; i++)
{
if (mPlayer.boundingBox.Intersects(enemies[i].boundingBoxEnemy))
{
mPlayer.Position.X = mPlayer.Position2.X;
/* Basicallyy what is happening, if the player hits the enemy it will stpawn him at position2, this is beacuase the player will always start the game at the start position, it is a 'const' unchangeable, but by saying that
* 'mPlayer.Position.X = mPlayer.Position2.X;' you are saying stating new coordinates for the player to spawn too, basically simple as that can't make it easier to understand you understand? ... needs to be a vector 2 aswell to use the xy
* */
if (mPlayer.Position.X == mPlayer.Position2.X)
{
//p.playerHealth -
lives = lives - 1;
respawn();
}
}
}
}
protected override void Draw(GameTime theGameTime)
{
graphics.GraphicsDevice.Clear(Color.CornflowerBlue);
spriteBatch.Begin(); // sprite batch objects are what is used to draw the 2D images on the screen
// switch statement
// a switch statement that will draw sprites and fonts depending on the gameState
switch (gameState)
{
case GameState.startMenu: // the line below isn't being displayed on the screen...
playButton.Draw(this.spriteBatch); // SOMETHING WRONG WITH THIS.
// spriteBatch.Draw(Content.Load<Texture2D>("menuScreen"), new Rectangle (0,0 , 800, 600), Color.White);
break;
case GameState.Playing:
// spriteBatch.Draw(mTexture, mPosition, Color.White);
mBackground1.Draw(this.spriteBatch);
mBackground2.Draw(this.spriteBatch);
mBackground3.Draw(this.spriteBatch);
mBackground4.Draw(this.spriteBatch);
mBackground5.Draw(this.spriteBatch);
foreach (enemies enemy in enemies)
enemy.Draw(spriteBatch);
mPlayer.Draw(this.spriteBatch);
enemyShip.Draw(this.spriteBatch);
spriteBatch.DrawString(livesFont, lives.ToString(+lives + " lives remaining: "), new Vector2(600, 20), Color.Red);
// spriteBatch.DrawString(scoreFont, score.ToString("score " + score + " :"), new Vector2(100, 20), Color.Red);
spriteBatch.DrawString(ammoFont, ammoCount.ToString("ammo " + ammoCount + ":"), new Vector2(600, 100), Color.Green);
break;
case GameState.Loading:
break;
case GameState.Paused:
break;
}
spriteBatch.End(); // the end is used so once you've added everything you wanted to add to the screen the end will draw them all for you.
base.Draw(theGameTime);
}
}
I have taken out a bit of code that wasn't relevant to the issue at hand. If it would be easier for you fix the issue then let me know and I will post all the code for the game1 class.
Many thanks.
Upvotes: 1
Views: 96
Reputation: 484
While there are.. many rooms for improvements in this code (why does your button inherit from the Game1 class just as an example) I believe your problem is due to your button never initializing the rectangle property. You set your size in the constructor yet your rectangle never gets initialized/set until the update method gets called. Meaning until the button.Update method gets called your rectangle is the width and height of 0, 0.. Your button.Update method doesn't get called until the button is clicked. This is why the button isn't visible. So to solve your immediate problem initialize your rectangle in the constructor.
public Button(Texture2D newText, GraphicsDevice graphics)
{
texture = newText;
size = new Vector2(graphics.Viewport.Width / 20, graphics.Viewport.Height / 10);
rectangle = new Rectangle(0, 0, size.X, size.Y);
}
Upvotes: 2