我已经在xna的主类中加载了一个音效文件,但当我试图在另一个类中运行它时,我会收到这个错误
{"对象引用未设置为对象的实例。"}
我是XNA课程的新手,所以我并不真正理解它们。如有任何帮助,我们将不胜感激。
这是主类的一部分
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 BreakingOut
{
/// <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;
bool is1P = true;
int lives = 3;
Texture2D startButtonTexture;
Vector2 buttonVec;
Texture2D exitButtonTexture;
Vector2 button2Vec;
int bricksWide = 10;
int bricksHigh = 7;
Texture2D brickImage;
Brick[,] bricks;
//rec for menu
Texture2D menuTexture;
Rectangle menuRec = new Rectangle(0, 0, 960, 640);
//rec for pause
Texture2D pauseTexture;
Rectangle pauseRec = new Rectangle(0, 0, 960, 640);
//lose
Texture2D loseTexture;
Rectangle loseRec = new Rectangle(0, 0, 960, 640);
Texture2D winTexture;
Rectangle winRec = new Rectangle(0, 0, 960, 640);
//sound effects
public SoundEffect BallHitSE;
SoundEffect WallHitSE;
SoundEffect StartSE;
//BGM
Song menuMusic;
Song gameMusic;
bool isGameMusicPlaying = false;
bool isMenuMusicPlaying = false;
float pauseTimer;
float exitTimer;
float muteTimer;
float SEmuteTimer;
//public int brickCount = 70;
SpriteFont font;
Vector2 mousePos;
enum gameStates
{
MENU,
GAME1P,
LOSE,
PAUSE,
WIN,
}
gameStates currentState = gameStates.MENU;
gameStates prevState = gameStates.MENU;
public Game1()
{
graphics = new GraphicsDeviceManager(this);
Content.RootDirectory = "Content";
IsMouseVisible = true;
graphics.PreferredBackBufferWidth = 960;
graphics.PreferredBackBufferHeight = 640;
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);
BallHitSE = Content.Load<SoundEffect>("BallHit");
WallHitSE = Content.Load<SoundEffect>("WallHit2");
StartSE = Content.Load<SoundEffect>("Start");
gameMusic = Content.Load<Song>("gameMusic");
menuMusic = Content.Load<Song>("menuMusic");
这是Ball级
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
namespace BreakingOut
{
class Ball
{
Vector2 motion;
Vector2 position;
Rectangle bounds;
bool collided;
public int brickCount = 70;
const float ballStartSpeed = 6.4f;
public float ballSpeed;
Texture2D texture;
Rectangle screenBounds;
SoundEffect BallHitSE;
//BallHitSE = new SoundEffect
public Rectangle Bounds
{
get
{
bounds.X = (int)position.X;
bounds.Y = (int)position.Y;
return bounds;
}
}
public Ball(Texture2D texture, Rectangle screenBounds)
{
bounds = new Rectangle(0, 0, texture.Width, texture.Height);
this.texture = texture;
this.screenBounds = screenBounds;
//Different things we tried
//BallHitSE = Content.Load<SoundEffect>("BallHit");
//BallHitSE = new soundeffect(what goes in here?);
//BallHitSE = Content.Manager.Load("path")
}
public void Update()
{
collided = false;
position += motion * ballSpeed;
ballSpeed += 0.001f;
CheckWallCollision();
}
public void CheckWallCollision()
{
if (position.X < 0)
{
position.X = 0;
motion.X *= -1;
//if (BallHitSE != null)
//{
BallHitSE.Play();
//}
}
if (position.X + texture.Width > screenBounds.Width)
{
position.X = screenBounds.Width - texture.Width;
motion.X *= -1;
//if (BallHitSE != null)
//{
BallHitSE.Play();
//}
}
if (position.Y < 0)
{
position.Y = 0;
motion.Y *= -1;
//if (BallHitSE != null)
//{
BallHitSE.Play();
//}
}
}
public void SetInStartPosition(Rectangle paddleLocation)
{
Random rand = new Random();
motion = new Vector2(rand.Next(2, 6), -rand.Next(2, 6));
motion.Normalize();
ballSpeed = ballStartSpeed;
position.Y = paddleLocation.Y - texture.Height;
position.X = paddleLocation.X + (paddleLocation.Width - texture.Width) / 2;
}
public bool OffBottom()
{
if (position.Y > screenBounds.Height)
return true;
return false;
}
public void PaddleCollision(Rectangle paddleLocation)
{
Rectangle ballLocation = new Rectangle(
(int)position.X,
(int)position.Y,
texture.Width,
texture.Height);
if (paddleLocation.Intersects(ballLocation))
{
position.Y = paddleLocation.Y - texture.Height;
motion.Y *= -1;
}
}
public void Deflection(Brick brick)
{
if (!collided)
{
motion.Y *= -1;
collided = true;
brickCount -= 1;
}
}
public void Draw(SpriteBatch spriteBatch)
{
spriteBatch.Draw(texture, position, Color.White);
for (int i = 1; i < 10; i++)
{
var drawPosition = position - (i * motion * 3);
var colour = Color.Lerp(Color.White, Color.Transparent, i * (20 / 100f));
spriteBatch.Draw(texture, drawPosition, colour);
}
}
}
}
XNA类与普通类没有什么不同,不要让它们愚弄你!
看来你只需要把这两个部分设置为相等即可。
球类:
public Ball(Texture2D texture, Rectangle screenBounds, SoundEffect ballHit/*NEW*/)
{
this.BallHitSE = ballHit;// NEW
bounds = new Rectangle(0, 0, texture.Width, texture.Height);
this.texture = texture;
this.screenBounds = screenBounds;
//Different things we tried
//BallHitSE = Content.Load<SoundEffect>("BallHit");
//BallHitSE = new soundeffect(what goes in here?);
//BallHitSE = Content.Manager.Load("path")
}
然后只需在构造函数中添加声音效果:
Ball ball = new Ball(texture, bounds, BallHitSE);
如果在Ball
类中使用这些SoundEffect
,则应将它们加载到Ball
类的LoadContent
中,而不是主类中
这就是为什么当你试图运行其中一个时会收到这个错误,它们在另一个类中初始化,并且仍然为null。
当然,如果你必须在Ball
类中加载一些东西,你需要传递ContentManager
,或者使Ball
类继承自GameComponent
或DrawableGameComponent
,以便以这种方式加载你的声音效果:
BallHitSE = Game.Content.Load<SoundEffect>("BallHit");
WallHitSE = Game.Content.Load<SoundEffect>("WallHit2");
编辑
通常我以这种方式管理音频:
public class AudioComponent : GameComponent
{
public enum LevelEffect { BadCollision, GoodCollision, PopUp }
public enum GameMusic { GameWin, GameLose, GameStart }
private Song winSound, loseSound, startSound;
private SoundEffect badCollSound, goodCollSound, popUp;
public AudioComponent()
{
}
public override void Initialize()
{
base.Initialize();
}
public void loadAudio(
Song winSound,
Song loseSound,
Song startSound,
SoundEffect badCollSound,
SoundEffect goodCollSound,
SoundEffect popUp
)
{
this.winSound = winSound;
this.loseSound = loseSound;
this.startSound = startSound;
this.badCollSound = badCollSound;
this.goodCollSound = goodCollSound;
this.popUp = popUp;
}
public void PlayGameMusic(GameMusic effType)
{
switch (effType)
{
case GameMusic.GameWin:
PlayMusic(winSound);
break;
case GameMusic.GameLose:
PlayMusic(loseSound);
break;
case GameMusic.GameStart:
PlayMusicRepeat(startSound);
break;
}
}
public void PlayLevelEffect(LevelEffect effType)
{
switch (effType)
{
case GameMusic.BadCollision:
PlayEffect(badCollSound);
break;
case GameMusic.GoodCollision:
PlayEffect(goodCollSound);
break;
case GameMusic.PopUp:
PlayEffect(popUp);
break;
}
}
public void PlayEffect(SoundEffect sound)
{
sound.Play();
}
public bool CheckAlreadyPlayingMusic()
{
return MediaPlayer.State == MediaState.Playing;
}
public void PlayMusic(Song song)
{
MediaPlayer.Play(song);
MediaPlayer.IsRepeating = false;
}
public void PlayMusicRepeat(Song song)
{
MediaPlayer.Play(song);
MediaPlayer.IsRepeating = true;
}
public void StopMusic()
{
MediaPlayer.Stop();
}
public void PauseMusic()
{
MediaPlayer.Pause();
}
public void ResumeMusic()
{
MediaPlayer.Resume();
}
public void ChangeVolume(float volume)
{
MediaPlayer.Volume = volume;
}
}
用户Kai Hartmann用一个简单的修复解决了这个问题
确保Ball在LoadContent()之前实例化。
然后交换这条线路
BallHitSE=Content.Load("BallHit");用这个
Ball.BallHitSE=Content.Load("BallHit");并更改您的Ball类中的变量到此
公共静态音效BallHitSE;
https://gamedev.stackexchange.com/a/66184/36332