Avdio3D

Stran posodobljena :
Datum ustvarjanja strani :

Opombe o tem Nasveti

Ta vzorec temelji na programih, objavljenih na naslednjih spletnih mestih. Kodo malo spremenim, da jo lažje razumem in razložim v japonščini. V bistvu uporabljamo izvirno kodo, kot je, tako da, če jo dejansko sprejmete v vašem programu igre, jo pravočasno popravite in uporabite.

Referenčno mesto

Poleg tega je pojasnjeno pod predpostavko, da imate nekaj osnovnih znanj o MonoGame in XNA. Glejte MonoGame Nasveti in XNA Nasveti za nesramno.

Predvsem kot matematika, vektorji, trigonometrične funkcije, matrice itd. so bistvenega pomena, zato vas prosimo, da veste, kaj so do neke mere.

okolje

peron
  • Windows 10
  • Koda se lahko uporablja na drugih platformah, ki podpirajo MonoGame
Vizualni studio
  • Vizualni studio 2019
.NET Jedro
  • 3.1
MonoGame
  • 3.8

O vzorcih

Na podlagi položaja kamere lahko slišite klic iz pasjega položaja in položaja mačke. Mačka obkroži in obkroži izvor, igralec pa lahko s ključem nadzoruje položaj kamere. Prepričajte se, da se način, kako slišite zvok, spreminja z vsako spremembo položaja kamere ali položaja mačke. Mislim, da je enostavno razumeti z uporabo slušalk. Nisem potrjen na kanalu 5.1.

Kako delovati

Kaj
je storiti Tipkovnica Gamepad (XInput) Dotik miške
Kamera naprej in nazaj ↑↓ Leva palica (zgoraj in spodaj) - -
Spreminjanje usmerjenosti fotoaparata ←→ Leva palica (levo in desno) - -
Konec igre Esc Hrbet - -

Kaj pripraviti

  • Pasja zvočna datoteka
  • Tri zvočne datoteke za mačke
  • Datoteka slike psa
  • Datoteka s sliko mačke
  • Datoteka zemeljska slika

Izvirni vzorec na uradnem mestu uporablja prebuilt vsebine .xnb datoteke. Če želite obdržati vzorce na uradnem mestu, ne uporabljajte mgcbs, jih dodajte neposredno v rešitev Visual Studio in jih kopirajte ob času gradnje.

Ne vem, zakaj prvotni vzorec jemlje to metodo, ampak mislim, da je verjetno zato, ker selimo starejše različice projekta, kot je. Seveda lahko uporabite mgcb za ustvarjanje iste datoteke. Projekti, ki jih je mogoče prenesti na to spletno mesto, so bili spremenjeni v različico MGCB.

program

Prenesite program za vse kode.

Ta vzorec je zasnovan tako, da je koda videti malo bolj splošno, medtem ko je predvajanje zvoka videti dobro v času zagona. Uporaba audio3D bi bila le veliko manj koda, vendar je opisana vzdolž izvirnega vzorca. Obdržal bom manj pomembne dele.

Projekt je sestavljen iz naslednjih kodnih datotek:

  • Avdio3DGame
  • AvdioManager
  • Mačka
  • Pes
  • IAudioEmitter
  • Program
  • QuadDrawer
  • SpriteEntity

Razred QuadDrawer

Ta razred je pomočni razred za risanje pravokotnih poligonov. Pravokotni poligoni se pogosto uporabljajo predvsem za prikazovanje 3D spritov (panojev). Ti nasveti se uporabljajo za panoje za mačke in pse, kot tudi za pravokotne prikaze tal.

Ta razred nima nič opraviti z Audio3D.

polje

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

Minimalne informacije, potrebne za risanje večugana. Izvlecite poligone iz vertex podatkov, ne da bi pripravljali podatke o modelu.

gradbenik

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

Ker je ta razred splošno uposljiv, prejmete primerek, GraphicsDevice ustvarjen v postopku inicializacije razreda iger.

Tukaj določimo učinek, ki je potreben za risanje sprita in položaj 4 ovink, potrebnih za pravokotni poligon. Velikost je treba pri risbi meriti, tako da je -1 do 1.

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

Nariše preneto teksturo na pravokotnik in jo nariše. Ker gre za osnovni postopek, ni kaj za omenite.

Če obstaja ena točka, textureRepeats je v argumentu mogoče določiti imenovano spremenljivko, tako da je mogoče spremeniti koordinate tekstura. Če je vertexPositionTexture.TextureCoordinate nastavljena preko območja od 0 do 1, je tekstura privzeto večkrat narisana. Z uporabo je mogoče izraziti, da je ploščice mogoče razporediti večkrat. Videti je, da imajo vzorci na tleh po vrsti več preprostih črno-belih slik.

Vmesnik IAudioEmitter

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

Opredeljeno kot entiteta, ki oddaja zvok. Ker so entitete, ki tokrat oddajajo zvok, psi in mačke, so podedovali v svojih razredih. Emitter potrebuje naslednje informacije:

Uporaba
lastnosti
Položaj Položaj entitete
Naprej Smer, ki jo je entiteta obrnjena (vektor)
Gor Na strani entitete. Smer, v kateri glava obstaja v osebi
Hitrost Hitrost premikanja entitete. Uporablja se za izračun dopplerjevih vrednosti.

Razred spriteentnosti

Razred za zastopanje 3D sprites (panoji). Je tudi oddajnik in podedoval IAudioEmitter . Psi in mačke podedovali ta razred.

lastnost

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

Ima podatke o lokaciji entitete itd. V bistvu imam informacije kot oddajnik. Je tudi risasta entiteta, zato ima tudi sliko (Teksturo), ki jo je treba prikazati.

Način posodabljanja

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

Opisuje položaj entitete in proces predvajanja zvoka, vendar ga izvaja v izpeljanem razredu.

Način risanje

/// <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 in mačke imajo različne podobe in položaje, drugi mehanizem za risanje pa je popolnoma enak, zato jih tukaj opisujem.

Vsaka transformacija in tekstura se preneseta na QuadDrawer za prikaz pravokotnega poligona. Ker je koordinatna transformacija osnovno znanje, pojasnila niso zajeta.

Matrix.CreateConstrainedBillboard Z metodo in informacijami o fotoaparatu preprosto predstavljajte panoje, zato jih učinkovito izrabite.

Pasji razred

To je razred, ki se pasje risanje in pojejo predvajanje. SpriteEntity Podedovanje razreda. Pes ostaja v fiksnem položaju v 3D prostoru.

polje

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

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

_timeDelay se uporablja v intervalih za predvajanje joka.

SoundEffectInstance _activeSound je primer za predvajanje zvoka. SoundEffectInstance Kot boste pogosto videli v razredu predvajanja zvoka, lahko to uporabite tako, kot je v 3D zvoku. _activeSound Mimogrede , šele kasneje prejmem referenco iz razreda AudioManager, zato je ne bom zavržla na strani razreda Dot.

Način posodabljanja

/// <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 tem vzorcu pes še dolgo ostane v istem položaju, zato so prvi štirje parametri določeni z odločilno stavko. Risba je narejena v osnovnem razredu.

_timeDelay se nato uporablja kot preostali čas za ustavitev, igranje joka.

AudioManager bo reproduciranjePlay3DSound v 3D prostoru tako, da prenesete ime joka, informacije o zanki in vaše lastne podatke kot oddajnik na .

Pasji razred je namenjen zankanju joka, zato vam ni treba pregloboko razmišljati, ker gre le za prilagoditev, na primer igranje ali ustavitev razvejanja.

Razred mačk

To je razred, ki naredi mačka risanje in pojejo predvajanje. SpriteEntity Podedovanje razreda. Mačka se giblje okoli izvora.

polje

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

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

_timeDelay uporablja na enak način kot pasji razred, s preostanek časa pred naslednjim čtivom.

Obstajajo tri vrste klicov mačk, ki so naključno izbrani in predvajani, vendar nimajo nič opraviti z Audio3D, ker so bonus element.

Način posodabljanja

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

Ker se mačka v krožnem gibanju obrne okoli izvora, jo obdela tako, da premika pot kroga z uporabo trigonometrične funkcije. Zaradi tega so se položaj, naprej in hitrost spremenili eden za drugim. Zato lahko pri zagonu programa vidite, da mačkov jok kroži okoli, tudi če fotoaparata ne premaknete.

_timeDelay Naslednja koda je postopek, v katerem je mačji jok naključno dodeljen in predvajan v rednih intervalih. audioManager.Play3DSound Podajam se metodi, ki je oddajnik. Vidite lahko, da se položaj predvajanja zvoka spreminja enega za enim.

Razred audioManager

To je končno bistvo Audio3D. 3D zvok sestavljajo poslušalec in oddajnik. Oddajnik že opredeljuje pse in mačke, zato razred AudioManager definira poslušalce. Običajno je več oddajnika, medtem ko je samo en poslušalec.

Ta razred podedujeGame GameComponent in registrira in uporablja komponento v razredu.

ActiveSound razred

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

Opredeljena je na dnu kode, vendar je razred za ohranjanje stanja, ki se igra. Ima informacije o predvajanem zvočnem primerku in predvajanem emiterju.

polje

// このマネージャーにロードされるすべてのサウンドエフェクトのリスト。
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 določa ime zvočne datoteke (ime sredstva) za nalaganje. Ker gre za vzorčni program, je definirano, da najprej naloži zvočno datoteko v velikem obsegu. Uvoženi zvočni podatki so shranjeni _soundEffects v programu .

AudioListener Listener je definicija poslušalca. Informacije o poslušalcih so opredeljene v, ker so public nastavljene iz razreda Igre.

AudioEmitter _emitter je definicija oddajnika pri uporabi 3D za predvajanje zvoka. V tem vzorcu je pri predvajanju zvoka vrednost vsakega oddajnika nastavljena na , tako da je to obrazec, _emitter ki ga deli kot primerek. Seveda lahko imate za vsak AudioEmitter predmet.

_activeSounds ima informacije o zvoku, ki ga predvajate v ActiveSound razredu, ki ste ga določili prej. Ker se informacije o emiterju ves čas spreminjajo, se uporabljajo za posodabljanje informacij o lokaciji itd.

gradbenik

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

GameComponent Ker podeduje razred, Game prejme primerek in ga preda osnovnemu razredu.

Inicializacija metode

/// <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 Ker podeduje razred, se samodejno imenuje ob inicializaciji.

SoundEffect.DistanceScale in so SoundEffect.DopplerScale parametri, namenjeni static 3D zvoku.

SoundEffect.DistanceScale da slišite zvok tudi v daljavi.

SoundEffect.DopplerScale je vpliv Dopplerjevega učinka. Višje kot je število, večji je Dopplerjev učinek.

_soundNames Shranite ime sredstva, ki je opredeljeno v zanki za nalaganje _soundEffects .

Način odstranjevanja

/// <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 Na koncu igre se samodejno imenuje, ker podeduje razred.

Uničujem vsa uvožena zvočna sredstva.

Način posodabljanja

/// <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 Ker podeduje razred, se samodejno kliče v postopku posodobitve.

Preverite trenutno predvajani zvok in, Apply3D če se predvaja, pokličite metodo za posodobitev lokacije zvoka, da se ujema z oddajnik. Če je katerikoli zvok dokončal predvajanje, se primerek zavrže.

Način predvajanja3DSound

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

Postopek predvajanja 3D zvoka od zunaj. Ima ime zvoka za predvajanje, ali zanke in emitter informacije.

Če želite predvajati zvok, ustvarite nov primerek zvoka iz zvočnega vira, ki ga hranite v _soundEffects. SoundEffectInstance lahko tudi zanko ali ne, zato nastavite informacije o zanki.

Ker ustvarjam kot ActiveSound stanje predvajanja, nastavim emiter informacije, ki je predmet predvajanja zvoka tam. Če želite uporabiti informacije o 3D lokaciji za zvok, Emitter boste dobili potrebno vrednost.

Apply3D Metoda je opisana spodaj, vendar je postopek uporabe 3D informacij od oddajnika na zvok.

Osnovni postopek 3D zvoka SoundEffectInstance.Play je začetek predvajanja s 3D naborom informacij. Ostalo je občasno posodabljanje 3D informacij, dokler zvok ne konča predvajanja.

Uporabi3D metodo

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

Postopek uporabe 3D efekta na določen zvočni primerek z uporabo poslušalca in oddajnika.

Vrednost vsakič nastavimo na _emitter skupnega primerka. Če ga že SoundEffectInstance.Apply3D AudioEmitter imate, preprosto podajte poslušalca in oddajnika metodi.

Razred zvoka3DGame

Na koncu poglejmo, za kaj gre v razredu igre.

polje

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 Registrira se GameComponents v , vendar ga ima kot polje, ker do tega dostopa posamično.

Drugi opredeljujejo pse, entitete mačk, teksture za risanje tal, četverica, informacije o kameri in vhodne informacije.

gradbenik

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 Ustvarite in registrirajte GameComponents se z .

Ustvarili ste tudi razrede mačk in psov.

Metoda LoadContent

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

Nalaganje tekstur, ki so potrebna za vsako risbo.

QuadDrawer je ustvarjen GraphicsDevice tukaj, ker zahteva .

Način posodabljanja

/// <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 Metode in UpdateCamera metode so postopek pridobivanja vhoda naprave in rokovanja s kamero, o katerem bomo razpravljali kasneje.

Ker sta položaj kamere in položaj poslušalca skoraj vedno enaka, je poslušalec po postopku posodobitve fotoaparata nastavljen na isto vrednost.

_cat Pokličite načine in posodobite _dog , da se premaknete in zaslišate.

Način risanje

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

Ustvari prikaz in projekcijske transformacije iz informacij o fotoaparatu.

Za tla je pravokotnik, narisan v QuadDrawerju, prikazan navpično, zato je zasukan tako, da je vodoravno in povečan zmerno. _quadDrawer.DrawQuad Drugi argument metode določa število ponovitev tekstura, ki določa, da se 32x32 listov pojavi ob strani.

_cat in _dog notranja plakata, zato se informacije o lokaciji kamere podajajo in izrisajo.

Način handleInput

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

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

Pridobljene so informacije na tipkovnici in igralni ploščici, določen pa je tudi konec igre.

Metoda UpdateCamera

/// <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 je nadzorovana, da se premika.

Vključuje tudi izračune, kot sta pospešek in trenje, vendar mislim, da verjetno upošteva Dopplerjev učinek na 3D zvok. Ker glede samega izračuna ne naredim nič posebnega, o tem ne bom razpravljal.

Povzetek

Po dolžini sem ga pokril, AudioManager a je ponavadi dovolj, da se sklicujem na razred, kako predvajati 3D zvok. V resnici večino težav opravi okvir, kajti to, kar delamo, SoundEffectInstance je nastavljanje 3D informacij v . Če ste vzorčeni le dele 3D zvoka, boste na koncu napisali malo dela v razredu Igre. Vendar pa pišem Nasveti na podlagi izvirne zgodbe, tako da je bilo veliko dlje.