2D top down collision detection? - c#

I have been trying to create a collision for a "top down view" like game. I have made a player class and a block class, in my Game1 class I have checked for the collision, don't know if this is a right way, but it's only a test right now. So if I intersect them I don't know what to do next.
This is my Game1.cs
using System; using System.Collections.Generic; using System.Linq;
using Microsoft.Xna.Framework; using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content; using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics; using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;
namespace Collision_Testing {
/// <summary>
/// This is the main type for your game
/// </summary>
public class Game1 : Microsoft.Xna.Framework.Game
{
GraphicsDeviceManager graphics;
SpriteBatch spriteBatch;
Player player = new Player(100, 100);
Block block = new Block(500, 500);
public Game1()
{
graphics = new GraphicsDeviceManager(this);
Content.RootDirectory = "Content";
graphics.PreferredBackBufferWidth = 800;
graphics.PreferredBackBufferHeight = 600;
}
/// <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();
}
/// <summary>
/// LoadContent will be called once per game and is the place to load
/// all of your content.
/// </summary>
protected override void LoadContent()
{
// Create a new SpriteBatch, which can be used to draw textures.
spriteBatch = new SpriteBatch(GraphicsDevice);
block.LoadContent(Content);
player.LoadContent(Content);
}
/// <summary>
/// UnloadContent will be called once per game and is the place to unload
/// all content.
/// </summary>
protected override void UnloadContent()
{
// TODO: Unload any non ContentManager content here
}
/// <summary>
/// Allows the game to run logic such as updating the world,
/// checking for collisions, gathering input, and playing audio.
/// </summary>
/// <param name="gameTime">Provides a snapshot of timing values.</param>
protected override void Update(GameTime gameTime)
{
// Allows the game to exit
if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed)
this.Exit();
block.Update(gameTime);
player.Update(gameTime);
base.Update(gameTime);
if (player.boundingBox.Intersects(block.boundingBox))
{
player.playerPos.X -= player.speed;
player.playerPos.Y -= player.speed;
}
}
/// <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();
player.Draw(spriteBatch);
block.Draw(spriteBatch);
spriteBatch.End();
base.Draw(gameTime);
}
} }
This is my Player.cs
using System; using System.Collections.Generic; using System.Linq;
using System.Text; using Microsoft.Xna.Framework; using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.Graphics; using Microsoft.Xna.Framework.Input;
namespace Collision_Testing {
class Player
{
public Vector2 playerPos;
public Texture2D playerTex;
public int speed;
KeyboardState oldState;
public Rectangle boundingBox;
public Player(int positionX, int positionY)
{
playerPos.X = positionX;
playerPos.Y = positionY;
speed = 14;
}
public void LoadContent(ContentManager Content)
{
playerTex = Content.Load<Texture2D>("player");
boundingBox = new Rectangle((int)playerPos.X, (int)playerPos.Y, playerTex.Width, playerTex.Height);
}
public void Update(GameTime gameTime)
{
KeyboardState newState = Keyboard.GetState();
if(newState.IsKeyDown(Keys.Right))
{
playerPos.X += speed;
}
if (newState.IsKeyDown(Keys.Left))
{
playerPos.X -= speed;
}
if (newState.IsKeyDown(Keys.Up))
{
playerPos.Y -= speed;
}
if (newState.IsKeyDown(Keys.Down))
{
playerPos.Y += speed;
}
oldState = newState;
}
public void Draw(SpriteBatch spriteBatch)
{
spriteBatch.Draw(playerTex, playerPos, Color.White);
}
} }
This is my Block.cs
using System; using System.Collections.Generic; using System.Linq;
using System.Text; using Microsoft.Xna.Framework; using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.Graphics; using Microsoft.Xna.Framework.Input;
namespace Collision_Testing {
class Block
{
public Vector2 blockPos;
public Texture2D blockTex;
public Rectangle boundingBox;
public Block(int blockX, int blockY)
{
blockPos.X = blockX;
blockPos.Y = blockY;
}
public void LoadContent(ContentManager Content)
{
blockTex = Content.Load<Texture2D>("wall");
boundingBox = new Rectangle((int)blockPos.X, (int)blockPos.Y, blockTex.Width, blockTex.Height);
}
public void Update(GameTime gameTime)
{
}
public void Draw(SpriteBatch spriteBatch)
{
spriteBatch.Draw(blockTex, blockPos, Color.White);
}
} }
I think I've done quite a good job for a beginner but don't know what to do next.

It looks to me like speed is a scalar. so when you intersect with the box,
if (player.boundingBox.Intersects(block.boundingBox))
{
player.playerPos.X -= player.speed;
player.playerPos.Y -= player.speed;
}
you're merely moving the player 14 units to the left, and 14 units up, regardless of where the player was.
It looks like you're intending to subtract the velocity. In order to do that, you first have to declare a velocity
public Vector2 playerVelocity;
make sure you initialize playerVelocity in your constructor.
and then you should modify the velocity instead of the position when measuring input
if(newState.IsKeyDown(Keys.Right))
{
playerVelocity.X = speed;
}
else if (newState.IsKeyDown(Keys.Left))
{
playerVelocity.X = -speed;
}
else
{
playerVelocity.X = 0;
}
...
playerPos += playerVelocity;
// i believe you can just add Vectors in XNA like this
// but if it makes you feel better you can do playerPos.X += playerVelocity.X
and then you can reverse your player's position when you collide
if (player.boundingBox.Intersects(block.boundingBox))
{
player.playerPos -= player.playerVelocity;
}

If your character doesn't stop moving I think you miss something like this:
if (newState.IsKeyUp(Keys.Up) && newState.IsKeyUp(Keys.Down) &&
newState.IsKeyUp(Keys.Left) && newState.IsKeyUp(Keys.Right))
{
playerVelocity = Vector2.Zero;
}

Related

XNA objects not drawing

So I have a problem that I cant figure out, and that is drawing objects into my main Game1 class from a class of drawablegamecomponent.
I'v been playing around with it for a bit and looking at other examples, but can't figure out the issue. There isn't much code as it is, so I'll just post the two classes I have, the main class Game1 and the class I want to draw, Balloon.
The error is in the draw method I get this...
An unhandled exception of type 'System.NullReferenceException' occurred in Burst.exe
Additional information: Object reference not set to an instance of an object.
Main Class.
using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;
namespace Burst
{
/// <summary>
/// This is the main type for your game
/// </summary>
public class Game1 : Microsoft.Xna.Framework.Game
{
GraphicsDeviceManager graphics;
SpriteBatch spriteBatch;
Rectangle bounds;
Balloon ball;
Diamond dia;
public Game1()
{
graphics = new GraphicsDeviceManager(this);
graphics.PreferredBackBufferWidth = 1152;
graphics.PreferredBackBufferHeight = 648;
Content.RootDirectory = "Content";
bounds = new Rectangle(0, 0, graphics.PreferredBackBufferWidth, graphics.PreferredBackBufferHeight);
ball = new Balloon(bounds, 1, this, spriteBatch);
dia = new Diamond(bounds, new Vector2(200, 200), this, spriteBatch);
}
/// <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();
}
/// <summary>
/// LoadContent will be called once per game and is the place to load
/// all of your content.
/// </summary>
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
}
/// <summary>
/// UnloadContent will be called once per game and is the place to unload
/// all content.
/// </summary>
protected override void UnloadContent()
{
// TODO: Unload any non ContentManager content here
}
/// <summary>
/// Allows the game to run logic such as updating the world,
/// checking for collisions, gathering input, and playing audio.
/// </summary>
/// <param name="gameTime">Provides a snapshot of timing values.</param>
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
ball.Update();
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();
// TODO: Add your drawing code here
ball.Draw(gameTime);
dia.Draw(gameTime);
spriteBatch.End();
base.Draw(gameTime);
}
}
}
Balloon Class:
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Burst
{
public class Balloon : Microsoft.Xna.Framework.DrawableGameComponent
{
Vector2 position;
Vector2 motion;
Texture2D texture;
Rectangle bounds;
Rectangle screenBounds;
Game game;
SpriteBatch spriteBatch;
float balloonSpeed = 4;
int colour = 0;
public Balloon(Rectangle screenBounds, int colour, Game game, SpriteBatch spriteBatch) : base (game)
{
this.colour = colour;
this.game = game;
this.spriteBatch = spriteBatch;
this.screenBounds = screenBounds;
this.position = new Vector2(200,200);
}
protected override void LoadContent()
{
switch (colour)
{
case 1: texture = Game.Content.Load<Texture2D>("Images/BlueBalloon");
break;
case 2: texture = Game.Content.Load<Texture2D>("Images/GreenBalloon");
break;
case 3: texture = Game.Content.Load<Texture2D>("Images/RedBalloon");
break;
case 4: texture = Game.Content.Load<Texture2D>("Images/YellowBalloon");
break;
case 5: texture = Game.Content.Load<Texture2D>("Images/PurpleBalloon");
break;
}
}
public Rectangle Bounds
{
get
{
bounds.X = (int)position.X;
bounds.Y = (int)position.Y;
return bounds;
}
}
public void Update()
{
position += motion * balloonSpeed;
}
private void CheckWallColision()
{
if (position.X < 0)
{
position.X = 0;
motion.X *= -1;
}
if (position.X + texture.Width > screenBounds.Width)
{
position.X = screenBounds.Width - texture.Width;
motion.X *= -1;
}
if (position.Y < 0)
{
position.Y = 0;
motion.Y *= -1;
}
if (position.Y + texture.Height > screenBounds.Height)
{
position.Y = screenBounds.Height - texture.Height;
motion.Y *= -1;
}
}
public void SetStartPosition()
{
Random rand = new Random();
motion = new Vector2(rand.Next(2, 6), -rand.Next(2, 6));
motion.Normalize();
position = new Vector2(200, 300);
}
public void Draw()
{
spriteBatch.Draw(texture, position, Color.White);
}
}
}
"spriteBatch" == null when you create objects "ball" and "dia".
You need move this code:
bounds = new Rectangle(0, 0, graphics.PreferredBackBufferWidth, graphics.PreferredBackBufferHeight);
ball = new Balloon(bounds, 1, this, spriteBatch);
dia = new Diamond(bounds, new Vector2(200, 200), this, spriteBatch);
to method "LoadContent". After creating "spriteBatch".

C# Monogame snake game

Well first i must say i am a complete noob, I just started with 2d graphics and i experiment on a snake game, in the Update method i call snakeUpdate which updates the position according the keystate the thing is it never updates the position, someone explain a bit please.
using System;
using System.Collections.Generic;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Storage;
using Microsoft.Xna.Framework.Utilities;
namespace SnakeGame1
{
/// <summary>
/// This is the main type for your game
/// </summary>
public class Game1 : Game
{
GraphicsDeviceManager graphics;
SpriteBatch spriteBatch;
private Texture2D background;
private Texture2D shuttle;
private Texture2D earth;
KeyboardState newState = new KeyboardState();
KeyboardState oldState = new KeyboardState();
private float angle = 0;
public Vector2 position= new Vector2(480,240);
public Vector2 velocity;
public Game1()
: base()
{
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();
}
/// <summary>
/// LoadContent will be called once per game and is the place to load
/// all of your content.
/// </summary>
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
background = Content.Load<Texture2D>("stars.jpg"); // change these names to the names of your images
shuttle = Content.Load<Texture2D>("shuttle.png"); // if you are using your own images.
earth = Content.Load<Texture2D>("earth.png");
}
/// <summary>
/// UnloadContent will be called once per game and is the place to unload
/// all content.
/// </summary>
protected override void UnloadContent()
{
// TODO: Unload any non ContentManager content here
}
/// <summary>
/// Allows the game to run logic such as updating the world,
/// checking for collisions, gathering input, and playing audio.
/// </summary>
/// <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 || Keyboard.GetState().IsKeyDown(Keys.Escape))
Exit();
listener();
snakeUp();
// TODO: Add your update logic here
//angle += 0.01f;
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);
// TODO: Add your drawing code here
spriteBatch.Begin();
spriteBatch.Draw(background, new Rectangle(0, 0, 800, 480), Color.White);
spriteBatch.Draw(earth, new Vector2(400, 240), Color.WhiteSmoke);
Vector2 origin = new Vector2(0, 0);
spriteBatch.Draw(shuttle, position, new Rectangle(0,0, shuttle.Width, shuttle.Height), Color.White, angle, origin, 0.5f, SpriteEffects.None, 1);
spriteBatch.End();
base.Draw(gameTime);
}
public void listener()
{
if (newState.IsKeyDown(Keys.Right) && (oldState.IsKeyUp(Keys.Right)))
velocity = new Vector2(3, 0);
if (newState.IsKeyDown(Keys.Left) && (oldState.IsKeyUp(Keys.Left)))
velocity = new Vector2(-3, 0);
if (newState.IsKeyDown(Keys.Down) && (oldState.IsKeyUp(Keys.Down)))
velocity = new Vector2(0, 3);
if (newState.IsKeyDown(Keys.Up) && (oldState.IsKeyUp(Keys.Up)))
velocity = new Vector2(0, -3);
}
public void snakeUp() {
position += velocity;
}
}
}
You're not assigning oldState and newState correctly: you're initializing those variables (incorrectly) only one time when Game1 is instantiated. You'll need something like this:
public class Game1 : Game {
KeyboardState oldState = Keyboard.GetState();
KeyboardState newState = Keyboard.GetState();
// ...
protected override void Update(GameTime gameTime) {
oldState = newState;
newState = Keyboard.GetState();
// ...
}
}
You are not updating your keyboard state. Write something like this inside your Update method (before listener):
oldState = newState;
newState = Keyboard.GetState();

I have an error in some basic XNA 4.0 code

I am new to XNA and found a tutorial online for making a pong like game using it.I am going through the tutorial but I am getting an error even though it is the exact same code.Here is my Game1.cs* code:
using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;
namespace WindowsGame1
{
/// <summary>
/// This is the main type for your game
/// </summary>
public class Game1 : Microsoft.Xna.Framework.Game
{
GraphicsDeviceManager graphics;
SpriteBatch spriteBatch;
Paddle paddle;
Rectangle screenBounds;
public Game1()
{
graphics = new GraphicsDeviceManager(this);
Content.RootDirectory = "Content";
screenBounds = new Rectangle(
0,
0,
graphics.PreferredBackBufferWidth,
graphics.PreferredBackBufferHeight);
}
/// <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();
}
/// <summary>
/// LoadContent will be called once per game and is the place to load
/// all of your content.
/// </summary>
protected override void LoadContent()
{
spriteBatch = new SpriteBatch(GraphicsDevice);
Texture2D tempTexture = Content.Load<Texture2D>("paddle");
paddle = new Paddle(tempTexture, screenBounds);
}
/// <summary>
/// UnloadContent will be called once per game and is the place to unload
/// all content.
/// </summary>
protected override void UnloadContent()
{
// TODO: Unload any non ContentManager content here
}
/// <summary>
/// Allows the game to run logic such as updating the world,
/// checking for collisions, gathering input, and playing audio.
/// </summary>
/// <param name="gameTime">Provides a snapshot of timing values.</param>
protected override void Update(GameTime gameTime)
{
// Allows the game to exit
if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed)
this.Exit();
paddle.Update();
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();
paddle.Draw(spriteBatch);
spriteBatch.End();
base.Draw(gameTime);
}
}
}
I also have this class
using System.Text;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
namespace BreakingOut
{
class Paddle
{
Vector2 position;
Vector2 motion;
float paddleSpeed = 8f;
KeyboardState keyboardState;
GamePadState gamePadState;
Texture2D texture;
Rectangle screenBounds;
public Paddle(Texture2D texture, Rectangle screenBounds)
{
this.texture = texture;
this.screenBounds = screenBounds;
SetInStartPosition();
}
public void Update()
{
motion = Vector2.Zero;
keyboardState = Keyboard.GetState();
gamePadState = GamePad.GetState(PlayerIndex.One);
if (keyboardState.IsKeyDown(Keys.Left))
motion.X = -1;
if (keyboardState.IsKeyDown(Keys.Right))
motion.X = 1;
if (gamePadState.ThumbSticks.Left.X < -.5f)
motion.X = -1;
if (gamePadState.ThumbSticks.Left.X > .5f)
motion.X = 1;
motion.X *= paddleSpeed;
position += motion;
LockPaddle();
}
private void LockPaddle()
{
if (position.X < 0)
position.X = 0;
if (position.X + texture.Width > screenBounds.Width)
position.X = screenBounds.Width - texture.Width;
}
public void SetInStartPosition()
{
position.X = (screenBounds.Width - texture.Width) / 2;
position.Y = screenBounds.Height - texture.Height - 5;
}
public void Draw(SpriteBatch spriteBatch)
{
spriteBatch.Draw(texture, position, Color.White);
}
public Rectangle GetBounds()
{
return new Rectangle(
(int)position.X,
(int)position.Y,
texture.Width,
texture.Height);
}
}
}
this code so far is just for creating a paddle that the user can move.I also have an image of the paddle loaded in properly.This is the error it produces:
The type or namespace name 'Paddle' could not be found (are you missing a using directive or an assembly reference?)
This is the part producing this error:
Paddle paddle;
I have done exactly what the tutorial has said to do and it worked for whoever made the tutorial.Any help would be hugely appreciated and if you need more info just ask.Thank you.
The Paddle class is inside the "BreakingOut" namespace, which is not referenced on your Game1 class.
So you can either add the "using BreakingOut" before the Game1 class, or change the namespace of Paddle.
Option 1 would look like this:
using Microsoft.Xna.Framework.Media;
using BreakingOut; // Add the namespace of the object!!!!!
namespace WindowsGame1
Option 2 would be:
using Microsoft.Xna.Framework.Input;
namespace WindowsGame1 // Change the namespace of your object!!!!!
{
class Paddle
{
You need a reference to your Paddle class namespace, but if the Paddle class is in the same project just rename the namespace to WindowsGame1.
as Jason struckholf is saying to change namespace of paddle class
use this code
using System.Text;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
namespace WindowsGame1
{
class Paddle
{
Vector2 position;
Vector2 motion;
float paddleSpeed = 8f;
KeyboardState keyboardState;
GamePadState gamePadState;
Texture2D texture;
Rectangle screenBounds;
public Paddle(Texture2D texture, Rectangle screenBounds)
{
this.texture = texture;
this.screenBounds = screenBounds;
SetInStartPosition();
}
public void Update()
{
motion = Vector2.Zero;
keyboardState = Keyboard.GetState();
gamePadState = GamePad.GetState(PlayerIndex.One);
if (keyboardState.IsKeyDown(Keys.Left))
motion.X = -1;
if (keyboardState.IsKeyDown(Keys.Right))
motion.X = 1;
if (gamePadState.ThumbSticks.Left.X < -.5f)
motion.X = -1;
if (gamePadState.ThumbSticks.Left.X > .5f)
motion.X = 1;
motion.X *= paddleSpeed;
position += motion;
LockPaddle();
}
private void LockPaddle()
{
if (position.X < 0)
position.X = 0;
if (position.X + texture.Width > screenBounds.Width)
position.X = screenBounds.Width - texture.Width;
}
public void SetInStartPosition()
{
position.X = (screenBounds.Width - texture.Width) / 2;
position.Y = screenBounds.Height - texture.Height - 5;
}
public void Draw(SpriteBatch spriteBatch)
{
spriteBatch.Draw(texture, position, Color.White);
}
public Rectangle GetBounds()
{
return new Rectangle(
(int)position.X,
(int)position.Y,
texture.Width,
texture.Height);
}
}
}

NullReferenceException was Unhandled - No idea why

I'm trying to code a very basic top down 2D game with XNA, and I've gotten to the part where I'm trying to add grass textures to the game and then draw those textures to the bottom portion of the screen.
However, I'm getting a "NullReferenceException was Unhandled" error on Line 32 of my Level.cs class. As I'm just new to XNA and fairly new (in comparison) to C#, I can't figure this out for the life of me.
UPDATE 1: Thanks mcmonkey4eva, that error is resolved. However, my code now stops during the Draw() method of my TestLevel class (Level.cs). The error is still a "NullReferenceException was Unhandled" error, and the methods are a bit different from what they were.
Anyone know this what I'm doing wrong here?
Here's my updated Level.cs class:
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;
using First.Tiles;
using First;
namespace First.Level
{
class TestLevel
{
//An array of groundtiles that will be set to grass, lava, etc
public GroundTile[,] groundlevel;
//Width/Height of the Level
int width, height;
Grass grass;
public TestLevel(int width, int height, ContentManager myContent)
{
content = myContent;
//I input my screen dimensions as my level size
this.width = width;
this.height = height;
groundlevel = new GroundTile[width, height];
grass = new Grass(content.Load<Texture2D>(#"Images\GroundTiles"));
}
//Drawing the grass near the bottom of the screen
public void generateGround()
{
for (int y = 0; y < height; y++)
{
for (int x = 0; x < width; x += 32)
{
if (y == (height - 100))
{
if (groundlevel[x, y] == null)
{
groundlevel[x, y] = grass;
}
}
}
}
}
public void draw(GameTime gameTime, SpriteBatch spriteBatch)
{
foreach(GroundTile ground in groundlevel)
{
ground.Draw(gameTime, spriteBatch); //Here's where the error is
}
}
public static ContentManager Content
{
get { return content; }
}
static ContentManager content;
}
}
Here's my updated Game1.cs class:
using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;
using First.Entity;
using First.Tiles;
using First.Level;
namespace First
{
/// <summary>
/// This is the main type for your game
/// </summary>
public class Game1 : Microsoft.Xna.Framework.Game
{
const int SCREEN_WIDTH = 600;
const int SCREEN_HEIGHT = 400;
GraphicsDeviceManager graphics;
SpriteBatch spriteBatch;
TestLevel level;
UserControlledSprite Lancer;
Texture2D lancerTexture;
Vector2 position = new Vector2(200, 200);
Point frameSize = new Point(32, 48);
int collisionOffset = 0;
Point currentFrame = new Point(0, 0);
Point sheetSize = new Point(4, 4);
Point spriteToUse = new Point(0, 0);
Vector2 speed = new Vector2(2, 2);
int millisecondsPerFrame = 500;
Rectangle clientBounds;
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
clientBounds = graphics.GraphicsDevice.Viewport.Bounds;
clientBounds.Width = SCREEN_WIDTH;
clientBounds.Height = SCREEN_HEIGHT;
this.IsMouseVisible = true;
base.Initialize();
}
/// <summary>
/// LoadContent will be called once per game and is the place to load
/// all of your content.
/// </summary>
protected override void LoadContent()
{
// Create a new SpriteBatch, which can be used to draw textures.
spriteBatch = new SpriteBatch(GraphicsDevice);
Content.RootDirectory = "Content";
level = new TestLevel(SCREEN_WIDTH, SCREEN_HEIGHT, Content);
level.generateGround();
lancerTexture = Content.Load<Texture2D>(#"Images\Lancer");
Lancer = new UserControlledSprite(lancerTexture, position, frameSize, collisionOffset,
currentFrame, sheetSize, spriteToUse, speed, millisecondsPerFrame);
}
/// <summary>
/// UnloadContent will be called once per game and is the place to unload
/// all content.
/// </summary>
protected override void UnloadContent()
{
// TODO: Unload any non ContentManager content here
}
/// <summary>
/// Allows the game to run logic such as updating the world,
/// checking for collisions, gathering input, and playing audio.
/// </summary>
/// <param name="gameTime">Provides a snapshot of timing values.</param>
protected override void Update(GameTime gameTime)
{
// Allows the game to exit
if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed)
this.Exit();
Lancer.Update(gameTime, clientBounds);
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();
Lancer.Draw(gameTime, spriteBatch);
level.draw(gameTime, spriteBatch);
spriteBatch.End();
base.Draw(gameTime);
}
}
}
Here's my Grass.cs class:
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;
using First.Tiles;
using First;
namespace First.Level
{
class TestLevel
{
//An array of groundtiles that will be set to grass, lava, etc
public GroundTile[,] groundlevel;
//Width/Height of the Level
int width, height;
Grass grass;
public TestLevel(int width, int height, ContentManager myContent)
{
content = myContent;
//I input my screen dimensions as my level size
this.width = width;
this.height = height;
groundlevel = new GroundTile[width, height];
grass = new Grass(content.Load<Texture2D>(#"Images\GroundTiles"));
}
//Drawing the grass near the bottom of the screen
public void generateGround()
{
for (int y = 0; y < height; y++)
{
for (int x = 0; x < width; x += 32)
{
if (y == (height - 100))
{
if (groundlevel[x, y] == null)
{
groundlevel[x, y] = grass;
}
}
}
}
}
public void draw(GameTime gameTime, SpriteBatch spriteBatch)
{
foreach(GroundTile ground in groundlevel)
{
ground.Draw(gameTime, spriteBatch);
}
}
public static ContentManager Content
{
get { return content; }
}
static ContentManager content;
}
}
Just in case, here's my GroundTile class too:
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;
using First.Entity;
namespace First.Tiles
{
class GroundTile
{
//public GroundTile grass = new Grass(content.Load<Texture2D>(#"Images\GroundTiles"));
// frameSize needs to be modular, for the objects above walking-ground level
public Texture2D texture;
protected Point frameSize;
public Point frame;
public Vector2 position;
int collisionOffset;
protected Point sheetSize = new Point(9, 19);
public GroundTile(Texture2D tiles, Point frame, Point frameSize, int collisionOffset)
{
this.frame = frame;
this.frameSize = frameSize;
this.collisionOffset = collisionOffset;
this.texture = tiles;
}
//Collision Detection, incase of water or something
public Rectangle collisionRect
{
get
{
return new Rectangle(
(int)position.X + collisionOffset,
(int)position.Y + collisionOffset,
frameSize.X - (collisionOffset * 2),
frameSize.Y - (collisionOffset * 2));
}
}
//Not really used, but just in case
public bool collidesWith(GroundTile tile, Sprite sprite)
{
if (sprite.collisionRect.Intersects(collisionRect))
{
sprite.position -= sprite.direction;
}
return false;
}
public static ContentManager Content
{
get { return content; }
}
static ContentManager content;
public GraphicsDevice Graphicsdevice
{
get { return graphicsDevice; }
}
GraphicsDevice graphicsDevice;
public virtual void Draw(GameTime gameTime, SpriteBatch spriteBatch)
{
spriteBatch.Draw(texture,
position,
new Rectangle(frame.X * frameSize.X,
frame.Y * frameSize.Y,
frameSize.X, frameSize.Y),
Color.White, 0, Vector2.Zero,
1f, SpriteEffects.None, 0);
}
}
}
You're accessing Content before it's set - or, rather, you're never setting it at all.
Change
public TestLevel(int width, int height)
{
//I input my screen dimensions as my level size
to
public TestLevel(int width, int height, ContentManager myContent)
{
content = myContent;
//I input my screen dimensions as my level size
and then add the Content argument when you create your TestLevel object (I assume from Game1.cs) (Note: Be sure to create TestLevel after you create the Content object [in the LoadContent method]!)
EDIT:
For the new problem:
You're not defining the contents of the array, except a single layer of grass...
The line
ground.Draw(gameTime, spriteBatch);
Change to
if (ground != null)
{
ground.Draw(gameTime, spriteBatch);
}
But you should also make sure that ground is actually getting filled with content... specifically, new tile objects for each and every point in the array, not just a single line, and not just the same 'grass' instance for every location.
I don't mean to offend, but you're dealing with pretty basic errors here. It might be beneficial for you to look up and follow some basic C# tutorials.
I don't know about XNA, but clearly you Content. returns null.
Is this a class name or a property of your level class? If it's a property, then make sure it is initialized. Otherwize, I don't understand how you would received a nullreferenceexception if you call a static property of a class

SpriteBatch System.ArgumentNullException

I am writing a simple game based on grid movements, something like Sokoban game. I need to use several different text files to store levels. I wrote some code, and now I get error:
System.ArgumentNullException "This method does not accept null for
this parameter. Nazwa parametru: texture"
Whole code is in several files. What is wrong with my code?
Game1.cs
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;
namespace Sokoban
{
/// <summary>
/// This is the main type for your game
/// </summary>
public class Game1 : Microsoft.Xna.Framework.Game
{
GraphicsDeviceManager graphics;
SpriteBatch spriteBatch;
public Texture2D tOtoczenie;
public Rectangle kOtoczenie;
Sceny scena;
public Game1()
{
graphics = new GraphicsDeviceManager(this);
graphics.PreferredBackBufferHeight = 660; // 11
graphics.PreferredBackBufferWidth = 900; // 15
Content.RootDirectory = "Content";
}
// Sterowanie po gridzie (en - grid movement with stops)
KeyboardState stanKlawiatury, poprzedniStanKlawiatury;
public bool WcisnietyKlawisz(Keys klawisz)
{
return stanKlawiatury.IsKeyDown(klawisz) && poprzedniStanKlawiatury.IsKeyUp(klawisz);
}
/// <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
scena = new Sceny();
base.Initialize();
}
/// <summary>
/// LoadContent will be called once per game and is the place to load
/// all of your content.
/// </summary>
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
tOtoczenie = Content.Load<Texture2D>("Otoczenie");
kOtoczenie = new Rectangle(0, 0, 900, 660);
}
/// <summary>
/// UnloadContent will be called once per game and is the place to unload
/// all content.
/// </summary>
protected override void UnloadContent()
{
// TODO: Unload any non ContentManager content here
}
/// <summary>
/// Allows the game to run logic such as updating the world,
/// checking for collisions, gathering input, and playing audio.
/// </summary>
/// <param name="gameTime">Provides a snapshot of timing values.</param>
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
poprzedniStanKlawiatury = stanKlawiatury;
stanKlawiatury = Keyboard.GetState();
if (WcisnietyKlawisz(Keys.Right))
scena.wspX += 60;
else if (WcisnietyKlawisz(Keys.Left))
scena.wspX -= 60;
else if (WcisnietyKlawisz(Keys.Up))
scena.wspY -= 60;
else if (WcisnietyKlawisz(Keys.Down))
scena.wspY += 60;
if (Keyboard.GetState().IsKeyDown(Keys.NumPad1))
scena.LoadScene("level1");
scena.Update();
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);
// TODO: Add your drawing code here
spriteBatch.Begin();
spriteBatch.Draw(tOtoczenie, kOtoczenie, Color.White);
spriteBatch.End();
scena.Draw(spriteBatch);
base.Draw(gameTime);
}
}
}
Sceny.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using System.IO;
using Microsoft.Xna.Framework.Content;
namespace Sokoban
{
public class Sceny
{
public List<ObiektyGry> sciany;
public List<ObiektyGry> sloty;
public List<ObiektyGry> diamenty;
public List<ObiektyGry> graczL;
public Texture2D tDiament;
public Texture2D tSlot;
public Texture2D tSciana;
public Rectangle kDiament;
public Rectangle kSlot;
public Rectangle kSciana;
public Texture2D tGracz;
public Rectangle kGracz;
public int wspX;
public int wspY;
public Sceny()
{
sciany = new List<ObiektyGry>();
sloty = new List<ObiektyGry>();
diamenty = new List<ObiektyGry>();
graczL = new List<ObiektyGry>();
}
public void LoadContent(ContentManager theContentManager, string theAssetName)
{
tGracz = theContentManager.Load<Texture2D>("Gracz");
tDiament = theContentManager.Load<Texture2D>("Diament");
tSlot = theContentManager.Load<Texture2D>("Slot");
tSciana = theContentManager.Load<Texture2D>("Ściana");
}
public void Update()
{
foreach (ObiektyGry obiekt in sciany)
obiekt.Update();
foreach (ObiektyGry obiekt in sloty)
obiekt.Update();
foreach (ObiektyGry obiekt in diamenty)
obiekt.Update();
foreach (ObiektyGry obiekt in graczL)
obiekt.Update();
}
public void Draw(SpriteBatch spriteBatch)
{
foreach (ObiektyGry obiekt in sciany)
obiekt.Draw(spriteBatch, obiekt.Tekstura, obiekt.Kształt);
foreach (ObiektyGry obiekt in sloty)
obiekt.Draw(spriteBatch, obiekt.Tekstura, obiekt.Kształt);
foreach (ObiektyGry obiekt in diamenty)
obiekt.Draw(spriteBatch, obiekt.Tekstura, obiekt.Kształt);
foreach (ObiektyGry obiekt in graczL)
obiekt.Draw(spriteBatch, obiekt.Tekstura, obiekt.Kształt);
}
public void LoadScene(string name)
{
sciany.Clear();
graczL.Clear();
diamenty.Clear();
sloty.Clear();
StreamReader reader = new StreamReader(name+".txt");
int x = 0;
int y = 0;
string file = reader.ReadToEnd();
for (int i = 0; i<file.Length; i++)
{
if (file[i] == 13)
{
y++;
x = 0;
}
else if (file[i] != 10)
x++;
if (file[i] == '1' ) // sciana
{
ObiektyGry sciana = new ObiektyGry();
sciana.Kształt = new Rectangle(x * 60, y * 60,60,60);
sciana.Tekstura = tSciana;
sciany.Add(sciana);
}
else if (file[i] == '2') // slot
{
ObiektyGry slot = new ObiektyGry();
slot.Kształt = new Rectangle(x * 60, y * 60, 60, 60);
slot.Tekstura = tSlot;
sloty.Add(slot);
}
else if (file[i] == '3') // diament
{
ObiektyGry diament = new ObiektyGry();
diament.Kształt = new Rectangle(x * 60, y * 60, 60, 60);
diament.Tekstura = tDiament;
diamenty.Add(diament);
}
else if (file[i] == '4') //gracz
{
ObiektyGry gracz = new ObiektyGry();
wspX = x * 60;
wspY = y * 60;
gracz.Kształt = new Rectangle(wspX, wspY, 60, 60);
gracz.Tekstura = tGracz;
graczL.Add(gracz);
}
}
}
}
}
ObiektyGry.cs
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 Sokoban
{
public class ObiektyGry
{
public Rectangle Kształt { get; internal set; }
public Texture2D Tekstura { get; internal set; }
public static ContentManager contentManager;
public ObiektyGry()
{
}
public void Update()
{
}
public void Draw(SpriteBatch spriteBatch, Texture2D Tekstura, Rectangle Ksztalt)
{
//Tekstura = obiekt.Tekstura;
//Kształt = obiekt.Kształt;
//spriteBatch.Begin();
spriteBatch.Draw(Tekstura, Ksztalt, Color.White);
//spriteBatch.End();
}
}
}
level1.txt (for example)
111111111111111
100000000000001
100000000000001
100000000000001
100020000000001
100000034000001
100000000000001
100000000000001
100000000000001
100000000000001
111111111111111
Yea, as already mentioned in the comments, you haven't loaded your textures for your sceny. I see that you have loaded your level, but not your textures...
So, I deleted all Sceny class and I implemented level changing in Game1 class. After that I hadn't any problem with textures at all!

Categories