I seem to be getting a null error and I can't for the life of me solve it. I'm basically creating a Tetris clone, but I can't seem to get this to work. I'm creating an array to hold the square shape, and then I am creating rectangles that are the same size, position etc as the square shape so I can use it for collision detection. I've also created rectangles for every tile space on the grid.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
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 Microsoft.Xna.Framework.Net;
using Microsoft.Xna.Framework.Storage;
namespace tetris
{
class square : sprite
{
// declare random, to be used with the position of the square shape
Random Rand = new Random();
public const int
START = 0, // newly created sprite
FALLING = 1, // square is falling
END = 2; // when sprite is finished
int _state;// state for the switch statement
//array for the square
public sprite[] squareArray = new sprite[4];
//create a new rectangle array so each square tile has a rectangle around it
public Rectangle[] shapeTile = new Rectangle[4];
const int startingWidth = 101;
const int startingHeight = 20;
const int height = 16;
const int width = 10;
// declare timer, to be used with the game clock for the square to be moving downward
int _timer;
// declare velocity for falling square
float _velocityX;
double _velocityY;
// declare rotation for square
double rotation;
// starting position for shape
public Vector2 startingPosition = new Vector2(205, 20);
// Constructor
public square(Texture2D tileImage, SpriteBatch sprite, Vector2 pos)
: base(tileImage, sprite, pos)
{
_velocityX = 1;
//starting position of the tile
pos = startingPosition;
//Initialises 2D array of tiles for square
//Array for the square!
for (int i = 0; i < 4; i++)
{
squareArray[i] = new sprite(tileImage, spriteBatch, startingPosition);
}
// put starting positions for each tile for the square
squareArray[0].position = new Vector2(startingPosition.X + 0, startingPosition.Y + 0);
squareArray[1].position = new Vector2(startingPosition.X + 35, startingPosition.Y + 0);
squareArray[2].position = new Vector2(startingPosition.X + 0, startingPosition.Y + 35);
squareArray[3].position = new Vector2(startingPosition.X + 35, startingPosition.Y + 35);
//shapeTile[0].X = squareArray[0].position.X;
//for (int q = 0; q < 4; q++)
//{
//for (int w = 0; w < 4; w++)
//{
//shapeTile[0] = new Rectangle((startingWidth + (q * 35)), (startingHeight + (w * 35)), 35, 35);
///// creating each rectangle so it has the same properties as the actual square (position, size etc)
shapeTile[0] = new Rectangle((int)(squareArray[0].position.X), (int)(squareArray[0].position.Y), shapeTile[0].Width, shapeTile[0].Height);
shapeTile[1] = new Rectangle((int)(squareArray[0].position.X), (int)(squareArray[1].position.Y), shapeTile[1].Width, shapeTile[1].Height);
shapeTile[2] = new Rectangle((int)(squareArray[2].position.X), (int)(squareArray[2].position.Y), shapeTile[2].Width, shapeTile[2].Height);
shapeTile[0] = new Rectangle((int)(squareArray[3].position.X), (int)(squareArray[3].position.Y), shapeTile[3].Width, shapeTile[3].Height);
{
_state = START; // start spawning square
}
}
public void Update(KeyboardState kbState)
{
switch (_state)
{
case START: // state 1, start
// tiles for the square are visible
squareArray[0].visible = true;
squareArray[1].visible = true;
squareArray[2].visible = true;
squareArray[3].visible = true;
_state = FALLING;
break;
case FALLING:
//movement of square using keyboard
if (kbState.IsKeyDown(Keys.Right))
{
squareArray[0].position.X += 35.0f * _velocityX; // X position moves 1 tile across
squareArray[1].position.X += 35.0f * _velocityX; // X position moves 1 tile across
squareArray[2].position.X += 35.0f * _velocityX; // X position moves 1 tile across
squareArray[3].position.X += 35.0f * _velocityX; // X position moves 1 tile across
}
if (kbState.IsKeyDown(Keys.Left))
{
squareArray[0].position.X -= 35.0f; // X position moves 1 tile across
squareArray[1].position.X -= 35.0f; // X position moves 1 tile across
squareArray[2].position.X -= 35.0f; // X position moves 1 tile across
squareArray[3].position.X -= 35.0f; // X position moves 1 tile across
}
if (kbState.IsKeyDown(Keys.Down))
{
squareArray[0].position.Y += 35.0f; // X position moves 1 tile across
squareArray[1].position.Y += 35.0f; // X position moves 1 tile across
squareArray[2].position.Y += 35.0f; // X position moves 1 tile across
squareArray[3].position.Y += 35.0f; // X position moves 1 tile across
}
//updating rectangles for square as it is moving
shapeTile[0].X = (int)(squareArray[0].position.X);
shapeTile[0].Y = (int)(squareArray[0].position.Y);
shapeTile[1].X = (int)(squareArray[1].position.X);
shapeTile[1].Y = (int)(squareArray[1].position.Y);
shapeTile[2].X = (int)(squareArray[2].position.X);
shapeTile[2].Y = (int)(squareArray[2].position.Y);
shapeTile[3].X = (int)(squareArray[3].position.X);
shapeTile[3].Y = (int)(squareArray[3].position.Y);
//end square if bottom tile it goes below the grid
if (squareArray[3].position.Y > 525)
{
_state = END;
}
//end square if bottom tile it goes below the grid
if (squareArray[2].position.Y > 525)
{
_state = END;
}
break;
case END:
// if square is finished, no longer see the tiles
Finished = true;
squareArray[0].visible = false;
squareArray[1].visible = false;
squareArray[2].visible = false;
squareArray[3].visible = false;
break;
}
}
//Draws tile using spritebatch
public void Draw(GameTime gameTime)
{
for (int i = 0; i < 4; i++)
{
squareArray[i].DrawTile(gameTime);
}
}
}
}
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 Microsoft.Xna.Framework.Net;
using Microsoft.Xna.Framework.Storage;
namespace tetris
{
class gameBoard
{
//create a new sprite array - tileArray
public sprite[,] tileArray;
const int height = 16;
const int width = 10;
// create a new rectangle array for the board
public Rectangle[,] recTile;
const int startingWidth = 101;
const int startingHeight = 20;
public gameBoard(SpriteBatch sprite, Texture2D tile)
{
//Initialises 2D array of tiles
tileArray = new sprite[width, height];
//Create and position each tile
for (int x = 0; x < width; x++)
{
for (int y = 0; y < height; y++)
{
tileArray[x, y] = new sprite(tile, sprite, new Vector2((startingWidth + (x * 35)), (startingHeight + (y * 35))));
}
}
// create and position each rectangle at the exact coordinates as every tile on the grid
recTile = new Rectangle[width, height];
for (int b = 0; b < width; b++)
{
for (int c = 0; c < height; c++)
{
recTile[b, c] = new Rectangle((startingWidth + (b * 35)), (startingHeight + (c * 35)), 35, 35);
}
}
}
public void Update(GameTime gameTime)
{
}
//Draws each sprite in the grid, if it is visible
public void Draw(GameTime gameTime)
{
for (int x = 0; x < width; x++)
{
for (int y = 0; y < height; y++)
{
if (tileArray[x, y].visible == true)
{
tileArray[x, y].DrawTile(gameTime);
}
}
}
}
}
}
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 Microsoft.Xna.Framework.Net;
using Microsoft.Xna.Framework.Storage;
namespace tetris
{
/// <summary>
/// This is the main type for your game
/// </summary>
public class Game1 : Microsoft.Xna.Framework.Game
{
GraphicsDeviceManager graphics;
SpriteBatch spriteBatch;
Texture2D background;
Texture2D tile;
gameBoard board;
square shape;
int _state;
int score;
SpriteFont messageFont;
const int
INSERT_COIN = 0,
PLAYING = 1,
GAME_OVER = 2;
public Game1()
{
graphics = new GraphicsDeviceManager(this);
//Sets size of window
graphics.PreferredBackBufferHeight = 800;
graphics.PreferredBackBufferHeight = 600;
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
board = new gameBoard (spriteBatch, tile);
shape = new square(tile, spriteBatch, new Vector2(110, 10));
//shape.shapeTile[0] = new Rectangle((int)(shape.squareArray[0].position.X), (int)(shape.squareArray[0].position.Y), shape.shapeTile[0].Width, shape.shapeTile[0].Height);
//shape.shapeTile[1] = new Rectangle((int)(shape.squareArray[0].position.X), (int)(shape.squareArray[1].position.Y), shape.shapeTile[1].Width, shape.shapeTile[1].Height);
//shape.shapeTile[2] = new Rectangle((int)(shape.squareArray[2].position.X), (int)(shape.squareArray[2].position.Y), shape.shapeTile[2].Width, shape.shapeTile[2].Height);
//shape.shapeTile[3] = new Rectangle((int)(shape.squareArray[3].position.X), (int)(shape.squareArray[3].position.Y), shape.shapeTile[3].Width, shape.shapeTile[3].Height);
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);
//Load images
background = Content.Load<Texture2D>("Background");
tile = Content.Load<Texture2D>("Tile");
messageFont = this.Content.Load<SpriteFont>("font");
// 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();
KeyboardState kbState = Keyboard.GetState();
// switch statement for the gameplay
switch (_state)
{
case INSERT_COIN:
shape = null;
score = 0;
if (kbState.IsKeyDown(Keys.Escape)) _state = PLAYING;
break;
case PLAYING:
if (shape == null) shape = new square(tile, spriteBatch, new Vector2(205, 20));
shape.Update(kbState);
board.Update(gameTime);
if (shape.Finished) score += 30;
if (shape.Finished) shape = null;
// create and position each rectangle at the exact coordinates as every tile on the grid
board.recTile = new Rectangle[10, 16];
for (int b = 0; b < 10; b++)
{
for (int c = 0; c < 16; c++)
{
board.recTile[b, c] = new Rectangle((101 + (b * 35)), (20 + (c * 35)), 35, 35);
}
}
////// TEST COLLISION //////
//for each tile in the square x
for (int q = 0; q < 4; q++)
{
//for each tile in the square y
for (int w = 0; w < 4; w++)
{
//for each tile on the board x axis
for (int b = 0; b < 10; b++)
{
//for each tile on the board y axis
for (int c = 0; c < 16; c++)
{
if ((shape.shapeTile[0].Intersects(board.recTile[b, c]))) //) // ERROR IS HERE!
{
board.tileArray[b, c].visible = true;
//shape.squareArray[1].visible = true;
//shape.squareArray[2].visible = true;
//shape.squareArray[3].visible = true;
}
}
}
}
}
break;
case GAME_OVER:
if (score == 40) _state = INSERT_COIN;
break;
default:
break;
}
// TODO: Add your update logic here
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();
switch (_state)
{
case INSERT_COIN:
spriteBatch.DrawString(messageFont, "Press ESC key to start game", new Vector2(220, 300), Color.White);
break;
case PLAYING:
spriteBatch.Draw(background, new Vector2(0, 0), Color.White);
board.Draw(gameTime);
if (shape != null) shape.Draw(gameTime);
break;
case GAME_OVER:
spriteBatch.Draw(background, new Vector2(0, 0), Color.White);
break;
default:
break;
}
spriteBatch.End();
// TODO: Add your drawing code here
base.Draw(gameTime);
}
}
}
Error at run-time is:
Object reference not set to an instance of an object.
Any help would be greatly appreciated.
DaveT