My first game in XNA(Little problem) - c#

this is my code so far:
Game1.cs Class:
public class Game1 : Microsoft.Xna.Framework.Game
{
GraphicsDeviceManager graphics;
SpriteBatch spriteBatch;
Player MyPlayer;
Texture2D Ball;
int GraphicsWidth,GraphicsHeight;
public Game1()
{
graphics = new GraphicsDeviceManager(this);
Content.RootDirectory = "Content";
}
protected override void Initialize()
{
GraphicsWidth = graphics.PreferredBackBufferWidth;
GraphicsHeight= graphics.PreferredBackBufferHeight;
MyPlayer = new Player(Ball, new Vector2(100, 100), Vector2.Zero);
base.Initialize();
}
protected override void LoadContent()
{
spriteBatch = new SpriteBatch(GraphicsDevice);
Ball = Content.Load<Texture2D>("Images/ball");
}
protected override void UnloadContent()
{
}
protected override void Update(GameTime gameTime)
{
if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed)
this.Exit();
base.Update(gameTime);
}
protected override void Draw(GameTime gameTime)
{
GraphicsDevice.Clear(Color.CornflowerBlue);
MyPlayer.Draw(spriteBatch);
base.Draw(gameTime);
}
}
Player class(The ball):
class Player
{
Texture2D Texture;
Vector2 Positon,Velocity;
public int Height
{
get { return this.Texture.Height; }
}
public int Width
{
get { return this.Texture.Width; }
}
public Player(Texture2D tex, Vector2 position,Vector2 velocity)
{
this.Texture = tex;
this.Positon = position;
this.Velocity = velocity;
}
public void Draw(SpriteBatch spriteBatch)
{
spriteBatch.Begin();
spriteBatch.Draw(Texture, Positon, Color.White);
spriteBatch.End();
}
}
When I try to debug the game I have the following error:
This method does not accept null for this parameter.
Parameter name: texture
In that part:
public void Draw(SpriteBatch spriteBatch)
{
spriteBatch.Begin();
spriteBatch.Draw(Texture, Positon, Color.White);
spriteBatch.End();
}
Btw, I'd like to ask if I can make this code better or something like that.
Thanks alot!

Looks like you create the Player object before you've loaded the Ball content, and thus, the player holds null instead of a texture, but the Ball field in the Game is the real texture.
I would move the creation of Player into LoadContent, after you've assigned the Ball.
Ball = Content.Load<Texture2D>("Images/ball");
MyPlayer = new Player(Ball, new Vector2(100, 100), Vector2.Zero);

I'm going to preface my answer by saying you should call spriteBatch.begin() and spriteBatch.end() in your Game1.cs Draw function instead of your Player.cs Draw function. It's expensive and you shouldn't do it more than once per draw frame, unless it's absolutely necessary (it's not in this case).
With regards to your actual question, you need to load your player in the LoadContent method rather than your Initialize method.

Initialize is happening before your texture is loaded.
try moving MyPlayer = new Player(Ball, new Vector2(100, 100), Vector2.Zero);
into your LoadContent method after you load the texture into Ball.

It looks like you're loading the ball texture after you've already initialized myPlayer with the "NULL" Ball texture

This is because Initialize is called before LoadContent, and at the point you create your Player the Ball texture is still null.
Either create the Player object in LoadContent, after you load the ball, or allow Player to load its own content.

Related

Cloning and drawing Objects in monogame

How do I clone an object then pick a random position, then draw it.
This is the code I have for the object:
public class Trash : ICloneable
{
private Texture2D _texture;
private float _rotation;
public Vector2 Position;
public Vector2 Origin;
public float RotationVelocity = 3f;
public float LinearVelocity = 4f;
public Trash(Texture2D texture)
{
_texture = texture;
}
public void Update()
{
// Do epic stuff here
}
public void Draw(SpriteBatch spriteBatch)
{
spriteBatch.Draw(_texture, Position, null, Color.White, _rotation, Origin, 1, SpriteEffects.None, 0f);
}
public object Clone()
{
return this.MemberwiseClone();
}
And this is code I have in Game1.cs so far:
public class Game1 : Game
{
GraphicsDeviceManager graphics;
SpriteBatch spriteBatch;
private SeaJam.Objects.Trash Trash;
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
base.Initialize();
}
protected override void LoadContent()
{
// Create a new SpriteBatch, which can be used to draw textures.
spriteBatch = new SpriteBatch(GraphicsDevice);
var texture = Content.Load<Texture2D>("Prototype");
Trash = new Objects.Trash(texture)
{
Position = new Vector2(100, 100),
Origin = new Vector2(texture.Width / 2, texture.Height - 25),
};
}
protected override void Update(GameTime gameTime)
{
Trash.Update();
base.Update(gameTime);
}
protected override void Draw(GameTime gameTime)
{
GraphicsDevice.Clear(Color.CornflowerBlue);
spriteBatch.Begin();
Trash.Draw(spriteBatch);
spriteBatch.End();
base.Draw(gameTime);
}
private void AddTrash()
{
var rnd = new System.Random();
var NewTrash = Trash.Clone();
}
The problem is Whenever I'd try to give a random position for the clone in the AddTrash() Method, I'd only get errors, such as "'object' does not contain a definition for 'Position' and no accessible extension method 'Position' accepting a first argument of type 'object' could be found (are you missing a using directive or an assembly reference?)"
your constructor:
public Trash(Texture2D texture)
{
_texture = texture;
}
Needs to be extended with the desired changeable parameters. In your case, it needs to add Position and Origin as parameter, and then apply it as a value.
Like this:
public Trash(Texture2D texture, Vector2 position, Vector2 origin)
{
_texture = texture;
Position = position;
Origin = origin;
}
And change the way you call it in the game1.cs as well, they need to work similair like texture:
var texture = Content.Load<Texture2D>("Prototype");
var position = new Vector2(100, 100),
var origin = new Vector2(texture.Width / 2, texture.Height - 25),
Trash = new Objects.Trash(texture, position, origin);
And as a tip: keep consistency in your field names, mixing in underscore and lowercase in one field, and uppercase in an other field will get confusing to understand. especially when the parameters needs a name different from the fields as well. I prefer to keep them all with the first letter uppercase.

Drawing a Sprite using Monogame

I'm just starting with Monogame and I'm trying to make a simple sprite, which later is meant to be a button. I've searched all around and done several tutorials, but I can't make it work. I just keep getting the blank, blue screen. Here's my code:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Content;
namespace Test_Game
{
class Main_Menu
{
//setting the variables
public Texture2D button1;
public Vector2 button1Pos;
public GraphicsDevice graphicsDevice;
GraphicsDeviceManager graphics;
public void initialize(Texture2D texture, Vector2 position, ContentManager Content)
{
//Getting the initialized stuff
button1 = Content.Load<Texture2D>("button_temp");
button1Pos.X = 30;
button1Pos.Y = 30;
}
public void Draw(SpriteBatch spriteBatch)
{
graphics.GraphicsDevice.Clear(Color.Black);
spriteBatch = new SpriteBatch(graphicsDevice);
//Just drawing the Sprite
spriteBatch.Begin();
spriteBatch.Draw(button1, new Rectangle(30, 30, 214, 101), Color.White);
spriteBatch.End();
}
}
}
Hope you can find an answer.
I can see many mistakes in your code, I would left a comment pointing all of the, but its too long.
Most of the mistakes come from this: you're not inheriting from Game class. Your line class Main_Menu should be class Main_Menu : Game. Always use this template for a game class:
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
namespace MyGame
{
public class MyGame : Game
{
GraphicsDeviceManager graphics;
SpriteBatch spriteBatch;
public MyGame()
{
graphics = new GraphicsDeviceManager(this);
Content.RootDirectory = "Content";
}
protected override void Initialize()
{
base.Initialize();
}
protected override void LoadContent()
{
spriteBatch = new SpriteBatch(GraphicsDevice);
}
protected override void UnloadContent()
{
}
protected override void Update(GameTime gameTime)
{
base.Update(gameTime);
}
protected override void Draw(GameTime gameTime)
{
GraphicsDevice.Clear(Color.CornflowerBlue);
base.Draw(gameTime);
}
}
}
From here on, you must fill this template with the following in mind:
Create your memory-only objects in the Initialize method;
Load and create file-related objects in the LoadContent method;
Add your game logic in the Update method;
Add your drawing logic in the Draw method;
Usually, do not bother with the constructor or the UnloadContent method.
Connecting your existing code with the template, we get the following:
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
namespace Test_Game
{
public class Main_Menu : Game
{
GraphicsDeviceManager graphics;
SpriteBatch spriteBatch;
Vector2 buttonPos; // our button position
Texture2D button; // our button texture
public MyGame()
{
graphics = new GraphicsDeviceManager(this);
Content.RootDirectory = "Content";
}
protected override void Initialize()
{
buttonPos = new Vector2(30, 30); // X=30, Y=30
base.Initialize();
}
protected override void LoadContent()
{
spriteBatch = new SpriteBatch(GraphicsDevice);
button = Content.Load<Texture2D>("button_temp"); // load texture
}
protected override void UnloadContent()
{
}
protected override void Update(GameTime gameTime)
{
// here we would add game logic
// things like moving game objects, detecting collisions, etc
base.Update(gameTime);
}
protected override void Draw(GameTime gameTime)
{
GraphicsDevice.Clear(Color.CornflowerBlue);
spriteBatch.Begin();
// draw our button
int buttonWidth = 214;
int buttonHeight = 101;
spriteBatch.Draw(button, new Rectangle(buttonPos.X, buttonPos.Y, buttonWidth, buttonHeight), Color.White);
spriteBatch.End();
base.Draw(gameTime);
}
}
}
This template is used in every game for the MonoGame and XNA frameworks, so you should find a LOT of content on the web about what each method of the Game class does.

C# XNA4.0 keyboardstate error

I am trying to move a sprite but it won't even let me debug.
When i try to debug i get the following error:
Error 1 The name 'keys' does not exist in the current context
What am i doing wrong? or is it something else? According to multiple sources this is one of the ways to make a sprite move.
I've never been able to use keyboard input to move something or make something happen for some reason. Kinda lost here :(
Here's the code:
public class Game1 : Microsoft.Xna.Framework.Game
{
Texture2D myTexture;
Vector2 spritePosition = Vector2.Zero;
Vector2 spriteSpeed = new Vector2(50.0f, 50.0f);
GraphicsDeviceManager graphics;
SpriteBatch spriteBatch;
KeyboardState keystate;
public Game1()
{
graphics = new GraphicsDeviceManager(this);
Content.RootDirectory = "Content";
}
protected override void Initialize()
{
base.Initialize();
}
protected override void LoadContent()
{
spriteBatch = new SpriteBatch(GraphicsDevice);
myTexture = Content.Load<Texture2D>("sprite");
}
protected override void UnloadContent()
{
}
protected override void Update(GameTime gameTime)
{
keystate = Keyboard.GetState();
if (keystate.IsKeyDown(keys.right))
spritePosition.X += spriteSpeed.X;
}
protected override void Draw(GameTime gameTime)
{
graphics.GraphicsDevice.Clear(Color.CornflowerBlue);
spriteBatch.Begin(SpriteSortMode.BackToFront, BlendState.AlphaBlend);
spriteBatch.Draw(myTexture, spritePosition, Color.White);
spriteBatch.End();
base.Draw(gameTime);
}
}
Use the actual XNA Keys enumeration (MSDN):
protected override void Update(GameTime gameTime)
{
keystate = Keyboard.GetState();
if (keystate.IsKeyDown(Keys.Right))
spritePosition.X += spriteSpeed.X;
}
Remember, C# is case sensitive!

Multiple RenderTargets in different drawableComponents XNA

Hi guys i have a little problem.
I have this 2 DrawableGameComponets (bigApple, smallApple) in both I'm drawing into a RenderTarget and then draw the RenderTarget in the backbuffer but this happens independently in each DrawableGameComponent.
The thing I want to achieve is that both DrawableGameComponents draw properly one in top of another.
Something like this:
This it's the screen with both drawableComponent with no rendertargets in each component.
But instead of that I get this:
This it's the screen with both drawableComponent with rendertargets in each component.
This is for a little game I'm working on. I'm planning to display in one drawable component and image from the camera and in the other drawable gamecomponent the game itself. But once I add another GameComponent to the Componets List, the one above the last added can't be seen.
This is the Code from each drawable Component.
SmallApple:
public class SmallApple:DrawableComponent2D
{
Texture2D apple;
public SmallApple(Game game)
: base(game)
{
//Do nothing
}
protected override void LoadContent()
{
apple = Game.Content.Load<Texture2D>("apple");
this.Size = new Vector2(apple.Width,
apple.Height);
renderTarget = new RenderTarget2D(GraphicsDevice,
(int)Size.X,
(int)Size.Y,
false,
SurfaceFormat.Color,
DepthFormat.None,
this.Game.GraphicsDevice.PresentationParameters.MultiSampleCount,
RenderTargetUsage.PreserveContents);
base.LoadContent();
}
public override void Initialize()
{
base.Initialize();
}
public override void Draw(GameTime gameTime)
{
GraphicsDevice.SetRenderTarget(renderTarget);
GraphicsDevice.Clear(ClearOptions.Target, Color.Transparent, 1f, 0);
this.SharedSpriteBatch.Begin(SpriteSortMode.Immediate, null);
this.SharedSpriteBatch.Draw(this.apple, this.Position, Color.White);
this.SharedSpriteBatch.End();
GraphicsDevice.SetRenderTarget(null);
this.SharedSpriteBatch.Begin();
this.SharedSpriteBatch.Draw(apple, this.Position,Color.White);
this.SharedSpriteBatch.End();
base.Draw(gameTime);
}
}
--
And the BigApple Class
public class BigApple:DrawableComponent2D
{
Texture2D apple;
public BigApple(Game game)
: base(game)
{
}
protected override void LoadContent()
{
base.LoadContent();
apple = Game.Content.Load<Texture2D>("apple");
this.Size = new Vector2(apple.Width, apple.Height);
renderTarget = new RenderTarget2D(GraphicsDevice,
(int)Size.X,
(int)Size.Y,
false,
SurfaceFormat.Color,
DepthFormat.None,
this.Game.GraphicsDevice.PresentationParameters.MultiSampleCount,
RenderTargetUsage.PreserveContents);
}
public override void Update(GameTime gameTime)
{
base.Update(gameTime);
}
public override void Draw(GameTime gameTime)
{
GraphicsDevice.SetRenderTarget(renderTarget);
GraphicsDevice.Clear(ClearOptions.Target, Color.Transparent, 1f, 0);
this.SharedSpriteBatch.Begin(SpriteSortMode.Immediate,null);
this.SharedSpriteBatch.Draw(this.apple, this.Position, Color.White);
this.SharedSpriteBatch.End();
GraphicsDevice.SetRenderTarget(null);
this.SharedSpriteBatch.Begin();
this.SharedSpriteBatch.Draw(renderTarget,new Rectangle((int)Position.X, (int)Position.Y, (int)GraphicsDevice.Viewport.Width, (int)GraphicsDevice.Viewport.Height), Color.White);
this.SharedSpriteBatch.End();
base.Draw(gameTime);
}
}
The class DrawableComponent2D is the one that contains the heritage from drawablegameComponent and has some variables to work with.
What is your XNA version?
If you use XNA 3.1 maybe your problem is here GraphicsDeviceCapabilities.MaxSimultaneousRenderTargets property
Solved!!. i have to add a method to the delegate:
graphics.PreparingDeviceSettings;
so this is the method:
private void GraphicsDevicePreparingDeviceSettings(object sender, PreparingDeviceSettingsEventArgs e) {
e.GraphicsDeviceInformation.PresentationParameters.RenderTargetUsage = RenderTargetUsage.PreserveContents;
}
And to add it to the graphicsDeviceManager is just one line:
graphics. PreparingDeviceSettings += GraphicsDevicePreparingDeviceSettings;
voilĂ !!! Thanks for your support

How to make texture move

I have problem. I have tryed how to make my texture move, but my solution is slow and it is not working. Does anybody know how to make texture2D move using C# XNAGamestudio. ANybody please help me!
EDIT:
GraphicsDeviceManager graphics;
SpriteBatch spriteBatch;
public Hashtable Objects = new Hashtable();
public Hashtable XPOS = new Hashtable();
public Hashtable YPOS = new Hashtable();
public int NUM = 0;
public bool UP = true;
public bool DOWN = false;
public bool LEFT = false;
public bool RIGHT = false;
......
protected override void Update(GameTime gameTime)
{
// Allows the game to exit
if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed)
this.Exit();
this.AddObject("Nameee", "C:\\Box.png");
// TODO: Add your update logic here
if (UP)
{
if (NUM != 25)
{
AppendObject(new Vector2((float)this.XPOS["Nameee"], (float)this.XPOS["Nameee"] - NUM), "Nameee");
NUM++;
Thread.Sleep(100);
}
else
UP = false;
}
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();
//spriteBatch.End();
//base.Draw(gameTime);
}
public void AddObject(string TagName, string ObjectImage)
{
Texture2D fileTexture;
using (FileStream fileStream = new FileStream(#ObjectImage, FileMode.Open))
{
fileTexture = Texture2D.FromStream(graphics.GraphicsDevice, fileStream);
}
if (!this.Objects.ContainsKey(TagName))
{
this.Objects.Add(TagName, fileTexture);
this.XPOS.Add(TagName, 0.0F);
this.YPOS.Add(TagName, 50.0F);
}
}
public void AppendObject(Vector2 pos, string tagName)
{
spriteBatch.Begin();
spriteBatch.Draw((Texture2D)this.Objects[tagName], new Vector2((float)this.XPOS[tagName], (float)this.YPOS[tagName]), Color.White);
spriteBatch.End();
}
Hmm, well technically, this looks like it should move a texture along the X axis.
As for performance, you may want to take these things into consideration:
You are calling this.AddObject("Nameee", "C:\\Box.png"); on every update. That's not a good thing. Call this once in your LoadContent() method.
Instead of using Thread.Sleep(100);, I would suggest tracking the time elapsed with GameTime. (Hit the comment if you need an example of how to do this)
You are creating a new vector2 on each pass for the texture position. While this probably doesn't have a noticeable performance hit since its only creating 10 a second (thanks to your Thread.Sleep(100);, I would suggest using the same one.
On a side note, I would recommend completely refactoring this code for a more object oriented approach. Create a class that holds a Texture2D and a Vector2. Then give it an Update() method and a Draw(SpriteBatch sb) method and perform your work in there.
That's just a suggestion though.
You can do something similar to this, and you should use the content manager to load assets.
public class Sprite
{
public Vector2 Position = Vector2.Zero;
public Texture2D Texture;
public float Scale = 1;
public void LoadAsset(Game game, string asset)
{
Texture = game.Content.Load<Texture2d>(asset);
}
public Draw(SpriteBatch batch)
{
batch.Draw(Texture, Position, null, Color.White, ...,... Scale,...);
}
}
//In your game:
List<Sprite> Sprites = new List<Sprite>();
Initialize()
{
base.Initialize();
Sprite myBox = new Box();
myBox.LoadAsset("Box");
Sprites.Add(myBox);
}
Update(GameTime gametime)
{
myBox.Position += Vector2.UnitX * Speed * (float) gametime.elapsed.TotalSeconds;
}
Draw()
{
batch.begin();
foreach (Sprite sprite in Sprites) sprite.Draw(batch);
batch.end();
}
Both good answers by Blau and justnS. I would also advise to take a look at some XNA tutorials to get a better understanding of the XNA Framework and how it should be used (i.e. the purpose of the separate Initialize(), LoadContent(), Update(), Draw(), etc methods).
Try these for starters:
Riemer's
MSDN
XNA Game Dev

Categories

Resources