# خلائی کھیل بنائیں حصہ 3: حرکت شامل کرنا اپنے پسندیدہ کھیلوں کے بارے میں سوچیں – جو انہیں دلچسپ بناتا ہے وہ صرف خوبصورت گرافکس نہیں ہیں، بلکہ یہ ہے کہ سب کچھ کیسے حرکت کرتا ہے اور آپ کے اعمال پر کیسے ردعمل ظاہر کرتا ہے۔ اس وقت، آپ کا خلائی کھیل ایک خوبصورت تصویر کی طرح ہے، لیکن ہم اس میں حرکت شامل کرنے والے ہیں جو اسے زندگی بخشے گی۔ جب ناسا کے انجینئرز نے اپولو مشنز کے لیے گائیڈنس کمپیوٹر پروگرام کیا، تو انہیں ایک جیسا چیلنج درپیش تھا: خلائی جہاز کو پائلٹ کے ان پٹ پر کیسے ردعمل دینا ہے جبکہ خودکار طور پر کورس کی اصلاحات کو برقرار رکھنا ہے؟ آج ہم جو اصول سیکھیں گے وہ انہی تصورات کی عکاسی کرتے ہیں – کھلاڑی کے کنٹرول شدہ حرکت کو خودکار نظام کے رویوں کے ساتھ منظم کرنا۔ اس سبق میں، آپ سیکھیں گے کہ خلائی جہاز کو اسکرین پر کیسے حرکت دی جائے، کھلاڑی کے احکامات پر کیسے ردعمل دیا جائے، اور ہموار حرکت کے نمونے کیسے بنائے جائیں۔ ہم ہر چیز کو قابل انتظام تصورات میں تقسیم کریں گے جو قدرتی طور پر ایک دوسرے پر تعمیر ہوتے ہیں۔ آخر میں، آپ کے کھلاڑی اپنے ہیرو جہاز کو اسکرین پر اڑائیں گے جبکہ دشمن کے جہاز اوپر گشت کریں گے۔ اس سے بھی اہم بات یہ ہے کہ آپ ان بنیادی اصولوں کو سمجھیں گے جو کھیل کی حرکت کے نظام کو طاقت دیتے ہیں۔ ## پری لیکچر کوئز [پری لیکچر کوئز](https://ff-quizzes.netlify.app/web/quiz/33) ## کھیل کی حرکت کو سمجھنا کھیل اس وقت زندہ محسوس ہوتے ہیں جب چیزیں حرکت کرنا شروع کرتی ہیں، اور بنیادی طور پر دو طریقے ہیں جن سے یہ ہوتا ہے: - **کھلاڑی کے کنٹرول شدہ حرکت**: جب آپ کوئی کلید دبائیں یا ماؤس پر کلک کریں، تو کچھ حرکت کرتا ہے۔ یہ آپ اور آپ کی کھیل کی دنیا کے درمیان براہ راست تعلق ہے۔ - **خودکار حرکت**: جب کھیل خود چیزوں کو حرکت دینے کا فیصلہ کرتا ہے – جیسے وہ دشمن کے جہاز جو اسکرین پر گشت کرنے کی ضرورت ہے چاہے آپ کچھ بھی نہ کریں۔ کمپیوٹر اسکرین پر اشیاء کو حرکت دینا آپ کے خیال سے زیادہ آسان ہے۔ یاد ہے وہ x اور y کوآرڈینیٹس جو آپ نے ریاضی کی کلاس میں سیکھے تھے؟ یہی وہ چیز ہے جس کے ساتھ ہم یہاں کام کر رہے ہیں۔ جب گلیلیو نے 1610 میں مشتری کے چاندوں کا مشاہدہ کیا، تو وہ بنیادی طور پر یہی کر رہا تھا – وقت کے ساتھ پوزیشنز کو پلاٹ کر کے حرکت کے نمونوں کو سمجھنا۔ اسکرین پر چیزوں کو حرکت دینا ایک فلیپ بک اینیمیشن بنانے جیسا ہے – آپ کو یہ تین آسان مراحل پر عمل کرنا ہوگا: 1. **پوزیشن کو اپ ڈیٹ کریں** – اپنی چیز کو کہاں ہونا چاہیے اسے تبدیل کریں (شاید اسے 5 پکسلز دائیں طرف لے جائیں) 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) کے بارے میں پڑھیں۔ ## کی بورڈ ایونٹس کو ہینڈل کریں یہ وہ جگہ ہے جہاں ہم کھلاڑی کے ان پٹ کو کھیل کی کارروائی سے جوڑتے ہیں۔ جب کوئی اسپیس بار دبائے تاکہ لیزر فائر کرے یا تیر کی کلید دبائے تاکہ ایسٹروئیڈ سے بچ سکے، آپ کے کھیل کو اس ان پٹ کا پتہ لگانا اور اس پر ردعمل دینا ہوگا۔ کی بورڈ ایونٹس ونڈو لیول پر ہوتے ہیں، یعنی آپ کی پوری براؤزر ونڈو ان کلیدوں کے دبانے کو سن رہی ہوتی ہے۔ دوسری طرف، ماؤس کلکس مخصوص عناصر سے منسلک ہو سکتے ہیں (جیسے کسی بٹن پر کلک کرنا)۔ ہمارے خلائی کھیل کے لیے، ہم کی بورڈ کنٹرولز پر توجہ مرکوز کریں گے کیونکہ یہی کھلاڑیوں کو کلاسک آرکیڈ کا احساس دیتا ہے۔ یہ مجھے یاد دلاتا ہے کہ 1800 کی دہائی میں ٹیلی گراف آپریٹرز کو مورز کوڈ ان پٹ کو معنی خیز پیغامات میں ترجمہ کرنا پڑتا تھا – ہم کچھ ایسا ہی کر رہے ہیں، کلیدوں کے دبانے کو کھیل کے احکامات میں ترجمہ کر رہے ہیں۔ کسی ایونٹ کو ہینڈل کرنے کے لیے آپ کو ونڈو کے `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 const id = setInterval(() => { // Move the enemy on the y axis enemy.y += 10; }, 100); ``` **یہ حرکت کا کوڈ کیا کرتا ہے:** - **ایک ٹimer بناتا ہے** جو ہر 100 ملی سیکنڈز پر چلتا ہے - **دشمن کے y-کوآرڈینیٹ کو ہر بار 10 پکسلز سے اپ ڈیٹ کرتا ہے** - **وقفہ ID کو محفوظ کرتا ہے** تاکہ ہم اسے بعد میں روک سکیں اگر ضرورت ہو - **دشمن کو خود بخود اسکرین پر نیچے کی طرف حرکت دیتا ہے** ## کھیل کا لوپ یہ وہ تصور ہے جو سب کچھ ایک ساتھ جوڑتا ہے – کھیل کا لوپ۔ اگر آپ کا کھیل ایک فلم ہوتا، تو کھیل کا لوپ فلم پروجیکٹر ہوتا، جو فریم کے بعد فریم دکھاتا تاکہ سب کچھ ہموار حرکت کرتا ہوا نظر آئے۔ ہر کھیل کے پیچھے ایک ایسا لوپ چل رہا ہوتا ہے۔ یہ ایک فنکشن ہے جو تمام کھیل کی اشیاء کو اپ ڈیٹ کرتا ہے، اسکرین کو دوبارہ بناتا ہے، اور اس عمل کو مسلسل دہراتا ہے۔ یہ آپ کے ہیرو، تمام دشمنوں، کسی بھی لیزر کے ارد گرد اڑنے – پورے کھیل کی حالت کو ٹریک کرتا ہے۔ یہ تصور مجھے یاد دلاتا ہے کہ ابتدائی فلم کے اینیمیٹرز جیسے والٹ ڈزنی کو کرداروں کو فریم بہ فریم دوبارہ بنانا پڑتا تھا تاکہ حرکت کا وہم پیدا ہو۔ ہم بھی یہی کر رہے ہیں، بس کوڈ کے ساتھ پنسل کے بجائے۔ یہاں ایک کھیل کا لوپ عام طور پر کوڈ میں کیسے نظر آ سکتا ہے: ```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); ``` **کھیل کے لوپ کی ساخت کو سمجھنا:** - **پورے کینوس کو صاف کرتا ہے** تاکہ پچھلا فریم ہٹایا جا سکے - **پس منظر کو ایک ٹھوس رنگ سے بھر دیتا ہے** - **تمام کھیل کی اشیاء کو ان کی موجودہ پوزیشنز میں دوبارہ بناتا ہے** - **اس عمل کو ہر 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://localhost:5000` پر - **آپ کے کھیل کی فائلوں کو پیش کرتی ہے** تاکہ آپ انہیں براؤزر میں ٹیسٹ کر سکیں اوپر دی گئی کمانڈ ایڈریس `http://localhost:5000` پر ایچ ٹی ٹی پی سرور شروع کرے گی۔ براؤزر کھولیں اور اس ایڈریس کو درج کریں، اس وقت یہ ہیرو اور تمام دشمنوں کو ظاہر کرے گا؛ ابھی کچھ حرکت نہیں ہو رہی ہے! ### کوڈ شامل کریں 1. **ہیرو، دشمن، اور کھیل کی اشیاء کے لیے مخصوص آبجیکٹس شامل کریں**، ان میں `x` اور `y` پراپرٹیز ہونی چاہئیں۔ (یاد رکھیں [وراثت یا کمپوزیشن](../README.md) کے حصے پر) *اشارہ* `کھیل کی اشیاء` وہ ہونی چاہیے جس میں `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. **[پب سب پیٹرن](../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. **کانسٹینٹس شامل کریں** اور 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(); ``` **سیٹ اپ کو سمجھنا:** - **پیغام کے کانسٹینٹس کی وضاحت کرتا ہے** تاکہ ٹائپوز سے بچا جا سکے اور ریفیکٹرنگ کو آسان بنایا جا سکے - **تصاویر، کینوس کنٹیکسٹ، اور کھیل کی حالت کے - **بناتا ہے** دشمنوں کی ایک گرڈ nested loops کے ذریعے - **تفویض کرتا ہے** دشمن کی تصویر ہر دشمن object کو - **شامل کرتا ہے** ہر دشمن کو global game objects array میں اور ایک `createHero()` فنکشن شامل کریں جو ہیرو کے لیے اسی طرح کا عمل کرے۔ ```javascript function createHero() { hero = new Hero( canvas.width / 2 - 45, canvas.height - canvas.height / 4 ); hero.img = heroImg; gameObjects.push(hero); } ``` **ہیرو کی تخلیق کیا کرتی ہے:** - **پوزیشن کرتا ہے** ہیرو کو اسکرین کے نیچے مرکز میں - **تفویض کرتا ہے** ہیرو کی تصویر ہیرو object کو - **شامل کرتا ہے** ہیرو کو game objects array میں rendering کے لیے اور آخر میں، ایک `drawGameObjects()` فنکشن شامل کریں تاکہ drawing شروع کی جا سکے: ```javascript function drawGameObjects(ctx) { gameObjects.forEach(go => go.draw(ctx)); } ``` **drawing فنکشن کو سمجھنا:** - **Iterates کرتا ہے** تمام game objects array میں - **Calls کرتا ہے** `draw()` method ہر object پر - **پاس کرتا ہے** canvas context تاکہ objects خود کو 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()` فنکشن شامل کریں تاکہ drawing شروع کی جا سکے: ```javascript function drawGameObjects(ctx) { gameObjects.forEach(go => go.draw(ctx)); } ``` آپ کے دشمن آپ کے ہیرو spaceship پر حملہ شروع کر دیں گے! --- ## GitHub Copilot Agent Challenge 🚀 یہاں ایک چیلنج ہے جو آپ کے گیم کی polish کو بہتر بنائے گا: boundaries اور smooth controls شامل کرنا۔ فی الحال، آپ کا ہیرو اسکرین سے باہر جا سکتا ہے، اور حرکت تھوڑی بے ترتیب محسوس ہو سکتی ہے۔ **آپ کا مشن:** اپنے spaceship کو زیادہ حقیقت پسندانہ بنائیں boundaries اور fluid movement کو نافذ کر کے۔ یہ بالکل ویسا ہی ہے جیسے NASA کے flight control systems spacecraft کو محفوظ operational parameters سے تجاوز کرنے سے روکتے ہیں۔ **یہ بنائیں:** ایک ایسا نظام جو آپ کے ہیرو spaceship کو اسکرین پر رکھے، اور controls کو smooth بنائے۔ جب کھلاڑی arrow key کو دبائے رکھیں، تو ship کو مسلسل glide کرنا چاہیے بجائے discrete steps میں حرکت کرنے کے۔ اسکرین boundaries پر پہنچنے پر visual feedback شامل کرنے پر غور کریں – شاید play area کے edge کو ظاہر کرنے کے لیے ایک subtle effect۔ [agent mode](https://code.visualstudio.com/blogs/2025/02/24/introducing-copilot-agent-mode) کے بارے میں مزید جانیں۔ ## 🚀 Challenge جیسے جیسے پروجیکٹس بڑھتے ہیں، code organization زیادہ اہم ہو جاتی ہے۔ آپ نے محسوس کیا ہوگا کہ آپ کی فائل functions، variables، اور classes کے ساتھ بھری ہوئی ہے۔ یہ بالکل ویسا ہی ہے جیسے Apollo mission کے engineers کو code کو واضح اور قابل انتظام بنانے کے لیے systems بنانا پڑے جن پر مختلف teams ایک ساتھ کام کر سکیں۔ **آپ کا مشن:** ایک software architect کی طرح سوچیں۔ آپ اپنے code کو کیسے organize کریں گے تاکہ چھ مہینے بعد، آپ (یا کوئی teammate) سمجھ سکے کہ کیا ہو رہا ہے؟ چاہے سب کچھ ابھی ایک فائل میں رہے، آپ بہتر organization بنا سکتے ہیں: - **متعلقہ functions کو گروپ کرنا** واضح comment headers کے ساتھ - **Concerns کو الگ کرنا** - game logic کو rendering سے الگ رکھیں - **Consistent naming** conventions کا استعمال variables اور functions کے لیے - **Modules یا namespaces بنانا** تاکہ گیم کے مختلف پہلوؤں کو organize کیا جا سکے - **Documentation شامل کرنا** جو ہر بڑے section کے مقصد کو بیان کرے **Reflection سوالات:** - آپ کے code کے کون سے حصے سب سے زیادہ مشکل ہیں جب آپ ان پر واپس آتے ہیں؟ - آپ اپنے code کو کیسے organize کر سکتے ہیں تاکہ کسی اور کے لیے contribute کرنا آسان ہو؟ - اگر آپ نئے features جیسے power-ups یا مختلف دشمن types شامل کرنا چاہیں تو کیا ہوگا؟ ## Post-Lecture Quiz [Post-lecture quiz](https://ff-quizzes.netlify.app/web/quiz/34) ## Review & Self Study ہم سب کچھ شروع سے بنا رہے ہیں، جو سیکھنے کے لیے شاندار ہے، لیکن یہاں ایک چھوٹا راز ہے – کچھ حیرت انگیز JavaScript frameworks موجود ہیں جو آپ کے لیے بہت سا کام آسان بنا سکتے ہیں۔ جب آپ ان بنیادی اصولوں میں آرام دہ محسوس کریں جو ہم نے cover کیے ہیں، تو یہ [دستیاب چیزوں کو explore کرنے](https://github.com/collections/javascript-game-engines) کے قابل ہے۔ Frameworks کو ایسے سمجھیں جیسے آپ کے پاس ایک اچھی طرح سے stocked toolbox ہو بجائے ہر tool کو خود بنانے کے۔ وہ ان code organization challenges کو حل کر سکتے ہیں جن کے بارے میں ہم نے بات کی، اور ایسے features پیش کر سکتے ہیں جنہیں خود بنانے میں ہفتے لگ جائیں گے۔ **Explore کرنے کے قابل چیزیں:** - گیم engines code کو کیسے organize کرتے ہیں – آپ ان کے clever patterns سے حیران ہوں گے - Performance tricks تاکہ canvas games butter-smooth چلیں - Modern JavaScript features جو آپ کے code کو صاف اور زیادہ maintainable بنا سکتے ہیں - گیم objects اور ان کے تعلقات کو manage کرنے کے مختلف طریقے ## Assignment [Comment your code](assignment.md) --- **اعلانِ لاتعلقی**: یہ دستاویز AI ترجمہ سروس [Co-op Translator](https://github.com/Azure/co-op-translator) کا استعمال کرتے ہوئے ترجمہ کی گئی ہے۔ ہم درستگی کے لیے کوشش کرتے ہیں، لیکن براہ کرم آگاہ رہیں کہ خودکار ترجمے میں غلطیاں یا غیر درستیاں ہو سکتی ہیں۔ اصل دستاویز کو اس کی اصل زبان میں مستند ذریعہ سمجھا جانا چاہیے۔ اہم معلومات کے لیے، پیشہ ور انسانی ترجمہ کی سفارش کی جاتی ہے۔ اس ترجمے کے استعمال سے پیدا ہونے والی کسی بھی غلط فہمی یا غلط تشریح کے لیے ہم ذمہ دار نہیں ہیں۔