گیم پیڈ API آپ کا ہے: جاوا اسکرپٹ سے کنٹرولر ان پٹ کو پڑھنے کے لیے ایک عملی گائیڈ

گیم پیڈ API سب سے چھوٹے براؤزر APIs میں سے ایک ہے جسے آپ کبھی استعمال کریں گے۔ 4 خصوصیات، 1 فنکشن، کوئی اجازت کا پیغام نہیں۔ آپ تقریباً 15 لائنوں میں اسکرین پر ایک کنٹرولر کھینچ سکتے ہیں۔

یہ 15 لائنیں بھی خاموشی سے رپورٹ کرتی ہیں کہ خراب کنٹرولر ٹھیک ہے۔

مجھے براؤزر پر مبنی کنٹرولر ٹیسٹر بنانے کا یہ ایک سست طریقہ معلوم ہوا۔ ایک صارف نے سائٹ کی وضاحت کو ای میل کیا کہ اس کا گیم پیڈ ٹھیک تھا کیونکہ وہ اپنی ملکیت کے ہر گیم میں اسٹک ڈرفٹ کو نمایاں طور پر دیکھ رہا تھا۔ وہ ٹھیک کہہ رہا تھا۔ براؤزر نے ہمیں 0 دیا ہے۔

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

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

انڈیکس

شرائط

یہ ایک عملی رہنما ہے۔ انسٹال کرنے کے لیے کچھ بھی نہیں ہے اور نہ ہی تعمیراتی اقدامات ہیں، لیکن ذیل کے کوڈ کے کام کرنے کے لیے کچھ چیزوں کو پورا کرنا ضروری ہے۔

آپ کو پہلے سے ہی کیا جاننے کی ضرورت ہے:

  • ایکشن لیول جاوا اسکرپٹ: فنکشنز، ارے، اور ارے طریقے reduce اور filterتیر فنکشنل اور ساختی سڑن۔

  • اینیمیشن فریم لوپ کیا ہے؟ کئی مثالیں اندرونی طور پر چلائی جاتی ہیں۔ requestAnimationFrame.

  • اپنے براؤزر کے ڈویلپر ٹولز کو کیسے کھولیں اور کوڈ کو کنسول میں پیسٹ کریں۔

ایک سیکشن تھوڑا سا ویکٹر ریاضی کرتا ہے، جیسے x اور y نمونوں کے سیٹ اور اس اوسط ویکٹر کی لمبائی کا اوسط۔ اگر Math.hypot(x, y) اگر یہ سمجھ میں آتا ہے، تو وہ حصہ بھی ہوگا.

آپ کے پاس کیا ہونا چاہیے:

  • ایک ڈیسک ٹاپ براؤزر جو گیم پیڈ API کو سپورٹ کرتا ہے۔ کروم، ایج، فائر فاکس، اور سفاری سبھی نے 2017 سے اس کی حمایت کی ہے، لہذا یہ آپ کی کھلی ہوئی ہر چیز کے لیے تقریباً یقینی طور پر دستیاب ہے۔

  • یہ ایک فزیکل گیم کنٹرولر ہے جو USB یا بلوٹوتھ کے ذریعے جڑا ہوا ہے۔ سافٹ ویئر میں اسے جعلی بنانے کا کوئی طریقہ نہیں ہے، اور نیچے دیئے گئے کوڈ میں سے کوئی بھی ہارڈ ویئر منسلک کیے بغیر کوئی مفید کام انجام نہیں دیتا ہے۔

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

کسی فریم ورک یا لائبریری کی ضرورت نہیں ہے، اور کسی این پی ایم انسٹالیشن کی ضرورت نہیں ہے۔ نیچے دیے گئے تمام بلاکس سادہ جاوا اسکرپٹ ہیں جو تحریری طور پر کام کرتا ہے۔

ٹیسٹر کام نہیں کر رہا ہے

یہ وہ ورژن ہے جسے تقریباً ہر کوئی پہلے لکھتا ہے: یہ وہ ورژن ہے جو زیادہ تر ٹیوٹوریلز میں پایا جاتا ہے۔

window.addEventListener("gamepadconnected", (e) => {
  const pad = navigator.getGamepads()[e.gamepad.index];
  console.log(pad.axes);    // [0, 0, 0, 0]
  console.log(pad.buttons.filter(b => b.pressed).length);   // 0
});

جب میں ایک ایسے کنٹرولر کو جوڑتا ہوں جس میں بہت زیادہ اسٹک ڈرفٹ ہوتا ہے (ایک کنٹرولر جو ہر گیم میں کردار کو اسکرین پر کھینچتا ہے)، یہ کچھ اس طرح پرنٹ کرتا ہے: [0, 0, 0, 0].

ان پانچ سطروں میں دو الگ الگ کیڑے ہیں، دوسرا دلچسپ ہے۔

آپ کو رائے شماری کیوں کرنی چاہئے۔

پہلا بگ یہ ہے کہ کوئی ان پٹ ایونٹس نہیں ہیں۔ gamepadconnected اور gamepaddisconnected آگ، اور یہ پوری واقعہ کی سطح ہے. موجود نہیں ہے gamepadaxischange اور نہیں gamepadbuttondown. اگر آپ جاننا چاہتے ہیں کہ چھڑی کیا کرتی ہے، تو آپ کو عام طور پر پوچھتے رہنا پڑتا ہے۔ requestAnimationFrame.

اسی بگ کا دوسرا حصہ: آپ کو کال کرنا ہے۔ navigator.getGamepads() ایک بار پھر ہر فریم۔ اسنیپ شاٹ لوٹاتا ہے۔ پکڑو Gamepad جب آپ کسی چیز کو پڑھتے ہیں اور اسے بعد میں پڑھتے ہیں، تو آپ اس چیز کو پکڑتے وقت سے ہمیشہ کے لیے قدریں منجمد کر دیتے ہیں۔

function loop() {
  const pads = navigator.getGamepads();     // re-read every frame, do not cache
  for (const pad of pads) {
    if (!pad) continue;                     // the array has empty slots, always guard
    render(pad.index, pad.axes, pad.buttons);
  }
  requestAnimationFrame(loop);
}
requestAnimationFrame(loop);

اس لوپ کے بارے میں دو عملی نوٹ۔

سب سے پہلے، انتظام بہت کم ہے. navigator.getGamepads() ایک مقررہ لمبائی کی صف لوٹاتا ہے۔ null یہ ایک سلاٹ میں ہے جس میں کچھ بھی منسلک نہیں ہے، لہذا یہ معمول کی بات ہے۔ for...of گارڈ کے بغیر، وہ پہلے پھینک دے گا. null.

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

یہاں ایک ایسا نمونہ ہے جو اچھی طرح سے کام کرتا ہے: یہ تقریباً 8 بار فی سیکنڈ کی کم شرح سے بیکار ہوتا ہے۔ setTimeoutیقینی بنائیں کہ خالص کنٹرولر ظاہر ہوتا ہے، پھر مکمل پر سوئچ کریں۔ requestAnimationFrame درحقیقت، ایک بار منسلک ہونے کے بعد، منقطع ہونے پر یہ واپس نیچے چلا جاتا ہے۔ API نمونے کے لیے سستا ہے، لیکن ہر صفحہ کے منظر میں 60 بار فی سیکنڈ نمونہ لینا بیکار ہے جیسا کہ کارکردگی کے پروفائل میں دیکھا گیا ہے۔

حفظان صحت کے قوانین

اب واقعی غیر دستاویزی حصے کے لئے اور کیوں ڈرفٹ کنٹرولر نے 0 کی اطلاع دی۔

Chromium کسی محور کی اصل قدر کی اطلاع نہیں دیتا جب تک کہ اس نے کم از کم ایک بار یہ طے نہ کر لیا ہو کہ وہ محور آرام پر ہے۔

جب تک صارف آگے نہیں بڑھتا۔ جب تک کہ براؤزر 0 کے قریب کسی چیز کا مشاہدہ نہ کرے۔

میکانزم ایک فائل میں واقع ہے جسے ڈیوائس/گیم پیڈ/گیم پیڈ_پیڈ_سٹیٹ_پرووائڈر.cc کہتے ہیں۔ براؤزر ہر منسلک کنٹرولر پر دو بٹ ​​فیلڈز کو برقرار رکھتا ہے۔ axis_mask اور button_mask. جب کہ محور پر بٹس سیٹ نہیں ہوتے ہیں، رپورٹ شدہ ویلیو کو سیٹ کرنے پر مجبور کیا جاتا ہے۔ 0.0. بٹ اس وقت سیٹ ہوتا ہے جب محور پہلی بار مستقل سے نیچے کی شدت کی اطلاع دیتا ہے۔ kMinAxisResetValueیہ ہے 0.1f. اس کے بعد سے، اصل قدر باہر بہتی ہے.

بٹن اسی طرح کام کرتے ہیں۔ button_maskزیادہ سخت جانچ کے ساتھ: بٹن کو دبائے نہ جانے کی اطلاع پر پہلی بار تھوڑا سا سیٹ کیا جاتا ہے۔ جب صفحہ لوڈ ہوتا ہے، تو ٹرگر ایک بٹن کے دبائے جانے یا درمیان میں ایک ٹوٹے ہوئے چشمے کی اطلاع دیتا ہے۔ pressed: false اور value: 0 جب تک کہ ہم براؤزر کو ایک بار جاری نہ دیکھیں۔

یہ کوئی بگ نہیں ہے اور یہ سمجھنے کے قابل ہے کہ یہ کیوں موجود ہے۔ جیسا کہ ماخذ بتاتا ہے، کنٹرولر ان پٹ کی اطلاع دے سکتا ہے جب کوئی اسے ہاتھ نہ لگا رہا ہو، یا تو ہارڈ ویئر کی خرابی کی وجہ سے یا کوئی بھاری چیز چھڑی سے ٹیک لگا رہی ہے۔ اس اصول کے بغیر، ان گمراہ کن ان پٹ کو صارف کی کارروائیوں کے طور پر سمجھا جائے گا اور صفحہ ان آلات کے بارے میں سیکھے گا جنہیں صارف نے ظاہر کرنے کا انتخاب نہیں کیا ہے۔ لہٰذا ہر ایک محور اور ہر بٹن کو یہ ثابت کرنا چاہیے کہ براؤزر آپ کو اس کے بارے میں بتانے سے پہلے ہی آرام کر سکتا ہے۔

نتائج اس کے برعکس ہیں جس کا آپ اندازہ لگا سکتے ہیں، لہذا انہیں غور سے پڑھیں۔

جتنا زیادہ بڑھے گا، براؤزر اتنا ہی لمبا اصرار کرے گا کہ کنٹرولر ٹھیک ہے۔

چھوٹی آفسیٹ والی چھڑی نیچے سے گزرتی ہے۔ 0.1 آپ جلد ہی کسی بھی فریم سے ماسک کو چھیلنے کے قابل ہو جائیں گے۔ بھاری پہنی ہوئی سلاخیں جو کھڑکی کے اندر سے محفوظ نہیں ہیں غیر معینہ مدت تک ڈھکی رہیں گی۔ جن کنٹرولرز کو رپورٹ کرنے کی سب سے زیادہ ضرورت ہوتی ہے وہ وہی ہیں جو کچھ بھی نہیں رپورٹ کرتے ہیں۔

یہ اس بات کی بھی وضاحت کرتا ہے کہ کنٹرولر ٹیسٹرز میں کیا جادو دکھائی دیتا ہے۔ "دونوں چھڑیوں کو پورے دائرے میں منتقل کریں” جیسی ہدایات کام نہیں کریں گی۔ اس کی وجہ یہ ہے کہ حرکت کرنے سے محور کھل جاتا ہے۔ یہ کام کرتا ہے کیونکہ واپسی پر ایک مکمل دائرہ مرکز سے گزرتا ہے۔

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

const start = performance.now();
let woke = false;

requestAnimationFrame(function loop() {
  const pad = navigator.getGamepads()[0];
  if (pad && !woke) {
    const [x, y] = pad.axes;
    if (x !== 0 || y !== 0) {
      woke = true;
      console.log(
        "left stick started reporting after",
        Math.round(performance.now() - start), "ms,",
        "first values:", x.toFixed(3), y.toFixed(3)
      );
    }
  }
  requestAnimationFrame(loop);
});

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

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

ہارڈ ویئر کی بھی شناخت نہیں کی جا سکتی۔

دوسرا تعجب چھوٹا ہے، لیکن یہ آپ کو UI پرت پر کاٹ دے گا۔

تفصیلات آپ کے لیے ہیں۔ pad.idیہ ایک تار ہے جسے براؤزر بناتا ہے۔ لینکس اور میک او ایس پر، یو ایس بی وینڈر اور پروڈکٹ آئی ڈی کو ہیکساڈیسیمل میں شامل کیا جاتا ہے اور ڈیوائس کے لیے دریافت کیا جا سکتا ہے۔ ونڈوز پر، XInput آلات (زیادہ تر Xbox طرز کے کنٹرولرز) کسی وینڈر یا پروڈکٹ کی شناخت کو ظاہر نہیں کرتے ہیں۔ تار یہ ہے: "Xbox 360 Controller (XInput STANDARD GAMEPAD)"تھرڈ پارٹی کلون بالکل وہی چیز رپورٹ کرتے ہیں جو ان کے ہارڈ ویئر کی طرح ہے۔

macOS کا اس کا اپنا ورژن ہے۔ ڈوئل شاک 4 میک او ایس پر کروم سے منسلک ہے: "Wireless Controller (STANDARD GAMEPAD)". کوئی وینڈر ID نہیں ہے، کوئی پروڈکٹ ID نہیں ہے، اور کوئی نام اتنا عام نہیں ہے کہ چھ غیر متعلقہ کنٹرولرز کے ذریعے اشتراک کیا جا سکے۔

آخری مسئلہ نے مجھے ایک حقیقی بگ دیا۔ ہماری گلیف رینڈرنگ کو پارس کر دیا گیا ہے۔ id چونکہ یہ ایک سٹرنگ ہے، میک پر ہر ڈوئل شاک 4 نے عام فال بیک لاگو کیا اور پلے اسٹیشن کنٹرولر پر Xbox طرز کے بٹن لیبل بنائے۔ فیچر استعمال کرنے والا کوئی بھی میک صارف مہینوں سے کچھ غلط دیکھ رہا ہے، اور کسی ونڈوز یا لینکس ٹیسٹ میں اسے نہیں ملا۔

اس کے بجائے، فنکشن پر مبنی برانچ۔

function describe(pad) {
  return {
    standard: pad.mapping === "standard",   // trust axes/buttons ordering only if true
    axes: pad.axes.length,                  // 4 on a normal twin stick pad
    buttons: pad.buttons.length,            // 17 on standard mapping with a guide button
    analogTriggers: pad.buttons.slice(6, 8).every(b => typeof b.value === "number"),
    rumble: Boolean(pad.vibrationActuator)
  };
}

استعمال کریں pad.id دکھاتا ہے اور صارفین کو یہ دیکھنے کی اجازت دیتا ہے کہ وہ کس چیز سے جڑے ہوئے ہیں۔ اپنے کوڈ کی فعالیت کا تعین کرنے کے لیے اسے استعمال نہ کریں۔

انسانی ہاتھوں میں بہاؤ بولو

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

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

دونوں صورتوں میں فرق یہ نہیں ہے کہ چھڑی مرکز سے کتنی دور ہے۔ دونوں ساتھ جاتے ہیں۔

گیٹ 1، کیا یہ ریسٹ ایریا کے قریب ہے؟ اصل بہاؤ عام طور پر ایک چھوٹا، مستقل آفسیٹ ہوتا ہے، نصف سے بھی کم انحراف۔ چھڑی پکڑے ہوئے ہاتھ عام طور پر بہت دور ہوتے ہیں۔ نمونے کی کھڑکی کا اوسط سائز تقریباً 0.6 سے کم ہونا چاہیے۔

کیا گیٹ 2 سمت سے مطابقت رکھتا ہے؟ یہ شخص کام کرنے والا شخص ہے۔ بہتے ہوئے یا غلط انداز میں لگائے گئے سینسرز میں ہوتے ہیں جو تھوڑی تبدیلی کے ساتھ ایک سمت میں رہتے ہیں۔ انسان کا ہاتھ بھٹک جاتا ہے چاہے وہ ساکت رہنے کی کوشش کرے۔ اوسط ویکٹر کی لمبائی کا اس کے انفرادی طول و عرض کی اوسط سے موازنہ کرتا ہے۔ اگر تمام نمونے ایک ہی سمت میں اشارہ کرتے ہیں، تو دونوں نمبر تقریباً برابر ہوں گے اور تناسب 1 کے قریب ہوگا۔ جیسے جیسے نمونہ پھیلتا ہے، اوسط ویکٹر اوسط سائز سے چھوٹا ہوتا جاتا ہے اور تناسب کم ہوتا جاتا ہے۔ آپ کو تقریباً 0.9 یا اس سے زیادہ کی ضرورت ہے۔

// samples: array of { x, y } collected over a rolling window, one per frame
function looksLikeDrift(samples) {
  if (samples.length < 30) return false;                 // not enough evidence yet

  const magnitude = s => Math.hypot(s.x, s.y);
  const meanMagnitude =
    samples.reduce((sum, s) => sum + magnitude(s), 0) / samples.length;

  if (meanMagnitude < 0.02) return false;                // resting at centre, nothing wrong
  if (meanMagnitude > 0.6) return false;                 // gate 1: too far out to be drift

  const meanX = samples.reduce((sum, s) => sum + s.x, 0) / samples.length;
  const meanY = samples.reduce((sum, s) => sum + s.y, 0) / samples.length;
  const coherence = Math.hypot(meanX, meanY) / meanMagnitude;

  return coherence > 0.9;                                // gate 2: holds one direction
}

اور جمع کرنے والے جو اسے فراہم کرتے ہیں وہ ہیں:

const window_ = [];
const WINDOW = 120;   // about two seconds at 60fps

requestAnimationFrame(function loop() {
  const pad = navigator.getGamepads()[0];
  if (pad) {
    window_.push({ x: pad.axes[0], y: pad.axes[1] });
    if (window_.length > WINDOW) window_.shift();
    if (looksLikeDrift(window_)) console.log("left stick looks like drift");
  }
  requestAnimationFrame(loop);
});

ریکارڈ شدہ لائیو کنٹرولر ان پٹ کے اسی 64 سیکنڈز کو دوبارہ چلا کر پیمائش کی گئی تھی، اور یہ کہ تھریشولڈ اور ٹائمر ورژن کے نتیجے میں بڑھے ہوئے حالات پیدا ہوئے، کیونکہ یہ درج ذیل دعویٰ کرنے کے قابل ہے: 2,144 فریم. ایک دو گیٹ ورژن نے اسے اٹھایا۔ صفر. اس ریکارڈنگ میں کوئی بہتی ہارڈ ویئر نہیں تھا۔ ان 2,144 فریموں میں تمام انسانوں کی لاٹھیاں حرکت میں شامل تھیں، جن میں سے بیشتر ہماری ہدایات پر عمل کرتے تھے۔

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

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

معلوم حدود

یہاں چار چیزیں ہیں جو آپ کو شپنگ سے پہلے جاننے کی ضرورت ہے۔

وائبریشن پورٹیبل نہیں ہے۔ خصوصیت کا پتہ لگانا pad.vibrationActuator رمبل کو بونس کے طور پر سمجھیں، کبھی ضرورت نہیں۔

غیر معیاری نقشہ سازی حقیقی ہے۔ جب pad.mapping ایسا نہیں "standard"محور اور بٹن آرڈر جیسا کہ براؤزر اور ڈرائیور نے اتفاق کیا ہے، اور انڈیکس 0 کے کچھ خاص ہونے کی ضمانت نہیں ہے۔ کیس کو ایڈریس کریں یا اسے واضح طور پر مسترد کریں، لیکن مفروضے نہ بنائیں۔

بلوٹوتھ پولنگ USB کے مقابلے میں کم مستقل ہے۔ چونکہ نمونے کے وقفے متزلزل ہوتے ہیں، اس لیے آپ جس چیز کا بھی وقت میں حساب لگاتے ہیں اسے مستقل 60Hz فرض کرنے کے بجائے گھمبیر ہونے کی اجازت دینی چاہیے۔

اور جدید کنٹرولرز کے لیے براؤزر سپورٹ ہارڈ ویئر سے پیچھے ہے۔ پچھلے سال جاری کردہ کنٹرولرز کو ایک براؤزر میں پہچانا جا سکتا ہے اور اسی سسٹم پر دوسرے میں نہیں۔ اس کی وجہ سے سوال "میرا کنٹرولر کام نہیں کر رہا ہے” براؤزرز میں کم از کم ہارڈ ویئر کے سوالات کے طور پر ظاہر ہوتا ہے۔

ختم

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

اس لیے سننے کے بجائے رائے شماری کریں اور دوبارہ پڑھیں۔ getGamepads() ہر فریم پر بھروسہ کرنے سے پہلے ہر محور کا خود کو ثابت کرنے کا انتظار کریں۔ id یہ ایک سٹرنگ ہے اور کسی کو مطلع کرنے سے پہلے کہ ہارڈ ویئر کو نقصان پہنچا ہے اس کا حد سے بڑا ہونا ضروری ہے۔

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

میں نے JoyCheck بنایا، ایک براؤزر پر مبنی گیم پیڈ ٹیسٹر جو یہ پیمائشیں تیار کرتا ہے۔

اوپر تک سکرول کریں۔