如何在不使用Content类的情况下加载MP3文件



我是C Sharp编程的初学者,我正在使用XNA SDK。我正在尝试制作一个简单的游戏来帮助我的同学们为学校学习,我决定如果有办法让他们在玩游戏时把他们想听的音乐放在一个文件中,让游戏自动加载音乐文件,并在播放列表中播放,我会喜欢的。

到目前为止,我可以通过检测文件路径名是否包含(".mp3")来让游戏检测文件是否是音乐,但我正在尝试使用for Loop将文件名加载到Song类型的列表中。代码如下所示。

(声明)

List<Song> songsToPlay;
string[] fileNames

(初始化)

fileNames[] = Directory.GetFiles(".Music")

(LoadContent)

for (int i = 0; i < fileNames.Count(); i++)
{
      if (fileNames[i].Contains(".mp3")
      {
          songsToPlay.Add(fileNames[i]);
      }
}

我一直在试图找到一种方法,将整个文件夹添加到内容目录中,并让它做一些更像的事情

for (int i = 0; i < fileNames.Count(); i++)
{
    songsToPlay.Add(Content.Load<Song>("fileNames[i]") 
}

我一直找不到办法。。。有人知道如何做到这一点,或者知道更好的方法吗?

如果项目内容中有文件,则应该使用ContentManager类。它提供的不仅仅是文件加载。例如,当您不再使用Content.Unload时,可以使用它卸载所有数据。

没有必要回避那个类。这个页面有一个示例,确切地显示了你想要做的事情:

public static Dictionary<string, T> LoadContent<T>(
    this ContentManager contentManager, string contentFolder)
{
   var dir = new DirectoryInfo(contentManager.RootDirectory
       + "\" + contentFolder);
   if (!dir.Exists)
      throw new DirectoryNotFoundException();
   var result = new Dictionary<string, T>();
   foreach (FileInfo file in dir.GetFiles("*.mp3"))
   {
      string key = Path.GetFileNameWithoutExtension(file.Name);
      result[key] = contentManager.Load<T>(
          contentManager.RootDirectory + "/" + contentFolder + "/" + key);
   }
   return result;
}

你可以这样使用它:

var songs = Content.LoadContent<Song>("Songs");

此代码略有改进

一旦你让上面的代码工作,我还建议你做一个小小的改变:

var dir = new DirectoryInfo(
    System.IO.Path.Combine(contentManager.RootDirectory, contentFolder));

在可能避免的情况下,你不应该通过字符串串联手动构建路径。我不知道你能对ContentManager路径做同样的事情,所以在这种情况下你可能不得不坚持使用字符串串联。

编辑:太多你还没有在课堂上使用的构造

由于您还没有在类中使用扩展方法或static关键字,而且可能还没有使用字典,因此有一种更简单的方法:

string contentFolder = "Music";
var dir = new DirectoryInfo(Content.RootDirectory + "\" + contentFolder);
if (!dir.Exists)
{
    // Todo: Display a message to the user instead?
    throw new DirectoryNotFoundException();
}
string[] files = dir.GetFiles("*.mp3");
for (int i = 0; i < files.Count(); ++i)
{
    FileInfo file = files[i];
    string key = System.IO.Path.GetFileNameWithoutExtension(file.Name);
    var song = Content.Load<Song>(
        Content.RootDirectory + "/" + contentFolder + "/" + key);
    songsToPlay.Add(song);
}

第2版:对第二个代码示例的一些解释

DirectoryInfo类允许您加载一个目录,这样您就可以枚举其中的所有文件

DirectoryInfo上的GetFiles方法允许您使用通配符样式的模式匹配来枚举文件。文件的通配符模式匹配意味着当给定这些模式时:

  • *.*-您正在查找名为<anything>.<anything>的文件
  • *.mp3-您正在寻找<anything>.mp3

throw表示抛出异常。这将故意停止执行代码,并显示一条好的错误消息("directory not found")和一个行号。关于异常处理,有很多需要学习,所以我不会试图通过这里的描述来公正地对待它。

GetFileNameWithoutExtension应该是显而易见的,因为它的名字很好。

Content.RootDirectory + "/" + contentFolder + "/" + key

最后一点代码将构建一个字符串,其中包含内容根目录、歌曲的子目录和每个文件名,使用它可以理解的名称(因为它不知道文件扩展名)。

var的意思是"无论我赋予它什么类型"。这是一条捷径。例如,不要键入:

List<string> someList = new List<string>();

您键入:

var someList = new List<string>();

var必须知道任务右侧的类型。这很有用,因为你可以避免重复自己。

使用var并不会赋予该变量任何神奇的能力。一旦您声明了一个不同类型的变量,就无法为其赋值。这只是实现完全相同功能的捷径。

使用Song.FromUri方法:

Song.FromUri("audio name", new Uri(@"C:audio.mp3"));

文件路径不能包含空格!

有关解决方法,请参阅此处:XNA 4 Song.fromUri包含空格

最新更新