Аудио3D

Страницата се актуализира :
Дата на създаване на страница :

Бележки по този съвети

Тази извадка се основава на програмите, публикувани на следните сайтове. Променям кода малко, за да го направя по-лесен за разбиране и да го обясня на японски. По принцип използваме оригиналния код, какъвто е, така че ако всъщност го приемете във вашата игрова програма, коригирайте го своевременно и го използвайте.

Референтен сайт

Освен това се обяснява с предположението, че имате някои основни познания за MonoGame и XNA. Вижте Съвети за моногейм и Съвети за XNA за грубото.

По-специално, тъй като математиката, векторите, тригонометричните функции, матриците и т.н. са от съществено значение, така че моля, знайте какви са в известна степен.

околна среда

платформа
  • Windows 10
  • Код може да се използва на други monoGame-активирани платформи
Визуално студио
  • Визуално студио 2019
.NET Ядро
  • 3.1
МоноГем
  • 3.8

Всичко за пробите

Въз основа на позицията на камерата можете да чуете обаждането от позицията на кучето и позицията на котката. Котката обикаля и обикаля произхода, а играчът може да контролира позицията на камерата с ключа. Уверете се, че начинът, по който чувате звука, се променя при всяка промяна в позицията на фотоапарата или позицията на котката. Мисля, че е лесно да се разбере с помощта на слушалки за уши. Непотвърден съм на канал 5.1.

Как да работите

Какво е да се направи клавиатура геймпад (XInput) мишка докосване
Камера напред и назад ↑↓ Ляв стик (Отгоре и отдолу) - -
Промяна на ориентацията на камерата ←→ Ляв стик (наляво и надясно) - -
Край на играта Esc Гръб - -

Какво да подготвим

  • Куче пискливи аудио файл
  • Три котешки пискливи аудио файлове
  • Файл с изображения на кучета
  • Файл с картини за котки
  • Файл с наземно изображение

Оригиналната проба на официалния сайт използва предварително застроени съдържание .xnb файлове. Ако искате да запазите пробите на официалния сайт, не използвайте mgcbs, добавете ги директно към вашето решение на Visual Studio и ги копирайте в момента на изграждане.

Не знам защо оригиналната проба взима този метод, но мисля, че вероятно е защото мигрираме по-стари версии на проекта, каквито е. Разбира се, можете да използвате mgcb за генериране на същия файл. Проектите, които могат да бъдат изтеглени на този сайт, са модифицирани във версията на MGCB.

програма

Изтеглете програмата за целия код.

Тази проба е предназначена да направи кода да изглежда малко по-общ, докато прави възпроизвеждането на звука да изглежда добре по време на изпълнение. Използването само на Audio3D би било много по-малко код, но е описано по оригиналната проба. Ще запазя по-малко важните части.

Проектът се състои от следните кодови файлове:

  • Аудио3DGame
  • АудиоУправлят
  • Котка
  • Куче
  • IAudioЕмитер
  • Програма
  • ЧетворкаДрауър
  • СпрайтЕнтитет

Клас quadDrawer

Този клас е помощен клас за рисуване на правоъгълни многоъгълни. Правоъгълните многоъгълни често се използват предимно за показване на 3D спрайтове (билбордове). Тези съвети се използват за билбордове за котки и кучета, както и за правоъгълни дисплеи на земята.

Този клас няма нищо общо с Audio3D.

поле

readonly GraphicsDevice _graphicsDevice;
readonly AlphaTestEffect _effect;
readonly VertexPositionTexture[] _vertices;

Минимална информация, необходима за рисуване на многоъгълни. Начертайте многоъгълника от vertex данни, без да подготвяте данни за модела.

Конструктор

/// <summary>
/// 新しい四辺形の描画ワーカーを作成します。
/// </summary>
public QuadDrawer(GraphicsDevice device)
{
  _graphicsDevice = device;

  _effect = new AlphaTestEffect(device);

  _effect.AlphaFunction = CompareFunction.Greater;
  _effect.ReferenceAlpha = 128;

  // 4つの頂点の配列を事前に割り当てます。
  _vertices = new VertexPositionTexture[4];

  _vertices[0].Position = new Vector3(1, 1, 0);
  _vertices[1].Position = new Vector3(-1, 1, 0);
  _vertices[2].Position = new Vector3(1, -1, 0);
  _vertices[3].Position = new Vector3(-1, -1, 0);
}

Тъй като този клас е универсално използваем, получавате GraphicsDevice екземпляр, създаден в процеса на инициализация на класа на играта.

Тук задаваме ефекта, необходим за рисуване на спрайт и позицията на 4-те вертикала, необходими за правоъгълния многоъгълник. Размерът трябва да бъде мащабиран при рисуване, така че е -1 до 1.

Метод drawQuad

/// <summary>
/// 3Dワールドの一部として四角形を描画します。
/// </summary>
public void DrawQuad(Texture2D texture, float textureRepeats, Matrix world, Matrix view, Matrix projection)
{
  // 指定されたテクスチャとカメラマトリックスを使用するようにエフェクトを設定します。
  _effect.Texture = texture;

  _effect.World = world;
  _effect.View = view;
  _effect.Projection = projection;

  // 指定された数のテクスチャの繰り返しを使用するように頂点配列を更新します。
  _vertices[0].TextureCoordinate = new Vector2(0, 0);
  _vertices[1].TextureCoordinate = new Vector2(textureRepeats, 0);
  _vertices[2].TextureCoordinate = new Vector2(0, textureRepeats);
  _vertices[3].TextureCoordinate = new Vector2(textureRepeats, textureRepeats);

  // 矩形を描画します。
  _effect.CurrentTechnique.Passes[0].Apply();

  _graphicsDevice.DrawUserPrimitives(PrimitiveType.TriangleStrip, _vertices, 0, 2);
}

Задава предадената текстура на правоъгълник и я начертава. Тъй като това е основен процес, няма какво да се отбележи.

Ако има една точка, в аргумента може да бъде зададена textureRepeats променлива, наречена, така че координатите на текстурата да могат да се променят. Ако vertexPositionTexture.TextureCoordinate е зададена извън диапазона от 0 до 1, текстурата се чертае многократно по подразбиране. Използвайки го, е възможно да се изрази, че плочки могат да бъдат подредени многократно. Всъщност карираните модели на земята изглежда имат множество прости черно-бели изображения, наредени.

IAudioЕмитер интерфейс

/// <summary>
/// 3D サウンドを再生するエンティティの位置と速度を検索するために AudioManager が使用するインターフェイス。
/// </summary>
public interface IAudioEmitter
{
  Vector3 Position { get; }
  Vector3 Forward { get; }
  Vector3 Up { get; }
  Vector3 Velocity { get; }
}

Дефиниран като обект, който излъчва звук. Тъй като образуванията, които излъчват звук този път, са кучета и котки, те са наследени в съответните си класове. Емитер се нуждае от следната информация:

Използване на собственост
Положение Позиция на обект
Напред Посоката, пред която е изправен обектът (вектор)
Нагоре Нагоре на субекта. Посоката, в която главата съществува в човек
Скорост Скоростта, с която се движи предприятието. Използва се за изчисляване на доплерови стойности.

Клас на спрайтЕнтност

Клас за представяне на 3D спрайтове (билбордове). Той също е излъчвател, и наследява IAudioEmitter . Кучетата и котките наследяват този клас.

свойство

/// <summary>エンティティの3D位置を取得または設定します。</summary>
public Vector3 Position { get; set; }

/// <summary>エンティティが向いている方向を取得または設定します。</summary>
public Vector3 Forward { get; set; }

/// <summary>このエンティティの上方向を取得または設定します。</summary>
public Vector3 Up { get; set; }

/// <summary>このエンティティの移動速度を取得または設定します。</summary>
public Vector3 Velocity { get; protected set; }

/// <summary>このエンティティの表示に使用されるテクスチャを取得または設定します。</summary>
public Texture2D Texture { get; set; }

Той разполага с информацията за местоположението на обекта и т.н. По принцип имам информация като излъчвател. Също така е графичен обект, така че има и изображение (Текстура), което да се показва.

Метод за актуализиране

/// <summary>
/// エンティティの位置を更新し、サウンドを再生できるようにします。
/// </summary>
public abstract void Update(GameTime gameTime, AudioManager audioManager);

Описва позицията на обекта и процеса на възпроизвеждане на звук, но го внедрява в производния клас.

Метод на рисуване

/// <summary>
/// エンティティをビルボードスプライトとして描画します。
/// </summary>
public void Draw(QuadDrawer quadDrawer, Vector3 cameraPosition, Matrix view, Matrix projection)
{
  Matrix world = Matrix.CreateTranslation(0, 1, 0) *
                 Matrix.CreateScale(800) *
                 Matrix.CreateConstrainedBillboard(Position, cameraPosition, Up, null, null);

  quadDrawer.DrawQuad(Texture, 1, world, view, projection);
}

Кучетата и котките имат различни образи и позиции, но другият механизъм за рисуване е точно същият, затова ги описвам тук.

Всяка трансформация и текстура се предава на QuadDrawer, за да се покаже правоъгълен многоъгълник. Тъй като координатната трансформация е основно знание, обясненията не са обхванати.

Matrix.CreateConstrainedBillboard Използвайте информация за метод и камера, за да представяте лесно билбордовете, така че ги използвайте ефективно.

Куче клас

Това е клас, който прави куче рисуване и пеене възпроизвеждане. SpriteEntity Наследяване на класа. Кучето остава в фиксирано положение в 3D пространство.

поле

/// <summary>サウンドを開始または停止するまでの時間。</summary>
TimeSpan _timeDelay = TimeSpan.Zero;

/// <summary>現在再生中のサウンド(ある場合)。</summary>
SoundEffectInstance _activeSound = null;

_timeDelay се използва на интервали от време, за да изиграете вика.

SoundEffectInstance _activeSound е екземпляр за възпроизвеждане на звук. SoundEffectInstance Както често ще виждате в класа на възпроизвеждане на звука, можете да използвате това, както е в 3D звук. Между другото _activeSound , получавам само препратка от класа AudioManager по-късно, така че няма да го изхвърля от страната на класа Dot.

Метод за актуализиране

/// <summary>
/// 犬の位置を更新し、音を鳴らします。
/// </summary>
public override void Update(GameTime gameTime, AudioManager audioManager)
{
  // エンティティを固定位置に設定します。
  Position = new Vector3(0, 0, -4000);
  Forward = Vector3.Forward;
  Up = Vector3.Up;
  Velocity = Vector3.Zero;

  // 時間遅延がなくなった場合は、ループ音を開始または停止します。 これは通常は永久に続きますが、6秒の遅延後に停止し、さらに4秒後に再起動します。
  _timeDelay -= gameTime.ElapsedGameTime;

  if (_timeDelay < TimeSpan.Zero)
  {
    if (_activeSound == null)
    {
      // 現在再生中のサウンドがない場合は、トリガーします。
      _activeSound = audioManager.Play3DSound("DogSound", true, this);

      _timeDelay += TimeSpan.FromSeconds(6);
    }
    else
    {
      // それ以外の場合は、現在のサウンドを停止します。
      _activeSound.Stop(false);
      _activeSound = null;

      _timeDelay += TimeSpan.FromSeconds(4);
    }
  }
}

В тази проба кучето остава в същото положение дълго време, така че първите четири параметъра са уточнени чрез решителен удар. Рисуването се прави в основния клас.

_timeDelay след това се използва като оставащото време, за да спрете, играейки вика.

AudioManager ще бъде възпроизведенPlay3DSound в 3D пространство, като предаде името на вика, информацията за цикъла и вашата собствена информация като излъчвател на .

Класът "Куче" е предназначен да примкава вика, така че не е нужно да мислите твърде дълбоко, защото това е просто корекция, като игра или спиране на разклоняването.

Котешки клас

Това е клас, който прави котешки рисуване и пеене възпроизвеждане. SpriteEntity Наследяване на класа. Котката се движи около произхода.

поле

/// <summary>次の音を鳴らすまでの時間。</summary>
TimeSpan _timeDelay = TimeSpan.Zero;

/// <summary>サウンドバリエーションから選択するための乱数ジェネレータ。</summary>
static readonly Random _random = new Random();

_timeDelay се използва по същия начин като класа куче, с останалото време преди следващото изстисква.

Има три вида котешки обаждания, които са произволно избрани и изиграни, но нямат нищо общо с Audio3D, защото са бонус елемент.

Метод за актуализиране

/// <summary>
/// 猫の位置を更新し、音を鳴らします。
/// </summary>
public override void Update(GameTime gameTime, AudioManager audioManager)
{
  // 猫を大きな円で動かします。
  double time = gameTime.TotalGameTime.TotalSeconds;

  float dx = (float)-Math.Cos(time);
  float dz = (float)-Math.Sin(time);

  Vector3 newPosition = new Vector3(dx, 0, dz) * 6000;

  // エンティティの位置と速度を更新します。
  Velocity = newPosition - Position;
  Position = newPosition;
  if (Velocity == Vector3.Zero)
  {
    Forward = Vector3.Forward;
  }
  else
  {
    Forward = Vector3.Normalize(Velocity);
  }

  Up = Vector3.Up;

  // 時間遅延がなくなった場合は、別の単発音をトリガーします。
  _timeDelay -= gameTime.ElapsedGameTime;

  if (_timeDelay < TimeSpan.Zero)
  {
    // 異なる3つのサウンドバリエーション(CatSound0、CatSound1、CatSound2)からランダムに選択します。
    string soundName = "CatSound" + _random.Next(3);

    audioManager.Play3DSound(soundName, false, this);

    _timeDelay += TimeSpan.FromSeconds(1.25f);
  }
}

Тъй като котката се обръща произхода с кръгло движение, тя го обработва така, че да движи траекторията на кръга, използвайки тригонометрична функция. В резултат на това позиция, напред и скорост са се променили един след друг. Ето защо, когато стартирате програмата, можете да видите, че вика на котката обикаля наоколо, дори ако не преместите камерата.

_timeDelay Следният код е процес, при който вика на котката се присвоява на случаен принцип и се играе на редовни интервали от време. audioManager.Play3DSound Предавам се на метода, който е излъчвател. Можете да видите, че позицията за възпроизвеждане на звука се променя един по един.

АудиоСменяч клас

Това най-накрая е същността на Audio3D. 3D звук се състои от слушател и излъчвател. Излъчващият вече определя кучета и котки, така че класът AudioManager определя слушателите. Обикновено има множество излъчватели, докато има само един слушател.

Този клас наследява иGame регистрира GameComponent и използва компонента в класа.

ActiveSound клас

/// <summary>
/// アクティブな3Dサウンドを追跡し、アタッチされているエミッターオブジェクトを記憶するための内部ヘルパークラス。
/// </summary>
private class ActiveSound
{
  public SoundEffectInstance Instance;
  public IAudioEmitter Emitter;
}

Той е дефиниран в долната част на кода, но е клас за запазване на състоянието, което се играе. Тя има информация за звуковата инстанция, която се възпроизвежда, и излъчвател се възпроизвежда.

поле

// このマネージャーにロードされるすべてのサウンドエフェクトのリスト。
static string[] _soundNames =
  {
    "CatSound0",
    "CatSound1",
    "CatSound2",
    "DogSound",
  };

/// <summary>音を聞くリスナーの情報です。これは通常カメラに一致するように設定されます。</summary>
public AudioListener Listener { get; } = new AudioListener();

/// <summary>AudioEmitter は、3Dサウンドを生成しているエンティティを表します。</summary>
readonly AudioEmitter _emitter = new AudioEmitter();

/// <summary>再生可能なすべての効果音を保存します。</summary>
readonly Dictionary<string, SoundEffect> _soundEffects = new Dictionary<string, SoundEffect>();

/// <summary>現在再生中のすべての3Dサウンドを追跡します。また、再生が終わったインスタンスの破棄にも使用します。</summary>
readonly List<ActiveSound> _activeSounds = new List<ActiveSound>();

_soundNames определя името на аудио файла (име на актива) за зареждане. Тъй като това е примерна програма, тя се определя да зареди аудио файла в насипно състояние първо. Импортираните звукови данни се _soundEffects съхраняват в .

AudioListener Listener е определението на слушателя. Информацията за слушателя е дефинирана в, защото е public зададена от класа Игра.

AudioEmitter _emitter е дефиницията на излъчващия при прилагане на 3D за възпроизвеждане на звук. В тази извадка, когато възпроизвеждате звук, стойността на всеки обект на излъчвател е зададена _emitter на , така че това е формуляр, който споделя такъв като екземпляр. Разбира се, можете да имате за всеки AudioEmitter обект.

_activeSounds има информация за звука, който възпроизвеждате в класа, който сте определили ActiveSound по-рано. Тъй като информацията за излъчвател се променя през цялото време, тя се използва за актуализиране на информацията за местоположението и т.н., както и за изхвърляне на звукови екземпляри, приключили с възпроизвеждането.

Конструктор

public AudioManager(Game game) : base(game) { }

GameComponent Тъй като наследява класа, Game той получава екземпляра и го предава на базовия клас.

Инициализиране на метод

/// <summary>
/// オーディオマネージャを初期化します。
/// </summary>
public override void Initialize()
{
  // ゲームの世界のスケールと一致するように、3Dオーディオのスケールを設定します。
  // DistanceScale は、離れるにつれて音量が変化する音の量を制御します。
  // DopplerScale は、サウンドを通過するときにピッチが変化するサウンドの量を制御します。
  SoundEffect.DistanceScale = 2000;
  SoundEffect.DopplerScale = 0.1f;

  // すべての効果音をロードします。
  foreach (string soundName in _soundNames)
  {
    _soundEffects.Add(soundName, Game.Content.Load<SoundEffect>(soundName));
  }

  base.Initialize();
}

GameComponent Тъй като наследява класа, той автоматично се нарича при инициализация.

SoundEffect.DistanceScale и SoundEffect.DopplerScale са параметри, посветени на static 3D звука.

SoundEffect.DistanceScale за да чуете звук дори в разстоянието.

SoundEffect.DopplerScale е влиянието на Доплер ефекта. По-висок брой, по-голям доплер ефект.

_soundNames Запишете името на актива, дефинирано в цикъл, за да заредите _soundEffects .

Изхвърлете метода

/// <summary>
/// 効果音データをアンロードします。
/// GameComponent として登録すればゲーム終了時に自動的に呼ばれます。
/// </summary>
protected override void Dispose(bool disposing)
{
  try
  {
    if (disposing)
    {
      foreach (SoundEffect soundEffect in _soundEffects.Values)
      {
        soundEffect.Dispose();
      }

      _soundEffects.Clear();
    }
  }
  finally
  {
    base.Dispose(disposing);
  }
}

GameComponent Автоматично се нарича в края на играта, защото наследява класа.

Унищожаване на всички внесени звукови активи.

Метод за актуализиране

/// <summary>
/// 3Dオーディオシステムの状態を更新します。
/// </summary>
public override void Update(GameTime gameTime)
{
  // 現在再生中のすべての3Dサウンドをループします。
  int index = 0;

  while (index < _activeSounds.Count)
  {
    ActiveSound activeSound = _activeSounds[index];

    if (activeSound.Instance.State == SoundState.Stopped)
    {
      // 音の再生が終了した場合は廃棄してください。
      activeSound.Instance.Dispose();

      // アクティブリストから削除します。
      _activeSounds.RemoveAt(index);
    }
    else
    {
      // サウンドがまだ再生されている場合は、3D設定を更新します。
      Apply3D(activeSound);

      index++;
    }
  }

  base.Update(gameTime);
}

GameComponent Тъй като наследява класа, той автоматично се нарича в процеса на актуализиране.

Проверете възпроизвеждания в момента звук и, ако се Apply3D възпроизвежда, обадете се на метода, за да актуализирате местоположението на звука, така че да съответства на излъчващия. Ако някакъв звук е приключил с възпроизвеждането, екземплярът се изхвърля.

Play3DSound метод

/// <summary>
/// 新しい3Dサウンドを設定し再生します。
/// </summary>
public SoundEffectInstance Play3DSound(string soundName, bool isLooped, IAudioEmitter emitter)
{
  ActiveSound activeSound = new ActiveSound();

  // インスタンスを生成し、インスタンス、エミッターを設定します。
  activeSound.Instance = _soundEffects[soundName].CreateInstance();
  activeSound.Instance.IsLooped = isLooped;

  activeSound.Emitter = emitter;

  // 3D 位置を設定します。
  Apply3D(activeSound);

  activeSound.Instance.Play();

  // このサウンドがアクティブであることを保存します。
  _activeSounds.Add(activeSound);

  return activeSound.Instance;
}

Процесът на възпроизвеждане на 3D звук отвън. Той има името на звука за възпроизвеждане, дали да се примка, и излъчвател информация.

Ако искате да възпроизведете звук, създайте нов звуков екземпляр от звуковия ресурс, който държите в _soundEffects. SoundEffectInstance също може да има цикъл или не, така че задайте информацията за цикъла.

Тъй като създавам като ActiveSound игрално състояние, задавам излъчвателска информация, която е обектът на възпроизвеждане на звука там. Ако искате да приложите 3D информация за местоположението към звук, ще Emitter получите нужната ви стойност.

Apply3D Методът е описан по-долу, но това е процесът на прилагане на 3D информация от излъчващия към звука.

Основният процес на 3D звука е да започнете възпроизвеждане с SoundEffectInstance.Play 3D информационен набор. Останалото е периодично да актуализирате 3D информацията, докато звукът приключи с възпроизвеждането.

Прилагане на3D метод

/// <summary>
/// 3Dサウンドの位置と速度の設定を更新します。
/// </summary>
private void Apply3D(ActiveSound activeSound)
{
  _emitter.Position = activeSound.Emitter.Position;
  _emitter.Forward = activeSound.Emitter.Forward;
  _emitter.Up = activeSound.Emitter.Up;
  _emitter.Velocity = activeSound.Emitter.Velocity;

  activeSound.Instance.Apply3D(Listener, _emitter);
}

Процесът на прилагане на 3D ефект към определен звуков екземпляр с помощта на слушатели и излъчватели.

Задаваме стойността на _emitter на общия екземпляр всеки път. Ако вече AudioEmitter имате SoundEffectInstance.Apply3D такъв, просто преминете слушателя и излъчвателя към метода.

Аудио3DGame клас

И накрая, нека да разгледаме за какво е класът на Играта.

поле

readonly GraphicsDeviceManager _graphics;
readonly AudioManager _audioManager;
readonly SpriteEntity _cat;
readonly SpriteEntity _dog;

/// <summary>地面の描画に使用するテクスチャーです。</summary>
Texture2D _checkerTexture;

QuadDrawer _quadDrawer;

Vector3 _cameraPosition = new Vector3(0, 512, 0);
Vector3 _cameraForward = Vector3.Forward;
Vector3 _cameraUp = Vector3.Up;
Vector3 _cameraVelocity = Vector3.Zero;

KeyboardState _currentKeyboardState;
GamePadState _currentGamePadState;

AudioManager Регистрира GameComponents се в , но го има като поле, защото има достъп до него поотделно.

Други определят куче, котешки образувания, текстури за наземно рисуване, квадравер, информация за камерата и входна информация.

Конструктор

public Audio3DGame()
{
  Content.RootDirectory = "Content";

  _graphics = new GraphicsDeviceManager(this);

  _audioManager = new AudioManager(this);

  // AudioManager を Components に追加して自動的に Update メソッドが呼ばれるようにします。
  Components.Add(_audioManager);

  _cat = new Cat();
  _dog = new Dog();
}

AudioManager Генериране и GameComponents регистриране с .

Генерирали сте и часовете "Котка и куче".

Метод на зарежданеСъдържание

/// <summary>
/// グラフィックコンテンツをロードします。
/// </summary>
protected override void LoadContent()
{
  _cat.Texture = Content.Load<Texture2D>("CatTexture");
  _dog.Texture = Content.Load<Texture2D>("DogTexture");

  _checkerTexture = Content.Load<Texture2D>("checker");

  // 四角形ポリゴンを描画するためのクラス
  _quadDrawer = new QuadDrawer(_graphics.GraphicsDevice);
}

Заредете текстурите, необходими за всяка рисунка.

QuadDrawer се GraphicsDevice генерира тук, защото изисква .

Метод за актуализиране

/// <summary>
/// ゲームがロジックを実行できるようにします。
/// </summary>
protected override void Update(GameTime gameTime)
{
  HandleInput();

  UpdateCamera();

  // 新しいカメラの位置について AudioManager に伝えます。
  _audioManager.Listener.Position = _cameraPosition;
  _audioManager.Listener.Forward = _cameraForward;
  _audioManager.Listener.Up = _cameraUp;
  _audioManager.Listener.Velocity = _cameraVelocity;

  // ゲームエンティティに動き回って音を鳴らすように伝えます。
  _cat.Update(gameTime, _audioManager);
  _dog.Update(gameTime, _audioManager);

  base.Update(gameTime);
}

HandleInput Методите и UpdateCamera методите са процесът на извличане на въвеждане на устройство и работа с камерата, който ще бъде обсъден по-късно.

Тъй като позицията на камерата и позицията на слушателя са почти винаги еднакви, слушателът е настроен на същата стойност след процеса на актуализиране на камерата.

_cat Обадете се на методите и _dog Актуализирайте, за да се движат и изкрещят, съответно.

Метод на рисуване

/// <summary>
/// ゲームが描画する必要があるときに呼び出されます。
/// </summary>
protected override void Draw(GameTime gameTime)
{
  var device = _graphics.GraphicsDevice;

  device.Clear(Color.CornflowerBlue);

  device.BlendState = BlendState.AlphaBlend;

  // カメラ行列を計算します。
  var view = Matrix.CreateLookAt(_cameraPosition, _cameraPosition + _cameraForward, _cameraUp);
  var projection = Matrix.CreatePerspectiveFieldOfView(1, device.Viewport.AspectRatio, 1, 100000);

  // チェッカーグラウンドポリゴンを描画します。
  var groundTransform = Matrix.CreateScale(20000) * Matrix.CreateRotationX(MathHelper.PiOver2);

  _quadDrawer.DrawQuad(_checkerTexture, 32, groundTransform, view, projection);

  // ゲームエンティティを描画します。
  _cat.Draw(_quadDrawer, _cameraPosition, view, projection);
  _dog.Draw(_quadDrawer, _cameraPosition, view, projection);

  base.Draw(gameTime);
}

Генерира изглед и прожекционни трансформации от информацията за камерата.

За земята правоъгълника, нарисуван в QuadDrawer, се показва вертикално, така че се завърта, за да бъде хоризонтален и увеличен умерено. _quadDrawer.DrawQuad Вторият аргумент на метода указва броя повторения на текстурата, който указва, че 32x32 листа се появяват един до друг.

_cat и _dog се билбордират вътрешно, така че информацията за местоположението на фотоапарата се предава и чертае.

ДръжкаВ входен метод

/// <summary>
/// ゲームを終了するための入力を処理します。
/// </summary>
void HandleInput()
{
  _currentKeyboardState = Keyboard.GetState();
  _currentGamePadState = GamePad.GetState(PlayerIndex.One);

  // 終了を確認します。
  if (_currentKeyboardState.IsKeyDown(Keys.Escape) ||
      _currentGamePadState.Buttons.Back == ButtonState.Pressed)
  {
    Exit();
  }
}

Придобива се информация за клавиатурата и геймпада, като се определя краят на играта.

АктуализиранеКамера метод

/// <summary>
/// カメラを動かすための入力を処理します。
/// </summary>
void UpdateCamera()
{
  const float turnSpeed = 0.05f;
  const float accelerationSpeed = 4;
  const float frictionAmount = 0.98f;

  // 左または右に曲がります。
  float turn = -_currentGamePadState.ThumbSticks.Left.X * turnSpeed;

  if (_currentKeyboardState.IsKeyDown(Keys.Left)) turn += turnSpeed;
  if (_currentKeyboardState.IsKeyDown(Keys.Right)) turn -= turnSpeed;

  _cameraForward = Vector3.TransformNormal(_cameraForward, Matrix.CreateRotationY(turn));

  // 前方または後方に加速します。
  float accel = _currentGamePadState.ThumbSticks.Left.Y * accelerationSpeed;

  if (_currentKeyboardState.IsKeyDown(Keys.Up)) accel += accelerationSpeed;
  if (_currentKeyboardState.IsKeyDown(Keys.Down)) accel -= accelerationSpeed;

  _cameraVelocity += _cameraForward * accel;

  // 現在の位置に速度を追加します。
  _cameraPosition += _cameraVelocity;

  // 摩擦力を加えます。
  _cameraVelocity *= frictionAmount;
}

Камерата се управлява, за да се движи.

Също така включва изчисления като ускорение и триене, но мисля, че вероятно отчита ефекта на Doppler върху 3D звука. Тъй като не правя нищо специално за самото изчисление, няма да го обсъждам.

Резюме

Покрих го на дължина, но обикновено е достатъчно да се позова на класа за AudioManager това как се възпроизвежда 3D звук. Всъщност повечето от трудностите се правят от рамката, защото това, което SoundEffectInstance правим, е задаването на 3D информация в . Ако сте пробовземали само частите от 3D звука, в крайна сметка ще пишете малко работа в класа Game. Въпреки това, пиша Съвети въз основа на оригиналната история, така че е било много по-дълго.