Audio3D

Pagina bijgewerkt :
Aanmaakdatum van pagina :

Opmerkingen over deze tips

Dit voorbeeld is gebaseerd op de programma's die op de volgende sites zijn gepubliceerd. Ik verander de code een beetje om het gemakkelijker te begrijpen en uit te leggen in het Japans. Kortom, we gebruiken de originele code zoals deze is, dus als je het daadwerkelijk in je spelprogramma gebruikt, corrigeer het dan tijdig en gebruik het.

Referentie site

Daarnaast wordt uitgelegd in de veronderstelling dat je enige basiskennis hebt over MonoGame en XNA. Zie MonoGame Tips en XNA Tips voor de onbeschofte.

In het bijzonder, omdat wiskunde, vectoren, goniometrische functies, matrices, enz. essentieel zijn, dus weet tot op zekere hoogte wat ze zijn.

milieu

perron
  • Windows 10
  • Code kan worden gebruikt op andere MonoGame-enabled platforms
Visual Studio
  • Visual Studio 2019
.NET Core
  • 3.1
Monogame
  • 3.8

Over voorbeelden

Op basis van de positie van de camera kunt u de roep horen vanuit de positie van de hond en de positie van de kat. De kat cirkelt en cirkelt de oorsprong en de speler kan de positie van de camera met de sleutel regelen. Zorg ervoor dat de manier waarop u het geluid hoort, verandert met elke verandering in de positie van de camera of de positie van de kat. Ik denk dat het gemakkelijk te begrijpen is met behulp van oortelefoons. Ik ben onbevestigd op kanaal 5.1.

Hoe te werken

Wat moet er gebeuren Keyboard Gamepad (XInput) Mouse Touch
Camera vooruit en achteruit ↑↓ Linker stick (boven en onder) - -
De camerastand wijzigen ←→ Linker stick (links en rechts) - -
Einde spel Esc Terug - -

Wat te bereiden

  • Hond piepen audiobestand
  • Drie cat piepende audiobestanden
  • Hond Afbeeldingsbestand
  • Cat afbeeldingsbestand
  • Gemalen afbeeldingsbestand

Het originele voorbeeld op de officiële site maakt gebruik van vooraf gebouwde . xnb-bestanden . Als u de voorbeelden op de officiële site wilt bewaren, gebruikt u geen mgcbs, voegt u ze rechtstreeks toe aan uw Visual Studio-oplossing en kopieert u ze tijdens het bouwen.

Ik weet niet waarom het oorspronkelijke voorbeeld deze methode gebruikt, maar ik denk dat het waarschijnlijk komt omdat we oudere versies van het project migreren zoals het is. Natuurlijk kunt u mgcb gebruiken om hetzelfde bestand te genereren. De projecten die op deze site kunnen worden gedownload, zijn aangepast naar de MGCB-versie.

programma

Download het programma voor alle code.

Dit voorbeeld is ontworpen om de code er iets algemener uit te laten zien en tegelijkertijd de geluidsweergave er goed uit te laten zien tijdens runtime. Alleen Audio3D gebruiken zou veel minder code zijn, maar het wordt beschreven langs het originele voorbeeld. De minder belangrijke onderdelen bewaar ik.

Het project bestaat uit de volgende codebestanden:

  • Audio3Dgame
  • Audiomanager
  • Kat
  • Hond
  • IAudioEmitter
  • Programma
  • Quaddrawer |
  • SpriteEntiteit

QuadDrawer klasse

Deze klasse is een hulpklasse voor het tekenen van rechthoekige veelhoeken. Rechthoekige polygonen worden vaak voornamelijk gebruikt om 3D-sprites (billboards) weer te geven. Deze tips worden gebruikt voor billboards voor katten en honden, maar ook voor rechthoekige weergaven van de grond.

Deze klasse heeft niets te maken met Audio3D.

veld

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

Minimale informatie die vereist is om polygonen te tekenen. Teken polygonen uit hoekpuntgegevens zonder modelgegevens voor te bereiden.

bouwer

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

Omdat deze klasse universeel bruikbaar is, ontvangt u GraphicsDevice een instantie die is gemaakt in het initialisatieproces van de gameklasse.

Hier stellen we het effect in dat nodig is om de sprite en de positie van de 4 hoekpunten te tekenen die nodig zijn voor de rechthoekige veelhoek. De grootte moet worden geschaald tijdens het tekenen, dus het is -1 tot 1.

DrawQuad methode

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

Hiermee stelt u de doorgegeven structuur in op een rechthoek en tekent u deze. Aangezien dit een basisproces is, is er niets op te merken.

Als er één punt is, kan een aangeroepen variabele worden opgegeven in textureRepeats het argument, zodat de coördinaten van de structuur kunnen worden gewijzigd. Als vertexPositionTexture.TextureCoordinate is ingesteld buiten het bereik 0 tot en met 1, wordt de structuur standaard herhaaldelijk getekend. Hiermee is het mogelijk om uit te drukken dat tegels herhaaldelijk kunnen worden gerangschikt. In feite lijken de geblokte patronen op de grond meerdere eenvoudige zwart-witafbeeldingen te hebben opgesteld.

IAudioEmitter-interface

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

Gedefinieerd als een entiteit die geluid uitzendt. Omdat de entiteiten die deze keer geluid uitzenden honden en katten zijn, worden ze geërfd in hun respectieve klassen. Emitter heeft de volgende informatie nodig:

Gebruik van onroerend goed
Positie Entiteitspositie
Voorwaarts De richting waarin de entiteit is gericht (vector)
Omhoog De up van de entiteit. De richting waarin het hoofd in een persoon bestaat
Snelheid De snelheid waarmee de entiteit beweegt. Wordt gebruikt om Doppler-waarden te berekenen.

Klasse SpriteEntity

Een klasse voor het weergeven van 3D-sprites (billboards). Het is ook een emitter en erft IAudioEmitter . Honden en katten erven deze klasse.

eigenschap

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

Het heeft de locatie-informatie van de entiteit, enz. In principe heb ik informatie als emitter. Het is ook een tekenentiteit, dus het heeft ook een afbeelding (Textuur) om weer te geven.

Update methode

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

Beschrijft de positie van de entiteit en het proces van het afspelen van geluid, maar implementeert het in de afgeleide klasse.

Tekenmethode

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

Honden en katten hebben verschillende afbeeldingen en posities, maar het andere tekenmechanisme is precies hetzelfde, dus ik beschrijf ze hier.

Elke transformatie en textuur wordt doorgegeven aan QuadDrawer om een rechthoekige veelhoek weer te geven. Aangezien coördinatentransformatie basiskennis is, worden verklaringen niet behandeld.

Matrix.CreateConstrainedBillboard Gebruik methode- en camera-informatie om billboards gemakkelijk weer te geven, dus maak er effectief gebruik van.

Hondenklasse

Het is een klas die hondentekenen en zingen afspeelt. SpriteEntity De klasse erven. De hond blijft in een vaste positie in de 3D-ruimte.

veld

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

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

_timeDelay wordt met tussenpozen gebruikt om de kreet te spelen.

SoundEffectInstance _activeSound is een voorbeeld voor het afspelen van een geluid. SoundEffectInstance Zoals je vaak zult zien in de klasse van geluidsweergave, kun je dit gebruiken zoals in 3D-geluid. Overigens _activeSound ontvang ik pas later een referentie van de Klasse AudioManager, dus ik zal deze niet weggooien aan de kant van de klasse Dot.

Update methode

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

In dit monster blijft de hond lange tijd in dezelfde positie, dus de eerste vier parameters worden gespecificeerd door een beslissende slag. Tekenen doe je in de basisklas.

_timeDelay wordt dan gebruikt als de resterende tijd om te stoppen en de kreet te spelen.

AudioManager wordt gereproduceerdPlay3DSound in de 3D-ruimte door de naam van de kreet, lusinformatie en uw eigen informatie als zender door te geven aan .

De Dog-les is ontworpen om het huilen te herhalen, zodat je niet te diep hoeft na te denken omdat het slechts een aanpassing is, zoals spelen of stoppen met vertakken.

Cat klasse

Het is een klas die kattentekenen en zingen afspeelt. SpriteEntity De klasse erven. De kat beweegt zich rond de oorsprong.

veld

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

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

_timeDelay wordt op dezelfde manier gebruikt als de Hondenles, met de rest van de tijd voor het volgende gepiep.

Er zijn drie soorten kattenoproepen die willekeurig worden geselecteerd en afgespeeld, maar ze hebben niets te maken met Audio3D omdat ze een bonuselement zijn.

Update methode

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

Omdat de kat in een cirkelvormige beweging om de oorsprong heen draait, verwerkt hij deze zodat hij de baan van de cirkel beweegt met behulp van een goniometrische functie. Als gevolg hiervan zijn positie, voorwaarts en snelheid achter elkaar veranderd. Daarom kunt u bij het uitvoeren van het programma zien dat het huilen van de kat rondcirkelt, zelfs als u de camera niet beweegt.

_timeDelay De volgende code is een proces waarbij het huilen van de kat willekeurig wordt toegewezen en met regelmatige tussenpozen wordt gespeeld. audioManager.Play3DSound Ik geef mezelf over aan de methode die een emitter is. U kunt zien dat de afspeelpositie van het geluid één voor één verandert.

AudioManager-klasse

Dit is eindelijk de essentie van Audio3D. Een 3D-geluid bestaat uit een luisteraar en een zender. De emitter definieert al honden en katten, dus de Klasse AudioManager definieert luisteraars. Er zijn meestal meerdere emitters, terwijl er maar één luisteraar is.

Deze klasse overerft enGame registreert GameComponent en gebruikt de component in de klasse.

ActiveSound-klasse

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

Het wordt onderaan de code gedefinieerd, maar het is een klasse voor het behoud van de status die wordt afgespeeld. Het bevat informatie over de geluidsinstantie die wordt afgespeeld en de emitter die wordt afgespeeld.

veld

// このマネージャーにロードされるすべてのサウンドエフェクトのリスト。
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 definieert de naam van het audiobestand (itemnaam) dat moet worden geladen. Omdat het een voorbeeldprogramma is, is het gedefinieerd om het audiobestand eerst in bulk te laden. De geïmporteerde geluidsgegevens _soundEffects worden opgeslagen in .

AudioListener Listener is de definitie van de luisteraar. Listenerinformatie wordt gedefinieerd in omdat deze public is ingesteld vanuit de klasse Game.

AudioEmitter _emitter is de definitie van de emitter bij het toepassen van 3D op het afspelen van geluid. In dit voorbeeld wordt bij het afspelen van een geluid de waarde van elk emitterobject ingesteld op _emitter , dus het is een formulier dat er een deelt als een instantie. Natuurlijk kun je voor elk AudioEmitter object hebben.

_activeSounds bevat informatie over het geluid dat u afspeelt in de klasse die u eerder hebt gedefinieerd ActiveSound . Omdat emitterinformatie voortdurend verandert, wordt deze gebruikt om locatiegegevens bij te werken, enzovoort, en om geluidsinstanties te verwijderen die klaar zijn met spelen.

bouwer

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

GameComponent Omdat het de klasse overerft, Game ontvangt het de instantie en geeft het deze door aan de basisklasse.

Initialiseren methode

/// <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 Omdat het de klasse overerft, wordt het automatisch aangeroepen bij initialisatie.

SoundEffect.DistanceScale en SoundEffect.DopplerScale zijn parameters gewijd aan static 3D-geluid.

SoundEffect.DistanceScale om geluid te horen, zelfs in de verte.

SoundEffect.DopplerScale is de invloed van het Doppler-effect. Hoe hoger het getal, hoe groter het Doppler-effect.

_soundNames Sla de itemnaam op die is gedefinieerd in een lus om te laden _soundEffects .

Weggooi methode

/// <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 Het wordt automatisch aangeroepen aan het einde van het spel omdat het de klasse erft.

Het vernietigen van alle geïmporteerde geluidsactiva.

Update methode

/// <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 Omdat het de klasse overerft, wordt het automatisch aangeroepen in het updateproces.

Controleer het geluid dat momenteel wordt afgespeeld en roep, als het wordt afgespeeld, de methode aan om de locatie van het geluid bij te werken zodat deze Apply3D overeenkomt met de zender. Als er klaar is met spelen, wordt de instantie verwijderd.

Play3DSound methode

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

Het proces van het afspelen van 3D-geluid van buitenaf. Het heeft de naam van het geluid dat moet worden afgespeeld, of het moet worden herhaald en informatie moet uitzenden.

Als u een geluid wilt afspelen, maakt u een nieuwe geluidsinstantie op basis van de geluidsbron die u in de _soundEffects bewaart. SoundEffectInstance kan ook een lus hebben of niet, dus stel de lusinformatie in.

Omdat ik maak als ActiveSound een afspeeltoestand, stel ik emitterinformatie in die het afspeelobject is van het geluid daar. Als u 3D-locatiegegevens op een geluid wilt toepassen, krijgt Emitter u de waarde die u nodig hebt.

Apply3D De methode wordt hieronder beschreven, maar het is het proces van het toepassen van 3D-informatie van de emitter op het geluid.

Het basisproces van 3D-geluid is om het afspelen te starten met SoundEffectInstance.Play een 3D-informatieset. De rest is om de 3D-informatie periodiek bij te werken totdat het geluid klaar is met spelen.

Apply3D-methode

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

Het proces waarbij een 3D-effect wordt toegepast op een opgegeven geluidsinstantie met behulp van listeners en emitters.

We stellen de waarde elke keer in op de _emitter van de gemeenschappelijke instantie. Als je SoundEffectInstance.Apply3D er al AudioEmitter een hebt, geef je de luisteraar en zender gewoon door aan de methode.

Audio3DGame Klasse

Laten we tot slot eens kijken waar de Game-klasse over gaat.

veld

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 Registreert GameComponents in , maar heeft het als een veld omdat het individueel toegankelijk is.

Anderen definiëren honden-, kattenentiteiten, texturen voor grondtekening, quaddrawer, camera-informatie en invoerinformatie.

bouwer

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 Genereer en GameComponents registreer met .

Je hebt ook de katten- en hondenklassen gegenereerd.

LoadContent-methode

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

Laad de texturen die nodig zijn voor elke tekening.

QuadDrawer wordt GraphicsDevice hier gegenereerd omdat vereist .

Update methode

/// <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 De methoden en UpdateCamera methoden zijn het proces van het ophalen van apparaatinvoer en het hanteren van de camera, die later zullen worden besproken.

Omdat de camerapositie en de listenerpositie bijna altijd hetzelfde zijn, wordt de listener na het updateproces van de camera op dezelfde waarde ingesteld.

_cat Roep de methoden en _dog Update aan om respectievelijk te bewegen en te piepen.

Tekenmethode

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

Genereert weergave- en projectietransformaties op basis van camera-informatie.

Voor de grond wordt de rechthoek die in QuadDrawer is getekend verticaal weergegeven, zodat deze horizontaal wordt gedraaid en matig wordt vergroot. _quadDrawer.DrawQuad Het tweede argument van de methode geeft het aantal herhalingen van de structuur op, waarmee wordt opgegeven dat 32x32-bladen naast elkaar worden weergegeven.

_cat en _dog worden intern gemarkeerd, zodat de locatiegegevens van de camera worden doorgegeven en getekend.

HandleInput-methode

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

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

Informatie op het toetsenbord en de gamepad wordt verkregen en het einde van het spel wordt bepaald.

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

De camera wordt bestuurd om te bewegen.

Het bevat ook berekeningen zoals versnelling en wrijving, maar ik denk dat het waarschijnlijk rekening houdt met het Doppler-effect op 3D-geluid. Omdat ik niets bijzonders doe aan de berekening zelf, zal ik er niet op ingaan.

Samenvatting

Ik heb het uitgebreid behandeld, maar het is meestal genoeg om naar de klas te verwijzen voor AudioManager het afspelen van 3D-geluid. In feite worden de meeste problemen gedaan door het raamwerk, omdat wat SoundEffectInstance we doen is 3D-informatie instellen in . Als je alleen de delen van het 3D-geluid hebt gesampled, schrijf je uiteindelijk een beetje werk in de gameklasse. Ik schrijf echter Tips op basis van het originele verhaal, dus het is al een stuk langer geleden.