|
|
<!--
|
|
|
CO_OP_TRANSLATOR_METADATA:
|
|
|
{
|
|
|
"original_hash": "022bbb5c869091b98f19e408e0c51d5d",
|
|
|
"translation_date": "2025-10-22T17:12:27+00:00",
|
|
|
"source_file": "6-space-game/3-moving-elements-around/README.md",
|
|
|
"language_code": "ne"
|
|
|
}
|
|
|
-->
|
|
|
# स्पेस गेम बनाउने भाग ३: गति थप्ने
|
|
|
|
|
|
आफ्नो मनपर्ने खेलहरूको बारेमा सोच्नुहोस् – तिनीहरूलाई आकर्षक बनाउने कुरा केवल राम्रो ग्राफिक्स मात्र होइन, तर सबै कुरा कसरी चल्छ र तपाईंको क्रियाकलापमा प्रतिक्रिया दिन्छ भन्ने हो। अहिले, तपाईंको स्पेस गेम एउटा सुन्दर चित्रजस्तै छ, तर हामी यसलाई जीवन्त बनाउने गति थप्न जाँदैछौं।
|
|
|
|
|
|
जब नासाका इन्जिनियरहरूले अपोलो मिशनहरूको लागि गाइडेंस कम्प्युटर प्रोग्राम गरे, उनीहरूले यस्तै चुनौतीको सामना गरे: कसरी एउटा अन्तरिक्ष यानलाई पाइलटको इनपुटमा प्रतिक्रिया दिनुहोस् र स्वचालित रूपमा कोर्स सुधारहरू कायम राख्नुहोस्? आज हामीले सिक्ने सिद्धान्तहरू त्यस्तै अवधारणाहरूको प्रतिध्वनि गर्छन् – खेलाडी-नियन्त्रित गति व्यवस्थापन र स्वचालित प्रणाली व्यवहारहरू।
|
|
|
|
|
|
यस पाठमा, तपाईंले सिक्नुहुनेछ कि कसरी स्पेसशिपलाई स्क्रिनमा ग्लाइड गराउने, खेलाडीको आदेशहरूमा प्रतिक्रिया दिने, र चिल्लो गति ढाँचाहरू सिर्जना गर्ने। हामी सबै कुरा व्यवस्थित अवधारणाहरूमा तोड्नेछौं जसले एकअर्कामा स्वाभाविक रूपमा निर्माण गर्छ।
|
|
|
|
|
|
अन्त्यमा, तपाईंले खेलाडीहरूलाई आफ्नो हिरो जहाजलाई स्क्रिनमा उडाउने र शत्रु जहाजहरू माथि गस्ती गर्ने देख्नुहुनेछ। अझ महत्त्वपूर्ण कुरा, तपाईंले खेल गति प्रणालीहरूलाई शक्ति दिने मुख्य सिद्धान्तहरू बुझ्नुहुनेछ।
|
|
|
|
|
|
## प्रि-लेक्चर क्विज
|
|
|
|
|
|
[प्रि-लेक्चर क्विज](https://ff-quizzes.netlify.app/web/quiz/33)
|
|
|
|
|
|
## खेलको गति बुझ्दै
|
|
|
|
|
|
खेलहरू तब जीवित हुन्छन् जब चीजहरू वरिपरि सर्न थाल्छन्, र यो दुई तरिकामा हुन्छ:
|
|
|
|
|
|
- **खेलाडी-नियन्त्रित गति**: जब तपाईंले कुनै कुञ्जी थिच्नुहुन्छ वा माउस क्लिक गर्नुहुन्छ, केही सर्छ। यो तपाईं र तपाईंको खेल संसारको बीचको प्रत्यक्ष जडान हो।
|
|
|
- **स्वचालित गति**: जब खेल आफैंले चीजहरू सार्ने निर्णय गर्छ – जस्तै ती शत्रु जहाजहरू जसले स्क्रिनमा गस्ती गर्नुपर्छ चाहे तपाईंले केही गरिरहनुभएको छैन।
|
|
|
|
|
|
कम्प्युटर स्क्रिनमा वस्तुहरू सार्नु सोचेभन्दा सजिलो छ। गणित कक्षाको x र y समन्वयहरू सम्झनुहोस्? हामी यहीसँग काम गर्दैछौं। जब ग्यालिलियोले १६१० मा बृहस्पतिको चन्द्रमाहरू ट्र्याक गरे, उनले मूलतः त्यही काम गरिरहेका थिए – गति ढाँचाहरू बुझ्न समयको साथमा स्थानहरू प्लट गर्दै।
|
|
|
|
|
|
स्क्रिनमा चीजहरू सार्नु फ्लिपबुक एनिमेसन सिर्जना गर्ने जस्तै हो – तपाईंले यी तीन सरल चरणहरू पालना गर्नुपर्छ:
|
|
|
|
|
|
1. **स्थिति अपडेट गर्नुहोस्** – तपाईंको वस्तु कहाँ हुनुपर्छ परिवर्तन गर्नुहोस् (शायद यसलाई ५ पिक्सल दायाँतिर सार्नुहोस्)
|
|
|
2. **पुरानो फ्रेम मेटाउनुहोस्** – स्क्रिन सफा गर्नुहोस् ताकि तपाईंले भूतिया ट्रेल्स नदेख्नुहोस्
|
|
|
3. **नयाँ फ्रेम बनाउनुहोस्** – तपाईंको वस्तुलाई यसको नयाँ स्थानमा राख्नुहोस्
|
|
|
|
|
|
यो पर्याप्त छिटो गर्नुहोस्, र बूम! तपाईंले खेलाडीहरूलाई प्राकृतिक लाग्ने चिल्लो गति पाउनुभयो।
|
|
|
|
|
|
यसले कोडमा कस्तो देखिन्छ:
|
|
|
|
|
|
```javascript
|
|
|
// Set the hero's location
|
|
|
hero.x += 5;
|
|
|
// Clear the rectangle that hosts the hero
|
|
|
ctx.clearRect(0, 0, canvas.width, canvas.height);
|
|
|
// Redraw the game background and hero
|
|
|
ctx.fillRect(0, 0, canvas.width, canvas.height);
|
|
|
ctx.fillStyle = "black";
|
|
|
ctx.drawImage(heroImg, hero.x, hero.y);
|
|
|
```
|
|
|
|
|
|
**यस कोडले के गर्छ:**
|
|
|
- **अपडेट गर्छ** हिरोको x-समन्वयलाई ५ पिक्सलले क्षैतिज रूपमा सार्न
|
|
|
- **सफा गर्छ** सम्पूर्ण क्यानभास क्षेत्रलाई पुरानो फ्रेम हटाउन
|
|
|
- **भर्छ** क्यानभासलाई कालो पृष्ठभूमि रंगले
|
|
|
- **पुन: बनाउँछ** हिरोको छवि नयाँ स्थानमा
|
|
|
|
|
|
✅ के तपाईं सोच्न सक्नुहुन्छ किन धेरै फ्रेमहरू प्रति सेकेन्डमा तपाईंको हिरो पुन: बनाउँदा प्रदर्शन लागत बढ्न सक्छ? [यस ढाँचाको विकल्पहरू](https://developer.mozilla.org/en-US/docs/Web/API/Canvas_API/Tutorial/Optimizing_canvas) बारे पढ्नुहोस्।
|
|
|
|
|
|
## कुञ्जीपाटी घटनाहरू ह्यान्डल गर्नुहोस्
|
|
|
|
|
|
यो त्यहाँ हो जहाँ हामी खेलाडीको इनपुटलाई खेलको क्रियामा जडान गर्छौं। जब कसैले लेजर फायर गर्न स्पेसबार थिच्छ वा एस्टेरोइडलाई डज गर्न एरो कुञ्जी थिच्छ, तपाईंको खेलले त्यो इनपुट पत्ता लगाउन र प्रतिक्रिया दिनुपर्छ।
|
|
|
|
|
|
कुञ्जीपाटी घटनाहरू विन्डो स्तरमा हुन्छन्, जसको अर्थ तपाईंको सम्पूर्ण ब्राउजर विन्डोले ती कुञ्जी थिचाइहरू सुन्दैछ। माउस क्लिकहरू, अर्कोतर्फ, विशिष्ट तत्वहरूमा बाँध्न सकिन्छ (जस्तै बटन क्लिक गर्दा)। हाम्रो स्पेस गेमको लागि, हामी कुञ्जीपाटी नियन्त्रणहरूमा ध्यान केन्द्रित गर्नेछौं किनभने यसले खेलाडीहरूलाई त्यो क्लासिक आर्केड अनुभव दिन्छ।
|
|
|
|
|
|
यसले मलाई १८०० को दशकमा टेलिग्राफ अपरेटरहरूले मोर्स कोड इनपुटलाई अर्थपूर्ण सन्देशहरूमा अनुवाद गर्नुपरेको सम्झाउँछ – हामी केही यस्तै गर्दैछौं, कुञ्जी थिचाइहरूलाई खेल आदेशहरूमा अनुवाद गर्दै।
|
|
|
|
|
|
घटना ह्यान्डल गर्न तपाईंले विन्डोको `addEventListener()` विधि प्रयोग गर्नुपर्छ र यसलाई दुई इनपुट प्यारामिटरहरू प्रदान गर्नुपर्छ। पहिलो प्यारामिटर घटनाको नाम हो, उदाहरणका लागि `keyup`। दोस्रो प्यारामिटर घटना घटेको परिणामस्वरूप बोलाउनुपर्ने कार्य हो।
|
|
|
|
|
|
यहाँ एउटा उदाहरण छ:
|
|
|
|
|
|
```javascript
|
|
|
window.addEventListener('keyup', (evt) => {
|
|
|
// evt.key = string representation of the key
|
|
|
if (evt.key === 'ArrowUp') {
|
|
|
// do something
|
|
|
}
|
|
|
});
|
|
|
```
|
|
|
|
|
|
**यहाँ के हुन्छ भन्ने कुरा तोड्दै:**
|
|
|
- **सुन्छ** सम्पूर्ण विन्डोमा कुञ्जीपाटी घटनाहरू
|
|
|
- **पकड्छ** घटना वस्तु जसले कुन कुञ्जी थिचिएको थियो भन्ने जानकारी समावेश गर्दछ
|
|
|
- **जाँच्छ** कि थिचिएको कुञ्जी विशिष्ट कुञ्जीसँग मेल खान्छ (यस अवस्थामा, माथि एरो)
|
|
|
- **कार्यान्वयन गर्छ** जब सर्त पूरा हुन्छ
|
|
|
|
|
|
कुञ्जी घटनाहरूको लागि त्यहाँ दुई गुणहरू छन् जुन तपाईंले कुन कुञ्जी थिचिएको थियो हेर्न प्रयोग गर्न सक्नुहुन्छ:
|
|
|
|
|
|
- `key` - यो थिचिएको कुञ्जीको स्ट्रिङ प्रतिनिधित्व हो, उदाहरणका लागि `'ArrowUp'`
|
|
|
- `keyCode` - यो संख्यात्मक प्रतिनिधित्व हो, उदाहरणका लागि `37`, `ArrowLeft` सँग मेल खान्छ
|
|
|
|
|
|
✅ कुञ्जी घटना हेरफेर खेल विकास बाहिर उपयोगी छ। यस प्रविधिको लागि तपाईं अन्य के उपयोग सोच्न सक्नुहुन्छ?
|
|
|
|
|
|
### विशेष कुञ्जीहरू: एक चेतावनी!
|
|
|
|
|
|
केही कुञ्जीहरूमा बिल्ट-इन ब्राउजर व्यवहारहरू हुन्छन् जसले तपाईंको खेलमा बाधा पुर्याउन सक्छ। एरो कुञ्जीहरूले पृष्ठ स्क्रोल गर्छन् र स्पेसबार तल जान्छ – जब कोही आफ्नो स्पेसशिप चलाउन खोज्दैछ, तपाईं यी व्यवहारहरू चाहनुहुन्न।
|
|
|
|
|
|
हामी यी डिफल्ट व्यवहारहरू रोक्न सक्छौं र हाम्रो खेलले इनपुटलाई ह्यान्डल गर्न सक्छ। यो प्रारम्भिक कम्प्युटर प्रोग्रामरहरूले कस्टम व्यवहारहरू सिर्जना गर्न प्रणाली इन्टरप्टहरू ओभरराइड गर्नुपरेको जस्तै हो – हामी ब्राउजर स्तरमा मात्र गर्दैछौं। यहाँ कसरी:
|
|
|
|
|
|
```javascript
|
|
|
const onKeyDown = function (e) {
|
|
|
console.log(e.keyCode);
|
|
|
switch (e.keyCode) {
|
|
|
case 37:
|
|
|
case 39:
|
|
|
case 38:
|
|
|
case 40: // Arrow keys
|
|
|
case 32:
|
|
|
e.preventDefault();
|
|
|
break; // Space
|
|
|
default:
|
|
|
break; // do not block other keys
|
|
|
}
|
|
|
};
|
|
|
|
|
|
window.addEventListener('keydown', onKeyDown);
|
|
|
```
|
|
|
|
|
|
**यो रोकथाम कोड बुझ्दै:**
|
|
|
- **जाँच्छ** विशिष्ट कुञ्जी कोडहरूको लागि जसले अनावश्यक ब्राउजर व्यवहार निम्त्याउन सक्छ
|
|
|
- **रोक्छ** एरो कुञ्जीहरू र स्पेसबारको लागि डिफल्ट ब्राउजर क्रिया
|
|
|
- **अनुमति दिन्छ** अन्य कुञ्जीहरू सामान्य रूपमा काम गर्न
|
|
|
- **प्रयोग गर्छ** `e.preventDefault()` ब्राउजरको बिल्ट-इन व्यवहार रोक्न
|
|
|
|
|
|
## खेल प्रेरित गति
|
|
|
|
|
|
अब कुरा गरौं वस्तुहरू जुन खेलाडीको इनपुट बिना सर्छ। स्क्रिनमा क्रुज गर्ने शत्रु जहाजहरू, सीधा रेखामा उड्ने गोलीहरू, वा पृष्ठभूमिमा बहने बादलहरूको बारेमा सोच्नुहोस्। यो स्वायत्त गति तपाईंको खेल संसारलाई जीवित महसुस गराउँछ जब कोही नियन्त्रणहरू छुँदैन।
|
|
|
|
|
|
हामी नियमित अन्तरालमा स्थिति अपडेट गर्न JavaScript को बिल्ट-इन टाइमरहरू प्रयोग गर्छौं। यो अवधारणा पेन्डुलम घडीहरू कसरी काम गर्छन् जस्तै हो – एक नियमित मेकानिज्म जसले निरन्तर, समयबद्ध कार्यहरू ट्रिगर गर्छ। यो कति सरल हुन सक्छ:
|
|
|
|
|
|
```javascript
|
|
|
const id = setInterval(() => {
|
|
|
// Move the enemy on the y axis
|
|
|
enemy.y += 10;
|
|
|
}, 100);
|
|
|
```
|
|
|
|
|
|
**यो गति कोडले के गर्छ:**
|
|
|
- **सिर्जना गर्छ** एक टाइमर जो प्रत्येक १०० मिलिसेकेन्डमा चल्छ
|
|
|
- **अपडेट गर्छ** शत्रुको y-समन्वयलाई प्रत्येक पटक १० पिक्सलले
|
|
|
- **भण्डारण गर्छ** अन्तराल आईडी ताकि हामी पछि यसलाई रोक्न सकौं
|
|
|
- **सर्छ** शत्रु स्वतः स्क्रिनमा तलतिर
|
|
|
|
|
|
## खेल लूप
|
|
|
|
|
|
यहाँ अवधारणा छ जसले सबै कुरा एकसाथ बाँध्छ – खेल लूप। यदि तपाईंको खेल एउटा चलचित्र हो भने, खेल लूप फिल्म प्रोजेक्टर हुनेछ, फ्रेम पछि फ्रेम देखाउँदै यति छिटो कि सबै कुरा चिल्लो रूपमा सर्छ।
|
|
|
|
|
|
प्रत्येक खेलमा यी लूपहरू मध्ये एक पर्दा पछाडि चलिरहेको हुन्छ। यो एउटा कार्य हो जसले सबै खेल वस्तुहरू अपडेट गर्छ, स्क्रिन पुन: बनाउँछ, र यो प्रक्रिया निरन्तर दोहोर्याउँछ। यसले तपाईंको हिरो, सबै शत्रुहरू, वरिपरि उडिरहेको कुनै पनि लेजरहरू – सम्पूर्ण खेल अवस्था ट्र्याक राख्छ।
|
|
|
|
|
|
यो अवधारणा मलाई प्रारम्भिक फिल्म एनिमेटरहरू जस्तै वाल्ट डिज्नीले पात्रहरूलाई फ्रेम द्वारा फ्रेम पुन: बनाउनु परेको सम्झाउँछ ताकि गति को भ्रम सिर्जना गर्न सकियोस्। हामी त्यही गर्दैछौं, केवल कोडको साथमा।
|
|
|
|
|
|
यहाँ खेल लूप सामान्यतया कस्तो देखिन्छ, कोडमा व्यक्त गरिएको छ:
|
|
|
|
|
|
```javascript
|
|
|
const gameLoopId = setInterval(() => {
|
|
|
function gameLoop() {
|
|
|
ctx.clearRect(0, 0, canvas.width, canvas.height);
|
|
|
ctx.fillStyle = "black";
|
|
|
ctx.fillRect(0, 0, canvas.width, canvas.height);
|
|
|
drawHero();
|
|
|
drawEnemies();
|
|
|
drawStaticObjects();
|
|
|
}
|
|
|
gameLoop();
|
|
|
}, 200);
|
|
|
```
|
|
|
|
|
|
**खेल लूप संरचना बुझ्दै:**
|
|
|
- **सफा गर्छ** सम्पूर्ण क्यानभास पुरानो फ्रेम हटाउन
|
|
|
- **भर्छ** पृष्ठभूमिलाई ठोस रंगले
|
|
|
- **पुन: बनाउँछ** सबै खेल वस्तुहरू तिनीहरूको वर्तमान स्थानहरूमा
|
|
|
- **दोहोरो गर्छ** यो प्रक्रिया प्रत्येक २०० मिलिसेकेन्डमा चिल्लो एनिमेसन सिर्जना गर्न
|
|
|
- **व्यवस्थापन गर्छ** फ्रेम दरलाई अन्तराल समय नियन्त्रण गरेर
|
|
|
|
|
|
## स्पेस गेम जारी राख्दै
|
|
|
|
|
|
अब हामी स्थिर दृश्यमा गति थप्नेछौं जुन तपाईंले पहिले निर्माण गर्नुभएको थियो। हामी यसलाई स्क्रिनशटबाट अन्तरक्रियात्मक अनुभवमा रूपान्तरण गर्न जाँदैछौं। हामी प्रत्येक टुक्रा अर्कोमा निर्माण सुनिश्चित गर्न चरणबद्ध रूपमा काम गर्नेछौं।
|
|
|
|
|
|
पछिल्लो पाठमा हामीले छोडेको कोड समात्नुहोस् (वा यदि तपाईंलाई नयाँ सुरुवात आवश्यक छ भने [भाग II- स्टार्टर](../../../../6-space-game/3-moving-elements-around/your-work) फोल्डरमा कोड सुरु गर्नुहोस्)।
|
|
|
|
|
|
**आज हामी के निर्माण गर्दैछौं:**
|
|
|
- **हिरो नियन्त्रणहरू**: एरो कुञ्जीहरूले तपाईंको स्पेसशिपलाई स्क्रिनमा चलाउनेछ
|
|
|
- **शत्रु गति**: ती एलियन जहाजहरूले आफ्नो आक्रमण सुरु गर्नेछन्
|
|
|
|
|
|
हामी यी सुविधाहरू कार्यान्वयन गर्न सुरु गरौं।
|
|
|
|
|
|
## सिफारिस गरिएका चरणहरू
|
|
|
|
|
|
`your-work` सब फोल्डरमा तपाईंको लागि सिर्जना गरिएका फाइलहरू पत्ता लगाउनुहोस्। यसले निम्न समावेश गर्नुपर्छ:
|
|
|
|
|
|
```bash
|
|
|
-| assets
|
|
|
-| enemyShip.png
|
|
|
-| player.png
|
|
|
-| index.html
|
|
|
-| app.js
|
|
|
-| package.json
|
|
|
```
|
|
|
|
|
|
तपाईं आफ्नो प्रोजेक्ट `your-work` फोल्डरमा टाइप गरेर सुरु गर्नुहोस्:
|
|
|
|
|
|
```bash
|
|
|
cd your-work
|
|
|
npm start
|
|
|
```
|
|
|
|
|
|
**यो आदेशले के गर्छ:**
|
|
|
- **तपाईंको प्रोजेक्ट निर्देशिका**मा जान्छ
|
|
|
- **HTTP सर्भर सुरु गर्छ** `http://localhost:5000` ठेगानामा
|
|
|
- **तपाईंको खेल फाइलहरू सेवा दिन्छ** ताकि तपाईं तिनीहरूलाई ब्राउजरमा परीक्षण गर्न सक्नुहुन्छ
|
|
|
|
|
|
माथिको आदेशले `http://localhost:5000` ठेगानामा HTTP सर्भर सुरु गर्नेछ। ब्राउजर खोल्नुहोस् र त्यो ठेगाना इनपुट गर्नुहोस्, अहिले यसले हिरो र सबै शत्रुहरूलाई प्रस्तुत गर्नुपर्छ; केही पनि सर्दैन - अझै!
|
|
|
|
|
|
### कोड थप्नुहोस्
|
|
|
|
|
|
1. **समर्पित वस्तुहरू थप्नुहोस्** `hero`, `enemy`, र `game object` को लागि, तिनीहरूसँग `x` र `y` गुणहरू हुनुपर्छ। ([Inheritance or composition](../README.md) को भाग सम्झनुहोस्।)
|
|
|
|
|
|
*सुझाव* `game object` त्यो हुनुपर्छ जससँग `x` र `y` र क्यानभासमा आफैंलाई चित्रण गर्ने क्षमता छ।
|
|
|
|
|
|
> **टिप**: नयाँ `GameObject` कक्षा थपेर यसको कन्स्ट्रक्टर तलको रूपमा परिभाषित गरेर सुरु गर्नुहोस्, र त्यसपछि यसलाई क्यानभासमा चित्रण गर्नुहोस्:
|
|
|
|
|
|
```javascript
|
|
|
class GameObject {
|
|
|
constructor(x, y) {
|
|
|
this.x = x;
|
|
|
this.y = y;
|
|
|
this.dead = false;
|
|
|
this.type = "";
|
|
|
this.width = 0;
|
|
|
this.height = 0;
|
|
|
this.img = undefined;
|
|
|
}
|
|
|
|
|
|
draw(ctx) {
|
|
|
ctx.drawImage(this.img, this.x, this.y, this.width, this.height);
|
|
|
}
|
|
|
}
|
|
|
```
|
|
|
|
|
|
**यो आधार कक्षा बुझ्दै:**
|
|
|
- **सामान्य गुणहरू परिभाषित गर्छ** जुन सबै खेल वस्तुहरूले साझा गर्छन् (स्थिति, आकार, छवि)
|
|
|
- **समावेश गर्छ** `dead` फ्ल्याग वस्तु हटाउन ट्र्याक गर्न
|
|
|
- **प्रदान गर्छ** `draw()` विधि जसले क्यानभासमा वस्तु प्रस्तुत गर्छ
|
|
|
- **डिफल्ट मानहरू सेट गर्छ** सबै गुणहरूको लागि जुन बच्चा कक्षाहरूले ओभरराइड गर्न सक्छन्
|
|
|
|
|
|
अब, यस `GameObject` लाई विस्तार गरेर `Hero` र `Enemy` सिर्जना गर्नुहोस्:
|
|
|
|
|
|
```javascript
|
|
|
class Hero extends GameObject {
|
|
|
constructor(x, y) {
|
|
|
super(x, y);
|
|
|
this.width = 98;
|
|
|
this.height = 75;
|
|
|
this.type = "Hero";
|
|
|
this.speed = 5;
|
|
|
}
|
|
|
}
|
|
|
```
|
|
|
|
|
|
```javascript
|
|
|
class Enemy extends GameObject {
|
|
|
constructor(x, y) {
|
|
|
super(x, y);
|
|
|
this.width = 98;
|
|
|
this.height = 50;
|
|
|
this.type = "Enemy";
|
|
|
const id = setInterval(() => {
|
|
|
if (this.y < canvas.height - this.height) {
|
|
|
this.y += 5;
|
|
|
} else {
|
|
|
console.log('Stopped at', this.y);
|
|
|
clearInterval(id);
|
|
|
}
|
|
|
}, 300);
|
|
|
}
|
|
|
}
|
|
|
```
|
|
|
|
|
|
**यी कक्षाहरूमा मुख्य अवधारणाहरू:**
|
|
|
- **`GameObject` बाट उत्तराधिकार लिन्छ** `extends` कीवर्ड प्रयोग गरेर
|
|
|
- **पेरेंट कन्स्ट्रक्टरलाई बोलाउँछ** `super(x, y)` प्रयोग गरेर
|
|
|
- **प्रत्येक वस्तु प्रकारको लागि विशिष्ट आयाम र गुणहरू सेट गर्छ**
|
|
|
- **स्वचालित गति कार्यान्वयन गर्छ** शत्रुहरूको लागि `setInterval()` प्रयोग गरेर
|
|
|
|
|
|
2. **कुञ्जी-घटना ह्यान्डलरहरू थप्नुहोस्** कुञ्जी नेभिगेसन ह्यान्डल गर्न (हिरोलाई माथि/तल, बायाँ/दायाँ सर्नुहोस्)
|
|
|
|
|
|
*स्मरण गर्नुहोस्* यो एक कार्टेसियन प्रणाली हो, माथि-बायाँ `0,0` हो। साथै एरो कुञ्जीहरू र स्पेसबारको लागि *डिफल्ट व्यवहार* रोक्न कोड थप्न सम्झनुहोस्।
|
|
|
|
|
|
> **टिप**: आफ्नो `onKeyDown` कार्य सिर्जना गर्नुहोस् र यसलाई विन्डोमा संलग्न गर्नुहोस्:
|
|
|
|
|
|
```javascript
|
|
|
const onKeyDown = function (e) {
|
|
|
console.log(e.keyCode);
|
|
|
// Add the code from the lesson above to stop default behavior
|
|
|
switch (e.keyCode) {
|
|
|
case 37:
|
|
|
case 39:
|
|
|
case 38:
|
|
|
case 40: // Arrow keys
|
|
|
case 32:
|
|
|
e.preventDefault();
|
|
|
break; // Space
|
|
|
default:
|
|
|
break; // do not block other keys
|
|
|
}
|
|
|
};
|
|
|
|
|
|
window.addEventListener("keydown", onKeyDown);
|
|
|
```
|
|
|
|
|
|
**यो घटना ह्यान्डलरले के गर्छ:**
|
|
|
- **कुञ्जीपाटी घटनाहरू सुन्छ** सम्पूर्ण विन्डोमा
|
|
|
- **कुञ्जी कोड लग गर्छ** कुन कुञ्जी थिचिएको छ डिबग गर्न मद्दत गर्न
|
|
|
- **डिफल्ट ब्राउजर व्यवहार रोक्छ** एरो कुञ्जीहरू र स्पेसबारको लागि
|
|
|
- **अन्य कुञ्जीहरूलाई सामान्य रूपमा काम गर्न अनुमति दिन्छ**
|
|
|
|
|
|
यस बिन्दुमा आफ्नो ब्राउजर कन्सोल जाँच गर्नुहोस्, र कुञ्जी थिचाइहरू लग भइरहेको हेर्नुहोस्।
|
|
|
|
|
|
3. **[Pub sub pattern](../README.md) कार्यान्वयन गर्नुहोस्**, यसले तपाईंको कोड सफा राख्छ जब तपाईं बाँकी भागहरू पालना गर्नुहुन्छ।
|
|
|
|
|
|
पब्लिश-सब्सक्राइब ढाँचाले तपाईंको कोडलाई घटनाको पत्ता लगाउने र घटनाको ह्यान्डल गर्नेबाट अलग गरेर व्यवस्थित गर्न मद्दत गर्छ। यसले तपाईंको कोडलाई अधिक मोड्युलर र मर्मत गर्न सजिलो बनाउँछ।
|
|
|
|
|
|
यो अन्तिम भाग गर्न, तपाईंले:
|
|
|
|
|
|
1. **विन्डोमा घटना सुन्ने कार्य थप्नुहोस्**:
|
|
|
|
|
|
```javascript
|
|
|
window.addEventListener("keyup", (evt) => {
|
|
|
if (evt.key === "ArrowUp") {
|
|
|
eventEmitter.emit(Messages.KEY_EVENT_UP);
|
|
|
} else if (evt.key === "ArrowDown") {
|
|
|
eventEmitter.emit(Messages.KEY_EVENT_DOWN);
|
|
|
} else if (evt.key === "ArrowLeft") {
|
|
|
eventEmitter.emit(Messages.KEY_EVENT_LEFT);
|
|
|
} else if (evt.key === "ArrowRight") {
|
|
|
eventEmitter.emit(Messages.KEY_EVENT_RIGHT);
|
|
|
}
|
|
|
});
|
|
|
```
|
|
|
|
|
|
**यो घटना प्रणालीले के गर्छ:**
|
|
|
- **कुञ्जीपाटी इनपुट पत्ता लगाउँछ** र यसलाई कस्टम खेल घटनाहरूमा रूपान्तरण गर्छ
|
|
|
- **इनपुट पत्ता लगाउने र खेलको तर्क अलग गर्छ**
|
|
|
- **नियन्त्रणहरू परिवर्तन गर्न सजिलो बनाउँछ** पछि खेल कोडलाई असर नगरी
|
|
|
- **एकै इनपुटमा धेरै प्रणालीहरूलाई प्रतिक्रिया दिन अनुमति दिन्छ**
|
|
|
|
|
|
2. **EventEmitter कक्षा सिर्जना गर्नुहोस्** सन्देशहरू प्रकाशित गर्न र सदस्यता लिन:
|
|
|
|
|
|
```javascript
|
|
|
class EventEmitter {
|
|
|
constructor() {
|
|
|
this.listeners = {};
|
|
|
}
|
|
|
|
|
|
on(message, listener) {
|
|
|
if (!this.listeners[message]) {
|
|
|
this.listeners[message] = [];
|
|
|
}
|
|
|
this.listeners[message].push(listener);
|
|
|
}
|
|
|
|
|
|
3. **Constants थप्नुहोस्** र EventEmitter सेटअप गर्नुहोस्:
|
|
|
|
|
|
```javascript
|
|
|
const Messages = {
|
|
|
KEY_EVENT_UP: "KEY_EVENT_UP",
|
|
|
KEY_EVENT_DOWN: "KEY_EVENT_DOWN",
|
|
|
KEY_EVENT_LEFT: "KEY_EVENT_LEFT",
|
|
|
KEY_EVENT_RIGHT: "KEY_EVENT_RIGHT",
|
|
|
};
|
|
|
|
|
|
let heroImg,
|
|
|
enemyImg,
|
|
|
laserImg,
|
|
|
canvas, ctx,
|
|
|
gameObjects = [],
|
|
|
hero,
|
|
|
eventEmitter = new EventEmitter();
|
|
|
```
|
|
|
|
|
|
**सेटअप बुझ्दै:**
|
|
|
- **सन्देश Constants परिभाषित गर्छ** टाइपोहरूबाट बच्न र रिफ्याक्टरिङ सजिलो बनाउन
|
|
|
- **छवि, क्यानभास सन्दर्भ, र खेल अवस्था**का लागि भेरिएबलहरू घोषणा गर्छ
|
|
|
- **पब्लिक-सब्सक्राइब प्रणालीको लागि ग्लोबल इभेन्ट इमिटर सिर्जना गर्छ**
|
|
|
- **सबै खेल वस्तुहरू समावेश गर्न एक एरे आरम्भ गर्छ**
|
|
|
|
|
|
4
|
|
|
- **शत्रुहरूको ग्रिड** nested loops प्रयोग गरेर बनाउँछ
|
|
|
- **शत्रुहरूको छवि** प्रत्येक शत्रु वस्तुमा असाइन गर्छ
|
|
|
- **प्रत्येक शत्रु**लाई ग्लोबल खेल वस्तुहरूको array मा थप्छ
|
|
|
|
|
|
र `createHero()` function थप्नुहोस् जसले नायकको लागि यस्तै प्रक्रिया गर्छ।
|
|
|
|
|
|
```javascript
|
|
|
function createHero() {
|
|
|
hero = new Hero(
|
|
|
canvas.width / 2 - 45,
|
|
|
canvas.height - canvas.height / 4
|
|
|
);
|
|
|
hero.img = heroImg;
|
|
|
gameObjects.push(hero);
|
|
|
}
|
|
|
```
|
|
|
|
|
|
**नायक सिर्जना के गर्छ:**
|
|
|
- **नायकलाई** स्क्रिनको तलको केन्द्रमा स्थान दिन्छ
|
|
|
- **नायकको छवि** नायक वस्तुमा असाइन गर्छ
|
|
|
- **नायकलाई** खेल वस्तुहरूको array मा थप्छ ताकि rendering गर्न सकियोस्
|
|
|
|
|
|
अन्तमा, `drawGameObjects()` function थप्नुहोस् ताकि drawing सुरु गर्न सकियोस्:
|
|
|
|
|
|
```javascript
|
|
|
function drawGameObjects(ctx) {
|
|
|
gameObjects.forEach(go => go.draw(ctx));
|
|
|
}
|
|
|
```
|
|
|
|
|
|
**Drawing function बुझ्ने:**
|
|
|
- **Array मा भएका सबै खेल वस्तुहरूमा** iterate गर्छ
|
|
|
- **प्रत्येक वस्तुमा** `draw()` method call गर्छ
|
|
|
- **Canvas context पास गर्छ** ताकि वस्तुहरूले आफूलाई render गर्न सकून्
|
|
|
|
|
|
तपाईंका शत्रुहरूले तपाईंको नायकको spaceship तर्फ अगाडि बढ्न सुरु गर्नुपर्छ!
|
|
|
}
|
|
|
}
|
|
|
```
|
|
|
|
|
|
and add a `createHero()` function to do a similar process for the hero.
|
|
|
|
|
|
```javascript
|
|
|
function createHero() {
|
|
|
hero = new Hero(
|
|
|
canvas.width / 2 - 45,
|
|
|
canvas.height - canvas.height / 4
|
|
|
);
|
|
|
hero.img = heroImg;
|
|
|
gameObjects.push(hero);
|
|
|
}
|
|
|
```
|
|
|
|
|
|
अन्तमा, `drawGameObjects()` function थप्नुहोस् ताकि drawing सुरु गर्न सकियोस्:
|
|
|
|
|
|
```javascript
|
|
|
function drawGameObjects(ctx) {
|
|
|
gameObjects.forEach(go => go.draw(ctx));
|
|
|
}
|
|
|
```
|
|
|
|
|
|
तपाईंका शत्रुहरूले तपाईंको नायकको spaceship तर्फ अगाडि बढ्न सुरु गर्नुपर्छ!
|
|
|
|
|
|
---
|
|
|
|
|
|
## GitHub Copilot Agent Challenge 🚀
|
|
|
|
|
|
यहाँ एउटा चुनौती छ जसले तपाईंको खेललाई अझ राम्रो बनाउँछ: सीमा र smooth controls थप्ने। अहिले, तपाईंको नायक स्क्रिनबाट बाहिर जान सक्छ, र movement अलि असहज लाग्न सक्छ।
|
|
|
|
|
|
**तपाईंको मिशन:** तपाईंको spaceship लाई अझ वास्तविक बनाउनुहोस् स्क्रिन सीमा र fluid movement लागू गरेर। यो NASA को flight control systems जस्तै हो जसले spacecraft लाई सुरक्षित operational parameters भन्दा बाहिर जानबाट रोक्छ।
|
|
|
|
|
|
**के बनाउने:** एउटा प्रणाली बनाउनुहोस् जसले तपाईंको नायकको spaceship लाई स्क्रिनमा राख्छ, र controls लाई smooth बनाउँछ। जब खेलाडीहरूले arrow key थिच्छन्, जहाजले discrete steps मा होइन, निरन्तर glide गर्नुपर्छ। स्क्रिन सीमा पुगेपछि subtle effect जस्तै play area को किनारा देखाउने visual feedback थप्न विचार गर्नुहोस्।
|
|
|
|
|
|
[agent mode](https://code.visualstudio.com/blogs/2025/02/24/introducing-copilot-agent-mode) को बारेमा यहाँ थप जान्नुहोस्।
|
|
|
|
|
|
## 🚀 Challenge
|
|
|
|
|
|
जसरी परियोजना बढ्छ, कोडको संगठन अझ महत्त्वपूर्ण हुन्छ। तपाईंले आफ्नो फाइल functions, variables, र classes सबै मिसिएको देख्नुभएको हुन सक्छ। यो Apollo mission को कोडलाई व्यवस्थित गर्ने इन्जिनियरहरूले स्पष्ट, maintainable प्रणाली बनाउनु परेको जस्तै हो जसमा धेरै टिमहरूले एकसाथ काम गर्न सकून्।
|
|
|
|
|
|
**तपाईंको मिशन:**
|
|
|
Software architect जस्तै सोच्नुहोस्। तपाईं आफ्नो कोडलाई कसरी व्यवस्थित गर्नुहुन्छ ताकि छ महिनापछि तपाईं (वा तपाईंको टिममेट) के भइरहेको छ भनेर बुझ्न सकून्? अहिले सबै कुरा एउटै फाइलमा भए पनि, तपाईं राम्रो संगठन बनाउन सक्नुहुन्छ:
|
|
|
|
|
|
- **सम्बन्धित functions लाई समूह बनाउने** स्पष्ट comment headers सहित
|
|
|
- **Concern अलग गर्ने** - खेलको logic र rendering अलग राख्ने
|
|
|
- **Variables र functions को लागि consistent naming** conventions प्रयोग गर्ने
|
|
|
- **Modules वा namespaces बनाउने** खेलको विभिन्न पक्षहरू व्यवस्थित गर्न
|
|
|
- **Documentation थप्ने** जसले प्रत्येक मुख्य भागको उद्देश्य व्याख्या गर्छ
|
|
|
|
|
|
**Reflection questions:**
|
|
|
- तपाईंको कोडको कुन भागहरू पुन: हेर्दा बुझ्न गाह्रो लाग्छ?
|
|
|
- तपाईंको कोडलाई कसरी व्यवस्थित गर्न सकिन्छ ताकि अरूले योगदान गर्न सजिलो होस्?
|
|
|
- यदि तपाईं power-ups वा विभिन्न शत्रु प्रकारहरू जस्ता नयाँ features थप्न चाहनुहुन्छ भने के हुन्छ?
|
|
|
|
|
|
## Post-Lecture Quiz
|
|
|
|
|
|
[Post-lecture quiz](https://ff-quizzes.netlify.app/web/quiz/34)
|
|
|
|
|
|
## Review & Self Study
|
|
|
|
|
|
हामीले सबै कुरा scratch बाट बनाउँदै आएका छौं, जुन सिक्नको लागि उत्कृष्ट छ, तर यहाँ एउटा सानो रहस्य छ – त्यहाँ केही अद्भुत JavaScript frameworks छन् जसले तपाईंको लागि धेरै काम गर्न सक्छ। हामीले कभर गरेका fundamentals मा सहज महसुस गरेपछि, [के उपलब्ध छ](https://github.com/collections/javascript-game-engines) भनेर अन्वेषण गर्नु लायक छ।
|
|
|
|
|
|
Frameworks लाई सोच्नुहोस् जस्तै राम्रोसँग भरिएको toolbox जसले प्रत्येक उपकरण हातले बनाउनुको सट्टा प्रदान गर्छ। तिनीहरूले ती कोड संगठन चुनौतीहरूको समाधान गर्न सक्छन् जुन हामीले कुरा गरेका थियौं, साथै तपाईंले आफैं बनाउन हप्ताहरू लाग्ने features पनि प्रदान गर्न सक्छन्।
|
|
|
|
|
|
**अन्वेषण गर्न लायक कुराहरू:**
|
|
|
- खेल इन्जिनहरूले कोडलाई कसरी व्यवस्थित गर्छन् – तपाईं clever patterns देखेर चकित हुनुहुनेछ
|
|
|
- Canvas खेलहरूलाई butter-smooth चलाउनका लागि performance tricks
|
|
|
- Modern JavaScript features जसले तपाईंको कोडलाई सफा र maintainable बनाउँछ
|
|
|
- खेल वस्तुहरू र तिनीहरूको सम्बन्ध व्यवस्थापन गर्ने विभिन्न दृष्टिकोणहरू
|
|
|
|
|
|
## Assignment
|
|
|
|
|
|
[Comment your code](assignment.md)
|
|
|
|
|
|
---
|
|
|
|
|
|
**अस्वीकरण**:
|
|
|
यो दस्तावेज़ AI अनुवाद सेवा [Co-op Translator](https://github.com/Azure/co-op-translator) प्रयोग गरेर अनुवाद गरिएको छ। हामी शुद्धताको लागि प्रयास गर्छौं, तर कृपया ध्यान दिनुहोस् कि स्वचालित अनुवादहरूमा त्रुटिहरू वा अशुद्धताहरू हुन सक्छ। यसको मूल भाषा मा रहेको मूल दस्तावेज़लाई आधिकारिक स्रोत मानिनुपर्छ। महत्वपूर्ण जानकारीको लागि, व्यावसायिक मानव अनुवाद सिफारिस गरिन्छ। यस अनुवादको प्रयोगबाट उत्पन्न हुने कुनै पनि गलतफहमी वा गलत व्याख्याको लागि हामी जिम्मेवार हुने छैनौं। |