![](/img/trans.png)
[英]XNA: NullReferenceException when playing SoundEffect from another class
[英]XNA soundEffect is null in when loaded in main class and called in another class
我已经将声音效果文件加载到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");
这是球课
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
中,而不是在主类中。
这就是为什么当您尝试运行一个错误时会收到该错误的原因,它们在另一个类中初始化并且仍然为空。
当然,如果您必须在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轻松轻松地解决了此问题
确保在LoadContent()之前实例化Ball。
然后交换这条线
BallHitSE = Content.Load(“ BallHit”); 有了这个
Ball.BallHitSE = Content.Load(“ BallHit”); 并将Ball类中的变量更改为此
公共静态SoundEffect BallHitSE;
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.