Audio3D

Stránky aktualizovány :
Datum vytvoření stránky :

Poznámky k těmto tipům

Tato ukázka je založena na programech publikovaných na následujících webech. Trochu změním kód, aby bylo snazší ho pochopit a vysvětlit v japonštině. V podstatě používáme původní kód tak, jak je, takže pokud jej skutečně přijmete do svého herního programu, opravte jej včas a použijte jej.

Referenční stránka

Kromě toho je vysvětleno za předpokladu, že máte nějaké základní znalosti o MonoGame a XNA. Viz MonoGame Tipy a XNA Tipy pro ruddly.

Zejména jako matematika, vektory, trigonometrické funkce, matice atd. jsou nezbytné, takže prosím víte, co to je do určité míry.

životní prostředí

nástupiště
  • Systém Windows 10
  • Kód lze použít na jiných platformách podporujících MonoGame
Vizuální sada
  • Vizuální sada 2019
.NET Core
  • 3.1
MonoGame
  • 3.8

O vzorcích

Na základě polohy kamery můžete slyšet volání z pozice psa a polohy kočky. Kočka krouží a krouží kolem počátku a hráč může ovládat polohu kamery pomocí klíče. Ujistěte se, že způsob, jakým slyšíte zvuk, se mění s každou změnou polohy kamery nebo polohy kočky. Myslím, že je snadné pochopit pomocí sluchátek. Jsem nepotvrzený na kanálu 5.1.

Jak pracovat

Co dělat Klávesnice Gamepad (XInput) Mouse Touch
Fotoaparát dopředu a dozadu ↑↓ Levá páčka (nahoře a dole) - -
Změna orientace kamery ←→ Levá páčka (levá a pravá) - -
Konec hry Esc Hřbet - -

Co připravit

  • Psí kvílení zvukový soubor
  • Tři zvukové soubory kočičího kvílení
  • Soubor s obrázkem psa
  • Soubor s obrázkem kočky
  • Soubor pozemního obrazu

Původní vzorek na oficiálních stránkách používá předem připravený obsah .xnb soubory. Pokud chcete ukázky zachovat na oficiálním webu, nepoužívejte mgcbs, přidejte je přímo do řešení sady Visual Studio a zkopírujte je v době sestavení.

Nevím, proč původní vzorek používá tuto metodu, ale myslím, že je to pravděpodobně proto, že migrujeme starší verze projektu tak, jak jsou. Samozřejmě můžete použít mgcb ke generování stejného souboru. Projekty, které lze stáhnout na tomto webu, byly upraveny na verzi MGCB.

program

Stáhněte si program pro veškerý kód.

Tato ukázka je navržena tak, aby kód vypadal trochu obecněji a zároveň aby přehrávání zvuku vypadalo dobře za běhu. Použití pouze Audio3D by bylo mnohem méně kódu, ale je to popsáno podél původní ukázky. Méně důležité části si nechám.

Projekt se skládá z následujících souborů kódu:

  • Audio3DHra
  • AudioManager
  • Kočka
  • Pes
  • IAudioEmitter
  • Program
  • Čtyřkolka
  • SpriteEntity

Třída QuadDrawer

Tato třída je pomocná třída pro kreslení obdélníkových mnohoúhelníků. Obdélníkové mnohoúhelníky se často používají především k zobrazení 3D skřítků (billboardů). Tyto tipy se používají pro billboardy pro kočky a psy, stejně jako pro obdélníkové zobrazení země.

Tato třída nemá nic společného s Audio3D.

pole

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

Minimální informace potřebné k nakreslení mnohoúhelníků. Kreslete mnohoúhelníky z dat vrcholů bez přípravy dat modelu.

konstruktor

/// <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);
}

Vzhledem k tomu, že tato třída je univerzálně použitelná, obdržíte GraphicsDevice instanci vytvořenou v procesu inicializace třídy hry.

Zde nastavíme efekt potřebný k nakreslení skřítku a polohy 4 vrcholů potřebných pro obdélníkový mnohoúhelník. Velikost by měla být při kreslení zmenšena, takže je -1 až 1.

DrawQuad – metoda

/// <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);
}

Nastaví předanou texturu na obdélník a nakreslí ji. Vzhledem k tomu, že se jedná o základní proces, není co poznamenat.

Pokud existuje jeden bod, může být v textureRepeats argumentu zadána proměnná, aby bylo možné změnit souřadnice textury. Pokud je vertexPositionTexture.TextureCoordinate nastavena mimo rozsah 0 až 1, textura se ve výchozím nastavení kreslí opakovaně. Pomocí něj je možné vyjádřit, že dlaždice lze uspořádat opakovaně. Ve skutečnosti se zdá, že kostkované vzory na zemi mají několik jednoduchých černobílých obrázků seřazených.

IAudioEmitter – rozhraní

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

Definováno jako entita, která vydává zvuk. Vzhledem k tomu, že entity, které tentokrát vydávají zvuk, jsou psi a kočky, jsou zděděny ve svých příslušných třídách. Emitor potřebuje následující informace:

Využití nemovitosti
Postavení Pozice subjektu
Vpřed Směr, kterým entita směřuje (vektor)
Nahoru Vzestup entity. Směr, ve kterém hlava existuje v osobě
Rychlost Rychlost, jakou se entita pohybuje. Používá se k výpočtu Dopplerových hodnot.

Třída SpriteEntity

Třída pro reprezentaci 3D skřítků (billboardů). Je také zářičem a dědí IAudioEmitter . Psi a kočky dědí tuto třídu.

vlastnost

/// <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; }

Má informace o poloze subjektu atd. V podstatě mám informace jako zářič. Je to také entita výkresu, takže má také obrázek (texturu), který se má zobrazit.

Metoda aktualizace

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

Popisuje pozici entity a proces přehrávání zvuku, ale implementuje ji do odvozené třídy.

Metoda kreslení

/// <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);
}

Psi a kočky mají různé obrázky a polohy, ale druhý kreslicí mechanismus je přesně stejný, takže je zde popisuji.

Každá transformace a textura je předána Do QuadDrawer, aby se zobrazil obdélníkový mnohoúhelník. Vzhledem k tomu, že transformace souřadnic je základní znalost, vysvětlení nejsou zahrnuta.

Matrix.CreateConstrainedBillboard Používejte metody a informace o kameře pro snadnou reprezentaci billboardů, takže je efektivně využívejte.

Třída psů

Je to třída, která dělá psí kreslení a zpěv přehrávání. SpriteEntity Zdědění třídy. Pes zůstává v pevné poloze ve 3D prostoru.

pole

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

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

_timeDelay se používá v intervalech k hraní výkřiku.

SoundEffectInstance _activeSound je příklad pro přehrávání zvuku. SoundEffectInstance Jak často uvidíte ve třídě přehrávání zvuku, můžete to použít tak, jak je to ve 3D zvuku. Mimochodem _activeSound , odkaz z třídy AudioManager dostávám až později, takže ho na straně třídy Dot nezahodím.

Metoda aktualizace

/// <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);
    }
  }
}

V tomto vzorku zůstává pes ve stejné poloze po dlouhou dobu, takže první čtyři parametry jsou určeny rozhodujícím úderem. Kreslení se provádí v základní třídě.

_timeDelay se pak používá jako zbývající čas k zastavení a hraní pláče.

AudioManager bude reprodukovánPlay3DSound ve 3D prostoru předáním názvu výkřiku, informací o smyčce a vašich vlastních informací jako vysílače .

Třída Dog je navržena tak, aby smyčkovala pláč, takže nemusíte přemýšlet příliš hluboko, protože je to jen úprava, jako je hraní nebo zastavení větvení.

Třída koček

Je to třída, která kreslí kočky a zpívá přehrávání. SpriteEntity Zdědění třídy. Kočka se pohybuje kolem původu.

pole

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

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

_timeDelay se používá stejným způsobem jako třída Dog, se zbytkem času před dalším kvílením.

Existují tři typy kočičích hovorů, které jsou náhodně vybrány a přehrávány, ale nemají nic společného s Audio3D, protože jsou bonusovým prvkem.

Metoda aktualizace

/// <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);
  }
}

Vzhledem k tomu, že kočka otáčí kolem počátku kruhovým pohybem, zpracovává ji tak, že pohybuje trajektorií kruhu pomocí trigonometrické funkce. V důsledku toho se pozice, vpřed a rychlost mění jeden po druhém. Proto, když spustíte program, můžete vidět, že kočičí výkřik krouží kolem, i když nehýbete kamerou.

_timeDelay Následující kód je proces, ve kterém je kočičí výkřik náhodně přiřazen a přehráván v pravidelných intervalech. audioManager.Play3DSound Předávám se metodě, která je emitorem. Můžete vidět, že pozice přehrávání zvuku se mění jeden po druhém.

AudioManager – třída

To je konečně podstata Audio3D. 3D zvuk se skládá z posluchače a vysílače. Vysílač již definuje psy a kočky, takže třída AudioManager definuje posluchače. Obvykle existuje více zářičů, zatímco existuje pouze jeden posluchač.

Tato třída dědí aGame registruje GameComponent a používá komponentu ve třídě.

ActiveSound – třída

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

Je definován v dolní části kódu, ale je to třída pro zachování stavu, který se přehrává. Obsahuje informace o přehrávané zvukové instanci a přehrávaném vysílači.

pole

// このマネージャーにロードされるすべてのサウンドエフェクトのリスト。
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 definuje název zvukového souboru (název datového zdroje), který se má načíst. Vzhledem k tomu, že se jedná o ukázkový program, je definován tak, aby nejprve hromadně načetl zvukový soubor. Importovaná zvuková data jsou uložena _soundEffects v programu .

AudioListener Listener je definice posluchače. Informace posluchače jsou definovány, protože public jsou nastaveny ze třídy Game.

AudioEmitter _emitter je definice zářiče při aplikaci 3D na přehrávání zvuku. V této ukázce je při přehrávání zvuku hodnota každého objektu vysílače nastavena na , takže se _emitter jedná o formulář, který sdílí jeden jako instanci. Samozřejmě můžete mít pro každý AudioEmitter objekt.

_activeSounds obsahuje informace o zvuku, který přehráváte ve třídě, kterou jste definovali ActiveSound dříve. Vzhledem k tomu, že se informace vysílače neustále mění, používají se k aktualizaci informací o poloze atd. a k vyřazení zvukových instancí, které dokončily přehrávání.

konstruktor

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

GameComponent Vzhledem k tomu, že zdědí třídu, Game obdrží instanci a předá ji základní třídě.

Inicializovat metodu

/// <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 Vzhledem k tomu, že dědí třídu, je automaticky volána při inicializaci.

SoundEffect.DistanceScale a SoundEffect.DopplerScale jsou parametry věnované 3D zvuku static .

SoundEffect.DistanceScale slyšet zvuk i v dálce.

SoundEffect.DopplerScale je vliv Dopplerova jevu. Čím vyšší číslo, tím větší je Dopplerův jev.

_soundNames Uložte název datového zdroje definovaný ve smyčce pro načtení _soundEffects .

Metoda likvidace

/// <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 Je automaticky volán na konci hry, protože dědí třídu.

Zničení všech importovaných zvukových aktiv.

Metoda aktualizace

/// <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 Vzhledem k tomu, že dědí třídu, je automaticky volána v procesu aktualizace.

Zkontrolujte právě přehrávaný zvuk a pokud se Apply3D přehrává, zavolejte metodu pro aktualizaci umístění zvuku tak, aby odpovídalo vysílači. Pokud se přehrávání zvuku dokončí, instance se zahodí.

Play3DSound – metoda

/// <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;
}

Proces přehrávání 3D zvuku zvenčí. Má název zvuku, který se má přehrát, zda se má opakovat, a informace o emitoru.

Chcete-li přehrát zvuk, vytvořte novou instanci zvuku ze zvukového zdroje, který uchováváte v _soundEffects. SoundEffectInstance může mít také smyčku nebo ne, takže nastavte informace o smyčce.

Vzhledem k tomu, že vytvářím jako ActiveSound přehrávací stav, nastavuji informace vysílače, která je objektem přehrávání zvuku. Pokud chcete na zvuk aplikovat 3D informace o poloze, získáte Emitter hodnotu, kterou potřebujete.

Apply3D Metoda je popsána níže, ale je to proces aplikace 3D informací z emitoru na zvuk.

Základním procesem 3D zvuku je spuštění přehrávání se sadou SoundEffectInstance.Play 3D informací. Zbytek je pravidelně aktualizovat 3D informace, dokud se zvuk nedokončí.

Apply3D – metoda

/// <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);
}

Proces použití 3D efektu na zadanou instanci zvuku pomocí posluchačů a zářičů.

Hodnotu nastavíme na _emitter běžné instance pokaždé. SoundEffectInstance.Apply3D Pokud již AudioEmitter nějaký máte, jednoduše předejte posluchače a zářič metodě.

Audio3DGame Třída

Nakonec se podívejme na to, o čem je třída Game.

pole

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 Registruje GameComponents se v programu , ale má jej jako pole, protože k němu přistupuje jednotlivě.

Jiní definují entity psů, koček, textury pro pozemní kreslení, kvadrawer, informace o kameře a vstupní informace.

konstruktor

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 Vygenerujte a GameComponents zaregistrujte se v rozhraní .

Vygenerovali jste také třídy Kočka a Pes.

LoadContent – metoda

/// <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);
}

Načtěte textury potřebné pro každý výkres.

QuadDrawer je GraphicsDevice zde generován, protože vyžaduje rozhraní .

Metoda aktualizace

/// <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 Metody a UpdateCamera metody jsou proces načítání vstupu zařízení a manipulace s kamerou, který bude popsán později.

Vzhledem k tomu, že pozice kamery a pozice posluchače jsou téměř vždy stejné, je posluchač po procesu aktualizace kamery nastaven na stejnou hodnotu.

_cat Zavolejte metody a _dog Update pro pohyb a kvílení.

Metoda kreslení

/// <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);
}

Generuje transformace pohledu a projekce z informací kamery.

Pro zem je obdélník nakreslený v QuadDrawer zobrazen svisle, takže je otočen tak, aby byl vodorovný a mírně zvětšený. _quadDrawer.DrawQuad Druhý argument metody určuje počet opakování textury, který určuje, že listy 32x32 se zobrazí vedle sebe.

_cat a _dog jsou interně billboardovány, takže informace o poloze kamery jsou předávány a kresleny.

HandleInput – metoda

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

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

Informace o klávesnici a gamepadu jsou získány a konec hry je určen.

UpdateCamera – metoda

/// <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;
}

Kamera se ovládá tak, aby se pohybovala.

Zahrnuje také výpočty, jako je zrychlení a tření, ale myslím, že pravděpodobně bere v úvahu Dopplerův efekt na 3D zvuk. Vzhledem k tomu, že se samotným výpočtem nedělám nic zvláštního, nebudu o tom diskutovat.

Shrnutí

Podrobně jsem se o tom zmínil, ale obvykle stačí odkázat na třídu AudioManager , jak hrát 3D zvuk. Ve skutečnosti je většina obtíží způsobena rámcem, protože to, co SoundEffectInstance děláme, je nastavení 3D informací do . Pokud jste nasamplovali pouze části 3D zvuku, skončíte s psaním malé práce ve třídě Game. Nicméně píšu Tipy založené na původním příběhu, takže je to mnohem delší.