我试图在我的子弹和敌人之间制造碰撞。我为每个创建了边框,并将它们放入自己的类中。但是,我在HandleCollision
函数中得到Null引用错误,特别是在带有边界框的if语句中。我还会发布我的其余代码。
我和两位讲师和一些同伴讨论过这个问题,因为子弹和敌人等于零。这是因为敌人需要几秒钟的时间才能产生,子弹只有在被射击后才会产生。为了解决这个问题,我添加了一个if语句来检查子弹或敌人是否为空但它仍然会引发相同的错误。
HandleCollision功能
private void HandleCollision()//collision
{
Sprite toRemove = null;
if (bullet != null || enemyTexture != null)
{
foreach (EnemySprite e in enemyList) //checks each enemy sprite
{
if (bullet.BoundingBox.Intersects(enemy.BoundingBox))
{
enemyList.Remove(enemy); //removes enemy
//toRemove = enemy;
break;
}
}
}
}
Game1.cs
public class Game1 : Microsoft.Xna.Framework.Game
{
GraphicsDeviceManager graphics;
SpriteBatch spriteBatch;
Rectangle spriteRectangle;
Rectangle bulletBounds;
Rectangle enemyBounds;
Sprite player;
Bullets bullet;
EnemySprite enemy;
Texture2D enemyTexture;
List<EnemySprite> enemyList = new List<EnemySprite>();
List<Bullets> bulletsList = new List<Bullets>();
//Pause
bool paused = false;
Texture2D pauseTexture;
Rectangle pauseRectangle;
KeyboardState pastKey;
Vector2 enemyPos = new Vector2(100, 400);
Vector2 Position;
Vector2 Distance;
Vector2 spriteOrigin;
Vector2 spriteVelocity;
const float tangentialVelocity = 5f;
float friction = 0.1f;
float rotation;
float timer = 0f;
float dropInterval = 2f;
float speed = 4f;
float angle;
Random random;
enum GameState
{
MainMenu,
Options,
Help,
Playing,
Exit,
}
GameState CurrentGameState = GameState.MainMenu;
// Screen adjustments
int screenWidth = 800, screenHeight = 600;
cButton btnPlay;
cButtonExit btnExit;
public Game1()
{
graphics = new GraphicsDeviceManager(this);
Content.RootDirectory = "Content";
}
protected override void Initialize()
{
// TODO: Add your initialization logic here
random = new Random();
Position = new Vector2(150, 150);
this.IsMouseVisible = true;
base.Initialize();
}
protected override void LoadContent()
{
// Create a new SpriteBatch, which can be used to draw textures.
spriteBatch = new SpriteBatch(GraphicsDevice);
player = new Sprite();
player.Texture = Content.Load<Texture2D>("graphics/player");
// Screen stuff
graphics.PreferredBackBufferWidth = screenWidth;
graphics.PreferredBackBufferHeight = screenHeight;
//graphics.IsFullScreen = true;
graphics.ApplyChanges();
IsMouseVisible = true;
btnPlay = new cButton(Content.Load<Texture2D>("Graphics/play"), graphics.GraphicsDevice);
btnPlay.setPosition(new Vector2(350, 190));
btnExit = new cButtonExit(Content.Load <Texture2D>("Graphics/exit"), graphics.GraphicsDevice);
btnExit.setPosition(new Vector2(350, 220));
enemyTexture = Content.Load<Texture2D>("graphics/enemy");
player.Texture = Content.Load<Texture2D>("Graphics/player");
int screenCenterX = GraphicsDevice.Viewport.Width / 2;
player.Position = new Vector2(screenCenterX - (player.Texture.Width / 2), screenHeight - player.Texture.Height - 20);
pauseTexture = Content.Load<Texture2D>("graphics/paused");
pauseRectangle = new Rectangle(0, 0, pauseTexture.Width, pauseTexture.Height);
Bullets.BulletTexture = Content.Load<Texture2D>("graphics/bullet");
}
protected override void Update(GameTime gameTime)
{
MouseState mouse = Mouse.GetState();
IsMouseVisible = true;
switch (CurrentGameState)
{
case GameState.MainMenu:
if (btnPlay.isClicked == true) CurrentGameState = GameState.Playing;
btnPlay.Update(mouse);
if (btnExit.isClicked == true) CurrentGameState = GameState.Help;
btnExit.Update(mouse);
if (btnExit.isClicked == true) CurrentGameState = GameState.Options;
btnExit.Update(mouse);
if (btnExit.isClicked == true) CurrentGameState = GameState.Exit;
btnExit.Update(mouse);
break;
case GameState.Playing:
timer += (float)gameTime.ElapsedGameTime.TotalSeconds;
if (timer >= dropInterval)
{
int yPos = random.Next(GraphicsDevice.Viewport.Height - 50);
enemyList.Add(new EnemySprite(enemyTexture, new Vector2(GraphicsDevice.Viewport.Width + 100, yPos)));
timer = 0f;
}
HandleCollision();
HandleMovingEnemy();
MouseState curMouse = Mouse.GetState();
Vector2 mouseLoc = new Vector2(curMouse.X, curMouse.Y);
Vector2 direction = mouseLoc - Position;
spriteRectangle = new Rectangle((int)Position.X, (int)Position.Y,
player.Texture.Width, player.Texture.Height);
Position = spriteVelocity + Position;
spriteOrigin = new Vector2(spriteRectangle.Width / 2, spriteRectangle.Height / 2);
Distance.X = mouse.X - Position.X;
Distance.Y = mouse.Y - Position.Y;
rotation = (float)Math.Atan2(Distance.Y, Distance.X); //calculates the rotation(trigonometry)
//angle = (float)(Math.Atan2(direction.Y, direction.X));
KeyboardState keyState = Keyboard.GetState();
if (keyState.IsKeyDown(Keys.A))
Position.X -= 2;
if (keyState.IsKeyDown(Keys.D))
Position.X += 2;
if (keyState.IsKeyDown(Keys.W))
Position.Y -= 2;
if (keyState.IsKeyDown(Keys.S))
Position.Y += 2;
//right and left edge detection
if (Position.X < 0)
Position = new Vector2(0, Position.Y);
int rightEdge = GraphicsDevice.Viewport.Width - player.Texture.Width;
if (Position.X > rightEdge)
Position = new Vector2(rightEdge, Position.Y);
//bottom and top edge detection
if (Position.Y < 0)
Position = new Vector2(Position.X, 0);
int bottomEdge = GraphicsDevice.Viewport.Height - player.Texture.Height;
if (Position.Y > bottomEdge)
Position = new Vector2(Position.X, bottomEdge);
if (!paused)
{
if (Keyboard.GetState().IsKeyDown(Keys.Escape))
{
paused = true;
btnPlay.isClicked = false; //so that everytime its paused I can pause it again
}
enemy.Update();
}
else if(paused)
{
if (btnPlay.isClicked)
{
paused = false;
speed = 4;
}
if (btnExit.isClicked)
Exit();
btnPlay.Update(mouse);
btnExit.Update(mouse);
}
if (Keyboard.GetState().IsKeyDown(Keys.C))
{
spriteVelocity.X = (float)Math.Cos(rotation) * tangentialVelocity;
spriteVelocity.Y = (float)Math.Sin(rotation) * tangentialVelocity;
}
else if (spriteVelocity != Vector2.Zero)
{
float i = spriteVelocity.X;
float j = spriteVelocity.Y;
spriteVelocity.X = i -= friction * i;
spriteVelocity.Y = j -= friction * j;
}
if (Keyboard.GetState().IsKeyDown(Keys.Space) && pastKey.IsKeyUp(Keys.Space))
Fire();
pastKey = Keyboard.GetState();
UpdateBullets();
break;
case GameState.Exit:
this.Exit();
break;
}
base.Update(gameTime);
}
public void UpdateBullets()
{
foreach (Bullets bullet in bulletsList)
{
bullet.position += bullet.velocity;
if(Vector2.Distance(bullet.position, Position) > 500) //finds position
bullet.isVisible = false;
}
for (int i = 0; i < bulletsList.Count; i++)
{
if (!bulletsList[i].isVisible)
{
bulletsList.RemoveAt(i);
i--;
}
}
}
//function to handle movement of enemies
private void HandleMovingEnemy()
{
List<EnemySprite> toRemove = new List<EnemySprite>();
foreach (EnemySprite e in enemyList)
{
if (e.Position.X < (-20))
{
toRemove.Add(e);
}
else
e.Position -= new Vector2(speed, 0);
}
if (toRemove.Count > 0)
{
foreach (EnemySprite e in toRemove)
{
enemyList.Remove(e);
}
}
}
private void HandleCollision()//collision
{
Sprite toRemove = null;
if (bullet != null || enemyTexture != null)
{
foreach (EnemySprite e in enemyList) //checks each enemy sprite
{
if (bullet.BoundingBox.Intersects(enemy.BoundingBox)) //checks if a sprite has intersected an enemy
{
enemyList.Remove(enemy); //removes enemy
//toRemove = enemy;
break;
}
}
}
}
public void Fire()
{
Bullets newBullet = new Bullets(Content.Load<Texture2D>("graphics/bullet"));
Bullets.BulletTexture = Content.Load<Texture2D>("graphics/bullet");
//newBullet.LoadContent(LoadContent);
newBullet.velocity = new Vector2((float)Math.Cos(rotation), (float)Math.Sin(rotation)) * 5f + spriteVelocity;
newBullet.position = Position + newBullet.velocity * 5;
newBullet.isVisible = true;
if (bulletsList.Count() < 20)
bulletsList.Add(newBullet);
}
protected override void Draw(GameTime gameTime)
{
GraphicsDevice.Clear(Color.CornflowerBlue);
spriteBatch.Begin();
switch (CurrentGameState)
{
case GameState.MainMenu:
spriteBatch.Draw(Content.Load<Texture2D>("Graphics/SeaSideDefenderMainMenu"), new Rectangle(0,0,screenWidth,screenHeight),Color.White);
btnPlay.Draw(spriteBatch);
btnExit.Draw(spriteBatch);
break;
case GameState.Playing:
spriteBatch.Draw(Content.Load<Texture2D>("Graphics/leveltest"), new Rectangle(0, 0, screenWidth, screenHeight), Color.White);
enemy = new EnemySprite();
enemy.Texture = Content.Load<Texture2D>("graphics/enemy");
enemy.Draw(spriteBatch);
spriteBatch.Draw(player.Texture, Position, null, Color.White, rotation, spriteOrigin, 1f, SpriteEffects.None, 0);
//player.Draw(spriteBatch);
foreach (EnemySprite e in enemyList)
{
e.Draw(spriteBatch);
}
foreach (Bullets bullet in bulletsList)
bullet.draw(spriteBatch);
/*for (int i; i < enemyList.Count; i++)
{
enemyList[i].Draw(spriteBatch);
}*/
if (paused)
{
speed = 0;
spriteBatch.Draw(Content.Load<Texture2D>("graphics/paused"), new Rectangle(0, 0, screenWidth, screenHeight), Color.White);
btnPlay.Draw(spriteBatch);
btnExit.Draw(spriteBatch);
}
break;
}
spriteBatch.End();
base.Draw(gameTime);
}
}
Bullets.cs
public class Bullets
{
public Texture2D texture;
public static Texture2D BulletTexture;
public Vector2 position;
public Vector2 velocity;
public Vector2 origin;
public bool isVisible;
public Rectangle BoundingBox
{
get { return new Rectangle((int)position.X, (int)position.Y, texture.Width, texture.Height); }
}
public Bullets(Texture2D newTexture)
{
texture = newTexture;
isVisible = false;
}
public void draw(SpriteBatch spriteBatch)
{
spriteBatch.Draw(texture,position,null,Color.White,0f,origin,1f, SpriteEffects.None, 0);
}
public void LoadContent(ContentManager Content)
{
BulletTexture = Content.Load<Texture2D>(@"graphics/bullet");
}
}
enemy.cs
public class EnemySprite
{
public Texture2D Texture { get; set; }
public Vector2 Position {get; set; }
public Vector2 origin;
public Vector2 velocity;
public Rectangle rectangle;
float rotation = 0f;
bool right;
float distance;
float oldDistance;
public Rectangle BoundingBox
{
get { return new Rectangle((int)Position.X, (int)Position.Y, Texture.Width, Texture.Height); } //uses enemy position and wiwdth to create bounding box
}
public EnemySprite() { }
public EnemySprite(Texture2D texture, Vector2 position)
{
Texture = texture;
Position = position;
oldDistance = distance;
}
float mouseDistance;
public void Update()
{
Position += velocity;
origin = new Vector2(Texture.Width / 2, Texture.Height / 2);
if (distance <= 0)
{
right = true;
velocity.X = 1f;
}
else if(distance <= oldDistance)
{
right = false;
velocity.X = -1f;
}
if (right) distance += 1; else distance -= 1;
MouseState mouse = Mouse.GetState();
mouseDistance = mouse.X - Position.X;
if (mouseDistance >= -200 && mouseDistance <= 200)
{
if (mouseDistance < -1)
velocity.X = -1f;
else if (mouseDistance > 1)
velocity.X = 1f;
else if (mouseDistance == 0)
velocity.X = 0f;
}
}
public void Draw(SpriteBatch spriteBatch)
{
if (Texture != null)
spriteBatch.Draw(Texture, Position, Color.White);
if (velocity.X > 0)
{
spriteBatch.Draw(Texture, Position, null, Color.White, rotation, origin, 1f, SpriteEffects.FlipHorizontally, 0f);
}
else
{
spriteBatch.Draw(Texture, Position, null, Color.White, rotation, origin, 1f, SpriteEffects.None, 0f);
}
}
}
答案 0 :(得分:1)
您尚未在game1.cs中的任何位置初始化全局变量Bullet
,因此您永远不会将bullet != null
视为真。然而,由于您已经在LoadContent()中初始化了enemyTexture != null
,因此您始终会enemyTexture
为真。
这意味着,在if
变量未初始化的情况下,您始终会输入Bullet
块。
希望这会引导您找到解决方案。
PS:如果这是最有帮助的,请将答案标记为“已接受”。