2014-10-02 12 views
0

저는 XNA에 대해 비교적 새롭고 경험이 없기 때문에 C# (http://xnagpa.net/xna4beginner.php)의 기본 브레이크 아웃 게임을 만드는 방법에 대한 Jamie McMahon의 안내를 따르고 있습니다. 최근에 Microsoft의 Game State Management 코드 샘플 (http://xbox.create.msdn.com/en-US/education/catalog/sample/game_state_management)을 우연히 발견하여 코드 샘플이 제공하는 메뉴를 활용할 수 있도록 브레이크 아웃 코드를 이동하려고 시도했습니다.spriteBatch.Begin이 NullReferenceException을 받고 있습니다.

#region File Description 
//----------------------------------------------------------------------------- 
// GameplayScreen.cs 
// 
// Microsoft XNA Community Game Platform 
// Copyright (C) Microsoft Corporation. All rights reserved. 
//----------------------------------------------------------------------------- 
#endregion 

#region Using Statements 
using System; 
using System.Threading; 
using Microsoft.Xna.Framework; 
using Microsoft.Xna.Framework.Content; 
using Microsoft.Xna.Framework.Graphics; 
using Microsoft.Xna.Framework.Input; 
using GameStateManagement; 
using System.Collections.Generic; 
using System.Linq; 
using Microsoft.Xna.Framework.Audio; 
using Microsoft.Xna.Framework.GamerServices; 
using Microsoft.Xna.Framework.Media; 
#endregion 

namespace Rebound 
{ 
    /// <summary> 
    /// This screen implements the actual game logic. It is just a 
    /// placeholder to get the idea across: you'll probably want to 
    /// put some more interesting gameplay in here! 
    /// </summary> 
    public class GameplayScreen : GameScreen 
    { 
     #region Fields 

     ContentManager content; 
     SpriteFont gameFont; 
     GraphicsDeviceManager graphics; 
     SpriteBatch spriteBatch; 

     Ball ball; 
     Paddle paddle; 
     Rectangle screenRectangle; 

     int bricksWide = 10; 
     int bricksHigh = 5; 
     Texture2D brickImage; 
     Brick[,] bricks; 

     float pauseAlpha; 

     InputAction pauseAction; 

     #endregion 

     #region Initialization 


     /// <summary> 
     /// Constructor. 
     /// </summary> 

     public GameplayScreen() 
     { 
      graphics = new GraphicsDeviceManager(this); 
      Content.RootDirectory = "Content"; 

      graphics.PreferredBackBufferWidth = 800; 
      graphics.PreferredBackBufferHeight = 480; 

      screenRectangle = new Rectangle(
       0, 
       0, 
       graphics.PreferredBackBufferWidth, 
       graphics.PreferredBackBufferHeight); 

      TransitionOnTime = TimeSpan.FromSeconds(1.5); 
      TransitionOffTime = TimeSpan.FromSeconds(0.5); 

      pauseAction = new InputAction(
       new Buttons[] { Buttons.Start, Buttons.Back }, 
       new Keys[] { Keys.Escape }, 
       true); 
     } 

     protected override void Initialize() 
     { 
      // TODO: Add your initialization logic here 
      base.Initialize(); 
     } 

     /// <summary> 
     /// Load graphics content for the game. 
     /// </summary> 
     /// 
     protected override void LoadContent() 
     { 
      spriteBatch = new SpriteBatch(GraphicsDevice); 

       gameFont = Content.Load<SpriteFont>("gamefont"); 

       Texture2D tempTexture = Content.Load<Texture2D>("paddle"); 
       paddle = new Paddle(tempTexture, screenRectangle); 

       tempTexture = Content.Load<Texture2D>("ball"); 
       ball = new Ball(tempTexture, screenRectangle); 

       brickImage = Content.Load<Texture2D>("brick"); 

       StartGame(); 

       // once the load has finished, we use ResetElapsedTime to tell the game's 
       // timing mechanism that we have just finished a very long frame, and that 
       // it should not try to catch up. 
       ScreenManager.Game.ResetElapsedTime(); 
      base.LoadContent(); 
     } 

     private void StartGame() 
     { 
      paddle.SetInStartPosition(); 
      ball.SetInStartPosition(paddle.GetBounds()); 

      bricks = new Brick[bricksWide, bricksHigh]; 

      for (int y = 0; y < bricksHigh; y++) 
      { 
       Color tint = Color.White; 

       switch (y) 
       { 
        case 0: 
         tint = Color.Blue; 
         break; 
        case 1: 
         tint = Color.Red; 
         break; 
        case 2: 
         tint = Color.Green; 
         break; 
        case 3: 
         tint = Color.Yellow; 
         break; 
        case 4: 
         tint = Color.Purple; 
         break; 
       } 

       for (int x = 0; x < bricksWide; x++) 
       { 
        bricks[x, y] = new Brick(
         brickImage, 
         new Rectangle(
          x * brickImage.Width, 
          y * brickImage.Height, 
          brickImage.Width, 
          brickImage.Height), 
         tint); 
       } 
      } 
     } 

     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> 


     #endregion 

     #region Update and Draw 


     /// <summary> 
     /// Updates the state of the game. This method checks the GameScreen.IsActive 
     /// property, so the game will stop updating when the pause menu is active, 
     /// or if you tab away to a different application. 
     /// </summary> 
     public override void Update(GameTime gameTime, bool otherScreenHasFocus, 
                 bool coveredByOtherScreen) 
     { 
      base.Update(gameTime, otherScreenHasFocus, false); 

      // Gradually fade in or out depending on whether we are covered by the pause screen. 
      if (coveredByOtherScreen) 
       pauseAlpha = Math.Min(pauseAlpha + 1f/32, 1); 
      else 
       pauseAlpha = Math.Max(pauseAlpha - 1f/32, 0); 

      if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed) 

       this.Exit(); 

      paddle.Update(); 
      ball.Update(); 

      foreach (Brick brick in bricks) 
      { 
       brick.CheckCollision(ball); 
      } 

      ball.PaddleCollision(paddle.GetBounds()); 

      if (ball.OffBottom()) 
       StartGame(); 

      base.Update(gameTime, otherScreenHasFocus, coveredByOtherScreen); 
     } 

     /// <summary> 
     /// Draws the gameplay screen. 
     /// </summary> 
     public override void Draw(GameTime gameTime) 
     { 
      // This game has a blue background. Why? Because! 
      ScreenManager.GraphicsDevice.Clear(ClearOptions.Target, 
               Color.CornflowerBlue, 0, 0); 
      spriteBatch.Begin(); 

      foreach (Brick brick in bricks) 
       brick.Draw(spriteBatch); 

      paddle.Draw(spriteBatch); 
      ball.Draw(spriteBatch); 

      spriteBatch.End(); 

      base.Draw(gameTime); 

      // If the game is transitioning on or off, fade it out to black. 
      if (TransitionPosition > 0 || pauseAlpha > 0) 
      { 
       float alpha = MathHelper.Lerp(1f - TransitionAlpha, 1f, pauseAlpha/2); 

       ScreenManager.FadeBackBufferToBlack(alpha); 
      } 
     } 


     #endregion 
    } 
} 

을 어디 내가 잘못 여기에 갈거야 : 나는 게임을 시작하려고 할 때마다 그러나, 나는 다음과 같은 코드 spriteBatch.Begin에서 NullReferenceException이 얻을? 나는이 오류에 대한 약간의 연구를 해왔고 아무 해결책도 나를 도왔다. 필자는 이런 종류의 일로 매우 경험이 없기 때문에 다른 코드의 중복이나 실수를 지적 해주십시오. 감사!

편집 : Microsoft의 GameStateManagement 코드 샘플에서 원본 GameplayScreen.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 Rebound 
{ 
    /// <summary> 
    /// This is the main type for your game 
    /// </summary> 
    public class Game1 : Microsoft.Xna.Framework.Game 
    { 
     GraphicsDeviceManager graphics; 
     SpriteBatch spriteBatch; 

     Ball ball; 
     Paddle paddle; 
     Rectangle screenRectangle; 

     int bricksWide = 10; 
     int bricksHigh = 5; 
     Texture2D brickImage; 
     Brick[,] bricks; 

     public Game1() 
     { 
      graphics = new GraphicsDeviceManager(this); 
      Content.RootDirectory = "Content"; 

      graphics.PreferredBackBufferWidth = 750; 
      graphics.PreferredBackBufferHeight = 600; 

      screenRectangle = 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() 
     { 
      // Create a new SpriteBatch, which can be used to draw textures. 
      spriteBatch = new SpriteBatch(GraphicsDevice); 

      Texture2D tempTexture = Content.Load<Texture2D>("paddle"); 
      paddle = new Paddle(tempTexture, screenRectangle); 

      tempTexture = Content.Load<Texture2D>("ball"); 
      ball = new Ball(tempTexture, screenRectangle); 

      brickImage = Content.Load<Texture2D>("brick"); 

      StartGame(); 
     } 

     private void StartGame() 
     { 
      paddle.SetInStartPosition(); 
      ball.SetInStartPosition(paddle.GetBounds()); 

      bricks = new Brick[bricksWide, bricksHigh]; 

      for (int y = 0; y < bricksHigh; y++) 
      { 
       Color tint = Color.White; 

       switch (y) 
       { 
        case 0: 
         tint = Color.Blue; 
         break; 
        case 1: 
         tint = Color.Red; 
         break; 
        case 2: 
         tint = Color.Green; 
         break; 
        case 3: 
         tint = Color.Yellow; 
         break; 
        case 4: 
         tint = Color.Purple; 
         break; 
       } 

       for (int x = 0; x < bricksWide; x++) 
       { 
        bricks[x, y] = new Brick(
         brickImage, 
         new Rectangle(
          x * brickImage.Width, 
          y * brickImage.Height, 
          brickImage.Width, 
          brickImage.Height), 
         tint); 
       } 
      } 
     } 

     /// <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(); 
      ball.Update(); 

      foreach (Brick brick in bricks) 
      { 
       brick.CheckCollision(ball); 
      } 

      ball.PaddleCollision(paddle.GetBounds()); 

      if (ball.OffBottom()) 
       StartGame(); 

      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(); 

      foreach (Brick brick in bricks) 
       brick.Draw(spriteBatch); 

      paddle.Draw(spriteBatch); 
      ball.Draw(spriteBatch); 

      spriteBatch.End(); 

      base.Draw(gameTime); 
     } 
    } 
} 

원래 GameplayScreen.cs :

#region File Description 
//----------------------------------------------------------------------------- 
// GameplayScreen.cs 
// 
// Microsoft XNA Community Game Platform 
// Copyright (C) Microsoft Corporation. All rights reserved. 
//----------------------------------------------------------------------------- 
#endregion 

#region Using Statements 
using System; 
using System.Threading; 
using Microsoft.Xna.Framework; 
using Microsoft.Xna.Framework.Content; 
using Microsoft.Xna.Framework.Graphics; 
using Microsoft.Xna.Framework.Input; 
using GameStateManagement; 
#endregion 

namespace GameStateManagementSample 
{ 
    /// <summary> 
    /// This screen implements the actual game logic. It is just a 
    /// placeholder to get the idea across: you'll probably want to 
    /// put some more interesting gameplay in here! 
    /// </summary> 
    class GameplayScreen : GameScreen 
    { 
     #region Fields 

     ContentManager content; 
     SpriteFont gameFont; 

     Vector2 playerPosition = new Vector2(100, 100); 
     Vector2 enemyPosition = new Vector2(100, 100); 

     Random random = new Random(); 

     float pauseAlpha; 

     InputAction pauseAction; 

     #endregion 

     #region Initialization 


     /// <summary> 
     /// Constructor. 
     /// </summary> 
     public GameplayScreen() 
     { 
      TransitionOnTime = TimeSpan.FromSeconds(1.5); 
      TransitionOffTime = TimeSpan.FromSeconds(0.5); 

      pauseAction = new InputAction(
       new Buttons[] { Buttons.Start, Buttons.Back }, 
       new Keys[] { Keys.Escape }, 
       true); 
     } 


     /// <summary> 
     /// Load graphics content for the game. 
     /// </summary> 
     public override void Activate(bool instancePreserved) 
     { 
      if (!instancePreserved) 
      { 
       if (content == null) 
        content = new ContentManager(ScreenManager.Game.Services, "Content"); 

       gameFont = content.Load<SpriteFont>("gamefont"); 

       // A real game would probably have more content than this sample, so 
       // it would take longer to load. We simulate that by delaying for a 
       // while, giving you a chance to admire the beautiful loading screen. 
       Thread.Sleep(1000); 

       // once the load has finished, we use ResetElapsedTime to tell the game's 
       // timing mechanism that we have just finished a very long frame, and that 
       // it should not try to catch up. 
       ScreenManager.Game.ResetElapsedTime(); 
      } 

#if WINDOWS_PHONE 
      if (Microsoft.Phone.Shell.PhoneApplicationService.Current.State.ContainsKey("PlayerPosition")) 
      { 
       playerPosition = (Vector2)Microsoft.Phone.Shell.PhoneApplicationService.Current.State["PlayerPosition"]; 
       enemyPosition = (Vector2)Microsoft.Phone.Shell.PhoneApplicationService.Current.State["EnemyPosition"]; 
      } 
#endif 
     } 


     public override void Deactivate() 
     { 
#if WINDOWS_PHONE 
      Microsoft.Phone.Shell.PhoneApplicationService.Current.State["PlayerPosition"] = playerPosition; 
      Microsoft.Phone.Shell.PhoneApplicationService.Current.State["EnemyPosition"] = enemyPosition; 
#endif 

      base.Deactivate(); 
     } 


     /// <summary> 
     /// Unload graphics content used by the game. 
     /// </summary> 
     public override void Unload() 
     { 
      content.Unload(); 

#if WINDOWS_PHONE 
      Microsoft.Phone.Shell.PhoneApplicationService.Current.State.Remove("PlayerPosition"); 
      Microsoft.Phone.Shell.PhoneApplicationService.Current.State.Remove("EnemyPosition"); 
#endif 
     } 


     #endregion 

     #region Update and Draw 


     /// <summary> 
     /// Updates the state of the game. This method checks the GameScreen.IsActive 
     /// property, so the game will stop updating when the pause menu is active, 
     /// or if you tab away to a different application. 
     /// </summary> 
     public override void Update(GameTime gameTime, bool otherScreenHasFocus, 
                 bool coveredByOtherScreen) 
     { 
      base.Update(gameTime, otherScreenHasFocus, false); 

      // Gradually fade in or out depending on whether we are covered by the pause screen. 
      if (coveredByOtherScreen) 
       pauseAlpha = Math.Min(pauseAlpha + 1f/32, 1); 
      else 
       pauseAlpha = Math.Max(pauseAlpha - 1f/32, 0); 

      if (IsActive) 
      { 
       // Apply some random jitter to make the enemy move around. 
       const float randomization = 10; 

       enemyPosition.X += (float)(random.NextDouble() - 0.5) * randomization; 
       enemyPosition.Y += (float)(random.NextDouble() - 0.5) * randomization; 

       // Apply a stabilizing force to stop the enemy moving off the screen. 
       Vector2 targetPosition = new Vector2(
        ScreenManager.GraphicsDevice.Viewport.Width/2 - gameFont.MeasureString("Insert Gameplay Here").X/2, 
        200); 

       enemyPosition = Vector2.Lerp(enemyPosition, targetPosition, 0.05f); 

       // TODO: this game isn't very fun! You could probably improve 
       // it by inserting something more interesting in this space :-) 
      } 
     } 


     /// <summary> 
     /// Lets the game respond to player input. Unlike the Update method, 
     /// this will only be called when the gameplay screen is active. 
     /// </summary> 
     public override void HandleInput(GameTime gameTime, InputState input) 
     { 
      if (input == null) 
       throw new ArgumentNullException("input"); 

      // Look up inputs for the active player profile. 
      int playerIndex = (int)ControllingPlayer.Value; 

      KeyboardState keyboardState = input.CurrentKeyboardStates[playerIndex]; 
      GamePadState gamePadState = input.CurrentGamePadStates[playerIndex]; 

      // The game pauses either if the user presses the pause button, or if 
      // they unplug the active gamepad. This requires us to keep track of 
      // whether a gamepad was ever plugged in, because we don't want to pause 
      // on PC if they are playing with a keyboard and have no gamepad at all! 
      bool gamePadDisconnected = !gamePadState.IsConnected && 
             input.GamePadWasConnected[playerIndex]; 

      PlayerIndex player; 
      if (pauseAction.Evaluate(input, ControllingPlayer, out player) || gamePadDisconnected) 
      { 
#if WINDOWS_PHONE 
       ScreenManager.AddScreen(new PhonePauseScreen(), ControllingPlayer); 
#else 
       ScreenManager.AddScreen(new PauseMenuScreen(), ControllingPlayer); 
#endif 
      } 
      else 
      { 
       // Otherwise move the player position. 
       Vector2 movement = Vector2.Zero; 

       if (keyboardState.IsKeyDown(Keys.Left)) 
        movement.X--; 

       if (keyboardState.IsKeyDown(Keys.Right)) 
        movement.X++; 

       if (keyboardState.IsKeyDown(Keys.Up)) 
        movement.Y--; 

       if (keyboardState.IsKeyDown(Keys.Down)) 
        movement.Y++; 

       Vector2 thumbstick = gamePadState.ThumbSticks.Left; 

       movement.X += thumbstick.X; 
       movement.Y -= thumbstick.Y; 

       if (input.TouchState.Count > 0) 
       { 
        Vector2 touchPosition = input.TouchState[0].Position; 
        Vector2 direction = touchPosition - playerPosition; 
        direction.Normalize(); 
        movement += direction; 
       } 

       if (movement.Length() > 1) 
        movement.Normalize(); 

       playerPosition += movement * 8f; 
      } 
     } 


     /// <summary> 
     /// Draws the gameplay screen. 
     /// </summary> 
     public override void Draw(GameTime gameTime) 
     { 
      // This game has a blue background. Why? Because! 
      ScreenManager.GraphicsDevice.Clear(ClearOptions.Target, 
               Color.CornflowerBlue, 0, 0); 

      // Our player and enemy are both actually just text strings. 
      SpriteBatch spriteBatch = ScreenManager.SpriteBatch; 

      spriteBatch.Begin(); 

      spriteBatch.DrawString(gameFont, "// TODO", playerPosition, Color.Green); 

      spriteBatch.DrawString(gameFont, "Insert Gameplay Here", 
            enemyPosition, Color.DarkRed); 

      spriteBatch.End(); 

      // If the game is transitioning on or off, fade it out to black. 
      if (TransitionPosition > 0 || pauseAlpha > 0) 
      { 
       float alpha = MathHelper.Lerp(1f - TransitionAlpha, 1f, pauseAlpha/2); 

       ScreenManager.FadeBackBufferToBlack(alpha); 
      } 
     } 


     #endregion 
    } 
} 
+0

[NullReferenceException은 무엇이며 어떻게 수정합니까?] (http://stackoverflow.com/questions/4660142/what-is-a-nullreferenceexception-and-how-do-i-fix-it) –

+0

나는 내가 spriteBatch를 초기화했다는 것을 확실히 확신하고 있으며, 그것이 어떻게 null로 올지 전혀 모른다. –

+0

아, 내가 위의 코드를 보여줌으로써 _Microsoft Permissive License (Ms-PL) _을 위반하고 있는지 궁금합니다. – MickyD

답변

0

당신은 LoadContentspriteBatch를 초기화된다. 무엇이든하기 전에 GamePlayScreen.Loadcontent()을 실행하고 있습니까? 이 GameScreen 개체를 사용하는 클래스를 우리에게 보여줄 수 있습니다. 반면에, 메인 클래스의 SpriteBatch 객체는 draw 메서드 GameScreen에 전달하여 사용할 수 있습니다.

public void Draw(GameTime gameTime, SpriteBatch spritebatch) 
{ 
} 

//In the main class (Game1) you can use draw like this: 

gameScreen.Draw(gameTime, spritebatch); 

또한 내 무승부 방법에서 GameTime을 사용한 적이 없습니다. GameTime afaik는 Update 메서드에서 논리를 업데이트하는 데 사용됩니다. 나는 네가 약간 난장판을 만들고 있다고 느낀다. 처음부터 다시 시작하십시오. 더 간단한 튜토리얼부터 시작하십시오. gameScreen에는 상속에 대한 기본 지식이 필요합니다. 게임 스크린 관리에 대해 더 알고 싶다면 상속에 대해 좀 더 배우십시오.

+0

GameScreen에서는 GameplayScreen을 의미합니까? 또한 Breakout 튜토리얼에서는 GameTime을 Draw 메서드에 추가한다고 말합니다. 나는이 튜토리얼을 따라 성공적인 브레이크 아웃 게임을 만들 수 있었고 게임 코드를 게임 상태 관리 용 Microsoft 코드 샘플과 병합하려고 했으므로 좋은 메뉴를 가질 수 있습니다. 나는 원래 Breakout 게임의 코드와 원본 GameplayScreen.cs로 Microsoft 코드 샘플에서 OP를 업데이트 할 것입니다. 정말 두 가지를 병합해야합니다. 그렇게하는 것이 더 부드러운 방법을 알면 나에게 도움이 될 수 있으면 감사 할 것입니다. –

0

코드에 activate 메서드가있는 것 같습니다 (방금 놓친 경우는 제외). 메모리에서 이것은 실제로 화면 관리자로부터 호출되는 메소드입니다. 이 메소드를 덮어 쓰고 거기에서 loadcontent 메소드를 호출하십시오. 또한 spritebatch를 다시 만들 필요가 없습니다. 메신저 확실히 화면 관리자가 그것에 대한 참조를 가지고 - 대신에 당신이 뭔가의 라인을 따라해야합니다 this.spritebatch = ScreenManager.Spritebatch;

다시 말하지만, 이것은 메모리에서 나왔습니다. 나중에 메신저를 다시 작성하고 내 프로젝트를 참조 할 수 있습니다.

0

먼저 텍스처 파일을 추가 했습니까? 왜냐하면 그것은 텍스쳐 파일을 찾아서로드 할 수 없기 때문입니다.