|
|
<!--
|
|
|
CO_OP_TRANSLATOR_METADATA:
|
|
|
{
|
|
|
"original_hash": "a6ce295ff03bb49df7a3e17e6e7100a0",
|
|
|
"translation_date": "2025-08-28T22:58:56+00:00",
|
|
|
"source_file": "6-space-game/4-collision-detection/README.md",
|
|
|
"language_code": "bn"
|
|
|
}
|
|
|
-->
|
|
|
# স্পেস গেম তৈরি করুন পার্ট ৪: লেজার যোগ করা এবং সংঘর্ষ সনাক্তকরণ
|
|
|
|
|
|
## প্রি-লেকচার কুইজ
|
|
|
|
|
|
[প্রি-লেকচার কুইজ](https://ff-quizzes.netlify.app/web/quiz/35)
|
|
|
|
|
|
এই পাঠে আপনি শিখবেন কীভাবে জাভাস্ক্রিপ্ট ব্যবহার করে লেজার ছোঁড়া যায়! আমরা আমাদের গেমে দুটি জিনিস যোগ করব:
|
|
|
|
|
|
- **একটি লেজার**: এই লেজারটি আপনার হিরোর জাহাজ থেকে ঊর্ধ্বমুখী ছোঁড়া হবে।
|
|
|
- **সংঘর্ষ সনাক্তকরণ**, *লেজার ছোঁড়ার* ক্ষমতা বাস্তবায়নের অংশ হিসেবে আমরা কিছু সুন্দর গেমের নিয়ম যোগ করব:
|
|
|
- **লেজার শত্রুকে আঘাত করে**: শত্রু লেজারের আঘাতে মারা যায়।
|
|
|
- **লেজার স্ক্রিনের শীর্ষে আঘাত করে**: স্ক্রিনের শীর্ষে আঘাত করলে লেজার ধ্বংস হয়ে যায়।
|
|
|
- **শত্রু এবং হিরোর সংঘর্ষ**: শত্রু এবং হিরো একে অপরকে আঘাত করলে উভয়ই ধ্বংস হয়ে যায়।
|
|
|
- **শত্রু স্ক্রিনের নিচে আঘাত করে**: শত্রু স্ক্রিনের নিচে পৌঁছালে শত্রু এবং হিরো উভয়ই ধ্বংস হয়ে যায়।
|
|
|
|
|
|
সংক্ষেপে, আপনি -- *হিরো* -- স্ক্রিনের নিচে পৌঁছানোর আগে লেজার দিয়ে সব শত্রুকে আঘাত করতে হবে।
|
|
|
|
|
|
✅ প্রথম কম্পিউটার গেমটি সম্পর্কে একটু গবেষণা করুন। এর কার্যকারিতা কী ছিল?
|
|
|
|
|
|
চলুন একসাথে বীরত্ব দেখাই!
|
|
|
|
|
|
## সংঘর্ষ সনাক্তকরণ
|
|
|
|
|
|
সংঘর্ষ সনাক্তকরণ কীভাবে করা যায়? আমাদের গেমের অবজেক্টগুলোকে চলমান আয়তক্ষেত্র হিসেবে ভাবতে হবে। কেন? কারণ গেম অবজেক্ট আঁকার জন্য ব্যবহৃত ইমেজটি একটি আয়তক্ষেত্র: এর `x`, `y`, `width` এবং `height` থাকে।
|
|
|
|
|
|
যদি দুটি আয়তক্ষেত্র, যেমন হিরো এবং শত্রু *অবস্থানগতভাবে একে অপরকে ছেদ করে*, তাহলে সংঘর্ষ ঘটে। এরপর কী ঘটবে তা গেমের নিয়মের উপর নির্ভর করে। সংঘর্ষ সনাক্তকরণ বাস্তবায়নের জন্য আপনাকে নিম্নলিখিত জিনিসগুলো করতে হবে:
|
|
|
|
|
|
1. গেম অবজেক্টের একটি আয়তক্ষেত্রের প্রতিনিধিত্ব পাওয়ার উপায়, যেমন:
|
|
|
|
|
|
```javascript
|
|
|
rectFromGameObject() {
|
|
|
return {
|
|
|
top: this.y,
|
|
|
left: this.x,
|
|
|
bottom: this.y + this.height,
|
|
|
right: this.x + this.width
|
|
|
}
|
|
|
}
|
|
|
```
|
|
|
|
|
|
2. একটি তুলনা ফাংশন, যা দেখতে এমন হতে পারে:
|
|
|
|
|
|
```javascript
|
|
|
function intersectRect(r1, r2) {
|
|
|
return !(r2.left > r1.right ||
|
|
|
r2.right < r1.left ||
|
|
|
r2.top > r1.bottom ||
|
|
|
r2.bottom < r1.top);
|
|
|
}
|
|
|
```
|
|
|
|
|
|
## জিনিস ধ্বংস করার উপায়
|
|
|
|
|
|
গেমে জিনিস ধ্বংস করতে হলে গেমকে জানাতে হবে যে এটি আর গেম লুপে আঁকা উচিত নয়, যা একটি নির্দিষ্ট ইন্টারভালে ট্রিগার হয়। এর একটি উপায় হলো, কোনো ঘটনা ঘটলে গেম অবজেক্টকে *মৃত* হিসেবে চিহ্নিত করা:
|
|
|
|
|
|
```javascript
|
|
|
// collision happened
|
|
|
enemy.dead = true
|
|
|
```
|
|
|
|
|
|
এরপর আপনি *মৃত* অবজেক্টগুলোকে স্ক্রিন পুনরায় আঁকার আগে সরিয়ে ফেলতে পারেন, যেমন:
|
|
|
|
|
|
```javascript
|
|
|
gameObjects = gameObject.filter(go => !go.dead);
|
|
|
```
|
|
|
|
|
|
## কীভাবে লেজার ছোঁড়া যায়
|
|
|
|
|
|
লেজার ছোঁড়া মানে হলো একটি কী-ইভেন্টে সাড়া দেওয়া এবং একটি অবজেক্ট তৈরি করা যা একটি নির্দিষ্ট দিকে চলে। এজন্য আমাদের নিম্নলিখিত ধাপগুলো সম্পন্ন করতে হবে:
|
|
|
|
|
|
1. **একটি লেজার অবজেক্ট তৈরি করুন**: হিরোর জাহাজের শীর্ষ থেকে, যা তৈরি হওয়ার সাথে সাথে স্ক্রিনের শীর্ষের দিকে ঊর্ধ্বমুখী চলতে শুরু করে।
|
|
|
2. **কী-ইভেন্টে কোড সংযুক্ত করুন**: কীবোর্ডে একটি কী নির্বাচন করতে হবে যা প্লেয়ার লেজার ছোঁড়ার প্রতিনিধিত্ব করে।
|
|
|
3. **একটি গেম অবজেক্ট তৈরি করুন যা দেখতে লেজারের মতো** যখন কী চাপা হয়।
|
|
|
|
|
|
## লেজারের কুলডাউন
|
|
|
|
|
|
লেজারটি প্রতিবার কী চাপলে ছোঁড়া উচিত, যেমন *স্পেস* কী। গেমটি খুব অল্প সময়ে অনেক বেশি লেজার তৈরি করা থেকে রোধ করতে আমাদের এটি ঠিক করতে হবে। এই সমস্যার সমাধান হলো একটি *কুলডাউন*, একটি টাইমার, বাস্তবায়ন করা যা নিশ্চিত করে যে একটি লেজার নির্দিষ্ট সময়ের মধ্যে শুধুমাত্র একবার ছোঁড়া যাবে। এটি নিম্নলিখিতভাবে বাস্তবায়ন করা যায়:
|
|
|
|
|
|
```javascript
|
|
|
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.
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
```
|
|
|
|
|
|
✅ স্পেস গেম সিরিজের প্রথম পাঠে ফিরে যান এবং *কুলডাউন* সম্পর্কে মনে করিয়ে নিন।
|
|
|
|
|
|
## কী তৈরি করতে হবে
|
|
|
|
|
|
আপনার আগের পাঠ থেকে বিদ্যমান কোড (যা আপনি পরিষ্কার এবং পুনর্গঠন করেছেন) নিয়ে এটি সম্প্রসারিত করবেন। পার্ট II থেকে কোড শুরু করুন অথবা [পার্ট III- স্টার্টার](../../../../../../../../../your-work) থেকে কোড ব্যবহার করুন।
|
|
|
|
|
|
> টিপ: আপনি যে লেজার নিয়ে কাজ করবেন তা ইতোমধ্যেই আপনার অ্যাসেট ফোল্ডারে রয়েছে এবং আপনার কোডে রেফারেন্স করা হয়েছে।
|
|
|
|
|
|
- **সংঘর্ষ সনাক্তকরণ যোগ করুন**, যখন একটি লেজার কোনো কিছুর সাথে সংঘর্ষ করে তখন নিম্নলিখিত নিয়মগুলো প্রযোজ্য হবে:
|
|
|
1. **লেজার শত্রুকে আঘাত করে**: শত্রু লেজারের আঘাতে মারা যায়।
|
|
|
2. **লেজার স্ক্রিনের শীর্ষে আঘাত করে**: স্ক্রিনের শীর্ষে আঘাত করলে লেজার ধ্বংস হয়ে যায়।
|
|
|
3. **শত্রু এবং হিরোর সংঘর্ষ**: শত্রু এবং হিরো একে অপরকে আঘাত করলে উভয়ই ধ্বংস হয়ে যায়।
|
|
|
4. **শত্রু স্ক্রিনের নিচে আঘাত করে**: শত্রু স্ক্রিনের নিচে পৌঁছালে শত্রু এবং হিরো উভয়ই ধ্বংস হয়ে যায়।
|
|
|
|
|
|
## সুপারিশকৃত ধাপ
|
|
|
|
|
|
`your-work` সাব ফোল্ডারে তৈরি করা ফাইলগুলো খুঁজে বের করুন। এটি নিম্নলিখিত বিষয়গুলো ধারণ করবে:
|
|
|
|
|
|
```bash
|
|
|
-| assets
|
|
|
-| enemyShip.png
|
|
|
-| player.png
|
|
|
-| laserRed.png
|
|
|
-| index.html
|
|
|
-| app.js
|
|
|
-| package.json
|
|
|
```
|
|
|
|
|
|
আপনার প্রজেক্ট শুরু করুন `your_work` ফোল্ডার থেকে টাইপ করে:
|
|
|
|
|
|
```bash
|
|
|
cd your-work
|
|
|
npm start
|
|
|
```
|
|
|
|
|
|
উপরেরটি একটি HTTP সার্ভার চালু করবে ঠিকানায় `http://localhost:5000`। একটি ব্রাউজার খুলুন এবং সেই ঠিকানাটি ইনপুট করুন, এখন এটি হিরো এবং সব শত্রু দেখাবে, কিছুই এখনও চলমান নয় :).
|
|
|
|
|
|
### কোড যোগ করুন
|
|
|
|
|
|
1. **আপনার গেম অবজেক্টের একটি আয়তক্ষেত্রের প্রতিনিধিত্ব সেটআপ করুন, সংঘর্ষ পরিচালনা করতে** নিচের কোডটি আপনাকে একটি `GameObject` এর আয়তক্ষেত্রের প্রতিনিধিত্ব পেতে সাহায্য করবে। আপনার GameObject ক্লাসটি সম্পাদনা করুন:
|
|
|
|
|
|
```javascript
|
|
|
rectFromGameObject() {
|
|
|
return {
|
|
|
top: this.y,
|
|
|
left: this.x,
|
|
|
bottom: this.y + this.height,
|
|
|
right: this.x + this.width,
|
|
|
};
|
|
|
}
|
|
|
```
|
|
|
|
|
|
2. **সংঘর্ষ পরীক্ষা করার কোড যোগ করুন** এটি একটি নতুন ফাংশন হবে যা পরীক্ষা করবে দুটি আয়তক্ষেত্র একে অপরকে ছেদ করছে কিনা:
|
|
|
|
|
|
```javascript
|
|
|
function intersectRect(r1, r2) {
|
|
|
return !(
|
|
|
r2.left > r1.right ||
|
|
|
r2.right < r1.left ||
|
|
|
r2.top > r1.bottom ||
|
|
|
r2.bottom < r1.top
|
|
|
);
|
|
|
}
|
|
|
```
|
|
|
|
|
|
3. **লেজার ছোঁড়ার ক্ষমতা যোগ করুন**
|
|
|
1. **কী-ইভেন্ট বার্তা যোগ করুন**। *স্পেস* কীটি হিরো জাহাজের ঠিক উপরে একটি লেজার তৈরি করবে। Messages অবজেক্টে তিনটি কনস্ট্যান্ট যোগ করুন:
|
|
|
|
|
|
```javascript
|
|
|
KEY_EVENT_SPACE: "KEY_EVENT_SPACE",
|
|
|
COLLISION_ENEMY_LASER: "COLLISION_ENEMY_LASER",
|
|
|
COLLISION_ENEMY_HERO: "COLLISION_ENEMY_HERO",
|
|
|
```
|
|
|
|
|
|
1. **স্পেস কী পরিচালনা করুন**। `window.addEventListener` এর keyup ফাংশনটি সম্পাদনা করুন স্পেস পরিচালনা করতে:
|
|
|
|
|
|
```javascript
|
|
|
} else if(evt.keyCode === 32) {
|
|
|
eventEmitter.emit(Messages.KEY_EVENT_SPACE);
|
|
|
}
|
|
|
```
|
|
|
|
|
|
1. **লিসেনার যোগ করুন**। `initGame()` ফাংশনটি সম্পাদনা করুন নিশ্চিত করতে যে স্পেস বার চাপলে হিরো লেজার ছোঁড়তে পারে:
|
|
|
|
|
|
```javascript
|
|
|
eventEmitter.on(Messages.KEY_EVENT_SPACE, () => {
|
|
|
if (hero.canFire()) {
|
|
|
hero.fire();
|
|
|
}
|
|
|
```
|
|
|
|
|
|
এবং একটি নতুন `eventEmitter.on()` ফাংশন যোগ করুন নিশ্চিত করতে যে শত্রু লেজারের সাথে সংঘর্ষ করলে কী ঘটবে:
|
|
|
|
|
|
```javascript
|
|
|
eventEmitter.on(Messages.COLLISION_ENEMY_LASER, (_, { first, second }) => {
|
|
|
first.dead = true;
|
|
|
second.dead = true;
|
|
|
})
|
|
|
```
|
|
|
|
|
|
1. **অবজেক্ট সরানো**, নিশ্চিত করুন যে লেজার ধীরে ধীরে স্ক্রিনের শীর্ষে চলে যায়। আপনি একটি নতুন Laser ক্লাস তৈরি করবেন যা `GameObject` কে প্রসারিত করবে, যেমন আপনি আগে করেছেন:
|
|
|
|
|
|
```javascript
|
|
|
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)
|
|
|
}
|
|
|
}
|
|
|
```
|
|
|
|
|
|
1. **সংঘর্ষ পরিচালনা করুন**, লেজারের জন্য সংঘর্ষের নিয়ম বাস্তবায়ন করুন। একটি `updateGameObjects()` ফাংশন যোগ করুন যা সংঘর্ষের জন্য অবজেক্টগুলো পরীক্ষা করে:
|
|
|
|
|
|
```javascript
|
|
|
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` এ যোগ করা হয়েছে।
|
|
|
|
|
|
4. **লেজারের কুলডাউন বাস্তবায়ন করুন**, যাতে এটি নির্দিষ্ট সময়ের মধ্যে শুধুমাত্র একবার ছোঁড়া যায়।
|
|
|
|
|
|
অবশেষে, Hero ক্লাসটি সম্পাদনা করুন যাতে এটি কুলডাউন করতে পারে:
|
|
|
|
|
|
```javascript
|
|
|
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;
|
|
|
}
|
|
|
}
|
|
|
```
|
|
|
|
|
|
এই পর্যায়ে, আপনার গেমে কিছু কার্যকারিতা রয়েছে! আপনি আপনার অ্যারো কী দিয়ে নেভিগেট করতে পারেন, স্পেস বার দিয়ে লেজার ছোঁড়তে পারেন, এবং শত্রুরা লেজারের আঘাতে অদৃশ্য হয়ে যায়। খুব ভালো কাজ করেছেন!
|
|
|
|
|
|
---
|
|
|
|
|
|
## 🚀 চ্যালেঞ্জ
|
|
|
|
|
|
একটি বিস্ফোরণ যোগ করুন! [স্পেস আর্ট রিপো](../../../../6-space-game/solution/spaceArt/readme.txt) এর গেম অ্যাসেটগুলো দেখুন এবং চেষ্টা করুন লেজার এলিয়েনকে আঘাত করলে একটি বিস্ফোরণ যোগ করতে।
|
|
|
|
|
|
## পোস্ট-লেকচার কুইজ
|
|
|
|
|
|
[পোস্ট-লেকচার কুইজ](https://ff-quizzes.netlify.app/web/quiz/36)
|
|
|
|
|
|
## পর্যালোচনা ও স্ব-অধ্যয়ন
|
|
|
|
|
|
আপনার গেমে এখন পর্যন্ত ব্যবহৃত ইন্টারভালগুলো নিয়ে পরীক্ষা করুন। আপনি এগুলো পরিবর্তন করলে কী ঘটে? [জাভাস্ক্রিপ্ট টাইমিং ইভেন্ট](https://www.freecodecamp.org/news/javascript-timing-events-settimeout-and-setinterval/) সম্পর্কে আরও পড়ুন।
|
|
|
|
|
|
## অ্যাসাইনমেন্ট
|
|
|
|
|
|
[সংঘর্ষ অন্বেষণ করুন](assignment.md)
|
|
|
|
|
|
---
|
|
|
|
|
|
**অস্বীকৃতি**:
|
|
|
এই নথিটি AI অনুবাদ পরিষেবা [Co-op Translator](https://github.com/Azure/co-op-translator) ব্যবহার করে অনুবাদ করা হয়েছে। আমরা যথাসম্ভব সঠিক অনুবাদ প্রদানের চেষ্টা করি, তবে অনুগ্রহ করে মনে রাখবেন যে স্বয়ংক্রিয় অনুবাদে ত্রুটি বা অসঙ্গতি থাকতে পারে। মূল ভাষায় থাকা নথিটিকে প্রামাণিক উৎস হিসেবে বিবেচনা করা উচিত। গুরুত্বপূর্ণ তথ্যের জন্য, পেশাদার মানব অনুবাদ সুপারিশ করা হয়। এই অনুবাদ ব্যবহারের ফলে কোনো ভুল বোঝাবুঝি বা ভুল ব্যাখ্যা হলে আমরা দায়বদ্ধ থাকব না। |