Monogame: Creating Draw Function In Class - c#

I am wanting to make a tile class that contains it's own drawing function. Below is what I have so far. The error that is showing when I run the coder is. "System.InvalidOperationException: 'Begin cannot be called again until End has been successfully called." This error message shows up on the spirteBatch.Begin() inside the class.
namespace TileGame.v3
{
class Tile
{
public Texture2D texture { get; set; }
public int X { get; set; }
public int Y { get; set; }
public int sourceX { get; set; }
public int sourceY { get; set; }
public int width { get; set; }
public int height { get; set; }
public void Draw(GameTime gameTime, SpriteBatch spriteBatch)
{
spriteBatch.Begin();
spriteBatch.Draw(texture, new Vector2(X, Y), new Rectangle(sourceX, sourceY, width, height), Color.White);
spriteBatch.End();
Draw(gameTime, spriteBatch);
}
}
}
namespace TileGame.v3
{
public class Game1 : Game
{
GraphicsDeviceManager graphics;
SpriteBatch spriteBatch;
Texture2D mark;
Texture2D peep1;
Texture2D ocean;
int x1 = 100;
int y1 = 100;
int x2 = 400;
int y2 = 400;
int tempx;
int tempy;
bool win = false;
Tile a = new Tile();
public Game1()
{
graphics = new GraphicsDeviceManager(this);
Content.RootDirectory = "Content";
}
protected override void Initialize()
{
base.Initialize();
}
protected override void LoadContent()
{
spriteBatch = new SpriteBatch(GraphicsDevice);
mark = Content.Load<Texture2D>("mark");
peep1 = Content.Load<Texture2D>("peep1");
ocean = Content.Load<Texture2D>("ocean");
a.texture = ocean;
}
protected override void UnloadContent()
{
// TODO: Unload any non ContentManager content here
}
protected override void Update(GameTime gameTime)
{
if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed || Keyboard.GetState().IsKeyDown(Keys.Escape))
Exit();
if (Keyboard.GetState().IsKeyDown(Keys.Enter))
{
tempx = x1;
x1 = x2;
x2 = tempx;
tempy = y1;
y1 = y2;
y2 = tempy;
win = true;
}
a.X = 100;
a.Y = 100;
a.sourceX = 300;
a.sourceY = 300;
a.width = 100;
a.height = 100;
base.Update(gameTime);
}
protected override void Draw(GameTime gameTime)
{
spriteBatch.Begin();
a.Draw(gameTime, spriteBatch);
spriteBatch.End();
base.Draw(gameTime);
}
}
}
The texture is 1920x1080 and I have tested drawing and cutting it and it has worked fine.

First of all, your code is probably incomplete, but you are never calling the draw method anywhere.
Let say you are calling it, are you sure your texture is bigger than 300x300? And what does that texture contains for (x,y = 300,300 to x,y = 400,400)? Does it have any color data in those positions?
If you answer yes to all of this, we will need more code to be able to help you with that.
Side node: Since this is a tile, you probably are going to render many of them. You don't need to call .Begin() and .End() for all of them. Simply call Begin() before the first tile and End() after the last one and you're good to go. This will make rendering much faster.

Related

Why my MonoGame simple app is lagging?

I wrote my simple game for Android with MonoGame API.
I touch the app was running with quite good performance but for sure I make simple FPS counter and the resoults was 54-60 fps with does not satisfied me, so i move my fps counter to the MonoGame template to see with part of my code was causing laggs and i found that even almost clear app run with the same speed of 54-60 fps. The problem was not comming from GC because there was no garbage to collect. Is there any option to avoid these lags? Here is the app:
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
namespace perf_test
{
public class FRAPS
{
float fps_from;
int fps;
public int fps_toshow;
public float in_Secs;
public void add_frame()
{
fps_from += in_Secs;
if (fps_from > 1)
{
fps_toshow = fps;
fps = 0;
fps_from = 0;
}
fps++;
}
}
public class numbers
{
Texture2D[] texture;
int num1, num2;
Vector2 pos1, pos2, origin;
public int number;
public void load(ContentManager content)
{
texture = new Texture2D[10];
for (int i = 0; i < 10; i++)
{
texture[i] = content.Load<Texture2D>(("" + i));
}
num1 = 0;
num2 = 0;
number = 22;
pos1 = new Vector2(250, 50);
pos2 = new Vector2(270, 50);
origin = new Vector2(10, 10);
}
public void update()
{
num1 = 0;
num2 = 0;
int nuu = number;
if (nuu > 10)
{
for (int i = 0; i < 10; i++)
{
if (number >= (i * 10))
{
num1 = i;
}
else break;
}
}
nuu -= num1 * 10;
for (int i = 0; i < 10; i++)
{
if (nuu >= i)
{
num2 = i;
}
else break;
}
}
public void draw()
{
if (number > 9) Game1.spriteBatch.Draw(texture[num1], pos1, origin: origin);
Game1.spriteBatch.Draw(texture[num2], pos2, origin: origin);
}
}
public class Game1 : Game
{
GraphicsDeviceManager graphics;
public static SpriteBatch spriteBatch;
FRAPS fraps;
numbers Numb;
public Game1()
{
graphics = new GraphicsDeviceManager(this);
Content.RootDirectory = "Content";
fraps = new FRAPS();
Numb = new numbers();
graphics.IsFullScreen = true;
graphics.PreferredBackBufferWidth = 800;
graphics.PreferredBackBufferHeight = 480;
graphics.SupportedOrientations = DisplayOrientation.LandscapeLeft | DisplayOrientation.LandscapeRight;
}
protected override void Initialize()
{
base.Initialize();
}
protected override void LoadContent()
{
spriteBatch = new SpriteBatch(GraphicsDevice);
Numb.load(Content);
}
protected override void UnloadContent()
{
}
protected override void Update(GameTime gameTime)
{
if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed)
Exit();
base.Update(gameTime);
}
protected override void Draw(GameTime gameTime)
{
GraphicsDevice.Clear(Color.CornflowerBlue);
spriteBatch.Begin();
fraps.in_Secs = (float)gameTime.ElapsedGameTime.TotalSeconds;
fraps.add_frame();
Numb.number = fraps.fps_toshow;
Numb.update();
Numb.draw();
spriteBatch.End();
base.Draw(gameTime);
}
}
}
Sorry for bad English, I am from Poland.
Set
IsFixedTimeStep = false;
in your Game1 constructor. XNA/Monogame automatically caps you at 60 FPS.

How to move my sprite in MonoGame using C#

First off, i'm fairly new to programming, about 2 months in, i dabbled a bit in Console Application, WinForms, and still using the ugly console to get better at algorithms in general. But now, I wanna start digging into game programming, because that's the reason i wanted to learn programming. I stumbled upon MonoGame, and while it's harder than say Unity, I got an immense sense of achievement after creating something by just using code. I already made a Space Invaders and Pong but nothing related to sprite animation, using spritesheets and moving a player. So 2 days ago, I started a platformer, divided my spritesheet, got some animation down, and now that it's time to move my player, I'm completely lost. I tried reading some tutorials on vectors, but it doesn't help in my case. Maybe you can shed some light on the matter.
So, without further ado, here's the code:
Game.cs
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
namespace MafiaJohnny
{
public class Game1 : Game
{
GraphicsDeviceManager graphics;
SpriteBatch spriteBatch;
private JohnnyPlayer johnnyPlayer;
public Game1()
{
graphics = new GraphicsDeviceManager(this);
Content.RootDirectory = "Content";
}
protected override void Initialize()
{
base.Initialize();
}
protected override void LoadContent()
{
spriteBatch = new SpriteBatch(GraphicsDevice);
Texture2D texture = Content.Load<Texture2D>("JohnnyDone");
johnnyPlayer = new JohnnyPlayer(texture, 2, 4);
}
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();
johnnyPlayer.Update(gameTime);
base.Update(gameTime);
}
protected override void Draw(GameTime gameTime)
{
GraphicsDevice.Clear(Color.White);
johnnyPlayer.Draw(spriteBatch, new Vector2(200, 200));
base.Draw(gameTime);
}
}
}
JohnnyPlayer.cs
using System;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.Input;
namespace MafiaJohnny
{
class JohnnyPlayer
{
public Texture2D Texture { get; set; }
public int Rows { get; set; }
public int Columns { get; set; }
private int currentFrame;
private int totalFrames;
//Slow down frame animation
private int timeSinceLastFrame = 0;
private int millisecondsPerFrame = 400;
public JohnnyPlayer(Texture2D texture, int rows, int columns)
{
Texture = texture;
Rows = rows;
Columns = columns;
currentFrame = 0;
totalFrames = Rows * Columns;
}
public void Update (GameTime gameTime)
{
timeSinceLastFrame += gameTime.ElapsedGameTime.Milliseconds;
if (timeSinceLastFrame > millisecondsPerFrame)
{
timeSinceLastFrame -= millisecondsPerFrame;
KeyboardState keystate = Keyboard.GetState();
//Idle animation
if (keystate.GetPressedKeys().Length == 0)
currentFrame++;
timeSinceLastFrame = 0;
if (currentFrame == 2)
currentFrame = 0;
//Walking Animation
if (keystate.IsKeyDown(Keys.Left))
{
}
}
}
public void Draw (SpriteBatch spriteBatch, Vector2 location)
{
int width = Texture.Width/Columns;
int height = Texture.Height / Rows;
int row = (int) ((float) currentFrame/Columns);
int column = currentFrame % Columns;
Rectangle sourceRectangle = new Rectangle(width * column, height * row, width, height);
Rectangle destinationRectangle = new Rectangle((int)location.X, (int)location.Y, width, height);
spriteBatch.Begin();
spriteBatch.Draw(Texture, destinationRectangle, sourceRectangle, Color.White);
spriteBatch.End();
}
}
}
So here's my code, find me an answer minions! Thank you is what I mean :)
You just need to change "location" so the sprite moves left/right/up/down. Also I recommend moving this code from JohnnyPlayer to another "controller" class.
Here:
http://www.gamefromscratch.com/post/2015/06/15/MonoGame-Tutorial-Creating-an-Application.aspx
They make a sprite and move it from left to right. In your case the texture on sprite changes in time (animation) but the movement is still the same.

Reset Texture2Ds in XNA

I'm Having a problem with an experiment of mine. I'm trying to make a method that fuses one Texture2D into another Texture2D, then reloads the Texture2D, this time moving the pasted texture in a new spot. I plan to perfect upon this method in later projects where I paste in a spotlight onto a dark background to "illuminate" the scenery behind it. While I managed to make the paste-to method work perfectly, I am having some major problems with the second part of my plan. I have the pasted texture set to a Vector2, where the X member increases by 1 every frame, thus dragging the pasted texture along the background. However, the background doesn't reset after each frame, leaving a drag mark on the background where the previous image was. For the last half hour I've been working to cure this problem by resetting the background texture to make it clean again for when it has the other image pasted onto it.
Here is my code.
namespace CopyTest
{
public class Image
{
public Texture2D Bitmap;
public Vector2 Position;
public String BitmapName;
public Rectangle Viewport;
public Color Tint = Color.White;
public void ResetViewportDimensions()
{
this.Viewport = new Rectangle(this.Viewport.X, this.Viewport.Y, Bitmap.Width, Bitmap.Height);
}
public void Draw(SpriteBatch Target)
{
}
public void FinalizeBitmap(ContentManager Target)
{
this.Bitmap = null;
this.Bitmap = Target.Load<Texture2D>(this.BitmapName);
}
public Image(Vector2 Position, String BitmapName)
{
this.BitmapName = BitmapName;
this.Position = Position;
}
}
public class Game1 : Microsoft.Xna.Framework.Game
{
GraphicsDeviceManager graphics;
SpriteBatch spriteBatch;
public Image Rainbow = new Image(new Vector2(0, 0), "Rainbow");
public Image Eye = new Image(new Vector2(0, 0), "Glow");
public Image PrintOut = new Image(new Vector2(0, 0), "Rainbow");
public Vector2 Destination = new Vector2(100, 50);
public void PrintTo(Image Source, Image Target, Vector2 Location)
{
Color[] A = new Color[Source.Bitmap.Width * Source.Bitmap.Width];
Color[] B = new Color[Target.Bitmap.Width * Target.Bitmap.Width];
int Y = 0;
int X = 0;
Source.Bitmap.GetData(A);
Target.Bitmap.GetData(B);
for (int i = 0; i < A.Length; i++)
{
B[(int)Location.X + X + (((int)Location.Y + Y) * Target.Bitmap.Width)] = A[i];
X++;
if (X == Source.Bitmap.Width)
{
X = 0;
Y++;
}
}
Target.Bitmap.SetData<Color>(B);
}
public Game1()
{
graphics = new GraphicsDeviceManager(this);
Content.RootDirectory = "Content";
}
protected override void Initialize()
{
base.Initialize();
}
protected override void LoadContent()
{
spriteBatch = new SpriteBatch(GraphicsDevice);
Eye.FinalizeBitmap(Content);
Rainbow.FinalizeBitmap(Content);
PrintOut.FinalizeBitmap(Content);
Eye.ResetViewportDimensions();
Rainbow.ResetViewportDimensions();
PrintOut.ResetViewportDimensions();
}
protected override void Update(GameTime gameTime)
{
// Allows the game to exit
if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed)
this.Exit();
GraphicsDevice.Textures[0] = null;
PrintOut.FinalizeBitmap(Content);
PrintTo(Eye, PrintOut, Destination);
Destination.Y++;
base.Update(gameTime);
}
protected override void Draw(GameTime gameTime)
{
GraphicsDevice.Clear(Color.CornflowerBlue);
spriteBatch.Begin();
spriteBatch.Draw(PrintOut.Bitmap, PrintOut.Position, PrintOut.Viewport, PrintOut.Tint);
spriteBatch.End();
base.Draw(gameTime);
}
}
Any help at all would be greatly appreciated.

XNA - No loading screen or menu

The problem is that it just shows a black screen and the loading mouse. It doesn't show the loading screen or the menu.
public class Game1 : Microsoft.Xna.Framework.Game
{
GraphicsDeviceManager graphics;
SpriteBatch spriteBatch;
SpriteBatch mBatch;
Texture2D mTheQuantumBros2;
MenuComponent menuComponent;
public static Rectangle screen;
public static string GameState = "Menu";
public Game1()
{
graphics = new GraphicsDeviceManager(this);
Content.RootDirectory = "Content";
graphics.PreferMultiSampling = false;
graphics.IsFullScreen = true;
graphics.PreferredBackBufferWidth = 1366;
graphics.PreferredBackBufferHeight = 768;
graphics.ApplyChanges();
}
protected override void Initialize()
{
// TODO: Add your initialization logic here
base.Initialize();
}
protected override void LoadContent()
{
spriteBatch = new SpriteBatch(GraphicsDevice);
mBatch = new SpriteBatch(this.graphics.GraphicsDevice);
ContentManager aLoader = new ContentManager(this.Services);
aLoader.RootDirectory = "Content";
mTheQuantumBros2 = aLoader.Load<Texture2D>("TheQuantumBros2") as Texture2D;
menuComponent.LoadContent(Content);
}
protected override void UnloadContent()
{
}
/// <param name="gameTime">Provides a snapshot of timing values.</param>
protected override void Update(GameTime gameTime)
{
if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed)
this.Exit();
switch (GameState)
{
case "Menu":
menuComponent.Update(gameTime);
break;
}
base.Update(gameTime);
}
/// <param name="gameTime">Provides a snapshot of timing values.</param>
protected override void Draw(GameTime gameTime)
{
GraphicsDevice.Clear(Color.Black);
spriteBatch.Begin();
switch (GameState)
{
case "Menu":
menuComponent.Draw(spriteBatch);
break;
}
base.Draw(gameTime);
}
}
Other class:
class MenuComponent
{
KeyboardState keyboard;
KeyboardState prevKeyboard;
SpriteBatch mBatch;
Texture2D mTheQuantumBros2;
GameTime gameTime;
MouseState mouse;
MouseState prevMouse;
SpriteFont spriteFont;
List<string> buttonList = new List<string>();
int selected = 0;
public MenuComponent()
{
buttonList.Add("Campaign");
buttonList.Add("Multiplayer");
buttonList.Add("Zombies");
buttonList.Add("Quit Game");
}
public void LoadContent(ContentManager Content)
{
spriteFont = Content.Load<SpriteFont>("Font");
}
public void Update(GameTime gameTime)
{
keyboard = Keyboard.GetState();
mouse = Mouse.GetState();
if (CheckKeyboard(Keys.Up))
{
if (selected > 0) selected--;
}
if (CheckKeyboard(Keys.Down))
{
if (selected < buttonList.Count - 1) selected++;
}
prevMouse = mouse;
prevKeyboard = keyboard;
}
public bool CheckMouse()
{
return (mouse.LeftButton == ButtonState.Pressed && prevMouse.LeftButton == ButtonState.Released);
}
public bool CheckKeyboard(Keys key)
{
return (keyboard.IsKeyDown(key) && prevKeyboard.IsKeyDown(key));
}
public void Draw(SpriteBatch spriteBatch)
{
Color color;
int linePadding = 3;
spriteBatch.Begin();
mBatch.Begin();
mBatch.Draw(mTheQuantumBros2, new Rectangle(300, 150, mTheQuantumBros2.Width, mTheQuantumBros2.Height), Color.White);
if (gameTime.TotalGameTime.TotalSeconds <= 3)
{
mBatch.End();
for (int i = 0; i < buttonList.Count; i++)
{
color = (i == selected) ? Color.LawnGreen : Color.Gold;
spriteBatch.DrawString(spriteFont, buttonList[i], new Vector2((Game1.screen.Width / 2) - (spriteFont.MeasureString(buttonList[i]).X / 2), (Game1.screen.Height / 2) - (spriteFont.LineSpacing * (buttonList.Count) / 2) + ((spriteFont.LineSpacing + linePadding) * i)), color);
}
spriteBatch.End();
}
}
}
What is the purpose of this statement: (gameTime.TotalGameTime.TotalSeconds <= 3)?
Also, you are never updating the game time in the menu component. So, the aforementioned code would behave unexpectedly.
You are also calling spriteBatch.Begin() twice before end is called... So that should be giving you an error. Check those for issues.
EDIT: Since you are only calling spriteBatch.End() IF less than 3 seconds have passed, it will never be called again after that? I think.
As a potential fix... I would try only calling spriteBatch.Begin() and spriteBatch.End() inside of game1.cs. So:
//In your menu class
public void Draw(SpriteBatch spriteBatch)
{
Color color;
int linePadding = 3;
if (gameTime.TotalGameTime.TotalSeconds <= 3)
{
mBatch.Begin();
mBatch.Draw(mTheQuantumBros2, new Rectangle(300, 150, mTheQuantumBros2.Width, mTheQuantumBros2.Height), Color.White);
mBatch.End();
}
else
{
for (int i = 0; i < buttonList.Count; i++)
{
color = (i == selected) ? Color.LawnGreen : Color.Gold;
spriteBatch.DrawString(spriteFont, buttonList[i], new Vector2((Game1.screen.Width / 2) - (spriteFont.MeasureString(buttonList[i]).X / 2), (Game1.screen.Height / 2) - (spriteFont.LineSpacing * (buttonList.Count) / 2) + ((spriteFont.LineSpacing + linePadding) * i)), color);
}
}
}
And back in game1.cs, call spriteBatch.End() right before base.Draw() is called.
In general, it is best to only use one spriteBatch, I believe it is simply faster than beginning and ending two different batches.
EDIT 2:
Just uhm... copy and paste I guess. It works fine after the adjustments I made (you can read about them at the bottom).
You're refactored code:
game1.cs:
GraphicsDeviceManager graphics;
SpriteBatch spriteBatch;
MenuComponent menuComponent;
public static Rectangle screen;
public static string GameState = "Menu";
public Game1()
{
graphics = new GraphicsDeviceManager(this);
Content.RootDirectory = "Content";
graphics.PreferMultiSampling = false;
//graphics.IsFullScreen = true;
graphics.PreferredBackBufferWidth = 1366;
graphics.PreferredBackBufferHeight = 768;
graphics.ApplyChanges();
}
protected override void Initialize()
{
base.Initialize();
}
protected override void LoadContent()
{
spriteBatch = new SpriteBatch(GraphicsDevice);
menuComponent = new MenuComponent();
menuComponent.LoadContent(Content, graphics.GraphicsDevice.Viewport.Width, graphics.GraphicsDevice.Viewport.Height);
}
protected override void UnloadContent()
{
}
/// <param name="gameTime">Provides a snapshot of timing values.</param>
protected override void Update(GameTime gameTime)
{
if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed)
this.Exit();
switch (GameState)
{
case "Menu":
menuComponent.Update(gameTime);
break;
}
base.Update(gameTime);
}
/// <param name="gameTime">Provides a snapshot of timing values.</param>
protected override void Draw(GameTime gameTime)
{
GraphicsDevice.Clear(Color.Black);
spriteBatch.Begin();
switch (GameState)
{
case "Menu":
menuComponent.Draw(spriteBatch, gameTime);
break;
}
spriteBatch.End();
base.Draw(gameTime);
}
MenuComponent:
KeyboardState keyboard;
KeyboardState prevKeyboard;
MouseState mouse;
MouseState prevMouse;
GraphicsDevice graphicsDevice;
Texture2D mTheQuantumBros2;
SpriteFont spriteFont;
List<string> buttonList = new List<string>();
int selected = 0;
int screenWidth;
int screenHeight;
public MenuComponent()
{
buttonList.Add("Campaign");
buttonList.Add("Multiplayer");
buttonList.Add("Zombies");
buttonList.Add("Quit Game");
}
public void LoadContent(ContentManager Content, int _screenWidth, int _screenHeight)
{
spriteFont = Content.Load<SpriteFont>("Font");
mTheQuantumBros2 = Content.Load<Texture2D>("TheQuantumBros2");
screenHeight = _screenHeight;
screenWidth = _screenWidth;
}
public void Update(GameTime gameTime)
{
keyboard = Keyboard.GetState();
mouse = Mouse.GetState();
if (CheckKeyboard(Keys.Up))
{
if (selected > 0) selected--;
}
if (CheckKeyboard(Keys.Down))
{
if (selected < buttonList.Count - 1) selected++;
}
prevMouse = mouse;
prevKeyboard = keyboard;
}
public bool CheckMouse()
{
return (mouse.LeftButton == ButtonState.Pressed && prevMouse.LeftButton == ButtonState.Released);
}
public bool CheckKeyboard(Keys key)
{
return (keyboard.IsKeyDown(key) && prevKeyboard.IsKeyDown(key));
}
public void Draw(SpriteBatch spriteBatch, GameTime gameTime)
{
Color color;
int linePadding = 3;
if (gameTime.TotalGameTime.TotalSeconds <= 3)
{
spriteBatch.Draw(mTheQuantumBros2, new Rectangle(300, 150, mTheQuantumBros2.Width, mTheQuantumBros2.Height), Color.White);
}
else
{
for (int i = 0; i < buttonList.Count; i++)
{
color = (i == selected) ? Color.LawnGreen : Color.Gold;
spriteBatch.DrawString(spriteFont, buttonList[i], new Vector2((screenWidth / 2) - (spriteFont.MeasureString(buttonList[i]).X / 2), (screenHeight / 2) - (spriteFont.LineSpacing * (buttonList.Count) / 2) + ((spriteFont.LineSpacing + linePadding) * i)), color);
}
}
}
There were a bunch of little issues. For example, you were setting the menuComp = to a new menu component on every update call, so all the old variables in there would be lost, hence there was no images loading. SpriteBatch.Begin() was being called twice in a row, and then end was being called twice in a row. One spriteBatch (from game1.cs preferrably) should be used to draw. By sending that spritebatch through the method, you do not need to call begin again, and it is simply better not to for performance reasons. Last thing I noticed (that I can think of) was that the graphics device was not being set to anything because you were constantly creating a new version of it. Oh also, you were calling graphicsDevice.Clear() way too early, this only should be called once per draw (at the beginning, so old graphical info is removed from the screen).
I debugged your program/code and there are a few problems:
There is a declaration of MenuComponent menuComponent, but you didn't create an instance in the Game1() constructor. So add: menuComponent = new MenuComponent()
There is a declaration of SpriteBatch mBatch, but you didn't create an instance in the MenuComponent() constructor. So create one. The same for GameTime gameTime variable.
At the moment I don't have SpriteFont and TheQuantumBros2 texture. Is it possible that you upload your project and share it?

Why is my Texture origin is incorrect at runtime?

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.

Categories