|
|
<!--
|
|
|
CO_OP_TRANSLATOR_METADATA:
|
|
|
{
|
|
|
"original_hash": "2e83e38c35dc003f046d7cc0bbfd4920",
|
|
|
"translation_date": "2025-08-25T22:22:41+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://localhost:5000` ঠিকানায় একটি HTTP সার্ভার চালু করবে। একটি ব্রাউজার খুলুন এবং এই ঠিকানাটি প্রবেশ করান, এখন এটি হিরো এবং সব শত্রু দেখাবে, যদিও কিছুই এখনও চলবে না :).
|
|
|
|
|
|
### কোড যোগ করুন
|
|
|
|
|
|
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;
|
|
|
}
|
|
|
}
|
|
|
```
|
|
|
|
|
|
এখন আপনার গেমে কিছু কার্যকারিতা রয়েছে! আপনি আপনার অ্যারো কী দিয়ে নেভিগেট করতে পারবেন, স্পেস বার দিয়ে লেজার ছুড়তে পারবেন, এবং শত্রুরা লেজারের আঘাতে অদৃশ্য হয়ে যাবে। দারুণ কাজ!
|
|
|
|
|
|
---
|
|
|
|
|
|
## 🚀 চ্যালেঞ্জ
|
|
|
|
|
|
একটি বিস্ফোরণ যোগ করুন! [Space Art রিপোজিটরি](../../../../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) ব্যবহার করে অনুবাদ করা হয়েছে। আমরা যথাসম্ভব সঠিকতার জন্য চেষ্টা করি, তবে অনুগ্রহ করে মনে রাখবেন যে স্বয়ংক্রিয় অনুবাদে ত্রুটি বা অসঙ্গতি থাকতে পারে। এর মূল ভাষায় থাকা নথিটিকে প্রামাণিক উৎস হিসেবে বিবেচনা করা উচিত। গুরুত্বপূর্ণ তথ্যের জন্য, পেশাদার মানব অনুবাদ সুপারিশ করা হয়। এই অনুবাদ ব্যবহারের ফলে কোনো ভুল বোঝাবুঝি বা ভুল ব্যাখ্যা হলে আমরা দায়বদ্ধ থাকব না। |