namespace SpaceInvader
{
/// <summary>
/// This is the main type for your game
/// </summary>
public class SpaceInvaders : Microsoft.Xna.Framework.Game
{
GraphicsDeviceManager graphics;
SpriteBatch spriteBatch;
Texture2D StarfieldImg;
Texture2D InvaderImg;
Texture2D AltInvaderImg;
Texture2D RocketLauncherImg;
Texture2D MissileImg;
int RocketXPos;
int AlienDirection;
int AlienSpeed;
Invader[] Invaders;
double Ticks;
Missile MissileFired;
public SpaceInvaders()
{
graphics = new GraphicsDeviceManager(this);
graphics.PreferredBackBufferWidth = 1024;
graphics.PreferredBackBufferHeight = 768;
graphics.ApplyChanges();
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
RocketXPos = 512;
AlienDirection = -1;
AlienSpeed = 16;
Invaders = new Invader[11];
int XPos = 512;
for (int Count = 0; Count < 11; Count++)
{
Invaders[Count] = new Invader();
Invaders[Count].SetXPos(XPos);
Invaders[Count].SetYPos(100);
XPos = XPos + 32;
}
Ticks = 0;
MissileFired = null;
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
StarfieldImg = Content.Load<Texture2D>("Starfield1024x768");
InvaderImg = Content.Load<Texture2D>("inv1");
AltInvaderImg = Content.Load<Texture2D>("inv12");
RocketLauncherImg = Content.Load<Texture2D>("LaserBase");
MissileImg = Content.Load<Texture2D>("bullet");
}
/// <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
MissileFired.Move();
if (Keyboard.GetState().IsKeyDown(Keys.Space))
{
MissileFired = new Missile(RocketXPos, 650);
}
if (Keyboard.GetState().IsKeyDown(Keys.Left))
{
RocketXPos = RocketXPos - 4;
}
if (Keyboard.GetState().IsKeyDown(Keys.Right))
{
RocketXPos = RocketXPos + 4;
}
if (RocketXPos < 100)
{
RocketXPos = 100;
}
if (RocketXPos > 924)
{
RocketXPos = 924;
}
Ticks = Ticks + gameTime.ElapsedGameTime.TotalMilliseconds;
if (Ticks > 500)
{
for (int Count = 0; Count < 11; Count++)
{
Invaders[Count].MoveHorizontal(AlienSpeed * AlienDirection);
}
if (Invaders[0].GetXPos() < 96)
{
AlienDirection = +1;
int XPos = 96;
for (int Count = 0; Count < 11; Count++)
{
Invaders[Count].MoveVertical(4);
Invaders[Count].SetXPos(XPos);
XPos = XPos + InvaderImg.Width;
}
}
if (Invaders[10].GetXPos() > 924)
{
AlienDirection = -1;
int XPos = 924 - InvaderImg.Width * 10;
for (int Count = 0; Count < 11; Count++)
{
Invaders[Count].MoveVertical(4);
Invaders[Count].SetXPos(XPos);
XPos = XPos + InvaderImg.Width;
}
}
Ticks = 0;
}
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)
{
spriteBatch.Begin();
spriteBatch.Draw(StarfieldImg, Vector2.Zero, Color.White);
spriteBatch.Draw(RocketLauncherImg, new Vector2(RocketXPos, 650), Color.White);
if (MissileFired != null)
{
Vector2 MissilePos = new
Vector2(MissileFired.GetPosition().X, MissileFired.GetPosition().Y - MissileImg.Height);
spriteBatch.Draw(MissileImg, MissilePos, Color.White);
}
for (int Count = 0; Count < 11; Count++)
{
spriteBatch.Draw(InvaderImg, Invaders[Count].GetPos(), Color.White);
}
spriteBatch.End();
base.Draw(gameTime);
}
}
}
尝试运行此游戏时,MissileFired.Move带有空引用异常的下划线。我认为它可能在绘制或更新方法中缺少一些东西,但我不知道。有关此异常的详细信息指出“对象引用未设置为对象的实例”。帮助会很棒,谢谢!。
答案 0 :(得分:2)
对象MissileFired
为空。当您尝试在空对象(例如Move()
)上调用成员时,您将获得NullReferenceException
。
从我在代码中看到的情况来看,MissileFired
是通过按键有条件地创建的,因此尝试使用它的代码可能首先执行空检查而不是假设它存在:
if (MissileFired != null)
{
MissileFired.Move();
}
对我来说这是有道理的,导弹只有在被射击时才会存在,但代码需要处理这两种情况。
答案 1 :(得分:1)
protected override void Initialize()
{
...
MissileFired = null;
...
}
这是一个问题 - 游戏启动后MissleFired为null,因此在您确定已初始化之前,不能在Update()方法中使用null-check。