Как загрузить файл MP3, не используя класс Content? - PullRequest
3 голосов
/ 08 января 2012

Я новичок в программировании на C Sharp и использую XNA SDK. Я пытаюсь сделать простую игру, чтобы помочь моим одноклассникам учиться в школе, и я решил, что мне было бы интересно, если бы был какой-то способ заставить их ставить музыку, которую они хотят слушать, играя в игру внутри файла, и игра автоматически загружает музыкальные файлы и воспроизводит их в плейлисте.

Пока я могу заставить игру определять, являются ли файлы музыкой, путем определения, содержит ли путь к файлу (". Mp3"), но я пытаюсь загрузить имя файла в список Тип песни, используя для цикла. Код выглядит следующим образом.

(Декларация)

List<Song> songsToPlay;
string[] fileNames

(Initialize)

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]") 
}

Мне не удалось найти какой-либо способ сделать это ... Кто-нибудь знает, как сделать эту работу, или лучший способ сделать это?

Ответы [ 2 ]

3 голосов
/ 08 января 2012

Если у вас есть файлы в вашем проекте, вы должны использовать 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);
}

Edit2: некоторые пояснения к этому второму примеру кода

Класс DirectoryInfo позволяет загрузить каталог, чтобы вы могли перечислить все файлы в нем.

Метод GetFiles на DirectoryInfo позволяет перечислять файлы, используя сопоставление с шаблоном подстановочного знака. Подстановочный шаблон сопоставления для файлов означает, что при задании следующих шаблонов

  • *.* - вы ищете файлы с именем <anything>.<anything>
  • *.mp3 - вы ищете <anything>.mp3

throw означает создание исключения. Это намеренно прекратит выполнение кода и отобразит хорошее сообщение об ошибке («каталог не найден») и номер строки. Существует лот , чтобы узнать об обработке исключений , поэтому я не буду пытаться отдать должное описанию здесь.

GetFileNameWithoutExtension должно быть очевидным, потому что оно хорошо названо.

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

Этот последний кусочек кода создаст строку, содержащую корневой каталог содержимого, подкаталог ваших песен и каждое имя файла, используя понятное ему имя (поскольку оно не знает о расширениях имени файла) .

var означает «любой тип, который я ему назначу». Это короткий путь. Например, вместо ввода:

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

Вы вводите:

var someList = new List<string>();

var должен знать, какой тип находится справа от назначения. Это полезно, потому что вы можете избегать повторения .

Использование var не наделяет переменную магическими способностями. Вы не сможете назначить переменную другого типа после того, как объявите переменную. Это просто сокращение для точно такой же функциональности.

0 голосов
/ 08 января 2012

Используйте метод Song.FromUri:

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

Путь к файлу не может содержать пробелы!

См. Здесь для обхода: XNA 4 Song.fromUri, содержащий пробелы

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...