I am getting an error message in this line:
player = new Player(this.Content.Load<Texture2D>("Player"),
actor.position,
this.spriteBatch,
enemyManager);
which tells me the actor object is null. How can I overcome this situation?
The exact error is:
Field Shmup.MyGame.actor is never assigned to, and will always have its default value null.
Here is my code:
class MyGame // [edit:] added based on below constructor
{
GraphicsDeviceManager graphics;
SpriteBatch spriteBatch;
Player player;
EnemyManager enemyManager;
Actor actor;
public MyGame()
{
graphics = new GraphicsDeviceManager(this);
IsMouseVisible = true;
Content.RootDirectory = "Content";
}
protected override void Initialize()
{
// TODO: Add your initialization logic here
base.Initialize();
}
protected override void LoadContent()
{
// Create a new SpriteBatch, which can be used to draw textures.
spriteBatch = new SpriteBatch(GraphicsDevice);
startTheGame();
}
protected override void UnloadContent()
{
// TODO: Unload any non ContentManager content here
}
protected override void Update(GameTime gameTime)
{
// Allows the game to exit
if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed)
{
this.Exit();
}
this.player.Update(gameTime);
this.enemyManager.Update(gameTime);
base.Update(gameTime);
}
protected override void Draw(GameTime gameTime)
{
GraphicsDevice.Clear(Color.Maroon);
this.spriteBatch.Begin();
this.player.Draw(gameTime);
this.enemyManager.Draw(gameTime);
this.spriteBatch.End();
base.Draw(gameTime);
}
void startTheGame()
{
enemyManager = new EnemyManager(this.Content.Load<Texture2D>("Enemy"), new Vector2(16), this.spriteBatch);
player = new Player(this.Content.Load<Texture2D>("Player"),actor.position, this.spriteBatch, enemyManager);
enemyManager.StartTheGame(10);
}
}
public class Actor
{
public Texture2D texture;
public Vector2 origin;
public SpriteBatch spriteBatch;
public Vector2 position;
public Rectangle boundingRectangle;
public Vector2 Position
{
get { return position; }
set
{
position = value;
boundingRectangle = new Rectangle((Int32)(position.X - origin.X), (Int32)(position.Y - origin.Y), texture.Width, texture.Height);
}
}
public Rectangle BoundingRectangle
{
get { return boundingRectangle; }
}
public Actor(Texture2D texture, Vector2 origin, SpriteBatch spriteBatch, Vector2 initialPosition)
{
this.texture = texture;
this.origin = origin;
this.spriteBatch = spriteBatch;
this.position = initialPosition;
boundingRectangle = new Rectangle((Int32)(initialPosition.X - origin.X), (Int32)(initialPosition.Y - origin.Y), texture.Width, texture.Height);
}
public virtual void Update(GameTime gameTime)
{ }
public virtual void Draw(GameTime gameTime)
{
this.spriteBatch.Draw(texture, position - origin, Color.White);
}
}
Like error says, you need to create an instance of Actor class.
In game constructor or in startTheGame Method(before creating an instance of Player class) you should create an instance of Actor class, something like :
this.actor = new Actor(variables...);
Related
So I have a code where the sprite spawn outside the window and I want it to move on a specific straight line depending on where it spawn say if the sprite spawn at the top it goes at the bottom and vise versa if the sprite then spawn to the left it will go right and vise versa.
Game1.cs code:
public class Game1 : Game
{
GraphicsDeviceManager graphics;
SpriteBatch spriteBatch;
Player player;
List<Enemy> enemies = new List<Enemy>();
public Vector2 ecords
{
get { return ecords; }
set { ecords = value; }
}
public Game1()
{
graphics = new GraphicsDeviceManager(this);
Content.RootDirectory = "Content";
}
protected override void Initialize()
{
base.Initialize();
}
protected override void LoadContent()
{
spriteBatch = new SpriteBatch(GraphicsDevice);
//player
Texture2D playertexture = Content.Load<Texture2D>("Player");
player = new Player(new Vector2(350, 175), playertexture);
//enemy
Texture2D enemytexture = Content.Load<Texture2D>("Enemy");
Random random = new Random();
var width = GraphicsDevice.Viewport.Width;
var height = GraphicsDevice.Viewport.Height;
for (int i = 0; i < 20; i++)
{
enemies.Add(new Enemy(new Vector2(random.Next(width, width + 100), random.Next(0, height)), enemytexture));
enemies.Add(new Enemy(new Vector2(random.Next(0 - 100, 0), random.Next(0, height)), enemytexture));
enemies.Add(new Enemy(new Vector2(random.Next(0, width), random.Next(-100, 0)), enemytexture));
enemies.Add(new Enemy(new Vector2(random.Next(0, width), random.Next(height, height + 100)), enemytexture));
}
}
protected override void UnloadContent()
{
}
protected override void Update(GameTime gameTime)
{
if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed || Keyboard.GetState().IsKeyDown(Keys.Escape))
Exit();
foreach (Enemy enemy in enemies)
{
enemy.Update(gameTime);
}
player.Update(gameTime);
base.Update(gameTime);
}
protected override void Draw(GameTime gameTime)
{
GraphicsDevice.Clear(Color.CornflowerBlue);
spriteBatch.Begin();
foreach (Enemy enemy in enemies)
{
enemy.Draw(spriteBatch);
}
player.Draw(spriteBatch);
spriteBatch.End();
base.Draw(gameTime);
}
}
Enemy.cs
class Enemy
{
Texture2D enemytexture;
Vector2 enemyposition;
public Enemy(Vector2 enemyposition, Texture2D enemytexture)
{
this.enemyposition = enemyposition;
this.enemytexture = enemytexture;
}
public void Update(GameTime gameTime)
{
}
public void Draw(SpriteBatch spriteBatch)
{
spriteBatch.Draw(enemytexture, enemyposition, Color.White);
}
}
One option would be to add a velocity (or you can name it movement/direction) to Enemy, passed to the constructor in a parameter just like your existing enemyposition. Then update the current position by adding the velocity in the Update method of Enemy:
public void Update(GameTime gameTime)
{
this.enemyposition += this.velocity;
}
You can use unit vectors (optionally multiplied by speed) for the velocity value:
var (left, right) = (-Vector2.UnitX, Vector2.UnitX);
var (up, down) = (-Vector2.UnitY, Vector2.UnitY);
float enemySpeed = 5.0f;
enemies.Add(new Enemy(
new Vector2(random.Next(width, width + 100), random.Next(0, height)),
enemytexture, velocity: left * enemySpeed));
// etc.
What am I doing wrong in this class? I'm using monogame and C# but my object won't render in the program.
class Player : Game
{
Texture2D PlayerSprite;
Vector2 PlayerPosition;
public Player()
{
Content.RootDirectory = "Content";
PlayerSprite = Content.Load<Texture2D>("spr_Player");
PlayerPosition = Vector2.Zero;
}
public void Update()
{
}
public void Draw(SpriteBatch SpriteBatch)
{
SpriteBatch.Begin();
SpriteBatch.Draw(PlayerSprite,PlayerPosition, new Rectangle(0, 0, 32,32), Color.White);
SpriteBatch.End();
}
}
The Load, Update, and Draw methods belong to the inherited Game class and are overrided by it.
You too need to start your SpriteBacth object.
GraphicsDevice object has exist in Game main class.
Try this:
class Player : Game
{
Texture2D PlayerSprite;
Vector2 PlayerPosition;
SpriteBatch spriteBatch;
public Player()
{
Content.RootDirectory = "Content";
PlayerSprite = Content.Load<Texture2D>("spr_Player");
PlayerPosition = Vector2.Zero;
}
protected override void LoadContent()
{
spriteBatch = new SpriteBatch(GraphicsDevice);
}
protected override void Update(GameTime gameTime)
{
}
protected override void Draw(GameTime gameTime)
{
spriteBatch.Begin();
spriteBatch.Draw(PlayerSprite,PlayerPosition, new Rectangle(0, 0, 32,32), Color.White);
spriteBatch.End();
}
}
I am actually a new student in XNA, finding this library very interesting, but I still lack some knowledge to go further as I felt on a issue I can't fix on my own :(
The spriteBatch.Draw() method says my texture is null, however I have loaded it in a Resources.cs class and passed the texture in MainMenu.cs, so I don't really know where the problem resides, if anybody could help me about that I would be very thankful !
Resources.cs
class Resources
{
public static Texture2D pixel;
public static Texture2D startButton, loadButton, quitButton;
public static SpriteFont consoleFont;
public static void LoadContent(ContentManager Content)
{
pixel = Content.Load<Texture2D>("Pixel");
consoleFont = Content.Load<SpriteFont>("Console");
// UI Ressources :
startButton = Content.Load<Texture2D>("UI/StartButton");
loadButton = Content.Load<Texture2D>("UI/LoadButton");
quitButton = Content.Load<Texture2D>("UI/QuitButton");
}
}
MainMenu.cs
class MainMenu
{
// Fields
List<Button> buttons = new List<Button>();
// Constructors
public MainMenu()
{
this.buttons.Add(new Button(new Vector2(480, 132), 256, 48, Resources.startButton));
this.buttons.Add(new Button(new Vector2(480, 212), 256, 48, Resources.loadButton));
this.buttons.Add(new Button(new Vector2(480, 292), 256, 48, Resources.quitButton));
}
// Methods
// Update
public void Update()
{
}
// Draw
public void Draw(SpriteBatch spriteBatch)
{
foreach (Button button in buttons)
{
button.Draw(spriteBatch);
}
}
}
Button.cs
class Button : UIElement
{
int width, height;
Texture2D texture;
public Button()
{
}
public Button(Vector2 b_position, int b_width, int b_height, Texture2D b_texture)
{
this.position = b_position;
this.width = b_width;
this.height = b_height;
this.texture = b_texture;
}
public void Update()
{
}
public void Draw(SpriteBatch spriteBatch)
{
spriteBatch.Draw(texture, position, Color.White);
}
}
Simple realy
You just have to know the calling order of functions of Game1. First, Game1 constructor is called. That's where you've put mainMenu = new MainMenu();. After that go Initialize, Load and so on. You have to move mainMenu = new MainMenu(); from Game1 constructor to Load function, after the Resources.LoadContent(Content);, so the resources can be loaded before they are used in MainMenu. Your Game1.cs code should look like this:
public class GameMain : Microsoft.Xna.Framework.Game
{
GraphicsDeviceManager graphics;
SpriteBatch spriteBatch;
MainMenu mainMenu;
public GameMain()
{
graphics = new GraphicsDeviceManager(this);
Content.RootDirectory = "Content";
this.IsMouseVisible = true;
}
protected override void Initialize()
{
// TODO: Add your initialization logic here
base.Initialize();
}
protected override void LoadContent()
{
// Create a new SpriteBatch, which can be used to draw textures.
spriteBatch = new SpriteBatch(GraphicsDevice);
// TODO: use this.Content to load your game content here
Resources.LoadContent(Content);
mainMenu = new MainMenu();
}
protected override void UnloadContent()
{
// TODO: Unload any non ContentManager content here
}
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
base.Update(gameTime);
}
protected override void Draw(GameTime gameTime)
{
GraphicsDevice.Clear(Color.CornflowerBlue);
// TODO: Add your drawing code here
spriteBatch.Begin();
mainMenu.Draw(spriteBatch);
spriteBatch.End();
base.Draw(gameTime);
}
}
While I do not see your Game class my first assumption is that your never calling the public static void LoadContent(ContentManager Content) method inside your Resources class. Since this function is instantiating your textures perhaps this isn't being called.
Thank you for your reply !
Indeed I forgot to include the Game class, is this the right way to call the resources ?
public class GameMain : Microsoft.Xna.Framework.Game
{
GraphicsDeviceManager graphics;
SpriteBatch spriteBatch;
MainMenu mainMenu;
public GameMain()
{
graphics = new GraphicsDeviceManager(this);
Content.RootDirectory = "Content";
this.IsMouseVisible = true;
mainMenu = new MainMenu();
}
protected override void Initialize()
{
// TODO: Add your initialization logic here
base.Initialize();
}
protected override void LoadContent()
{
// Create a new SpriteBatch, which can be used to draw textures.
spriteBatch = new SpriteBatch(GraphicsDevice);
// TODO: use this.Content to load your game content here
Resources.LoadContent(Content);
}
protected override void UnloadContent()
{
// TODO: Unload any non ContentManager content here
}
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
base.Update(gameTime);
}
protected override void Draw(GameTime gameTime)
{
GraphicsDevice.Clear(Color.CornflowerBlue);
// TODO: Add your drawing code here
spriteBatch.Begin();
mainMenu.Draw(spriteBatch);
spriteBatch.End();
base.Draw(gameTime);
}
}
I am getting an error when I try to get the mouse position.
This is my player class. I am trying to make the player sprite move by mouse cursor
class Player : Actor
{
public MouseState mState;
EnemyManager enemyManager;
public Player(Texture2D texture, Vector2 origin, SpriteBatch spriteBatch, EnemyManager enemyManager)
: base(texture, origin, spriteBatch, new Vector2(250.0f, 516.0f))
{
this.enemyManager = enemyManager;
}
public override void Update(GameTime gameTime)
{
//KeyboardState keyboardState = Keyboard.GetState();
//if (keyboardState.IsKeyDown(Keys.Left))
//{
// if (this.Position.X > 32.0f)
// {
// this.Position -= 10.0f * Vector2.UnitX;
// }
//}
//if (keyboardState.IsKeyDown(Keys.Right))
//{
// if (this.Position.X < 748.0f)
// {
// this.Position += 10.0f * Vector2.UnitX;
// }
//}
MouseState mState = Mouse.GetState();
this.Position = new Vector2(mState.x, mState.y);
// Collisions...
foreach (Enemy e in this.enemyManager.Enemies)
{
if (this.BoundingRectangle.Intersects(e.BoundingRectangle))
{
e.OnHit();
break;
}
}
base.Update(gameTime);
}
}
and this is my Actor class which has position variables
namespace Shmup
{
public class Actor
{
public Texture2D texture;
public Vector2 origin;
public SpriteBatch spriteBatch;
public Vector2 position;
public Rectangle boundingRectangle;
public Vector2 Position
{
get { return position; }
set { position = value; }
}
public Rectangle BoundingRectangle
{
get { return boundingRectangle; }
}
public Actor(Texture2D texture, Vector2 origin, SpriteBatch spriteBatch, Vector2 initialPosition)
{
this.texture = texture;
this.origin = origin;
this.spriteBatch = spriteBatch;
this.position = initialPosition;
boundingRectangle = new Rectangle((Int32)(initialPosition.X - origin.X), (Int32)(initialPosition.Y - origin.Y), texture.Width, texture.Height);
}
public virtual void Update(GameTime gameTime)
{
}
public virtual void Draw(GameTime gameTime)
{
this.spriteBatch.Draw(texture, position - origin, Color.White);
}
}
}
my main class
public class MyGame : Microsoft.Xna.Framework.Game
{
GraphicsDeviceManager graphics;
SpriteBatch spriteBatch;
Player player;
EnemyManager enemyManager;
Actor actor;
public MyGame()
{
graphics = new GraphicsDeviceManager(this);
IsMouseVisible = true;
Content.RootDirectory = "Content";
}
protected override void Initialize()
{
// TODO: Add your initialization logic here
Actor actor = new Actor();
base.Initialize();
}
protected override void LoadContent()
{
// Create a new SpriteBatch, which can be used to draw textures.
spriteBatch = new SpriteBatch(GraphicsDevice);
startTheGame();
}
protected override void UnloadContent()
{
// TODO: Unload any non ContentManager content here
}
protected override void Update(GameTime gameTime)
{
// Allows the game to exit
if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed)
{
this.Exit();
}
this.player.Update(gameTime);
this.enemyManager.Update(gameTime);
base.Update(gameTime);
}
protected override void Draw(GameTime gameTime)
{
GraphicsDevice.Clear(Color.Maroon);
this.spriteBatch.Begin();
this.player.Draw(gameTime);
this.enemyManager.Draw(gameTime);
this.spriteBatch.End();
base.Draw(gameTime);
}
void startTheGame()
{
enemyManager = new EnemyManager(this.Content.Load<Texture2D>("Enemy"), new Vector2(16), this.spriteBatch);
player = new Player(this.Content.Load<Texture2D>("Player"),actor.position, this.spriteBatch, enemyManager);
enemyManager.StartTheGame(10);
}
}
This line is the problem I think:
this.Position = new Vector2(mState.x, mState.y);
x and y are not publicly exposed on MouseState. You need to capitalize them (C# is case-sensitive). Use this instead:
this.Position = new Vector2(mState.X, mState.Y);
"making these changes gives me a different error Object reference not set to an instance of an object in the line player = new Player(this.Content.Load("Player"),actor.position, this.spriteBatch, enemyManager); on my main class it says Error 'Shmup.Actor' does not contain a constructor that takes 0 arguments –"
The constructor for Actor requires - Texture2D texture, Vector2 origin, SpriteBatch spriteBatch, Vector2 initialPosition .
So you would need to change the "Actor actor = new Actor();" into LoadContent() or a separate method after you have supplied all the information required to declare a new Actor.
It should read something along these lines(replace each argument with the proper item from your game class):
Actor actor = new Actor( texture, origin, spriteBatch, initialPosition);
If you do that it will fix the error, If you don't you will continue to get the error unless you define a constructor in Actor that takes 0 arguments. Hope this helps somewhat.
Alright, so this is the code:
Game1.cs Class:
public class Game1 : Microsoft.Xna.Framework.Game
{
KeyboardState keyboard;
GraphicsDeviceManager graphics;
SpriteBatch spriteBatch;
Player MyPlayer;
Texture2D Ball;
public Game1()
{
graphics = new GraphicsDeviceManager(this);
Content.RootDirectory = "Content";
}
protected override void Initialize()
{
IsMouseVisible = true;
graphics.IsFullScreen = true;
base.Initialize();
}
protected override void LoadContent()
{
spriteBatch = new SpriteBatch(GraphicsDevice);
Ball = Content.Load<Texture2D>("Images/Ball");
MyPlayer = new Player(new Vector2(700, 700), Ball);
}
protected override void UnloadContent()
{
}
protected override void Update(GameTime gameTime)
{
keyboard = Keyboard.GetState();
if (keyboard.IsKeyDown(Keys.Escape))
this.Exit();
MyPlayer.Update(gameTime);
base.Update(gameTime);
}
protected override void Draw(GameTime gameTime)
{
GraphicsDevice.Clear(Color.CornflowerBlue);
spriteBatch.Begin();
MyPlayer.Draw(spriteBatch);
spriteBatch.End();
base.Draw(gameTime);
}
}
Game object class:
abstract class GameObject
{
protected Vector2 position;
protected Texture2D texture;
public GameObject(Vector2 Position, Texture2D Texture)
{
position = Vector2.Zero;
this.texture = Texture;
}
protected Vector2 Position { set; get; }
protected Texture2D Texture { set; get; }
protected float X
{
set { position.X = value; }
get { return position.X; }
}
protected float Y
{
set
{
position.Y = value;
}
get
{
return position.Y;
}
}
public int GraphicsWidth { set; get; }
public int GraphicsHeight { set; get; }
}
Player class:
class Player : GameObject
{
KeyboardState keyboard;
bool IsJump = false;
int SpeedX = 5;
int SpeedY = 5;
public Player(Vector2 position, Texture2D tex):base(position,tex)
{
}
public int Height
{
get { return this.texture.Height; }
}
public int Width
{
get { return this.texture.Width; }
}
public void intialize()
{
}
public void Draw(SpriteBatch spriteBatch)
{
spriteBatch.Draw(texture, Position, Color.White);
}
public void Update(GameTime gameTime)
{
keyboard = Keyboard.GetState();
if (keyboard.IsKeyDown(Keys.D))
{
X += SpeedX;
}
else if (keyboard.IsKeyDown(Keys.A))
{
X-= SpeedX;
}
if (X > GraphicsWidth)
{
X = GraphicsWidth;
}
}
}
When I'm debugging it, My ball texture is in (0,0) (TOP LEFT). Instead of (700,700).
BTW, If anyone can give me some advices if I made anything wrong, or anything I should change, it Would be great!!
Thanks alot for helpers.
EDIT: Anyone.. please? I suppose it's not so hard to figure it out ><.
In your GameObject constructor you are setting the position to Vector2.Zero and not to your param Position.
public GameObject(Vector2 Position, Texture2D Texture)
{
position = Vector2.Zero;
this.texture = Texture;
}
should be
public GameObject(Vector2 Position, Texture2D Texture)
{
position = Position;
this.texture = Texture;
}
There are two issues I see. The first one, answered by CraigW, you've already fixed:
protected Vector2 position;
public GameObject(Vector2 Position, Texture2D Texture)
{
position = Vector2.Zero; // <---- this needs to be position = Position
this.texture = Texture;
}
protected Vector2 Position { set; get; }
The second issue is your Position property. When you declare a property using the { get; set; } syntax the compiler is implicitly giving you a backing field to store the value of the property. But you're creating your own position field as well. Your position field is getting set to the value passed in the constructor (assuming you've fixed issue #1 in your constructor that is), but the getter for your Position property is returning the compiler generated field, which you haven't set to anything.
There are two ways you can fix this. Either remove your position field and reference the Position property everywhere, or modify your property to use your position field.
Fix Option #1: just use the Position property
// protected Vector2 position; // <----- remove this
public GameObject(Vector2 Position, Texture2D Texture)
{
this.Position = Position;
this.texture = Texture;
}
Fix Option #2: Change your Position property to use your field
protected Vector2 Position { get { return position; } set { position = value; } }
-7? What did you do deserve this!?
I think there's a logic error somewhere in your code, change this:
public void Draw(SpriteBatch spriteBatch)
{
spriteBatch.Draw(texture, Position, Color.White);
}
To this:
public void Draw(SpriteBatch spriteBatch)
{
spriteBatch.Draw(texture, new Vector2(700,700), Color.White);
}
And see how it works for you (it should work fine) :)
From there you're going to have to work backwards to find where Position is not being set to the value you want.
Personally I've never been a fan of gameobject, much better to create your own base types since you have total control over how they work and can more easily solve issues that pop up.