I see to be running into a problem here. I know it's easier to show code samples so here you go.
This is my main game class
namespace WindowsGame4
{
public enum MoveDirection { Left, Right, Up, Down, None}
public enum GameState { MainMenu, LevelOne, PauseScreen }
public class Game1 : Microsoft.Xna.Framework.Game
{
GraphicsDeviceManager graphics;
SpriteBatch spriteBatch;
GameState gameState = GameState.LevelOne;
LevelOne levelOne = new LevelOne();
MainMenu mainMenu = new MainMenu();
public Game1()
{
graphics = new GraphicsDeviceManager(this);
Content.RootDirectory = "Content";
}
protected override void Initialize()
{
if(gameState == GameState.MainMenu)
{
this.IsMouseVisible = true;
mainMenu.Initialize(gameState);
}
if(gameState == GameState.LevelOne)
{
levelOne.Initialize();
}
base.Initialize();
}
protected override void LoadContent()
{
float viewportWidth = GraphicsDevice.Viewport.TitleSafeArea.Width;
float viewportHeight = GraphicsDevice.Viewport.TitleSafeArea.Height;
//pass in content manager, so we can load our textures and content from the class instead of from the main game code
if(gameState == GameState.MainMenu)
{
mainMenu.LoadContent(Content, viewportWidth, viewportHeight);
}
if(gameState == GameState.LevelOne)
{
levelOne.LoadContent(Content, viewportWidth, viewportHeight);
}
spriteBatch = new SpriteBatch(GraphicsDevice);
}
protected override void UnloadContent()
{
}
protected override void Update(GameTime gameTime)
{
if (gameState == GameState.MainMenu)
{
mainMenu.Update(gameTime);
gameState = mainMenu.ReturnGameState();
}
if (gameState == GameState.LevelOne)
{
levelOne.Update(gameTime);
}
base.Update(gameTime);
}
protected override void Draw(GameTime gameTime)
{
GraphicsDevice.Clear(Color.CornflowerBlue);
spriteBatch.Begin();
if (gameState == GameState.MainMenu)
{
mainMenu.Draw(spriteBatch);
}
if (gameState == GameState.LevelOne)
{
levelOne.Draw(spriteBatch);
}
spriteBatch.End();
base.Draw(gameTime);
}
}
}
My idea is, I can use the gamestate enum to switch between what I load for the player, like a menu or the main gameplay part. However I'm not sure if that is the right way to go about building a game in XNA. I'm VERY new to this, both xna and programming and structuring a program.
The problem I'm running in to so far is when I try this, it sas "object reference not set to an instance of an object." I'm not sure what that mean, as it is referring to right before I attempt to draw the stuff happening in my levelone class.
EDIT for Shiro, Here is the level one class
namespace WindowsGame4 { class LevelOne { GameState gameState;
Rizerd rizerd = new Rizerd();
Player player = new Player();
public void Initialize()
{
}
public void LoadContent(ContentManager Content, float viewportWidth, float viewportHeight)
{
Vector2 position = new Vector2(viewportWidth / 2, viewportHeight / 2);
Vector2 rizardPosition = new Vector2(viewportWidth / 3, viewportHeight / 3);
player.Initialize(Content.Load<Texture2D>("warriorspritesheet"), Content.Load<Texture2D>("hitbox"), Content.Load<Texture2D>("horizontalSwordHitbox"), Content.Load<Texture2D>("VerticalSwordHitbox"), position, 4, 4);
rizerd.Initialize(Content.Load<Texture2D>("rizerd"), Content.Load<Texture2D>("rizardBounding"), rizardPosition, 2, 2);
}
public void Update(GameTime gameTime)
{
rizerd.Update(gameTime);
player.Update(gameTime);
}
public void Draw(SpriteBatch spriteBatch)
{
player.Draw(spriteBatch);
rizerd.Draw(spriteBatch);
}
}
}
As well as the player class and the sprite class that is the base class for player
PLAYER CLASS namespace WindowsGame4 { class Player : Sprites { string name; int health; int mana; int score; int damage = 34;
MouseState mouseState;
MouseState previousMouseState;
bool IsAttacking = false;
int attackFrameTime = 250;
int mouseDelay = 350;
public bool mouseUsed = false;
int elapsedMouseTime;
Texture2D horizontalSword;
Texture2D verticalSword;
Vector2 swordHitBoxLocationDown;
Vector2 swordHitBoxLocationUp;
Vector2 swordHitBoxLocationRight;
Vector2 swordHitBoxLocationLeft;
public Rectangle swordDown;
public Rectangle swordUp;
public Rectangle swordRight;
public Rectangle swordLeft;
KeyboardState debugPress;
bool debug;
public bool playerCollide;
//using initialize to pull the texture and frame count info into the GetFrames animation interfaces
public void Initialize(Texture2D sprite, Texture2D boundingSprite, Texture2D horizontalSword, Texture2D verticalSword, Vector2 position, int frameRows, int frameColumns)
{
this.position = position;
frameTime = 170;
direction = MoveDirection.Down;
speed = 3.0f;
this.horizontalSword = horizontalSword;
this.verticalSword = verticalSword;
GetFrames(sprite, frameRows, frameColumns);
SetBoundingBox(boundingSprite, position, sprite);
SetSwordCollision();
}
public void Update(GameTime gameTime)
{
UpdateSwordCollision(gameTime);
MovementAnimation(gameTime);
//debug boolean switch
debugPress = Keyboard.GetState();
if(debugPress.IsKeyDown(Keys.F))
{
debug = true;
}
if(debugPress.IsKeyDown(Keys.G))
{
debug = false;
}
}
public void Draw(SpriteBatch spriteBatch)
{
DrawFrame(spriteBatch, position);
//debug, for checking hitbox location and activation
if(playerCollide == true)
{
spriteBatch.Draw(playerBoundingSprite, playerBoundingPosition, Color.White);
}
else
{
}
}
//calculates the swords hitboxes based on the texture passed in for them, as well of the original sprites bounding position
public void SetSwordCollision()
{
swordHitBoxLocationDown.Y = playerBoundingPosition.Y + playerBoundingSprite.Height - 2;
swordHitBoxLocationDown.X = playerBoundingPosition.X + ((playerBoundingSprite.Width / 2 - verticalSword.Width / 2) + 4);
swordDown = new Rectangle((int)swordHitBoxLocationDown.X, (int)swordHitBoxLocationDown.Y, verticalSword.Width, verticalSword.Height);
swordHitBoxLocationLeft.Y = playerBoundingPosition.Y + ((playerBoundingSprite.Height / 2) - 3);
swordHitBoxLocationLeft.X = playerBoundingPosition.X - horizontalSword.Width - 1;
swordLeft = new Rectangle((int)swordHitBoxLocationLeft.X, (int)swordHitBoxLocationLeft.Y, horizontalSword.Width, horizontalSword.Height);
swordHitBoxLocationUp.Y = playerBoundingPosition.Y - verticalSword.Height;
swordHitBoxLocationUp.X = playerBoundingPosition.X + (playerBoundingSprite.Width / 2 - verticalSword.Width / 2);
swordUp = new Rectangle((int)swordHitBoxLocationUp.X, (int)swordHitBoxLocationUp.Y, verticalSword.Width, verticalSword.Height);
swordHitBoxLocationRight.Y = playerBoundingPosition.Y + (playerBoundingSprite.Height / 2) - 3;
swordHitBoxLocationRight.X = playerBoundingPosition.X + playerBoundingSprite.Width;
swordRight = new Rectangle((int)swordHitBoxLocationRight.X, (int)swordHitBoxLocationRight.Y, horizontalSword.Width, horizontalSword.Height);
}
//updates the sword hitbox's position, the textures position as well, when the sprite moves
public void UpdateSwordCollision(GameTime gameTime)
{
if (direction == MoveDirection.Up && Idle == false)
{
swordHitBoxLocationDown.Y -= speed;
swordDown.Y -= (int)speed;
swordHitBoxLocationLeft.Y -= speed;
swordLeft.Y -= (int)speed;
swordHitBoxLocationRight.Y -= speed;
swordRight.Y -= (int)speed;
swordHitBoxLocationUp.Y -= speed;
swordUp.Y -= (int)speed;
}
if (direction == MoveDirection.Left && Idle == false)
{
swordHitBoxLocationDown.X -= speed;
swordDown.X -= (int)speed;
swordHitBoxLocationLeft.X -= speed;
swordLeft.X -= (int)speed;
swordHitBoxLocationRight.X -= speed;
swordRight.X -= (int)speed;
swordHitBoxLocationUp.X -= speed;
swordUp.X -= (int)speed;
}
if (direction == MoveDirection.Down && Idle == false)
{
swordHitBoxLocationDown.Y += speed;
swordDown.Y += (int)speed;
swordHitBoxLocationLeft.Y += speed;
swordLeft.Y += (int)speed;
swordHitBoxLocationRight.Y += speed;
swordRight.Y += (int)speed;
swordHitBoxLocationUp.Y += speed;
swordUp.Y += (int)speed;
}
if (direction == MoveDirection.Right && Idle == false)
{
swordHitBoxLocationDown.X += speed;
swordDown.X += (int)speed;
swordHitBoxLocationLeft.X += speed;
swordLeft.X += (int)speed;
swordHitBoxLocationRight.X += speed;
swordRight.X += (int)speed;
swordHitBoxLocationUp.X += speed;
swordUp.X += (int)speed;
}
}
public void MouseInput(GameTime gameTime)
{
previousMouseState = mouseState;
mouseState = Mouse.GetState();
//elapsed mout time and mousedelay allow us to use gametime to limit button mashing of the attack button
elapsedMouseTime += (int)gameTime.ElapsedGameTime.Milliseconds;
//using a previous mouse state to register buttonstate release and current mousestate to register buttonstate pressed at the same time
//prevents the system from registering the button being held down
if (mouseUsed == false)
{
if (mouseState.LeftButton == ButtonState.Pressed && previousMouseState.LeftButton == ButtonState.Released)
{
//elapsed time here is used to time out the attack frame, when we press the mouse button, the frame is timed out, when it is timed out, our speed and frame goes back to normal--
//--using previous frame. also our isattacking goes to false at the end of the time.
elapsedTime = 0;
elapsedMouseTime = 0;
IsAttacking = true;
speed = 0;
mouseUsed = true;
}
}
if(mouseUsed == true)
{
Idle = true;
}
//only call moveobject if the mouse cooldown completes
else if(mouseUsed == false)
{
MoveObject();
}
if(elapsedMouseTime > mouseDelay)
{
mouseUsed = false;
}
//if the attack frame is done, then set the speed to normal and go back to the frame you were at before the attack frame.
//also set isattacking to false
if (elapsedTime > attackFrameTime)
{
currentFrame = previousFrame;
speed = 3.0f;
IsAttacking = false;
}
//idle frames, these will be defaulted to based on MoveDirection enum and if the player is idle via no keyboard input
if (direction == MoveDirection.Left && Idle == true)
{
if (IsAttacking == true)
{
currentFrame = 8;
}
else if (IsAttacking == false)
{
currentFrame = 0;
previousFrame = currentFrame;
}
}
}
public void MovementAnimation(GameTime gameTime)
{
MouseInput(gameTime);
//using elapsed time to measure how long a frame has been on screen
elapsedTime += (int)gameTime.ElapsedGameTime.TotalMilliseconds;
if (direction == MoveDirection.Right && Idle == true)
{
if(IsAttacking == true)
{
currentFrame = 9;
}
else if(IsAttacking == false)
{
currentFrame = 3;
previousFrame = currentFrame;
}
}
if (direction == MoveDirection.Up && Idle == true)
{
if(IsAttacking == true)
{
currentFrame = 11;
}
else if (IsAttacking == false)
{
currentFrame = 7;
previousFrame = currentFrame;
}
}
if (direction == MoveDirection.Down && Idle == true)
{
if(IsAttacking == true)
{
currentFrame = 10;
}
else if (IsAttacking == false)
{
currentFrame = 5;
previousFrame = currentFrame;
}
}
//movement frames paired with our MoveDirection enum
//first we check if the player is not idle
if (direction == MoveDirection.Down && Idle == false)
{
//then we set the frame based on what our direction is
if (IsAttacking == true)
{
currentFrame = 10;
}
else if (IsAttacking == false)
{
currentFrame = 5;
previousFrame = currentFrame;
}
//as long as the proper time has passed, we will go to the next frame
if (elapsedTime > frameTime)
{
currentFrame = 4;
previousFrame = currentFrame;
//we wait for the proper amount of time to pass again, then we set the elapsed time to zero
//then as long as we are receiving false for idle, the frame will go back to 5, and repeat
if (elapsedTime > frameTime * 2)
{
elapsedTime = 0;
}
}
}
if (direction == MoveDirection.Left && Idle == false)
{
if (IsAttacking == true)
{
currentFrame = 8;
}
else if (IsAttacking == false)
{
currentFrame = 0;
previousFrame = currentFrame;
}
if (elapsedTime > frameTime)
{
currentFrame = 1;
previousFrame = currentFrame;
if (elapsedTime > frameTime * 2)
{
elapsedTime = 0;
}
}
}
if (direction == MoveDirection.Right && Idle == false)
{
if (IsAttacking == true)
{
currentFrame = 9;
}
else if (IsAttacking == false)
{
currentFrame = 3;
previousFrame = currentFrame;
}
if (elapsedTime > frameTime)
{
currentFrame = 2;
previousFrame = currentFrame;
if (elapsedTime > frameTime * 2)
{
elapsedTime = 0;
}
}
}
if (direction == MoveDirection.Up && Idle == false)
{
if (IsAttacking == true)
{
currentFrame = 11;
}
else if (IsAttacking == false)
{
currentFrame = 7;
previousFrame = currentFrame;
}
if (elapsedTime > frameTime)
{
currentFrame = 6;
previousFrame = currentFrame;
if (elapsedTime > frameTime * 2)
{
elapsedTime = 0;
}
}
}
}
}
}
SPRITE CLASS
class Sprites : IMovement, IAnimation
{
protected Texture2D sprite;
protected bool Idle = true;
protected Vector2 position;
protected float speed;
protected MoveDirection direction;
protected KeyboardState currentButtonPress;
protected KeyboardState previousButtonPress;
protected int rows;
protected int columns;
protected int currentFrame;
protected int previousFrame;
protected int totalFrames;
protected int elapsedTime;
protected int frameTime;
protected Texture2D playerBoundingSprite;
public Rectangle playerBoundingRectangle;
protected Vector2 playerBoundingPosition;
//calculates sprites bounding position and size based on the texture atlas passed in and the position of the sprite itself
public void SetBoundingBox(Texture2D boundingSprite, Vector2 position, Texture2D atlas)
{
playerBoundingSprite = boundingSprite;
playerBoundingPosition.Y = position.Y + ((atlas.Height / (columns * 2)) - (boundingSprite.Height / 2));
playerBoundingPosition.X = position.X + ((atlas.Width / (rows * 2)) - (boundingSprite.Width / 2));
playerBoundingRectangle = new Rectangle((int)playerBoundingPosition.X, (int)playerBoundingPosition.Y, boundingSprite.Width, boundingSprite.Height);
}
//updates the sprites position and the direction of our movedirection enum
public void MoveObject()
{
previousButtonPress = currentButtonPress;
currentButtonPress = Keyboard.GetState();
if(currentButtonPress.IsKeyDown(Keys.W))
{
Idle = false;
direction = MoveDirection.Up;
position.Y -= speed;
playerBoundingPosition.Y -= speed;
playerBoundingRectangle.Y -= (int)speed;
}
else if(currentButtonPress.IsKeyDown(Keys.A))
{
Idle = false;
direction = MoveDirection.Left;
position.X -= speed;
playerBoundingPosition.X -= speed;
playerBoundingRectangle.X -= (int)speed;
}
else if(currentButtonPress.IsKeyDown(Keys.S))
{
Idle = false;
direction = MoveDirection.Down;
position.Y += speed;
playerBoundingPosition.Y += speed;
playerBoundingRectangle.Y += (int)speed;
}
else if(currentButtonPress.IsKeyDown(Keys.D))
{
Idle = false;
direction = MoveDirection.Right;
position.X += speed;
playerBoundingPosition.X += speed;
playerBoundingRectangle.X += (int)speed;
}
else
{
Idle = true;
}
}
public void GetFrames(Texture2D spriteSheet, int rows, int columns)
{
//when i load content for this player, Ill use the constructor parameters from the player class and pass them into the parameters for this method.
sprite = spriteSheet;
this.rows = rows;
this.columns = columns;
currentFrame = 0;
totalFrames = this.rows * this.columns;
}
public void DrawFrame(SpriteBatch spriteBatch, Vector2 position)
{
//get the width and height of the current frame
int width = sprite.Width / columns;
int height = sprite.Height / rows;
//calculates the current row we are on based on what frame we are on
//calculates the current column we are on based on what frame we are on
//for currentRow, the float it return will determine what row we are on
//for current column, the remainder will determine which column we are on
int currentRow = (int)((float)currentFrame / (float)columns);
int currentColumn = currentFrame % columns;
Rectangle sourceRectangle;
Rectangle destinationRectangle;
sourceRectangle = new Rectangle(width * currentColumn, height * currentRow, width, height);
destinationRectangle = new Rectangle((int)position.X, (int)position.Y, width, height);
spriteBatch.Draw(sprite, destinationRectangle, sourceRectangle, Color.White);
}
}
}
LoadContent()
is being called once per game, solevelOne.LoadContent(...)
is never being called, because the logical conditionif(gameState == GameState.LevelOne)
is not true at the start of the game \$\endgroup\$