Ήχος3D

Σελίδα ενημέρωση :
Ημερομηνία δημιουργίας σελίδας :

Σημειώσεις σχετικά με αυτές τις συμβουλές

Αυτό το δείγμα βασίζεται στα προγράμματα που δημοσιεύονται στις ακόλουθες τοποθεσίες. Αλλάζω λίγο τον κώδικα για να διευκολύνω την κατανόηση και την εξήγησή του στα ιαπωνικά. Βασικά, χρησιμοποιούμε τον αρχικό κώδικα ως έχει, οπότε αν πραγματικά τον υιοθετήσετε στο πρόγραμμα παιχνιδιού σας, διορθώστε τον εγκαίρως και χρησιμοποιήστε τον.

Τοποθεσία αναφοράς

Επιπλέον, εξηγείται με την υπόθεση ότι έχετε κάποιες βασικές γνώσεις σχετικά με το MonoGame και το XNA. Δείτε συμβουλές monogame και συμβουλές XNA για το ruddly.

Συγκεκριμένα, καθώς τα μαθηματικά, οι φορείς, οι τριγωνομετρικές λειτουργίες, οι μήτρες κ.λπ.

περιβάλλον

πλατφόρμα
  • Παράθυρα 10
  • Ο κώδικας μπορεί να χρησιμοποιηθεί σε άλλες πλατφόρμες με δυνατότητα MonoGame
Οπτικό Στούντιο
  • Οπτικό Στούντιο 2019
.NET πυρήνας
  • 3.1
Μονογαμιό
  • 3.8

Σχετικά με τα δείγματα

Με βάση τη θέση της κάμερας, μπορείτε να ακούσετε την κλήση από τη θέση του σκύλου και τη θέση της γάτας. Η γάτα περιβάλει και περιβάλει την προέλευση και η συσκευή αναπαραγωγής μπορεί να ελέγξει τη θέση της φωτογραφικής μηχανής με το κλειδί. Βεβαιωθείτε ότι ο τρόπος που ακούτε τον ήχο αλλάζει με κάθε αλλαγή στη θέση της φωτογραφικής μηχανής ή στη θέση της γάτας. Νομίζω ότι είναι εύκολο να καταλάβουμε χρησιμοποιώντας ακουστικά. Είμαι ανεπιβεβαίωτος στο κανάλι 5.1.

Πώς να λειτουργήσετε

πληκτρολόγιο
Τι πρέπει να κάνετε gamepad (XInput) άγγιγμα του ποντικιού
Κάμερα προς τα εμπρός και προς τα πίσω ↑↓ Αριστερό ραβδί (επάνω και κάτω) - -
Αλλαγή προσανατολισμού κάμερας ←→ Αριστερό ραβδί (αριστερά και δεξιά) - -
Τέλος παιχνιδιού Εσκτ Πλάτη - -

Τι να προετοιμάσετε

  • Αρχείο ήχου squeal σκυλιών
  • Τρία αρχεία ήχου κατσαρόλυσης
  • Αρχείο εικόνας σκύλου
  • Αρχείο εικόνας γάτας
  • Αρχείο εικόνας εδάφους

Το αρχικό δείγμα στην επίσημη ιστοσελίδα χρησιμοποιεί προκατασκευασμένο περιεχόμενο .xnb αρχεία. Αν θέλετε να διατηρήσετε τα δείγματα στον επίσημο ιστότοπο, μην χρησιμοποιείτε mgcbs, προσθέστε τα απευθείας στη λύση του Visual Studio και αντιγράψτε τα κατά τη διάρκεια της κατασκευής.

Δεν ξέρω γιατί το αρχικό δείγμα παίρνει αυτή τη μέθοδο, αλλά νομίζω ότι είναι πιθανώς επειδή μεταναστεύουμε παλαιότερες εκδόσεις του έργου όπως είναι. Φυσικά, μπορείτε να χρησιμοποιήσετε mgcb για να δημιουργήσετε το ίδιο αρχείο. Τα έργα που μπορείτε να κατεβάσετε σε αυτόν τον ιστότοπο έχουν τροποποιηθεί στην έκδοση MGCB.

πρόγραμμα

Κατεβάστε το πρόγραμμα για όλο τον κώδικα.

Αυτό το δείγμα έχει σχεδιαστεί για να κάνει τον κώδικα να φαίνεται λίγο πιο γενικός, ενώ κάνει την αναπαραγωγή ήχου να φαίνεται καλή κατά το χρόνο εκτέλεσης. Η χρήση του Audio3D μόνο θα ήταν πολύ λιγότερος κώδικας, αλλά περιγράφεται κατά μήκος του αρχικού δείγματος. Θα κρατήσω τα λιγότερο σημαντικά μέρη.

Το έργο αποτελείται από τα ακόλουθα αρχεία κώδικα:

  • Ακουστικό3D Παιχνίδι
  • Συσκευή ήχου
  • Γάτα
  • Σκύλος
  • Ιουντιοεμίτερ
  • Πρόγραμμα
  • Τετράτροχο
  • Σπαρτάδης

Κατηγορία Τετράδας

Αυτή η τάξη είναι μια τάξη βοηθών για τη σχεδίαση ορθογώνιων πολυγώνων. Τα ορθογώνια πολύγωνα χρησιμοποιούνται συχνά κυρίως για την εμφάνιση 3D sprites (διαφημιστικές πινακίδες). Αυτές οι συμβουλές χρησιμοποιούνται για διαφημιστικές πινακίδες για γάτες και σκύλους, καθώς και για ορθογώνιες οθόνες του εδάφους.

Αυτή η τάξη δεν έχει καμία σχέση με το Audio3D.

αγρός

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

Ελάχιστες πληροφορίες που απαιτούνται για την σχεδίαση πολυγώνων. Σχεδιάστε πολύγωνα από τα δεδομένα της κορυφής χωρίς να προετοιμάσετε δεδομένα μοντέλου.

κατασκευαστής

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

  _effect = new AlphaTestEffect(device);

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

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

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

Επειδή αυτή η κλάση είναι καθολικά χρησιμοποιήσιμη, GraphicsDevice λαμβάνετε μια παρουσία που δημιουργήθηκε στη διαδικασία προετοιμασίας κλάσης παιχνιδιού.

Εδώ, θέτουν το αποτέλεσμα που είναι απαραίτητο για να σχεδιάσουμε το ξωτικό και τη θέση των 4 κορυφών που απαιτούνται για το ορθογώνιο πολύγωνο. Το μέγεθος πρέπει να κλιμακώνεται κατά το σχέδιο, οπότε είναι -1 έως 1.

Μέθοδος DrawQuad

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

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

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

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

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

Ορίζει τη μεταβιβαζμένη υφή σε ένα ορθογώνιο και το σχεδιάζει. Δεδομένου ότι πρόκειται για μια βασική διαδικασία, δεν υπάρχει τίποτα να σημειωθεί.

Εάν υπάρχει ένα σημείο, μια μεταβλητή που ονομάζεται μπορεί να καθοριστεί στο textureRepeats όρισμα, έτσι ώστε οι συντεταγμένες της υφής να μπορούν να αλλάξουν. Εάν το vertexPositionTexture.TextureCoordinate έχει οριστεί πέρα από την περιοχή 0 έως 1, η υφή σχεδιάζεται επανειλημμένα από προεπιλογή. Χρησιμοποιώντας το, είναι δυνατό να εκφράσετε ότι τα πλακίδια μπορούν να τακτοποιηθούν επανειλημμένα. Στην πραγματικότητα, τα καρό μοτίβα στο έδαφος φαίνεται να έχουν πολλαπλές απλές ασπρόμαυρες εικόνες.

Διασύνδεση IAudioEmitter

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

Ορίζεται ως οντότητα που εκπέμπει ήχο. Δεδομένου ότι οι οντότητες που εκπέμπουν ήχο αυτή τη φορά είναι οι σκύλοι και οι γάτες, κληρονομούνται στις αντίστοιχες τάξεις τους. Ο εκπομπός χρειάζεται τις ακόλουθες πληροφορίες:

Χρήση ακινήτου
Θέση Θέση οντότητας
Διαβιβάζω Η κατεύθυνση που αντιμετωπίζει η οντότητα (διάνυσμα)
Πάνω Η άνοδος της οντότητας. Η κατεύθυνση προς την οποία το κεφάλι υπάρχει σε ένα άτομο
Ταχύτητα Η ταχύτητα με την οποία κινείται η οντότητα. Χρησιμοποιείται για τον υπολογισμό των τιμών Doppler.

Κλάση "SpriteEntity"

Μια κλάση για την αναπαράσταση 3D sprites (διαφημιστικές πινακίδες). Είναι επίσης ένας εκπομπός και κληρονομεί IAudioEmitter . Τα σκυλιά και οι γάτες κληρονομούν αυτή την τάξη.

ιδιοκτησία

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

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

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

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

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

Έχει τις πληροφορίες θέσης της οντότητας, κ.λπ. Βασικά έχω πληροφορίες ως πομπός. Είναι επίσης μια οντότητα σχεδίασης, οπότε έχει επίσης μια εικόνα (Υφή) για εμφάνιση.

Μέθοδος ενημέρωσης

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

Περιγράφει τη θέση της οντότητας και τη διαδικασία αναπαραγωγής ήχου, αλλά την υλοποιεί στην παραγόμενη κλάση.

Μέθοδος ισοπαλίας

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

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

Τα σκυλιά και οι γάτες έχουν διαφορετικές εικόνες και θέσεις, αλλά ο άλλος μηχανισμός σχεδίασης είναι ακριβώς ο ίδιος, οπότε τους περιγράφω εδώ.

Κάθε μετασχηματισμός και υφή μεταβιβάζεται στο QuadDrawer για να εμφανίσει ένα ορθογώνιο πολύγωνο. Δεδομένου ότι ο μετασχηματισμός συντεταγμένων είναι βασική γνώση, οι εξηγήσεις δεν καλύπτονται.

Matrix.CreateConstrainedBillboard Χρησιμοποιήστε πληροφορίες μεθόδου και κάμερας για να αναπαραστήσετε εύκολα τις διαφημιστικές πινακίδες, οπότε χρησιμοποιήστε τις αποτελεσματικά.

Κατηγορία σκυλιών

Είναι μια τάξη που κάνει το σκυλί να σχεδιάζει και να τραγουδάει αναπαραγωγή. SpriteEntity Κληρονομώ την τάξη. Ο σκύλος παραμένει σε σταθερή θέση σε τρισδιάστατο χώρο.

αγρός

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

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

_timeDelay χρησιμοποιείται κατά διαστήματα για να παίξει την κραυγή.

SoundEffectInstance _activeSound είναι μια περίπτωση αναπαραγωγής ενός ήχου. SoundEffectInstance Όπως θα βλέπετε συχνά στην κατηγορία της αναπαραγωγής ήχου, μπορείτε να το χρησιμοποιήσετε όπως είναι στον ήχο 3D. Παρεμπιπτόντως _activeSound , λαμβάνω μόνο μια αναφορά από την κλάση AudioManager αργότερα, οπότε δεν θα την απορρίψω από την πλευρά της κλάσης Dot.

Μέθοδος ενημέρωσης

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

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

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

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

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

Σε αυτό το δείγμα, ο σκύλος παραμένει στην ίδια θέση για μεγάλο χρονικό διάστημα, οπότε οι πρώτες τέσσερις παράμετροι καθορίζονται από ένα αποφασιστικό χτύπημα. Η σχεδίαση γίνεται στη βασική τάξη.

_timeDelay χρησιμοποιείται στη συνέχεια ως ο εναπομείνας χρόνος για να σταματήσει, παίζοντας την κραυγή.

AudioManager θα αναπαραχθείPlay3DSound σε τρισδιάστατο χώρο περνώντας το όνομα της κραυγής, των πληροφοριών βρόχου και των δικών σας πληροφοριών ως εκπομπών στο .

Η τάξη dog έχει σχεδιαστεί για να επαναλαμβάνει την κραυγή, οπότε δεν χρειάζεται να σκέφτεστε πολύ βαθιά επειδή είναι απλά μια προσαρμογή, όπως το παιχνίδι ή η διακοπή της διακλάδωσης.

Κατηγορία γάτας

Είναι μια τάξη που κάνει το σχέδιο γάτας και την αναπαραγωγή τραγουδιού. SpriteEntity Κληρονομώ την τάξη. Η γάτα κινείται γύρω από την προέλευση.

αγρός

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

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

_timeDelay χρησιμοποιείται με τον ίδιο τρόπο όπως η τάξη dog, με τον υπόλοιπο χρόνο πριν από την επόμενη καταδίωξή.

Υπάρχουν τρεις τύποι κλήσεων γάτας που επιλέγονται και αναπαράγονται τυχαία, αλλά δεν έχουν καμία σχέση με το Audio3D επειδή είναι ένα στοιχείο μπόνους.

Μέθοδος ενημέρωσης

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

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

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

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

  Up = Vector3.Up;

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

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

    audioManager.Play3DSound(soundName, false, this);

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

Δεδομένου ότι η γάτα γυρίζει γύρω από την προέλευση με κυκλική κίνηση, την επεξεργάζεται έτσι ώστε να μετακινεί την τροχιά του κύκλου χρησιμοποιώντας μια τριγωνομετρική λειτουργία. Ως αποτέλεσμα, η θέση, προς τα εμπρός και η ταχύτητα έχουν αλλάξει το ένα μετά το άλλο. Ως εκ τούτου, όταν εκτελείτε το πρόγραμμα, μπορείτε να δείτε ότι η κραυγή της γάτας κάνει κύκλους ακόμα και αν δεν μετακινήσετε την κάμερα.

_timeDelay Ο ακόλουθος κώδικας είναι μια διαδικασία στην οποία η κραυγή της γάτας εκχωρείται τυχαία και παίζεται σε τακτά χρονικά διαστήματα. audioManager.Play3DSound Περνάω τον εαυτό μου στη μέθοδο που είναι ο εκπομπός. Μπορείτε να δείτε ότι η θέση αναπαραγωγής του ήχου αλλάζει μία προς μία.

Κλάση AudioManager

Αυτή είναι τελικά η ουσία του Audio3D. Ένας τρισδιάστατος ήχος αποτελείται από έναν ακροατή και έναν πομπό. Ο εκπομπός ορίζει ήδη σκύλους και γάτες, οπότε η τάξη AudioManager ορίζει τους ακροατές. Υπάρχουν συνήθως πολλαπλοί εκπομποί, ενώ υπάρχει μόνο ένας ακροατής.

Αυτή η κλάση κληρονομεί καιGame καταχωρεί GameComponent και χρησιμοποιεί το στοιχείο στην κλάση.

Ενεργή κλάση Άουτ

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

Ορίζεται στο κάτω μέρος του κώδικα, αλλά είναι μια κλάση για τη διατήρηση της κατάστασης που παίζει. Έχει πληροφορίες σχετικά με την ηχητική παρουσία που αναπαράγεται και τον πομπό που αναπαράγεται.

αγρός

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

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

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

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

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

_soundNames Καθορίζει το όνομα του αρχείου ήχου (όνομα περιουσιακού στοιχείου) που θα φορτωθεί. Δεδομένου ότι είναι ένα δείγμα προγράμματος, ορίζεται η φόρτωση του αρχείου ήχου χύμα πρώτα. Τα εισαγόμενα δεδομένα ήχου αποθηκεύονται _soundEffects στο .

AudioListener Listener είναι ο ορισμός του ακροατή. Οι πληροφορίες ακρόασης ορίζονται επειδή έχουν public οριστεί από την κλάση Game.

AudioEmitter _emitter είναι ο ορισμός του εκπομπού κατά την εφαρμογή του 3D στην αναπαραγωγή ήχου. Σε αυτό το δείγμα, κατά την αναπαραγωγή ενός ήχου, η τιμή κάθε αντικειμένου εκπομπών έχει οριστεί σε _emitter , επομένως είναι μια φόρμα που μοιράζεται έναν ως παρουσία. Φυσικά, μπορείτε να έχετε για κάθε AudioEmitter αντικείμενο.

_activeSounds Έχει πληροφορίες σχετικά με τον ήχο που αναπαυόσουν στην τάξη που όρισες ActiveSound νωρίτερα. Επειδή οι πληροφορίες εκπομπών αλλάζουν συνέχεια, χρησιμοποιούνται για την ενημέρωση πληροφοριών τοποθεσίας κ.λπ., και για την απόρριψη παρουσιών ήχου που έχουν ολοκληρωθεί την αναπαραγωγή.

κατασκευαστής

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

GameComponent Επειδή κληρονομεί την κλάση, Game λαμβάνει την παρουσία και τη μεταβιβάζει στη βασική κλάση.

Μέθοδος προετοιμασίας

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

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

  base.Initialize();
}

GameComponent Επειδή κληρονομεί την κλάση, καλείται αυτόματα κατά την προετοιμασία.

SoundEffect.DistanceScale και SoundEffect.DopplerScale είναι παράμετροι αφιερωμένες στον static τρισδιάστατο ήχο.

SoundEffect.DistanceScale να ακούω ήχο ακόμα και στο βάθος.

SoundEffect.DopplerScale είναι η επίδραση του φαινομένου Ντόπλερ. Όσο μεγαλύτερος είναι ο αριθμός, τόσο μεγαλύτερο είναι το φαινόμενο Ντόπλερ.

_soundNames Αποθηκεύστε το όνομα του περιουσιακού στοιχείου που έχει οριστεί σε βρόχο για φόρτωση _soundEffects .

Μέθοδος απόρριψης

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

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

GameComponent Καλείται αυτόματα στο τέλος του παιχνιδιού επειδή κληρονομεί την κλάση.

Καταστρέφοντας όλα τα εισαγόμενα υγιή περιουσιακά στοιχεία.

Μέθοδος ενημέρωσης

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

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

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

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

      index++;
    }
  }

  base.Update(gameTime);
}

GameComponent Επειδή κληρονομεί την κλάση, καλείται αυτόματα στη διαδικασία ενημέρωσης.

Ελέγξτε τον ήχο που αναπαράγεται αυτήν τη στιγμή και, εάν Apply3D αναπαράγεται, καλέστε τη μέθοδο για να ενημερώσετε τη θέση του ήχου για να ταιριάζει με τον πομπό. Εάν κάποιος ήχος έχει ολοκληρωθεί η αναπαραγωγή, η παρουσία απορρίπτεται.

Μέθοδος Play3DSound

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

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

  activeSound.Emitter = emitter;

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

  activeSound.Instance.Play();

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

  return activeSound.Instance;
}

Η διαδικασία αναπαραγωγής ήχου 3D από έξω. Έχει το όνομα του ήχου για αναπαραγωγή, αν θα βρόχο, και πληροφορίες εκπομπής.

Εάν θέλετε να αναπαραγάγετε έναν ήχο, δημιουργήστε μια νέα παρουσία ήχου από τον πόρο ήχου που διατηρείτε στο _soundEffects. SoundEffectInstance μπορεί επίσης να έχει βρόχο ή όχι, οπότε ορίστε τις πληροφορίες βρόχου.

Δεδομένου ότι δημιουργώ ως ActiveSound κατάσταση αναπαραγωγής, ορίζω πληροφορίες εκπομπών που είναι το αντικείμενο αναπαραγωγής του ήχου εκεί. Αν θέλετε να εφαρμόσετε πληροφορίες τοποθεσίας 3D σε έναν ήχο, θα Emitter λάβετε την τιμή που χρειάζεστε.

Apply3D Η μέθοδος περιγράφεται παρακάτω, αλλά είναι η διαδικασία εφαρμογής πληροφοριών 3D από τον εκπομπό στον ήχο.

Η βασική διαδικασία του ήχου 3D είναι να ξεκινήσετε την αναπαραγωγή με SoundEffectInstance.Play σύνολο πληροφοριών 3D. Το υπόλοιπο είναι να ενημερώνετε περιοδικά τις πληροφορίες 3D μέχρι να ολοκληρωθεί η αναπαραγωγή του ήχου.

Εφαρμογή μεθόδου3D

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

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

Η διαδικασία εφαρμογής ενός εφέ 3D σε μια καθορισμένη παρουσία ήχου χρησιμοποιώντας ακροατές και πομπούς.

Ορίσετε την τιμή στο _emitter της κοινής παρουσίας κάθε φορά. Εάν έχετε SoundEffectInstance.Apply3D ήδη AudioEmitter ένα, απλά περάστε τον ακροατή και τον πομπό στη μέθοδο.

Κλάση ήχου3DGame

Τέλος, ας δούμε τι είναι το μάθημα του παιχνιδιού.

αγρός

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

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

QuadDrawer _quadDrawer;

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

KeyboardState _currentKeyboardState;
GamePadState _currentGamePadState;

AudioManagerGameComponents Εγγράφεται στο , αλλά το έχει ως πεδίο επειδή έχει πρόσβαση σε αυτό ξεχωριστά.

Άλλοι ορίζουν σκύλους, οντότητες γάτας, υφές για σχέδιο εδάφους, τετράτροχο, πληροφορίες κάμερας και πληροφορίες εισόδου.

κατασκευαστής

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

  _graphics = new GraphicsDeviceManager(this);

  _audioManager = new AudioManager(this);

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

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

AudioManager Δημιουργήστε και GameComponents εγγραφείτε στο .

Έχετε επίσης δημιουργήσει τα μαθήματα γάτας και σκύλου.

Μέθοδος 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);
}

Τοποθετήστε τις υφές που απαιτούνται για κάθε σχέδιο.

QuadDrawer δημιουργείται GraphicsDevice εδώ, επειδή απαιτεί .

Μέθοδος ενημέρωσης

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

  UpdateCamera();

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

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

  base.Update(gameTime);
}

HandleInput Οι μέθοδοι και UpdateCamera οι μέθοδοι είναι η διαδικασία ανάκτησης της εισόδου της συσκευής και του χειρισμού της φωτογραφικής μηχανής, η οποία θα συζητηθεί αργότερα.

Δεδομένου ότι η θέση της φωτογραφικής μηχανής και η θέση του ακροατή είναι σχεδόν πάντα τα ίδια, ο ακροατής έχει ρυθμιστεί στην ίδια τιμή μετά τη διαδικασία ενημέρωσης της φωτογραφικής μηχανής.

_cat Καλέστε τις μεθόδους ενημέρωσης και _dog ενημέρωσης για να μετακινήσετε και να τσιρίξει, αντίστοιχα.

Μέθοδος ισοπαλίας

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

  device.Clear(Color.CornflowerBlue);

  device.BlendState = BlendState.AlphaBlend;

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

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

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

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

  base.Draw(gameTime);
}

Δημιουργεί μετασχηματισμούς προβολής και προβολής από πληροφορίες κάμερας.

Για το έδαφος, το ορθογώνιο που σχεδιάζεται στο QuadDrawer εμφανίζεται κατακόρυφα, έτσι περιστρέφεται για να είναι οριζόντιο και μεγεθυμένο μέτρια. _quadDrawer.DrawQuad Το δεύτερο όρισμα της μεθόδου καθορίζει τον αριθμό των επαναλήψεων της υφής, ο οποίος καθορίζει ότι τα φύλλα 32x32 εμφανίζονται δίπλα-δίπλα.

_cat και _dog ανηφορίζονται εσωτερικά, οπότε οι πληροφορίες τοποθεσίας της φωτογραφικής μηχανής μεταβιβάζονται και σχεδιάζονται.

Μέθοδος HandleInput

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

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

Οι πληροφορίες στο πληκτρολόγιο και το gamepad αποκτώνται και καθορίζεται το τέλος του παιχνιδιού.

Μέθοδος ΕνημέρωσηςCamera

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

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

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

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

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

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

  _cameraVelocity += _cameraForward * accel;

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

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

Η κάμερα ελέγχεται για να κινείται.

Περιλαμβάνει επίσης υπολογισμούς όπως επιτάχυνση και τριβή, αλλά νομίζω ότι πιθανώς λαμβάνει υπόψη την επίδραση Doppler στον ήχο 3D. Δεδομένου ότι δεν κάνω τίποτα ιδιαίτερο για τον ίδιο τον υπολογισμό, δεν θα το συζητήσω.

Περίληψη

Το έχω καλύψει εκτενώς, αλλά συνήθως είναι αρκετό για να αναφερθεί στην τάξη για AudioManager το πώς να παίξετε ήχο 3D. Στην πραγματικότητα, οι περισσότερες δυσκολίες γίνονται από το πλαίσιο, επειδή αυτό που SoundEffectInstance κάνουμε είναι να ορίσετε πληροφορίες 3D σε . Αν έχετε δοκιμάσει μόνο τα μέρη του ήχου 3D, θα καταλήχετε να γράφετε λίγη δουλειά στην τάξη παιχνιδιών. Ωστόσο, γράφω συμβουλές με βάση την αρχική ιστορία, οπότε έχει περάσει πολύ περισσότερος χρόνος.