Ääni3D

Sivu päivitetty :
Sivun luontipäivämäärä :

Huomautuksia näistä vinkeistä

Tämä esimerkki perustuu seuraavissa sivustoissa julkaistuihin ohjelmiin. Muutan koodia hieman, jotta se olisi helpompi ymmärtää ja selittää japaniksi. Periaatteessa käytämme alkuperäistä koodia sellaisenaan, joten jos todella otat sen käyttöön peliohjelmassasi, korjaa se ajoissa ja käytä sitä.

Viitesivusto

Lisäksi se selitetään olettamuksella, että sinulla on jonkin verran perustietoa MonoGamesta ja XNA: sta. Katso MonoGame-vinkit ja XNA-vinkit ruddlylle.

Erityisesti matematiikka, vektorit, trigonometriset toiminnot, matriisit jne., Ovat välttämättömiä, joten tiedä, mitä ne ovat jossain määrin.

ympäristö

lava
  • Windows 10
  • Koodia voidaan käyttää muilla MonoGame-yhteensopivilla alustoilla
Visual Studio
  • Visual Studio 2019
.NET-ydin
  • 3.1
MonoGame
  • 3.8

Tietoja näytteistä

Kameran sijainnin perusteella voit kuulla kutsun koiran sijainnista ja kissan sijainnista. Kissa ympyröi ja ympyröi alkuperän, ja pelaaja voi hallita kameran sijaintia avaimella. Varmista, että äänen kuuleminen muuttuu jokaisen kameran sijainnin tai kissan sijainnin muutoksen myötä. Mielestäni on helppo ymmärtää kuulokkeiden avulla. Minua ei ole vahvistettu kanavalla 5.1.

Miten toimia

Mitä tehdä näppäimistön peliohjain (XInput) Hiiren kosketus
Kamera eteen- ja taaksepäin ↑↓ Vasen sauva (ylä- ja alaosa) - -
Kameran suunnan muuttaminen ←→ Vasen sauva (vasen ja oikea) - -
Pelin loppu Esc Selkä - -

Mitä valmistaa

  • Koiran squeal äänitiedosto
  • Kolme kissan vinkumista äänitiedostoa
  • Koiran kuvatiedosto
  • Kissan kuvatiedosto
  • Maadoituskuvatiedosto

Alkuperäinen näyte virallisella sivustolla käyttää valmiiksi rakennettuja sisältöjä .xnb tiedostoja. Jos haluat säilyttää näytteet virallisella sivustolla, älä käytä mgcbs: ää, lisää ne suoraan Visual Studio -ratkaisuusi ja kopioi ne rakennushetkellä.

En tiedä, miksi alkuperäinen näyte käyttää tätä menetelmää, mutta luulen, että se johtuu todennäköisesti siitä, että siirrämme projektin vanhempia versioita sellaisenaan. Voit tietysti käyttää mgcb: tä saman tiedoston luomiseen. Projektit, jotka voidaan ladata tältä sivustolta, on muutettu MGCB-versioon.

ohjelma

Lataa ohjelma kaikille koodeille.

Tämä näyte on suunniteltu saamaan koodi näyttämään hieman yleisemmältä ja samalla saamaan äänen toisto näyttämään hyvältä suorituksen aikana. Vain Audio3D: n käyttäminen olisi paljon vähemmän koodia, mutta se on kuvattu alkuperäisessä näytteessä. Pidän vähemmän tärkeät osat.

Projekti koostuu seuraavista kooditiedostoista:

  • Audio3DGame
  • AudioManager
  • Kissa
  • Koira
  • IAudioEmitter
  • Ohjelma
  • QuadDrawer
  • SpriteEntity

QuadDrawer-luokka

Tämä luokka on avustajaluokka suorakulmaisten monikulmioiden piirtämiseen. Suorakulmaisia monikulmioita käytetään usein ensisijaisesti 3D-spritien (mainostaulujen) näyttämiseen. Näitä vinkkejä käytetään kissojen ja koirien mainostauluihin sekä maan suorakulmaisiin näyttöihin.

Tällä luokalla ei ole mitään tekemistä Audio3D: n kanssa.

pelto

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

Monikulmioiden piirtämiseen tarvitaan vähimmäistiedot. Piirrä monikulmioita kärkipistetiedoista valmistelematta mallitietoja.

rakentaja

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

Koska tämä luokka on yleisesti käyttökelpoinen, saat GraphicsDevice esiintymän, joka on luotu peliluokan alustusprosessissa.

Tässä asetamme tarvittavan vaikutuksen spriten piirtämiseksi ja suorakulmaisen monikulmion edellyttämien 4 kärkipisteen sijainnin piirtämiseksi. Koko on skaalattava piirtämisen aikana, joten se on -1 - 1.

DrawQuad-menetelmä

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

Määrittää välitetyn materiaalikuvion suorakulmioksi ja piirtää sen. Koska tämä on perusprosessi, ei ole mitään huomautettavaa.

Jos argumentissa textureRepeats on yksi piste, muuttuja, jota kutsutaan, voidaan määrittää, jotta tekstuurin koordinaatteja voidaan muuttaa. Jos vertexPositionTexture.TextureCoordinate on asetettu alueen 0 - 1 ulkopuolelle, materiaalikuvio piirretään oletusarvoisesti toistuvasti. Sen avulla on mahdollista ilmaista, että laatat voidaan järjestää toistuvasti. Itse asiassa maassa olevilla ruudullisilla kuvioilla näyttää olevan useita yksinkertaisia mustavalkoisia kuvia.

IAudioEmitter-käyttöliittymä

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

Määritetty entiteetiksi, joka säteilee ääntä. Koska tällä kertaa ääntä lähettävät entiteetit ovat koiria ja kissoja, ne periytyvät omissa luokissaan. Emitter tarvitsee seuraavat tiedot:

Ominaisuuden käyttö
Asema Entiteetin toimi
Eteenpäin Entiteetin suunta (vektori)
Ylös Entiteetin nousu. Suunta, jossa pää on henkilössä
Nopeus Nopeus, jolla entiteetti liikkuu. Käytetään Doppler-arvojen laskemiseen.

SpriteEntity-luokka

Luokka, joka edustaa 3D-sprittejä (mainostauluja). Se on myös emitteri ja perii IAudioEmitter . Koirat ja kissat perivät tämän luokan.

ominaisuus

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

Sillä on yksikön sijaintitiedot jne. Periaatteessa minulla on tietoa päästöjen aiheuttajana. Se on myös piirustusentiteetti, joten siinä on myös kuva (pintakuvio) näytettäväksi.

Päivitä-menetelmä

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

Kuvaa entiteetin sijainnin ja äänen toistoprosessin, mutta toteuttaa sen johdetussa luokassa.

Piirrä menetelmä

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

Koirilla ja kissoilla on erilaiset kuvat ja asennot, mutta toinen piirustusmekanismi on täsmälleen sama, joten kuvailen niitä täällä.

Jokainen muunnos ja rakenne välitetään QuadDrawerille suorakulmaisen monikulmion näyttämiseksi. Koska koordinaattimuunnos on perustietoa, selityksiä ei käsitellä.

Matrix.CreateConstrainedBillboard Käytä menetelmä- ja kameratietoja edustamaan mainostauluja helposti, joten käytä niitä tehokkaasti.

Koiraluokka

Se on luokka, joka tekee koiran piirtämistä ja laulamista. SpriteEntity Luokan periminen. Koira pysyy kiinteässä asennossa 3D-tilassa.

pelto

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

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

_timeDelay käytetään säännöllisin väliajoin itkun toistamiseen.

SoundEffectInstance _activeSound on esimerkki äänen toistamisesta. SoundEffectInstance Kuten usein näet äänen toistoluokassa, voit käyttää tätä sellaisenaan 3D-äänessä. Muuten _activeSound , saan viittauksen AudioManager-luokasta vain myöhemmin, joten en hylkää sitä Dot-luokan puolella.

Päivitä-menetelmä

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

Tässä näytteessä koira pysyy samassa asennossa pitkään, joten neljä ensimmäistä parametria määritetään ratkaisevalla iskulla. Piirustus tehdään perusluokassa.

_timeDelay käytetään sitten jäljellä olevana ajankohtana pysähtyä, soittamalla huutoa.

AudioManager toistetaanPlay3DSound 3D-tilassa välittämällä itkun nimi, silmukan tiedot ja omat tietosi lähettimenä -järjestelmään.

Koira-luokka on suunniteltu silmukkaan itku, joten sinun ei tarvitse ajatella liian syvälle, koska se on vain säätö, kuten pelaaminen tai haarautumisen lopettaminen.

Kissan luokka

Se on luokka, joka piirtää kissaa ja laulaa toistoa. SpriteEntity Luokan periminen. Kissa liikkuu alkuperän ympärillä.

pelto

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

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

_timeDelay käytetään samalla tavalla kuin Koira-luokkaa, ja loput ajasta ennen seuraavaa vinkumista.

On olemassa kolmenlaisia kissakutsuja, jotka valitaan satunnaisesti ja toistetaan, mutta niillä ei ole mitään tekemistä Audio3D: n kanssa, koska ne ovat bonuselementti.

Päivitä-menetelmä

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

Koska kissa kääntyy alkuperän ympäri pyöreällä liikkeellä, se käsittelee sitä niin, että se siirtää ympyrän liikerataa trigonometrisellä toiminnolla. Tämän seurauksena sijainti, eteenpäin ja Nopeus ovat muuttuneet yksi toisensa jälkeen. Siksi, kun suoritat ohjelman, voit nähdä, että kissan itku kiertää ympäri, vaikka et siirrä kameraa.

_timeDelay Seuraava koodi on prosessi, jossa kissan itku osoitetaan satunnaisesti ja pelataan säännöllisin väliajoin. audioManager.Play3DSound Siirryn menetelmään, joka on päästöjen aiheuttaja. Voit nähdä, että äänen toistoasento muuttuu yksitellen.

AudioManager-luokka

Tämä on vihdoin Audio3D: n ydin. 3D-ääni koostuu kuuntelijasta ja säteilijästä. Emitteri määrittelee jo koirat ja kissat, joten AudioManager-luokka määrittelee kuuntelijat. Säteilijöitä on yleensä useita, kun taas kuuntelijoita on vain yksi.

Tämä luokka perii,Game rekisteröi GameComponent ja käyttää luokan komponenttia.

ActiveSound-luokka

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

Se on määritelty koodin alaosassa, mutta se on luokka pelaavan tilan säilyttämiseksi. Siinä on tietoa toistettavasta ääniesiintymästä ja toistettavasta emitteristä.

pelto

// このマネージャーにロードされるすべてのサウンドエフェクトのリスト。
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 määrittää ladattavan äänitiedoston nimen (resurssin nimen). Koska se on esimerkkiohjelma, äänitiedosto on määritetty lataamaan ensin joukkona. Tuodut äänitiedot tallennetaan _soundEffects -järjestelmään.

AudioListener Listener on kuuntelijan määritelmä. Kuuntelijan tiedot määritetään -järjestelmässä, koska ne public on määritetty Peli-luokasta.

AudioEmitter _emitter on lähettimen määritelmä, kun 3D:tä käytetään äänentoistoon. Tässä esimerkissä ääntä toistettaessa kunkin lähetinobjektin arvoksi _emitter määritetään , joten se on lomake, joka jakaa yhden esiintymänä. Tietenkin voit saada jokaiselle AudioEmitter esineelle.

_activeSounds sisältää tietoja äänestä, jota toistat aiemmin määrittämässäsi ActiveSound luokassa. Koska lähetintiedot muuttuvat koko ajan, sitä käytetään sijaintitietojen päivittämiseen jne., Ja hylkäämään toiston lopettaneet ääniesiintymät.

rakentaja

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

GameComponent Koska se perii luokan, Game se vastaanottaa esiintymän ja välittää sen perusluokkaan.

Alusta menetelmä

/// <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 Koska se perii luokan, sitä kutsutaan automaattisesti alustuksen yhteydessä.

SoundEffect.DistanceScale ja SoundEffect.DopplerScale ovat parametreja, jotka on omistettu 3D-äänelle static .

SoundEffect.DistanceScale kuulla ääntä jopa etäisyydellä.

SoundEffect.DopplerScale on Doppler-vaikutuksen vaikutus. Mitä suurempi luku, sitä suurempi doppler-vaikutus.

_soundNames Tallenna silmukassa määritetty resurssin nimi lataamista _soundEffects varten .

Hävittämismenetelmä

/// <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 Sitä kutsutaan automaattisesti pelin lopussa, koska se perii luokan.

Tuhoan kaikki tuodut äänivarat.

Päivitä-menetelmä

/// <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 Koska se perii luokan, sitä kutsutaan automaattisesti päivitysprosessissa.

Tarkista toistettava ääni ja, jos sitä Apply3D toistetaan, soita menetelmään päivittääksesi äänen sijainnin vastaamaan lähetintä. Jos jonkin äänen toistaminen on päättynyt, esiintymä hylätään.

Play3DSound-menetelmä

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

Prosessi, jossa 3D-ääntä toistetaan ulkopuolelta. Siinä on toistettavan äänen nimi, olipa kyseessä silmukka ja säteilevä tieto.

Jos haluat toistaa äänen, luo uusi ääniesiintymä _soundEffects säilytettävästä ääniresurssista. SoundEffectInstance voi olla myös silmukka tai ei, joten aseta silmukan tiedot.

Koska luon toistotilana ActiveSound , asetan lähetintiedot, jotka ovat siellä olevan äänen toisto-objekti. Jos haluat käyttää 3D-sijaintitietoja äänessä, saat Emitter tarvitsemasi arvon.

Apply3D Menetelmä on kuvattu alla, mutta se on prosessi, jossa 3D-tietoja levitetään säteilijästä ääneen.

3D-äänen perusprosessi on aloittaa toisto 3D-tietojoukolla SoundEffectInstance.Play . Loput on päivittää 3D-tiedot säännöllisesti, kunnes ääni on toistettu.

Apply3D-menetelmä

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

Prosessi, jossa 3D-tehostetta käytetään määritettyyn ääni-esiintymään kuuntelijoiden ja säteilijöiden avulla.

Asetamme arvon yleisen esiintymän _emitter joka kerta. Jos sinulla SoundEffectInstance.Apply3D on jo AudioEmitter sellainen, siirrä vain kuuntelija ja lähetin menetelmään.

Audio3DGame-luokka

Lopuksi katsotaanpa, mistä Peli-luokassa on kyse.

pelto

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 Rekisteröityy GameComponents -järjestelmään, mutta pitää sitä kenttänä, koska se käyttää sitä erikseen.

Toiset määrittelevät koiran, kissan entiteetit, maapiirustuksen tekstuurit, quaddrawerin, kameratiedot ja syöttötiedot.

rakentaja

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 Luo ja GameComponents rekisteröi -toiminnolla .

Olet myös luonut Kissa ja koira -luokat.

LoadContent-menetelmä

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

Lataa kuhunkin piirustukseen tarvittavat pintakuviot.

QuadDrawer luodaan GraphicsDevice tässä, koska se vaatii .

Päivitä-menetelmä

/// <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 Menetelmät ja UpdateCamera menetelmät ovat prosessi laitteen tulon hakemiseksi ja kameran käsittelemiseksi, josta keskustellaan myöhemmin.

Koska kameran sijainti ja kuuntelijan sijainti ovat lähes aina samat, kuuntelija asetetaan samaan arvoon kameran päivitysprosessin jälkeen.

_cat Voit siirtää ja vinkua valitsemalla - ja _dog Päivitä-menetelmiä.

Piirrä menetelmä

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

Luo näkymä- ja projektiomuunnokset kameran tiedoista.

Maassa QuadDrawerissa piirretty suorakulmio näytetään pystysuunnassa, joten sitä kierretään vaakasuoraksi ja suurennetaan kohtalaisesti. _quadDrawer.DrawQuad Menetelmän toinen argumentti määrittää tekstuurin toistojen määrän, mikä määrittää, että 32x32 arkkia näkyy vierekkäin.

_cat ja _dog mainostetaan sisäisesti, joten kameran sijaintitiedot välitetään ja piirretään.

HandleInput-menetelmä

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

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

Näppäimistön ja peliohjaimen tiedot hankitaan, ja pelin loppu määritetään.

UpdateCamera-menetelmä

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

Kameraa ohjataan liikkumaan.

Se sisältää myös laskelmia, kuten kiihtyvyyttä ja kitkaa, mutta luulen, että se todennäköisesti ottaa huomioon Doppler-vaikutuksen 3D-ääneen. Koska en tee mitään erityistä itse laskelmalle, en keskustele siitä.

Yhteenveto

Olen peittänyt sen pitkään, mutta yleensä riittää, että viittaat luokkaan AudioManager 3D-äänen toistamiseksi. Itse asiassa suurin osa vaikeuksista tapahtuu kehyksellä, koska teemme SoundEffectInstance 3D-tietojen asettamisen . Jos olet ottanut näytteitä vain 3D-äänen osista, päädyt kirjoittamaan pienen työn Peli-luokkaan. Kirjoitan kuitenkin vinkkejä alkuperäisen tarinan perusteella, joten siitä on paljon kauemmin.