Как да заредите MP3 файл, без всъщност да използвате класа Content?

Аз съм начинаещ в програмирането със C Sharp и използвам XNA SDK. Опитвам се да направя проста игра, за да помогна на моите съученици с ученето за училище, и реших, че бих искал, ако има някакъв начин да ги накарам да поставят музика, която искат да слушат, докато играят играта, във файл и да имате играта автоматично Заредете музикалните файлове и ги пуснете в списък за изпълнение.

Досега успявам да накарам играта да открие дали файловете са музика, като открия дали името на пътя на файла съдържа(".mp3"), но всъщност се опитвам да заредя името на файла в списък от тип Song, използвайки for Loop. Кодът изглежда така.

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

List<Song> songsToPlay;
string[] fileNames

(Инициализиране)

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

(Зареждане на съдържание)

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

Не можах да намеря някакъв начин да направя това... Някой знае ли как да накара това да работи или по-добър начин да го направя?


person Matthew K. Crandall    schedule 07.01.2012    source източник


Отговори (2)


Ако имате вашите файлове в съдържанието на вашия проект, трябва да използвате класът 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 обаче не дава никакви магически способности на променливата. Няма да можете да присвоите променлива от различен тип, след като сте декларирали променливата. Това е просто пряк път за абсолютно същата функционалност.

person Merlyn Morgan-Graham    schedule 07.01.2012
comment
Имам малък проблем с това... Уча се как да програмирам само от няколко месеца... Аз съм в клас по компютърно програмиране и досега всъщност никога не сме говорили как да използваме статично поле и никога не сме навлизали в много подробности за това как да използваме методи за връщане на стойност. Опитах се да разбера това и получих малко, но все още съм изгубен... Може би, ако имаше някакъв начин, бих могъл да разбера как това всъщност работи малко по-задълбочено... - person Matthew K. Crandall; 08.01.2012
comment
@MatthewCrandall: Това е метод, а не поле. Въпреки че е статичен. Освен това е метод за разширение. Ще напиша модифицирана версия, която се вписва във вашите съществуващи учения :) - person Merlyn Morgan-Graham; 08.01.2012
comment
Благодаря... Винаги съм го чувал като статично поле. Знам какво е метод, но тъй като беше статично и не разбирам какво всъщност прави статичното или какво представлява, просто го нарекох статично поле. Просто никога не съм работил с ContentManager, RootDirectory или Dictionary, така че просто нямам представа какво наистина се случва... може би, ако мога да получа още обяснение за това как работи, бих могъл да разбера какво се случва :) - person Matthew K. Crandall; 08.01.2012
comment
@MatthewCrandall: Ще стане! Публикувах версия на кода, която сега прилича повече на вашия оригинален код. Ще се опитам да добавя и някакво обяснение. - person Merlyn Morgan-Graham; 08.01.2012
comment
@MatthewCrandall: Добре, приключих с добавянето на моите обяснения. Уведомете ме, ако съм ви объркал повече или ако имате въпроси, на които не съм отговорил :) Освен това не се колебайте да следвате връзката extension methods или static, която поставих в отговора си, за да прочетете малко повече за тях. - person Merlyn Morgan-Graham; 08.01.2012
comment
Всъщност проследих повечето от тях и планирам да прочета и двете... Опитах да добавя всичко това в метода LoadContent, но той се връща с няколко грешки. Чудя се дали не пропускам нещо друго? Той казва, че не може имплицитно да преобразува тип 'string' в 'System.IO.FileInfo'. Има същата грешка по-късно, но в обратен ред, където не може да конвертира от System.IO.FileInfo[] в string[]... двете грешки са в (съответно) string[] files = dir.GetFiles(* mp3); и по-късно във FileInfo file = files[i]; - person Matthew K. Crandall; 08.01.2012
comment
Току-що прегледах кода. dir.GetFile(*.mp3) Връща масив от файлове от тип System.IO.FileInfo[], а не като низ, така че също се нуждае от известно преобразуване от System.IO.FileInfo[] int a string[]. Опитах да го променя, като добавих .ToString() в края на израза, но след това се казва, че не мога да конвертирам тип низ към тип string[], така че се чудя дали трябва да го запазя като низ и след това да използвам разделяне, за да разбиете низа в масив и след това да заредите файла от този масив от низове, вместо да се опитвате да дадете стойност от тип string[] на DirectoryInfo[].... - person Matthew K. Crandall; 08.01.2012
comment
@MatthewCrandall: Вероятно съм прецакал тази част, защото всъщност не съм писал кода в компилатора. FileInfo[] трябва да е добре за променливата files. - person Merlyn Morgan-Graham; 08.01.2012
comment
да Разбрах, че FileInfo ще работи, съвсем сам... няма проблем, разбираемо е. Сега имам друг проблем. Очевидно CSharp всъщност не може да зарежда директни MP3, поне по начина, по който се опитваме да го накараме да работи. Продължава да казва грешка, CSharp не може да отвори файла. Сигурни ли сте, че използвате правилната програма за качване?... Има ли някакъв начин да проверите дали има MP3, да ги конвертирате в XNB. Обикновено, когато зареждам звук, ръчно го добавям в препратките към съдържанието и той автоматично го преобразува. Чудя се дали трябва да конвертирам програмно от MP3 в XNB, за да работи. - person Matthew K. Crandall; 11.01.2012

Използвайте метода Song.FromUri :

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

Пътят на файла не може да съдържа интервали!

Вижте тук за заобиколно решение: XNA 4 Song.fromUri, съдържащ интервали

person George Duckett    schedule 07.01.2012