آڈیو 3 ڈی

جب صفحے کی تازہ کاری :
صفحہ تخلیق تاریخ :

اس تجاویز پر نوٹ

یہ نمونہ مندرجہ ذیل سائٹس پر شائع ہونے والے پروگراموں پر مبنی ہے۔ میں کوڈ کو تھوڑا سا تبدیل کرتا ہوں تاکہ جاپانی زبان میں اسے سمجھنا اور سمجھانا آسان ہو۔ بنیادی طور پر، ہم اصل کوڈ کا استعمال کرتے ہیں جیسا کہ ہے، لہذا اگر آپ واقعی اسے اپنے گیم پروگرام میں اپناتے ہیں تو اسے بروقت درست کریں اور اسے استعمال کریں۔

حوالہ سائٹ

اس کے علاوہ، یہ مفروضے پر وضاحت کی گئی ہے کہ آپ کو مونو گیم اور ایکس این اے کے بارے میں کچھ بنیادی علم ہے۔ رڈلی کے لئے مونو گیم ٹپس اور ایکس این اے ٹپس دیکھیں۔

خاص طور پر، چونکہ ریاضی، سمتیہ، مثلثی افعال، میٹرکس وغیرہ ضروری ہیں، لہذا براہ کرم جانیں کہ وہ کسی حد تک کیا ہیں۔

ماحول

پلیٹ فارم
  • ونڈوز 10
  • کوڈ کو دیگر مونو گیم فعال پلیٹ فارمز پر استعمال کیا جا سکتا ہے
بصری سٹوڈیو
  • ویژیول سٹوڈیو 2019
.نیٹ کور
  • 3.1
مونو گیم
  • 3.8

نمونوں کے بارے میں

کیمرے کی پوزیشن کی بنیاد پر، آپ کتے کی پوزیشن اور بلی کی پوزیشن سے کال سن سکتے ہیں. بلی دائرے اور اصل چکر, اور کھلاڑی کلید کے ساتھ کیمرے کی پوزیشن کو کنٹرول کر سکتے ہیں. اس بات کو یقینی بنائیں کہ جس طرح آپ آواز سنتے ہیں وہ کیمرے کی پوزیشن یا بلی کی پوزیشن میں ہر تبدیلی کے ساتھ تبدیل ہوتا ہے۔ میرے خیال میں ایر فون کا استعمال کرنا سمجھنا آسان ہے۔ میں چینل 5.1 پر غیر مصدقہ ہوں.

کام کرنے کا طریقہ

کی ہے
بورڈ گیم پیڈ (ایکس ان پٹ) ماؤس ٹچ کرنے کے لئے کیا
کیمرہ آگے اور پیچھے ↑↓ بائیں چھڑی (اوپر اور نیچے) - -
کیمرے کا رخ تبدیل کریں ←→ بائیں چھڑی (بائیں اور دائیں) - -
کھیل کا اختتام ایس سی واپس - -

کیا تیار کرنا ہے

  • کتا چیخ آڈیو فائل
  • تین بلی چیخ آڈیو فائلیں
  • کتا تصویر فائل
  • بلی تصویر مسل
  • زمینی تصویر مسل

آفیشل سائٹ پر اصل نمونہ پہلے سے تعمیر شدہ مواد .ایکس این بی فائلوں کا استعمال کرتا ہے۔ اگر آپ نمونے آفیشل سائٹ پر رکھنا چاہتے ہیں تو ایم جی سی بی ایس کا استعمال نہ کریں، انہیں براہ راست اپنے ویژیول اسٹوڈیو حل میں شامل کریں، اور انہیں تعمیر کے وقت نقل کریں۔

میں نہیں جانتا کہ اصل نمونہ یہ طریقہ کیوں لے رہا ہے، لیکن میں سمجھتا ہوں کہ اس کی وجہ شاید یہ ہے کہ ہم اس منصوبے کے پرانے ورژن کو نقل مکانی کر رہے ہیں جیسا کہ ہے۔ یقینا، آپ اسی فائل کو پیدا کرنے کے لئے ایم جی سی بی کا استعمال کرسکتے ہیں۔ اس سائٹ پر ڈاؤن لوڈ کیے جانے والے منصوبوں کو ایم جی سی بی ورژن میں تبدیل کردیا گیا ہے۔

پروگرام

تمام کوڈ کے لیے پروگرام ڈاؤن لوڈ کریں۔

یہ نمونہ کوڈ کو تھوڑا زیادہ عمومی دکھانے کے لئے ڈیزائن کیا گیا ہے جبکہ رن ٹائم پر ساؤنڈ پلے بیک کو اچھا دکھاتا ہے۔ آڈیو 3ڈی کا استعمال صرف بہت کم کوڈ ہوگا، لیکن اسے اصل نمونے کے ساتھ بیان کیا گیا ہے۔ میں کم اہم حصے رکھوں گا.

یہ منصوبہ درج ذیل کوڈ فائلوں پر مشتمل ہے:

  • آڈیو3ڈی گیم
  • آڈیو منیجر
  • بلی
  • کتا
  • آئی آڈیو ایمیٹر
  • پروگرام
  • کواڈ دراز
  • سپرائیٹ ادارہ

کواڈ دراز کلاس

یہ طبقہ مستطیل کثیر الاضلاع بنانے کے لیے مددگار طبقہ ہے۔ مستطیل کثیر الاضلاع اکثر بنیادی طور پر تھری ڈی اسپرائیٹس (بل بورڈز) دکھانے کے لیے استعمال کیے جاتے ہیں۔ یہ تجاویز بلیوں اور کتوں کے لئے بل بورڈز کے ساتھ ساتھ زمین کے مستطیل ڈسپلے کے لئے بھی استعمال کی جاتی ہیں۔

اس کلاس کا آڈیو 3ڈی سے کوئی تعلق نہیں ہے۔

کھیت

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 ہے۔

قرعہ اندازی طریقہ

/// <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 ایک متغیر کو اختصاص کیا جا سکتا ہے، تاکہ ساخت کے متناسقات کو تبدیل کیا جا سکے۔ اگر ورٹیکس پوزیشن ٹیکسچر.ٹیکسچر کوآرڈینیٹ حد 0 سے 1 سے آگے سیٹ ہے، تو بناوٹ کو ڈیفالٹ کے ذریعہ بار بار کھینچا جاتا ہے۔ اس کا استعمال کرتے ہوئے یہ اظہار ممکن ہے کہ ٹائلز کو بار بار ترتیب دیا جا سکتا ہے۔ درحقیقت، زمین پر چیکڈ پیٹرن میں متعدد سادہ سیاہ اور سفید تصاویر قطار میں کھڑی نظر آتی ہیں۔

آئی آڈیو ایمیٹر انٹرفیس

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

ایک ایسی ہستی کے طور پر تعریف کی جاتی ہے جو آواز خارج کرتی ہے۔ چونکہ اس بار آواز خارج کرنے والے ادارے کتے اور بلیاں ہیں، اس لئے وہ اپنی اپنی کلاسوں میں وراثت میں ملی ہیں۔ ایمیٹر کو مندرجہ ذیل معلومات کی ضرورت ہے:

کا
پراپرٹیاستعمال
پوزیشن وجودی مقام
آگے جس سمت وجود کا سامنا ہے (سمتیہ)
اوپر ہستی کی اپ. وہ سمت جس میں سر ایک شخص میں موجود ہے
سمتار جس رفتار سے وجود حرکت کرتا ہے۔ ڈوپلر اقدار کا حساب لگانے کے لیے استعمال کیا جاتا ہے۔

سپرائیٹ ادارہ کلاس

تھری ڈی اسپرائیٹس (بل بورڈز) کی نمائندگی کرنے کے لئے ایک کلاس۔ یہ بھی ایک ایمیٹر ہے، اور وراثت میں ہے 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);
}

کتوں اور بلیوں کی مختلف تصاویر اور پوزیشنیں ہیں، لیکن دوسرا ڈرائنگ میکانزم بالکل ایک ہی ہے، لہذا میں انہیں یہاں بیان کرتا ہوں۔

ہر تبدیلی اور ساخت کواڈڈراور کو ایک مستطیل کثیر الاضلاع دکھانے کے لئے منتقل کیا جاتا ہے۔ چونکہ مربوط تبدیلی بنیادی علم ہے، اس لیے وضاحتوں کا احاطہ نہیں کیا جاتا۔

Matrix.CreateConstrainedBillboard بل بورڈز کی آسانی سے نمائندگی کرنے کے لئے طریقہ کار اور کیمرے کی معلومات کا استعمال کریں، لہذا ان کا موثر استعمال کریں۔

کتے کی کلاس

یہ ایک کلاس ہے جو کتے کی ڈرائنگ اور پلے بیک گاتی ہے۔ SpriteEntity کلاس کے وارث. کتا ٣ ڈی جگہ میں ایک مقررہ پوزیشن میں رہتا ہے۔

کھیت

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

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

_timeDelay رونے کے لئے وقفے وقفے سے استعمال کیا جاتا ہے۔

SoundEffectInstance _activeSound آواز بجانے کی ایک مثال ہے۔ SoundEffectInstance جیسا کہ آپ اکثر آواز پلے بیک کی کلاس میں دیکھیں گے، آپ اسے استعمال کر سکتے ہیں جیسا کہ تھری ڈی آواز میں ہے۔ ویسے _activeSound ، مجھے بعد میں صرف آڈیو منیجر کلاس سے ایک حوالہ موصول ہوتا ہے، لہذا میں اسے ڈاٹ کلاس کی طرف سے مسترد نہیں کروں گا۔

طریقہ تازہ کاری کریں

/// <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 جائے گا۔

کتے کی کلاس رونے کو لوپ کرنے کے لئے ڈیزائن کی گئی ہے، لہذا آپ کو زیادہ گہرائی سے سوچنے کی ضرورت نہیں ہے کیونکہ یہ صرف ایک ایڈجسٹمنٹ ہے، جیسے کھیلنا یا شاخبندی روکنا۔

بلی کلاس

یہ ایک کلاس ہے جو بلی ڈرائنگ اور گانا پلے بیک کرتی ہے۔ SpriteEntity کلاس کے وارث. بلی اصل کے ارد گرد گھوم رہی ہے۔

کھیت

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

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

_timeDelay کتے کی کلاس کی طرح ہی استعمال کیا جاتا ہے، اگلی چیخ سے پہلے باقی وقت کے ساتھ.

بلی کی کالز کی تین اقسام ہیں جو بے ترتیب طور پر منتخب اور چلائی جاتی ہیں، لیکن ان کا آڈیو 3ڈی سے کوئی تعلق نہیں ہے کیونکہ وہ ایک بونس عنصر ہیں۔

طریقہ تازہ کاری کریں

/// <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 میں اپنے آپ کو اس طریقہ کار کی طرف منتقل کر رہا ہوں جو ایک ایمیٹر ہے۔ آپ دیکھ سکتے ہیں کہ آواز کی پلے بیک پوزیشن ایک ایک کر کے تبدیل ہو جاتی ہے۔

آڈیو منیجر کلاس

آخر کار یہ آڈیو 3ڈی کا نچوڑ ہے۔ تھری ڈی آواز سننے والے اور ایمیٹر پر مشتمل ہوتی ہے۔ ایمیٹر پہلے ہی کتوں اور بلیوں کی وضاحت کرتا ہے، لہذا آڈیو منیجر کلاس سننے والوں کی وضاحت کرتی ہے۔ عام طور پر متعدد ایمیٹرز ہوتے ہیں، جبکہ صرف ایک سننے والا ہوتا ہے۔

یہ طبقہ وراثت میں ملتا ہے اور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 گیم کلاس سے سیٹ کی جاتی ہے۔

AudioEmitter _emitter پلے بیک آواز پر تھری ڈی لگاتے وقت ایمیٹر کی تعریف ہے۔ اس نمونے میں آواز بجاتے وقت ہر ایمیٹر آبجیکٹ کی قدر مقرر _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 3ڈی آواز کے لیے 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 چل رہا ہے تو ایمیٹر سے میل کھانے کے لیے آواز کے مقام کو اپ ڈیٹ کرنے کے طریقہ کار کو کال کریں۔ اگر کوئی آواز کھیلنا ختم کر چکی ہے تو مثال کو مسترد کر دیا جاتا ہے۔

پلے تھری ڈی ساؤنڈ طریقہ

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

باہر سے تھری ڈی آواز بجانے کا عمل۔ اس میں کھیلنے کے لئے آواز کا نام ہے، چاہے لوپ کرنا ہے، اور ایمیٹر معلومات۔

اگر آپ آواز بجانا چاہتے ہیں تو آواز کے وسائل سے ایک نئی آواز کی مثال بنائیں جو آپ _soundEffects میں رکھتے ہیں۔ SoundEffectInstance لوپ بھی ہو سکتا ہے یا نہیں، لہذا لوپ معلومات سیٹ کریں۔

چونکہ میں ایک کھیلنے کی ریاست کے طور پر ActiveSound تخلیق کر رہا ہوں، میں نے ایمیٹر معلومات سیٹ کی ہے کہ وہاں آواز کی پلے بیک چیز ہے. اگر آپ کسی آواز پر تھری ڈی لوکیشن معلومات لگانا چاہتے ہیں تو آپ کو وہ قدر ملے گی Emitter جس کی آپ کو ضرورت ہے۔

Apply3D طریقہ ذیل میں بیان کیا گیا ہے، لیکن یہ ایمیٹر سے آواز پر تھری ڈی معلومات کا اطلاق کرنے کا عمل ہے۔

تھری ڈی آواز کا بنیادی عمل تھری ڈی معلومات سیٹ کے ساتھ SoundEffectInstance.Play پلے بیک شروع کرنا ہے۔ باقی وقتا فوقتا تھری ڈی معلومات کو اپ ڈیٹ کرنا ہے جب تک آواز چل نا ختم نہ ہو جائے۔

3ڈی طریقہ لگائیں

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

سننے والوں اور ایمیٹرز کا استعمال کرتے ہوئے ایک مخصوص آواز مثال پر تھری ڈی اثر کا اطلاق کرنے کا عمل۔

ہم ہر بار عام مثال کے _emitter کی قدر مقرر کرتے ہیں۔ اگر آپ SoundEffectInstance.Apply3D کے پاس پہلے سے ہی AudioEmitter ایک ہے، تو صرف سننے والے اور ایمیٹر کو طریقہ کار سے گزرائیں۔

آڈیو3ڈی گیم کلاس

آخر میں، چلو گیم کلاس کے بارے میں کیا ہے پر نظر ڈالتے ہیں.

کھیت

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 میں رجسٹر کرتا GameComponents ہے، لیکن اسے ایک میدان کے طور پر ہے کیونکہ یہ انفرادی طور پر اس تک رسائی حاصل کرتا ہے۔

دوسرے کتے، بلی کے اداروں، گراؤنڈ ڈرائنگ کے لئے بناوٹ، کواڈراور، کیمرے کی معلومات، اور ان پٹ معلومات کی وضاحت کرتے ہیں۔

تعمیرکار

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 رجسٹر کریں جس کے ساتھ .

آپ نے بلی اور کتے کی کلاسیں بھی تیار کی ہیں۔

مشمول اتلاف کا طریقہ

/// <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.DrawQuad طریقہ کار کی دوسری دلیل میں ساخت کے تکرار کی تعداد کی وضاحت کی گئی ہے، جس میں واضح کیا گیا ہے کہ 32ایکس 32 ورق ساتھ ساتھ ظاہر ہوتے ہیں۔

_cat اور _dog اندرونی طور پر بل بورڈ کیے جاتے ہیں، لہذا کیمرے کے مقام کی معلومات پاس کی جاتی ہیں اور کھینچی جاتی ہیں۔

ہینڈل ان پٹ طریقہ

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

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

کی بورڈ اور گیم پیڈ پر معلومات حاصل کی جاتی ہیں، اور کھیل کے اختتام کا تعین کیا جاتا ہے۔

تازہ ترین کیمرہ طریقہ

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

کیمرے کو حرکت دینے کے لیے کنٹرول کیا جاتا ہے۔

اس میں تیزی اور رگڑ جیسے حساب بھی شامل ہیں، لیکن میں سمجھتا ہوں کہ یہ شاید تھری ڈی آواز پر ڈوپلر اثر کو مدنظر رکھے ہوئے ہے۔ چونکہ میں حساب کتاب کے بارے میں کوئی خاص کام نہیں کرتا، میں اس پر بات نہیں کروں گا۔

خلاصہ

میں نے اسے لمبائی میں ڈھانپ لیا ہے، لیکن یہ عام طور پر کلاس کا حوالہ دینے کے لئے AudioManager کافی ہے کہ تھری ڈی آواز کیسے بجائی جائے۔ درحقیقت، زیادہ تر مشکلات فریم ورک کے ذریعہ کی جاتی ہیں، کیونکہ ہم جو کچھ SoundEffectInstance کر رہے ہیں وہ تھری ڈی معلومات کو ترتیب دے رہا ہے۔ اگر آپ نے صرف تھری ڈی آواز کے حصوں کا نمونہ لیا ہے، تو آپ گیم کلاس میں تھوڑا سا کام لکھیں گے۔ تاہم، میں اصل کہانی پر مبنی تجاویز لکھ رہا ہوں، لہذا یہ بہت طویل ہو گیا ہے۔