पॉइंटर लॉक और फ़र्स्ट पर्सन शूटर कंट्रोल

जॉन मैककटचान
जॉन मैककटचान

शुरुआती जानकारी

पॉइंटर लॉक एपीआई, ब्राउज़र गेम में फ़र्स्ट-पर्सन शूटर कंट्रोल को ठीक से लागू करने में मदद करता है. उदाहरण के लिए, माउस की गतिविधि के बिना, खिलाड़ी का कर्सर स्क्रीन के दाएं किनारे पर पहुंच सकता है और दाईं ओर आगे की गतिविधि छूट जाएगी - ऐसा करने से वह व्यू सही से पैन नहीं कर पाएगा और खिलाड़ी बुरे लोगों का पीछा नहीं कर पाएगा और उन्हें अपनी मशीन गन से पकड़ नहीं पाएगा. ऐसा होने पर खिलाड़ी हताश हो जाता है. पॉइंटर लॉक का इस्तेमाल करने पर, ऐसा हो सकता है कि आपकी साइट के लिए कोई गड़बड़ी न हो.

Pointer Lock API आपके ऐप्लिकेशन को ये काम करने की अनुमति देता है:

  • माउस की मूवमेंट के साथ-साथ, माउस के रॉ डेटा की ऐक्सेस पाएं
  • सभी माउस इवेंट को किसी खास एलिमेंट पर रूट करें

पॉइंटर लॉक सक्षम करने के दुष्प्रभाव के रूप में, माउस कर्सर छिपा हुआ है, जो आपको अपनी इच्छा से ऐप्स-विशिष्ट पॉइंटर बनाने या माउस पॉइंटर को छिपाने की सुविधा देता है, ताकि उपयोगकर्ता माउस से फ़्रेम को आगे बढ़ा सके. रिलेटिव माउस मूवमेंट, पिछली फ़्रेम से माउस पॉइंटर की पोज़िशन का डेल्टा है. भले ही, उसकी कुल पोज़िशन कुछ भी हो. उदाहरण के लिए, अगर माउस पॉइंटर (640, 480) से (520, 490) पर चला गया, तो रिलेटिव मूवमेंट (-120, 10) थी. नीचे एक इंटरैक्टिव उदाहरण दिया गया है, जिसमें माउस की स्थिति के डेल्टा को सामान्य तौर पर दिखाया गया है.

इस ट्यूटोरियल में दो विषयों के बारे में बताया गया है: पॉइंटर लॉक इवेंट को चालू और प्रोसेस करने के बारे में बुनियादी बातें और फ़र्स्ट-पर्सन शूटर कंट्रोल स्कीम को लागू करने के बारे में जानकारी. ठीक है, इस लेख को पूरा पढ़ने के बाद आपको पता चल जाएगा कि पॉइंटर लॉक का इस्तेमाल कैसे किया जाता है. साथ ही, अपने ब्राउज़र गेम के लिए क्वैक स्टाइल के कंट्रोल कैसे लागू किए जाते हैं!

वेबसाइट का अलग-अलग ब्राउज़र पर चलना

ब्राउज़र सहायता

  • 37
  • 13
  • 50
  • 10.1

सोर्स

पॉइंटर लॉक मकैनिक्स

सुविधा की पहचान करने वाली सुविधा

यह पता लगाने के लिए कि उपयोगकर्ता के ब्राउज़र में पॉइंटर लॉक की सुविधा काम करती है या नहीं, आपको दस्तावेज़ ऑब्जेक्ट में pointerLockElement या वेंडर-प्रीफ़िक्स वाले वर्शन की जांच करनी होगी. कोड में:

var havePointerLock = 'pointerLockElement' in document ||
    'mozPointerLockElement' in document ||
    'webkitPointerLockElement' in document;

फ़िलहाल, पॉइंटर लॉक की सुविधा सिर्फ़ Firefox और Chrome पर उपलब्ध है. फ़िलहाल, Opera और IE में यह सुविधा काम नहीं करती.

सक्रिय कर रहा है

पॉइंटर लॉक को चालू करना, दो चरणों वाली प्रोसेस है. सबसे पहले, जब आपका ऐप्लिकेशन किसी खास एलिमेंट के लिए पॉइंटर लॉक का अनुरोध करता है, तो यह चालू हो जाता है. इसके बाद, उपयोगकर्ता की अनुमति मिलते ही pointerlockchange इवेंट ट्रिगर हो जाता है. escape बटन दबाकर, उपयोगकर्ता किसी भी समय पॉइंटर लॉक को रद्द कर सकता है. आपका ऐप्लिकेशन, प्रोग्रैम्ड तरीके से पॉइंटर लॉक से बाहर भी आ सकता है. पॉइंटर लॉक रद्द होने पर, pointerlockchange इवेंट ट्रिगर होता है.

element.requestPointerLock = element.requestPointerLock ||
                 element.mozRequestPointerLock ||
                 element.webkitRequestPointerLock;
// Ask the browser to lock the pointer
element.requestPointerLock();

// Ask the browser to release the pointer
document.exitPointerLock = document.exitPointerLock ||
               document.mozExitPointerLock ||
               document.webkitExitPointerLock;
document.exitPointerLock();

बस ऊपर दिए गए कोड की ज़रूरत है. जब ब्राउज़र पॉइंटर को लॉक करता है, तो एक बबल, पॉप-अप के ज़रिए उपयोगकर्ता को यह बताएगा कि आपके ऐप्लिकेशन ने पॉइंटर को लॉक कर दिया है और उन्हें यह निर्देश देगा कि वे 'Esc' कुंजी दबाकर इसे रद्द कर सकते हैं.

Chrome में पॉइंटर लॉक जानकारी बार.
Chrome में मौजूद Pointer Lock का जानकारी बार.

इवेंट हैंडलिंग

आपके ऐप्लिकेशन को दो इवेंट के लिए, लिसनर को जोड़ना होगा. पहला तरीका pointerlockchange है, जो पॉइंटर लॉक की स्थिति में बदलाव होने पर ट्रिगर होता है. दूसरा mousemove है, जो माउस के हिलने पर फ़ायर होता है.

// Hook pointer lock state change events
document.addEventListener('pointerlockchange', changeCallback, false);
document.addEventListener('mozpointerlockchange', changeCallback, false);
document.addEventListener('webkitpointerlockchange', changeCallback, false);

// Hook mouse move events
document.addEventListener("mousemove", this.moveCallback, false);

pointerlockchange कॉलबैक में, आपको यह देखना होगा कि पॉइंटर अभी-अभी लॉक हुआ है या अनलॉक है. यह पता करना आसान है कि पॉइंटर लॉक चालू किया गया था या नहीं: जांच करें कि जिस एलिमेंट के लिए पॉइंटर लॉक का अनुरोध किया गया है वह document.pointerLockElement के बराबर है या नहीं. अगर ऐसा है, तो आपके ऐप्लिकेशन ने पॉइंटर को लॉक कर दिया है. अगर ऐसा नहीं है, तो पॉइंटर को उपयोगकर्ता या आपके कोड से अनलॉक किया गया था.

if (document.pointerLockElement === requestedElement ||
  document.mozPointerLockElement === requestedElement ||
  document.webkitPointerLockElement === requestedElement) {
  // Pointer was just locked
  // Enable the mousemove listener
  document.addEventListener("mousemove", this.moveCallback, false);
} else {
  // Pointer was just unlocked
  // Disable the mousemove listener
  document.removeEventListener("mousemove", this.moveCallback, false);
  this.unlockHook(this.element);
}

पॉइंटर लॉक के चालू होने पर clientX, clientY, screenX, और screenY एक जैसे रहते हैं. movementX और movementY को उतने पिक्सल के साथ अपडेट किया जाता है जितनी बार, पिछले इवेंट के डिलीवर होने के बाद, पॉइंटर को मूव किया जा सकता था. बदली हुई पहचान वाले कोड में:

event.movementX = currentCursorPositionX - previousCursorPositionX;
event.movementY = currentCursorPositionY - previousCursorPositionY;

mousemove कॉलबैक के अंदर, इवेंट के movementX और movementY फ़ील्ड से माउस की गति का डेटा निकाला जा सकता है.

function moveCallback(e) {
  var movementX = e.movementX ||
      e.mozMovementX          ||
      e.webkitMovementX       ||
      0,
  movementY = e.movementY ||
      e.mozMovementY      ||
      e.webkitMovementY   ||
      0;
}

कैच करने में हुई गड़बड़ियां

अगर पॉइंटर डालने या उससे बाहर निकलने पर कोई गड़बड़ी होती है, तो pointerlockerror इवेंट सक्रिय होता है. इस इवेंट में कोई डेटा अटैच नहीं है.

document.addEventListener('pointerlockerror', errorCallback, false);
document.addEventListener('mozpointerlockerror', errorCallback, false);
document.addEventListener('webkitpointerlockerror', errorCallback, false);

फ़ुल-स्क्रीन की ज़रूरत है?

मूल रूप से पॉइंटर लॉक, FullScreen API से जुड़ा होता है. इसका मतलब है कि पॉइंटर को लॉक करने से पहले, एलिमेंट को फ़ुलस्क्रीन मोड में होना चाहिए. यह अब सही नहीं है और पॉइंटर लॉक का उपयोग आपके ऐप्लिकेशन के किसी भी एलिमेंट के लिए फ़ुल-स्क्रीन में किया जा सकता है या नहीं.

फ़र्स्ट-पर्सन शूटर कंट्रोल का उदाहरण

हमने पॉइंटर लॉक की सुविधा चालू कर दी है और आपको इवेंट मिल रहे हैं. अब इसका उदाहरण तैयार किया जा सकता है. क्या आपने कभी सोचा है कि Quake में कंट्रोल कैसे काम करते हैं? तैयार हो जाएं, क्योंकि मैं उन्हें कोड के साथ समझाने वाली हूं!

फ़र्स्ट-पर्सन शूटर कंट्रोल, इन चार मुख्य तरीकों को ध्यान में रखकर बनाए गए हैं:

  • मौजूदा लुक वेक्टर के साथ आगे और पीछे जाना
  • वर्तमान स्ट्रैफ़ वेक्टर को बाईं और दाईं ओर ले जाएं
  • व्यू यॉ घुमाना (बाएं और दाएं)
  • व्यू पिच को घुमाना (ऊपर और नीचे)

इस कंट्रोल स्कीम को लागू करने वाले गेम में डेटा के सिर्फ़ तीन हिस्सों की ज़रूरत होती है: कैमरे की पोज़िशन, कैमरे की पोज़िशन, लुक वेक्टर, और कॉन्स्टेंट अप वेक्टर. अप वेक्टर हमेशा (0, 1, 0) होता है. ऊपर बताए गए सभी चारों मकैनिक, कैमरे की पोज़िशन में बदलाव करते हैं. साथ ही, कैमरा अलग-अलग तरह से वेक्टर दिखाता है.

चलन

डेक पर सबसे पहले मूवमेंट चाहिए. नीचे दिए गए डेमो में, हलचल को स्टैंडर्ड W, A, S, और D बटन के साथ मैप किया गया है. W और S बटन, कैमरे को आगे और पीछे की ओर ले जाते हैं. वहीं A और D बटन, कैमरे को बाईं और दाईं तरफ़ ले जाते हैं. कैमरे को आगे और पीछे ले जाना आसान है:

// Forward direction
var forwardDirection = vec3.create(cameraLookVector);
// Speed
var forwardSpeed = dt * cameraSpeed;
// Forward or backward depending on keys held
var forwardScale = 0.0;
forwardScale += keyState.W ? 1.0 : 0.0;
forwardScale -= keyState.S ? 1.0 : 0.0;
// Scale movement
vec3.scale(forwardDirection, forwardScale * forwardSpeed);
// Add scaled movement to camera position
vec3.add(cameraPosition, forwardDirection);

बाईं और दाईं ओर स्ट्रैफ़ करने के लिए, स्ट्रैफ़ दिशा की ज़रूरत होती है. क्रॉस प्रॉडक्ट की मदद से, स्ट्रैफ़ की दिशा का पता लगाया जा सकता है:

// Strafe direction
var strafeDirection = vec3.create();
vec3.cross(cameraLookVector, cameraUpVector, strafeDirection);

स्ट्रैफ़ की दिशा तय करने के बाद, स्ट्रैफ़ मूवमेंट को लागू करना, आगे या पीछे जाने जैसा ही होता है.

आगे है व्यू को रोटेट करना.

यॉ

यॉ या कैमरा व्यू का हॉरिज़ॉन्टल रोटेशन, कॉन्सटेंट अप वेक्टर का सिर्फ़ एक रोटेशन है. किसी आर्बिट्रेरी ऐक्सिस के चारों ओर, कैमरा लुक वेक्टर को घुमाने के लिए एक सामान्य कोड नीचे दिया गया है. यह एक क्वाटर्नियन बनाकर काम करता है. यह axis के आस-पास deltaAngle रेडियन के रोटेशन को दिखाता है. इसके बाद, कैमरे के लुक वेक्टर को घुमाने के लिए क्वाटर्नियन का इस्तेमाल करता है:

// Extract camera look vector
var frontDirection = vec3.create();
vec3.subtract(this.lookAtPoint, this.eyePoint, frontDirection);
vec3.normalize(frontDirection);
var q = quat4.create();
// Construct quaternion
quat4.fromAngleAxis(deltaAngle, axis, q);
// Rotate camera look vector
quat4.multiplyVec3(q, frontDirection);
// Update camera look vector
this.lookAtPoint = vec3.create(this.eyePoint);
vec3.add(this.lookAtPoint, frontDirection);

गाना पिच करें

कैमरा व्यू की पिच या वर्टिकल रोटेशन लागू करना एक जैसा है. हालांकि, अप वेक्टर के चारों ओर रोटेशन के बजाय, स्ट्रैफ़ वेक्टर के चारों ओर रोटेशन लागू किया जाता है. पहला चरण है, स्ट्रैफ़ वेक्टर को कंप्यूट करना और फिर कैमरे के लुक वेक्टर को उस ऐक्सिस के चारों ओर घुमाना.

खास जानकारी

पॉइंटर लॉक एपीआई से, आपको माउस के कर्सर को कंट्रोल करने की सुविधा मिलती है. अगर आप वेब गेम बना रहे हैं, तो आपके खिलाड़ियों को खेलना बंद करने पर भी वह बहुत पसंद आएगा. ऐसा इसलिए, क्योंकि उन्होंने उत्साहित होकर माउस को विंडो से बाहर निकाल दिया है और आपके गेम को माउस अपडेट मिलने बंद हो गए हैं. इस्तेमाल आसान है:

  • पॉइंटर लॉक की स्थिति ट्रैक करने के लिए, pointerlockchange इवेंट लिसनर जोड़ें
  • किसी खास एलिमेंट के लिए, पॉइंटर लॉक का अनुरोध करना
  • अपडेट पाने के लिए, mousemove इवेंट लिसनर जोड़ें

बाहरी डेमो

References