# အာကာသဂိမ်း တည်ဆောက်ခြင်း အပိုင်း ၄: လေဆာထည့်သွင်းခြင်းနှင့် တိုက်မိမှုများကို စစ်ဆေးခြင်း ## မိန့်ခွန်းမတိုင်မီ စစ်တမ်း [မိန့်ခွန်းမတိုင်မီ စစ်တမ်း](https://ff-quizzes.netlify.app/web/quiz/35) ဒီသင်ခန်းစာမှာ JavaScript ကို အသုံးပြုပြီး လေဆာပစ်ပေါက်နည်းကို သင်ယူပါမည်။ ဂိမ်းမှာ အောက်ပါအရာ ၂ ခုကို ထည့်သွင်းပါမည်- - **လေဆာ**: ဒီလေဆာကို သင်၏သူရဲကောင်းရဲ့ သင်္ဘောမှ အပေါ်ဘက်သို့ ပစ်ပေါက်ပါမည်။ - **တိုက်မိမှု စစ်ဆေးခြင်း**: *ပစ်ပေါက်ခြင်း* စနစ်ကို အကောင်အထည်ဖော်ရာတွင် ဂိမ်းစည်းကမ်းများကို ထည့်သွင်းပါမည်။ - **လေဆာသည် ရန်သူကို ထိမိခြင်း**: ရန်သူသည် လေဆာထိမိပါက သေဆုံးမည်။ - **လေဆာသည် မျက်နှာပြင်အပေါ်ဘက်ကို ထိမိခြင်း**: လေဆာသည် မျက်နှာပြင်အပေါ်ဘက်ကို ထိမိပါက ဖျက်သိမ်းမည်။ - **ရန်သူနှင့် သူရဲကောင်း တိုက်မိခြင်း**: ရန်သူနှင့် သူရဲကောင်း တိုက်မိပါက နှစ်ဦးလုံး ဖျက်သိမ်းမည်။ - **ရန်သူသည် မျက်နှာပြင်အောက်ဘက်ကို ထိမိခြင်း**: ရန်သူသည် မျက်နှာပြင်အောက်ဘက်ကို ထိမိပါက ရန်သူနှင့် သူရဲကောင်း ဖျက်သိမ်းမည်။ အတိုချုံး来说၊ သင် -- *သူရဲကောင်း* -- သည် ရန်သူများကို မျက်နှာပြင်အောက်ဘက်သို့ ရောက်မီ လေဆာဖြင့် ထိမိစေရန် လိုအပ်ပါသည်။ ✅ ကွန်ပျူတာဂိမ်းပထမဆုံးရေးသားခဲ့သော ဂိမ်းအကြောင်းကို သုတေသနလုပ်ပါ။ ၎င်း၏ လုပ်ဆောင်ချက်များက ဘာတွေလဲ? အတူတူ သူရဲကောင်းဖြစ်ကြစို့! ## တိုက်မိမှု စစ်ဆေးခြင်း တိုက်မိမှုကို ဘယ်လိုလုပ်မလဲ? ဂိမ်းအရာဝတ္ထုများကို ရှုထောင့်များအဖြစ် သတ်မှတ်ပြီး ရွေ့လျားနေသည်ဟု စဉ်းစားရမည်။ ဘာကြောင့်လဲဆိုတော့ ဂိမ်းအရာဝတ္ထုကို ရေးဆွဲရန် အသုံးပြုသော ပုံရိပ်သည် ရှုထောင့်ပုံစံဖြစ်သည်။ ၎င်းတွင် `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); ``` ## လေဆာကို ဘယ်လိုပစ်မလဲ လေဆာပစ်ခြင်းသည် key-event ကို တုံ့ပြန်ခြင်းနှင့် အပေါ်ဘက်သို့ ရွေ့လျားသော အရာဝတ္ထုတစ်ခုကို ဖန်တီးခြင်းဖြစ်သည်။ ထို့ကြောင့် အောက်ပါအဆင့်များကို လုပ်ဆောင်ရမည်- 1. **လေဆာအရာဝတ္ထုတစ်ခု ဖန်တီးပါ**: သူရဲကောင်းရဲ့ သင်္ဘောအပေါ်ဘက်မှ ဖန်တီးပြီး မျက်နှာပြင်အပေါ်ဘက်သို့ ရွေ့လျားစတင်ပါမည်။ 2. **Key event ကို code ဖြင့် ချိတ်ဆက်ပါ**: ကီးဘုတ်ပေါ်ရှိ key တစ်ခုကို ရွေးချယ်ပြီး လေဆာပစ်ခြင်းကို ကိုယ်စားပြုရမည်။ 3. **လေဆာပုံစံရှိသော ဂိမ်းအရာဝတ္ထုတစ်ခု ဖန်တီးပါ**: key ကို နှိပ်သောအခါ။ ## လေဆာပစ်ခြင်းအတွက် Cooldown လေဆာသည် သင် key ကို နှိပ်တိုင်း ပစ်ရမည်။ ဥပမာ *space* key ကို အသုံးပြုပါ။ ဂိမ်းသည် အလွန်တိုတောင်းသောအချိန်အတွင်း လေဆာများ အလွန်များစွာ ဖန်တီးခြင်းကို ကာကွယ်ရန် လိုအပ်သည်။ ၎င်းကို *cooldown* ဟုခေါ်သော timer ကို အသုံးပြုခြင်းဖြင့် ပြုလုပ်နိုင်သည်။ ၎င်းကို အောက်ပါနည်းဖြင့် အကောင်အထည်ဖော်နိုင်သည်- ```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. } } } ``` ✅ *Cooldowns* အကြောင်းကို သင်၏ အာကာသဂိမ်း စီးရီး၏ ပထမဆုံးသင်ခန်းစာမှ ပြန်လည်သတိရပါ။ ## ဘာကို တည်ဆောက်မလဲ သင်သည် ယခင်သင်ခန်းစာမှ ရှိပြီးသား code ကို (သင်သည် သန့်စင်ပြီး ပြန်လည်ဖွဲ့စည်းထားသင့်သည်) ယူပြီး တိုးချဲ့ပါမည်။ အပိုင်း II မှ code ကို စတင်အသုံးပြုပါ၊ သို့မဟုတ် [အပိုင်း III- starter](../../../../../../../../../your-work) တွင် code ကို အသုံးပြုပါ။ > tip: သင်လုပ်ဆောင်ရမည့် လေဆာသည် assets folder တွင် ရှိပြီး သင်၏ code မှ ရည်ညွှန်းထားပြီးဖြစ်သည်။ - **တိုက်မိမှု စစ်ဆေးမှုကို ထည့်သွင်းပါ**၊ လေဆာသည် အရာဝတ္ထုတစ်ခုနှင့် တိုက်မိသောအခါ အောက်ပါစည်းကမ်းများကို လိုက်နာရမည်- 1. **လေဆာသည် ရန်သူကို ထိမိခြင်း**: ရန်သူသည် လေဆာထိမိပါက သေဆုံးမည်။ 2. **လေဆာသည် မျက်နှာပြင်အပေါ်ဘက်ကို ထိမိခြင်း**: လေဆာသည် မျက်နှာပြင်အပေါ်ဘက်ကို ထိမိပါက ဖျက်သိမ်းမည်။ 3. **ရန်သူနှင့် သူရဲကောင်း တိုက်မိခြင်း**: ရန်သူနှင့် သူရဲကောင်း တိုက်မိပါက နှစ်ဦးလုံး ဖျက်သိမ်းမည်။ 4. **ရန်သူသည် မျက်နှာပြင်အောက်ဘက်ကို ထိမိခြင်း**: ရန်သူသည် မျက်နှာပြင်အောက်ဘက်ကို ထိမိပါက ရန်သူနှင့် သူရဲကောင်း ဖျက်သိမ်းမည်။ ## အကြံပြုထားသော အဆင့်များ `your-work` sub folder တွင် ဖန်တီးထားသော ဖိုင်များကို ရှာပါ။ ၎င်းတွင် အောက်ပါအရာများ ပါဝင်သင့်သည်- ```bash -| assets -| enemyShip.png -| player.png -| laserRed.png -| index.html -| app.js -| package.json ``` သင်၏ project ကို `your_work` folder မှ စတင်ရန် အောက်ပါ command ကို ရိုက်ပါ- ```bash cd your-work npm start ``` အထက်ပါ command သည် HTTP Server ကို `http://localhost:5000` လိပ်စာတွင် စတင်ပါမည်။ Browser ကို ဖွင့်ပြီး ထိုလိပ်စာကို ထည့်သွင်းပါ။ ယခုအချိန်တွင် သူရဲကောင်းနှင့် ရန်သူများကို ဖော်ပြထားပြီး မည်သည့်အရာမျှ မရွေ့လျားသေးပါ။ ### Code ထည့်သွင်းပါ 1. **ဂိမ်းအရာဝတ္ထု၏ ရှုထောင့်ကို ကိုယ်စားပြုရန် code ကို စတင်ပါ** အောက်ပါ code သည် `GameObject` ၏ ရှုထောင့်ကို ကိုယ်စားပြုနိုင်သည်။ သင်၏ GameObject class ကို ပြင်ဆင်ပါ- ```javascript rectFromGameObject() { return { top: this.y, left: this.x, bottom: this.y + this.height, right: this.x + this.width, }; } ``` 2. **တိုက်မိမှု စစ်ဆေးမှု code ကို ထည့်သွင်းပါ** ရှုထောင့် ၂ ခု တိုက်မိမိမိစစ်ဆေးသော လုပ်ဆောင်ချက်အသစ်တစ်ခုကို ဖန်တီးပါ- ```javascript function intersectRect(r1, r2) { return !( r2.left > r1.right || r2.right < r1.left || r2.top > r1.bottom || r2.bottom < r1.top ); } ``` 3. **လေဆာပစ်ခြင်းစွမ်းရည်ကို ထည့်သွင်းပါ** 1. **Key-event message ကို ထည့်သွင်းပါ** *space* key သည် သူရဲကောင်းရဲ့ သင်္ဘောအပေါ်တွင် လေဆာတစ်ခု ဖန်တီးရမည်။ Messages object တွင် constants ၃ ခုကို ထည့်သွင်းပါ- ```javascript KEY_EVENT_SPACE: "KEY_EVENT_SPACE", COLLISION_ENEMY_LASER: "COLLISION_ENEMY_LASER", COLLISION_ENEMY_HERO: "COLLISION_ENEMY_HERO", ``` 1. **Space key ကို ကိုင်တွယ်ပါ** `window.addEventListener` keyup function ကို ပြင်ဆင်ပြီး space key ကို ကိုင်တွယ်ပါ- ```javascript } else if(evt.keyCode === 32) { eventEmitter.emit(Messages.KEY_EVENT_SPACE); } ``` 1. **Listeners ကို ထည့်သွင်းပါ** `initGame()` function ကို ပြင်ဆင်ပြီး space bar ကို နှိပ်သောအခါ သူရဲကောင်းသည် လေဆာပစ်နိုင်ရန် သေချာပါစေ- ```javascript eventEmitter.on(Messages.KEY_EVENT_SPACE, () => { if (hero.canFire()) { hero.fire(); } ``` နှင့် ရန်သူသည် လေဆာနှင့် တိုက်မိသောအခါ လိုက်နာရမည့် အပြုအမူကို သေချာစေရန် `eventEmitter.on()` function အသစ်တစ်ခုကို ထည့်သွင်းပါ- ```javascript eventEmitter.on(Messages.COLLISION_ENEMY_LASER, (_, { first, second }) => { first.dead = true; second.dead = true; }) ``` 1. **Object ကို ရွေ့လျားပါ** လေဆာသည် မျက်နှာပြင်အပေါ်ဘက်သို့ တဖြည်းဖြည်း ရွေ့လျားရမည်။ သင်သည် `GameObject` ကို extend လုပ်ထားသည့်အတိုင်း Laser class အသစ်တစ်ခုကို ဖန်တီးပါ- ```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. **တိုက်မိမှုကို ကိုင်တွယ်ပါ** လေဆာအတွက် တိုက်မိမှုစည်းကမ်းများကို အကောင်အထည်ဖော်ပါ။ တိုက်မိသော objects များကို စစ်ဆေးသော `updateGameObjects()` function ကို ထည့်သွင်းပါ- ```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); } ``` `window.onload` တွင် သင်၏ game loop ထဲသို့ `updateGameObjects()` ကို ထည့်သွင်းပါ။ 4. **လေဆာအတွက် cooldown ကို အကောင်အထည်ဖော်ပါ** လေဆာသည် အလွန်တိုတောင်းသောအချိန်အတွင်း ပစ်မရနိုင်ရန် သေချာစေရန်။ နောက်ဆုံးတွင် Hero class ကို ပြင်ဆင်ပြီး cooldown လုပ်နိုင်စေရန်- ```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; } } ``` ယခုအချိန်တွင် သင်၏ဂိမ်းတွင် functionality ရှိပါပြီ! Arrow keys ဖြင့် navigation ပြုလုပ်နိုင်ပြီး space bar ဖြင့် လေဆာပစ်နိုင်သည်။ ရန်သူများသည် လေဆာထိမိသောအခါ ပျောက်ကွယ်သွားသည်။ ကောင်းမွန်ပါတယ်! --- ## 🚀 စိန်ခေါ်မှု ပေါက်ကွဲမှုကို ထည့်သွင်းပါ! [Space Art repo](../../../../6-space-game/solution/spaceArt/readme.txt) တွင် ရှိသော game assets ကို ကြည့်ပြီး ရန်သူကို လေဆာထိသောအခါ ပေါက်ကွဲမှုကို ထည့်သွင်းရန် ကြိုးစားပါ။ ## မိန့်ခွန်းပြီးနောက် စစ်တမ်း [မိန့်ခွန်းပြီးနောက် စစ်တမ်း](https://ff-quizzes.netlify.app/web/quiz/36) ## ပြန်လည်သုံးသပ်ခြင်းနှင့် ကိုယ်တိုင်လေ့လာခြင်း သင်၏ဂိမ်းတွင် interval များကို စမ်းသပ်ပါ။ ၎င်းကို ပြောင်းလဲသောအခါ ဘာဖြစ်မလဲ? [JavaScript timing events](https://www.freecodecamp.org/news/javascript-timing-events-settimeout-and-setinterval/) အကြောင်းပိုမိုဖတ်ရှုပါ။ ## လုပ်ငန်းတာဝန် [တိုက်မိမှုများကို စူးစမ်းပါ](assignment.md) --- **အကြောင်းကြားချက်**: ဤစာရွက်စာတမ်းကို AI ဘာသာပြန်ဝန်ဆောင်မှု [Co-op Translator](https://github.com/Azure/co-op-translator) ကို အသုံးပြု၍ ဘာသာပြန်ထားပါသည်။ ကျွန်ုပ်တို့သည် တိကျမှုအတွက် ကြိုးစားနေပါသော်လည်း၊ အလိုအလျောက် ဘာသာပြန်မှုများတွင် အမှားများ သို့မဟုတ် မတိကျမှုများ ပါဝင်နိုင်သည်ကို သတိပြုပါ။ မူရင်းဘာသာစကားဖြင့် ရေးသားထားသော စာရွက်စာတမ်းကို အာဏာရှိသော ရင်းမြစ်အဖြစ် သတ်မှတ်သင့်ပါသည်။ အရေးကြီးသော အချက်အလက်များအတွက် လူ့ဘာသာပြန်ပညာရှင်များမှ ပရော်ဖက်ရှင်နယ် ဘာသာပြန်မှုကို အကြံပြုပါသည်။ ဤဘာသာပြန်မှုကို အသုံးပြုခြင်းမှ ဖြစ်ပေါ်လာသော အလွဲအလွတ်များ သို့မဟုတ် အနားလွဲမှုများအတွက် ကျွန်ုပ်တို့သည် တာဝန်မယူပါ။