15 KiB
ساخت یک بازی فضایی قسمت ۴: اضافه کردن لیزر و تشخیص برخوردها
آزمون پیش از درس
در این درس یاد میگیرید که چگونه با استفاده از جاوااسکریپت لیزر شلیک کنید! ما دو ویژگی به بازی خود اضافه خواهیم کرد:
- لیزر: این لیزر از سفینه قهرمان شما شلیک شده و به صورت عمودی به سمت بالا حرکت میکند.
- تشخیص برخورد: به عنوان بخشی از قابلیت شلیک، قوانین جذابی به بازی اضافه میکنیم:
- برخورد لیزر با دشمن: دشمن در صورت برخورد با لیزر نابود میشود.
- برخورد لیزر با بالای صفحه: لیزر در صورت برخورد با بالای صفحه نابود میشود.
- برخورد دشمن و قهرمان: دشمن و قهرمان در صورت برخورد با یکدیگر نابود میشوند.
- برخورد دشمن با پایین صفحه: دشمن و قهرمان در صورت رسیدن دشمن به پایین صفحه نابود میشوند.
به طور خلاصه، شما -- قهرمان -- باید تمام دشمنان را با لیزر نابود کنید قبل از اینکه به پایین صفحه برسند.
✅ کمی تحقیق کنید درباره اولین بازی کامپیوتری که تاکنون نوشته شده است. عملکرد آن چگونه بود؟
بیایید با هم قهرمان باشیم!
تشخیص برخورد
چگونه میتوانیم برخوردها را تشخیص دهیم؟ باید اشیاء بازی خود را به عنوان مستطیلهایی که حرکت میکنند در نظر بگیریم. چرا؟ چون تصویری که برای نمایش یک شیء بازی استفاده میشود یک مستطیل است: این تصویر دارای x
، y
، عرض
و ارتفاع
است.
اگر دو مستطیل، یعنی قهرمان و دشمن، همپوشانی داشته باشند، برخورد رخ داده است. اینکه چه اتفاقی باید بیفتد به قوانین بازی بستگی دارد. برای پیادهسازی تشخیص برخورد، به موارد زیر نیاز دارید:
-
روشی برای دریافت نمای مستطیلی از یک شیء بازی، چیزی شبیه به این:
rectFromGameObject() { return { top: this.y, left: this.x, bottom: this.y + this.height, right: this.x + this.width } }
-
یک تابع مقایسه، این تابع میتواند به این شکل باشد:
function intersectRect(r1, r2) { return !(r2.left > r1.right || r2.right < r1.left || r2.top > r1.bottom || r2.bottom < r1.top); }
چگونه اشیاء را نابود کنیم
برای نابود کردن اشیاء در بازی، باید به بازی اطلاع دهید که دیگر نباید این آیتم را در حلقه بازی که در یک بازه زمانی مشخص اجرا میشود، نمایش دهد. یک روش برای این کار این است که یک شیء بازی را در صورت وقوع یک اتفاق به عنوان مرده علامتگذاری کنید، به این صورت:
// collision happened
enemy.dead = true
سپس میتوانید اشیاء مرده را قبل از بازپخش صفحه مرتب کنید، به این صورت:
gameObjects = gameObject.filter(go => !go.dead);
چگونه لیزر شلیک کنیم
شلیک لیزر به معنای پاسخ به یک رویداد کلید و ایجاد یک شیء است که در یک جهت خاص حرکت میکند. بنابراین باید مراحل زیر را انجام دهید:
- ایجاد یک شیء لیزر: از بالای سفینه قهرمان شما، که پس از ایجاد شروع به حرکت به سمت بالای صفحه میکند.
- اتصال کد به یک رویداد کلید: باید یک کلید روی صفحهکلید انتخاب کنیم که نمایانگر شلیک لیزر توسط بازیکن باشد.
- ایجاد یک شیء بازی که شبیه لیزر باشد وقتی کلید فشار داده میشود.
زمانبندی شلیک لیزر
لیزر باید هر بار که کلید فشار داده میشود، مانند space، شلیک شود. برای جلوگیری از تولید تعداد زیادی لیزر در مدت زمان کوتاه، باید این مشکل را حل کنیم. راهحل این مشکل پیادهسازی چیزی به نام زمانبندی است، یک تایمر که اطمینان حاصل میکند لیزر فقط در بازههای زمانی مشخصی شلیک شود. میتوانید این کار را به این صورت انجام دهید:
class Cooldown {
constructor(time) {
this.cool = false;
setTimeout(() => {
this.cool = true;
}, time)
}
}
class Weapon {
constructor {
}
fire() {
if (!this.cooldown || this.cooldown.cool) {
// produce a laser
this.cooldown = new Cooldown(500);
} else {
// do nothing - it hasn't cooled down yet.
}
}
}
✅ به درس ۱ در سری بازی فضایی مراجعه کنید تا درباره زمانبندی یادآوری کنید.
چه چیزی بسازیم
شما باید کد موجود (که باید آن را پاکسازی و بازسازی کرده باشید) از درس قبلی را گسترش دهید. یا با کد قسمت دوم شروع کنید یا از کد قسمت سوم - شروعکننده استفاده کنید.
نکته: لیزری که با آن کار خواهید کرد، قبلاً در پوشه داراییهای شما قرار دارد و توسط کد شما ارجاع داده شده است.
- تشخیص برخورد اضافه کنید، وقتی لیزر با چیزی برخورد میکند، قوانین زیر باید اعمال شوند:
- برخورد لیزر با دشمن: دشمن در صورت برخورد با لیزر نابود میشود.
- برخورد لیزر با بالای صفحه: لیزر در صورت برخورد با بالای صفحه نابود میشود.
- برخورد دشمن و قهرمان: دشمن و قهرمان در صورت برخورد با یکدیگر نابود میشوند.
- برخورد دشمن با پایین صفحه: دشمن و قهرمان در صورت رسیدن دشمن به پایین صفحه نابود میشوند.
مراحل پیشنهادی
فایلهایی که برای شما ایجاد شدهاند را در پوشه your-work
پیدا کنید. این پوشه باید شامل موارد زیر باشد:
-| assets
-| enemyShip.png
-| player.png
-| laserRed.png
-| index.html
-| app.js
-| package.json
پروژه خود را در پوشه your_work
با تایپ کردن دستور زیر شروع کنید:
cd your-work
npm start
دستور بالا یک سرور HTTP را در آدرس http://localhost:5000
راهاندازی میکند. یک مرورگر باز کنید و این آدرس را وارد کنید، در حال حاضر باید قهرمان و تمام دشمنان را نمایش دهد، اما هنوز هیچ چیزی حرکت نمیکند :).
اضافه کردن کد
-
ایجاد نمای مستطیلی برای شیء بازی برای مدیریت برخورد کد زیر به شما اجازه میدهد نمای مستطیلی از یک
GameObject
دریافت کنید. کلاس GameObject خود را ویرایش کنید تا آن را گسترش دهید:rectFromGameObject() { return { top: this.y, left: this.x, bottom: this.y + this.height, right: this.x + this.width, }; }
-
اضافه کردن کدی که برخورد را بررسی کند این یک تابع جدید خواهد بود که بررسی میکند آیا دو مستطیل همپوشانی دارند یا خیر:
function intersectRect(r1, r2) { return !( r2.left > r1.right || r2.right < r1.left || r2.top > r1.bottom || r2.bottom < r1.top ); }
-
اضافه کردن قابلیت شلیک لیزر
-
اضافه کردن پیام رویداد کلید. کلید space باید یک لیزر درست بالای سفینه قهرمان ایجاد کند. سه ثابت در شیء Messages اضافه کنید:
KEY_EVENT_SPACE: "KEY_EVENT_SPACE", COLLISION_ENEMY_LASER: "COLLISION_ENEMY_LASER", COLLISION_ENEMY_HERO: "COLLISION_ENEMY_HERO",
-
مدیریت کلید space. تابع
window.addEventListener
مربوط به رویداد keyup را ویرایش کنید تا کلید space را مدیریت کند:} else if(evt.keyCode === 32) { eventEmitter.emit(Messages.KEY_EVENT_SPACE); }
-
اضافه کردن شنوندهها. تابع
initGame()
را ویرایش کنید تا اطمینان حاصل شود که قهرمان میتواند هنگام فشار دادن کلید space شلیک کند:eventEmitter.on(Messages.KEY_EVENT_SPACE, () => { if (hero.canFire()) { hero.fire(); }
و یک تابع جدید
eventEmitter.on()
اضافه کنید تا رفتار هنگام برخورد دشمن با لیزر را مدیریت کند:eventEmitter.on(Messages.COLLISION_ENEMY_LASER, (_, { first, second }) => { first.dead = true; second.dead = true; })
-
حرکت دادن شیء، اطمینان حاصل کنید که لیزر به تدریج به بالای صفحه حرکت میکند. یک کلاس جدید Laser ایجاد کنید که از
GameObject
گسترش مییابد، همانطور که قبلاً انجام دادهاید:class Laser extends GameObject { constructor(x, y) { super(x,y); (this.width = 9), (this.height = 33); this.type = 'Laser'; this.img = laserImg; let id = setInterval(() => { if (this.y > 0) { this.y -= 15; } else { this.dead = true; clearInterval(id); } }, 100) } }
-
مدیریت برخوردها، قوانین برخورد برای لیزر را پیادهسازی کنید. یک تابع
updateGameObjects()
اضافه کنید که اشیاء برخوردی را برای ضربهها بررسی کند:function updateGameObjects() { const enemies = gameObjects.filter(go => go.type === 'Enemy'); const lasers = gameObjects.filter((go) => go.type === "Laser"); // laser hit something lasers.forEach((l) => { enemies.forEach((m) => { if (intersectRect(l.rectFromGameObject(), m.rectFromGameObject())) { eventEmitter.emit(Messages.COLLISION_ENEMY_LASER, { first: l, second: m, }); } }); }); gameObjects = gameObjects.filter(go => !go.dead); }
مطمئن شوید که
updateGameObjects()
را در حلقه بازی خود درwindow.onload
اضافه کنید. -
پیادهسازی زمانبندی برای لیزر، به طوری که فقط در بازههای زمانی مشخصی شلیک شود.
در نهایت، کلاس Hero را ویرایش کنید تا بتواند زمانبندی داشته باشد:
class Hero extends GameObject { constructor(x, y) { super(x, y); (this.width = 99), (this.height = 75); this.type = "Hero"; this.speed = { x: 0, y: 0 }; this.cooldown = 0; } fire() { gameObjects.push(new Laser(this.x + 45, this.y - 10)); this.cooldown = 500; let id = setInterval(() => { if (this.cooldown > 0) { this.cooldown -= 100; } else { clearInterval(id); } }, 200); } canFire() { return this.cooldown === 0; } }
-
در این مرحله، بازی شما دارای برخی قابلیتها است! میتوانید با کلیدهای جهتدار حرکت کنید، با کلید space لیزر شلیک کنید، و دشمنان هنگام برخورد با لیزر ناپدید میشوند. آفرین!
🚀 چالش
یک انفجار اضافه کنید! به داراییهای بازی در مخزن هنر فضایی نگاهی بیندازید و سعی کنید هنگام برخورد لیزر با یک بیگانه، یک انفجار اضافه کنید.
آزمون پس از درس
مرور و مطالعه شخصی
با بازههای زمانی در بازی خود تا اینجا آزمایش کنید. وقتی آنها را تغییر میدهید چه اتفاقی میافتد؟ درباره رویدادهای زمانبندی جاوااسکریپت بیشتر بخوانید.
تکلیف
سلب مسئولیت:
این سند با استفاده از سرویس ترجمه هوش مصنوعی Co-op Translator ترجمه شده است. در حالی که ما تلاش میکنیم دقت را حفظ کنیم، لطفاً توجه داشته باشید که ترجمههای خودکار ممکن است شامل خطاها یا نادرستیها باشند. سند اصلی به زبان اصلی آن باید به عنوان منبع معتبر در نظر گرفته شود. برای اطلاعات حیاتی، ترجمه حرفهای انسانی توصیه میشود. ما مسئولیتی در قبال سوء تفاهمها یا تفسیرهای نادرست ناشی از استفاده از این ترجمه نداریم.