Merge branch 'main' into loc-query-strings-fix

This commit is contained in:
RP1458
2021-02-15 14:27:08 +01:00
committed by GitHub
126 changed files with 6818 additions and 235 deletions

View File

@@ -217,7 +217,7 @@ Think about how the pub-sub pattern can enhance a game. Which parts should emit
## Review & Self Study
Learn more about Pub/Sub by [reading about it](https://docs.microsoft.com/en-us/azure/architecture/patterns/publisher-subscriber?WT.mc_id=academic-4621-cxa).
Learn more about Pub/Sub by [reading about it](https://docs.microsoft.com/en-us/azure/architecture/patterns/publisher-subscriber?WT.mc_id=academic-13441-cxa).
## Assignment

View File

@@ -211,6 +211,6 @@ A medida que las cosas se complican cuando tu juego crece, este patrón permanec
## Revisión y autoestudio
Obtenga más información sobre Pub / Sub al [leer sobre él](https://docs.microsoft.com/en-us/azure/architecture/patterns/publisher-subscriber?WT.mc_id=academic-4621-cxa).
Obtenga más información sobre Pub / Sub al [leer sobre él](https://docs.microsoft.com/en-us/azure/architecture/patterns/publisher-subscriber?WT.mc_id=academic-13441-cxa).
**Tarea**: [Mock up a game](assignment.es.md)

View File

@@ -211,11 +211,11 @@ eventEmitter.on(Messages.HERO_MOVE_LEFT, () => {
## लेक्चर बाद की क्विज
[लेक्चर बाद की क्विज](https://nice-beach-0fe9e9d0f.azurestaticapps.net/quiz/30?loc=30)
[लेक्चर बाद की क्विज](https://nice-beach-0fe9e9d0f.azurestaticapps.net/quiz/30?loc=hi)
## समीक्षा और स्व अध्ययन
pub/sub[के बारे में पढ़े](https://docs.microsoft.com/en-us/azure/altecture/patterns/publisher-subscriber?WT.mc_id=academic-4621-cxa) और अधिक जानें .
pub/sub[के बारे में पढ़े](https://docs.microsoft.com/en-us/azure/altecture/patterns/publisher-subscriber?WT.mc_id=academic-13441-cxa) और अधिक जानें .
## असाइनमेंट

View File

@@ -29,7 +29,7 @@
クラスに特定の振る舞いを追加するために `クラス``継承` と組み合わせて使うという考え方です。
✅ 継承は理解しておくべき重要な概念です。[継承に関する MdN の記事](https://developer.mozilla.org/ja/docs/Web/JavaScript/Inheritance_and_the_prototype_chain)で詳しく解説しています。
✅ 継承は理解しておくべき重要な概念です。[継承に関する MDN の記事](https://developer.mozilla.org/ja/docs/Web/JavaScript/Inheritance_and_the_prototype_chain)で詳しく解説しています。
コードで表現すると、ゲームオブジェクトは通常このようになります。
@@ -136,7 +136,7 @@ const tree = createStatic(0,0, 'Tree');
ゲーム開発に共通するもう一つのパターンは、ゲームのユーザーエクスペリエンスとパフォーマンスを処理する問題を扱っています。
## Pub/sub パターン
## Pub/Sub パターン
✅ Pub/Sub は 'publish-subscribe' の略です。
@@ -217,7 +217,7 @@ pub-sub パターンがどのようにゲームを盛り上げるかを考えて
## 復習と自己学習
Pub/Sub については、[こちらを読んでみてください](https://docs.microsoft.com/ja-jp/azure/architecture/patterns/publisher-subscriber?WT.mc_id=academic-4621-cxa)。
Pub/Sub については、[こちらを読んでみてください](https://docs.microsoft.com/ja-jp/azure/architecture/patterns/publisher-subscriber?WT.mc_id=academic-13441-cxa)。
## 課題

View File

@@ -217,7 +217,7 @@ pub-sub 패턴이 어떻게 게임을 발전시킬 수 있는지 생각해보세
## 리뷰 & 자기주도 학습
[reading about it](https://docs.microsoft.com/en-us/azure/architecture/patterns/publisher-subscriber?WT.mc_id=academic-4621-cxa)으로 Pub/Sub에 대해 조금 더 배워봅시다.
[reading about it](https://docs.microsoft.com/en-us/azure/architecture/patterns/publisher-subscriber?WT.mc_id=academic-13441-cxa)으로 Pub/Sub에 대해 조금 더 배워봅시다.
## 과제

View File

@@ -0,0 +1,224 @@
# Membina Permainan Angkasa Bahagian 1: Pengenalan
![video](../../images/pewpew.gif)
## Kuiz Pra Kuliah
[Kuiz Pra Kuliah](https://nice-beach-0fe9e9d0f.azurestaticapps.net/quiz/29)
### Warisan dan Komposisi dalam pembangunan permainan
Dalam pelajaran sebelumnya, tidak banyak yang perlu dikhawatirkan mengenai reka bentuk reka bentuk aplikasi yang anda buat, kerana skop projeknya sangat kecil. Namun, apabila aplikasi anda bertambah besar dan luas, keputusan seni bina menjadi perhatian yang lebih besar. Terdapat dua pendekatan utama untuk membuat aplikasi yang lebih besar dalam JavaScript: *komposisi* atau *pewarisan*. Terdapat kebaikan dan keburukan untuk kedua-duanya tetapi mari kita jelaskan dari dalam konteks permainan.
✅ Salah satu buku pengaturcaraan paling terkenal yang pernah ditulis ada kaitannya dengan [corak reka bentuk](https://en.wikipedia.org/wiki/Design_Patterns).
Dalam permainan, anda mempunyai `objek permainan` yang merupakan objek yang ada di layar. Ini bermakna mereka mempunyai lokasi pada sistem koordinat kartesian, yang dicirikan oleh mempunyai koordinat `x` dan `y`. Semasa anda mengembangkan permainan, anda akan melihat bahawa semua objek permainan anda mempunyai harta benda yang biasa, biasa untuk setiap permainan yang anda buat, iaitu elemen yang:
- **berdasarkan lokasi** Sebilangan besar, jika tidak semua, elemen permainan berdasarkan lokasi. Ini bermaksud bahawa mereka mempunyai lokasi, `x` dan` y`.
- **bergerak** Ini adalah objek yang boleh berpindah ke lokasi baru. Ini biasanya pahlawan, raksasa atau NPC (watak bukan pemain), tetapi tidak misalnya, objek statik seperti pokok.
- **merosakkan diri** Objek-objek ini hanya wujud untuk jangka masa yang ditetapkan sebelum mereka disiapkan untuk dihapus. Biasanya ini diwakili oleh boolean `mati` atau `dimusnahkan` yang memberi isyarat kepada mesin permainan bahawa objek ini tidak lagi boleh diberikan.
- **cool-down** 'Cool-down' adalah sifat khas di antara objek yang berumur pendek. Contoh biasa ialah sekeping teks atau kesan grafik seperti letupan yang hanya dapat dilihat selama beberapa milisaat.
✅ Fikirkan permainan seperti Pac-Man. Bolehkah anda mengenal pasti empat jenis objek yang disenaraikan di atas dalam permainan ini?
### Menyatakan tingkah laku
Yang kami terangkan di atas adalah tingkah laku yang boleh dimiliki oleh objek permainan. Jadi bagaimana kita mengekodkannya? Kita boleh menyatakan tingkah laku ini sebagai kaedah yang berkaitan dengan kelas atau objek.
**Kelas**
Ideanya adalah untuk menggunakan `kelas` bersama dengan `pewarisan` untuk menyelesaikan penambahan tingkah laku tertentu ke kelas.
✅ Warisan adalah konsep penting untuk difahami. Ketahui lebih lanjut mengenai [artikel MDN mengenai pewarisan](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Inheritance_and_the_prototype_chain).
Diekspresikan melalui kod, objek permainan biasanya dapat terlihat seperti ini:
```javascript
//menubuhkan kelas GameObject
class GameObject {
constructor(x, y, type) {
this.x = x;
this.y = y;
this.type = type;
}
}
//kelas ini akan memperluaskan sifat kelas yang ada pada GameObject
class Movable extends GameObject {
constructor(x,y, type) {
super(x,y, type)
}
//objek bergerak ini dapat dipindahkan di skrin
moveTo(x, y) {
this.x = x;
this.y = y;
}
}
//ini adalah kelas khusus yang meluaskan kelas Bergerak, sehingga dapat memanfaatkan semua sifat yang diwarisi
class Hero extends Movable {
constructor(x,y) {
super(x,y, 'Hero')
}
}
//kelas ini, sebaliknya, hanya mewarisi sifat GameObject
class Tree extends GameObject {
constructor(x,y) {
super(x,y, 'Tree')
}
}
//hero dapat bergerak...
const hero = new Hero();
hero.moveTo(5,5);
//tetapi pokok tidak boleh
const tree = new Tree();
```
✅ Luangkan masa beberapa minit untuk membayangkan semula pahlawan Pac-Man (misalnya Inky, Pinky atau Blinky) dan bagaimana ia ditulis dalam JavaScript.
**Komposisi**
Cara yang berbeza untuk menangani pewarisan objek adalah dengan menggunakan *Komposisi*. Kemudian, objek menyatakan tingkah laku mereka seperti ini:
```javascript
//buat pemalar untuk gameObject
const gameObject = {
x: 0,
y: 0,
type: ''
};
//...dan satu constant untuk bergerak
const movable = {
moveTo(x, y) {
this.x = x;
this.y = y;
}
}
//buat pemalar movableObject terdiri daripada pemalar gameObject dan bergerak
const movableObject = {...gameObject, ...movable};
//kemudian buat fungsi untuk membuat Hero baru yang mewarisi sifat movableObject
function createHero(x, y) {
return {
...movableObject,
x,
y,
type: 'Hero'
}
}
//...dan objek statik yang hanya mewarisi sifat gameObject
function createStatic(x, y, type) {
return {
...gameObject
x,
y,
type
}
}
//buat hero dan gerakkannya
const hero = createHero(10,10);
hero.moveTo(5,5);
//dan buat pokok statik yang hanya berdiri
const tree = createStatic(0,0, 'Tree');
```
**Corak mana yang harus saya gunakan?**
Terpulang kepada anda corak yang anda pilih. JavaScript menyokong kedua-dua paradigma ini.
--
Pola lain yang biasa dalam pengembangan permainan menangani masalah menangani pengalaman dan prestasi pengguna permainan.
## Corak pub / sub
✅ Pub / Sub bermaksud 'publish-subscribe'
Corak ini mengemukakan idea bahawa bahagian aplikasi anda yang berbeza tidak boleh saling mengenali. Kenapa begitu? Ini menjadikannya lebih mudah untuk melihat apa yang berlaku secara umum jika pelbagai bahagian dipisahkan. Ini juga menjadikannya lebih mudah untuk mengubah tingkah laku secara tiba-tiba jika anda perlu Bagaimana kita mencapainya? Kami melakukan ini dengan mewujudkan beberapa konsep:
- **mesej**: Mesej biasanya merupakan rentetan teks yang disertai dengan muatan pilihan (sekeping data yang menjelaskan tentang mesej itu) Mesej biasa dalam permainan boleh menjadi `KEY_PRESSED_ENTER`.
- **publish**: Elemen ini *menerbitkan* mesej dan mengirimkannya kepada semua pelanggan.
- **subscriber**: Elemen ini *mendengar* mesej tertentu dan menjalankan beberapa tugas sebagai hasil daripada menerima mesej ini, seperti menembakkan laser.
Pelaksanaannya cukup kecil tetapi coraknya sangat kuat. Inilah cara ia dapat dilaksanakan:
```javascript
//sediakan kelas EventEmitter yang mengandungi pendengar
class EventEmitter {
constructor() {
this.listeners = {};
}
//apabila mesej diterima, biarkan pendengar menangani muatannya
on(message, listener) {
if (!this.listeners[message]) {
this.listeners[message] = [];
}
this.listeners[message].push(listener);
}
//semasa mesej dihantar, hantarkannya kepada pendengar dengan muatan
emit(message, payload = null) {
if (this.listeners[message]) {
this.listeners[message].forEach(l => l(message, payload))
}
}
}
```
Untuk menggunakan kod di atas, kita dapat membuat implementasi yang sangat kecil:
```javascript
//sediakan struktur mesej
const Messages = {
HERO_MOVE_LEFT: 'HERO_MOVE_LEFT'
};
//memanggil eventEmitter yang anda tetapkan di atas
const eventEmitter = new EventEmitter();
//sediakan hero
const hero = createHero(0,0);
//biarkan eventEmitter tahu untuk menonton mesej yang berkaitan dengan pahlawan yang bergerak ke kiri, dan bertindak di atasnya
eventEmitter.on(Messages.HERO_MOVE_LEFT, () => {
hero.move(5,0);
});
//sediakan tetingkap untuk mendengarkan acara keyup, khususnya jika anak panah kiri dipukul, mengirimkan pesan untuk menggerakkan pahlawan ke kiri
window.addEventListener('keyup', (evt) => {
if (evt.key === 'ArrowLeft') {
eventEmitter.emit(Messages.HERO_MOVE_LEFT)
}
});
```
Di atas kami menyambungkan acara papan kekunci, `ArrowLeft` dan menghantar mesej `HERO_MOVE_LEFT`. Kami mendengar mesej itu dan memindahkan `hero` sebagai hasilnya. Kekuatan dengan corak ini ialah pendengar acara dan wira tidak saling mengenali antara satu sama lain. Anda boleh memetakan semula `ArrowLeft` ke kekunci `A`. Selain itu mungkin untuk melakukan sesuatu yang sama sekali berbeza pada `ArrowLeft` dengan membuat beberapa pengeditan pada fungsi `on` eventEmitter:
```javascript
eventEmitter.on(Messages.HERO_MOVE_LEFT, () => {
hero.move(5,0);
});
```
Oleh kerana keadaan menjadi lebih rumit semasa permainan anda berkembang, corak ini tetap sama dalam kerumitan dan kod anda tetap bersih. Sangat digalakkan untuk menggunakan corak ini.
---
## 🚀 Cabaran
Fikirkan bagaimana corak pub-sub dapat meningkatkan permainan. Bahagian mana yang harus memancarkan acara, dan bagaimana reaksi permainan terhadapnya? Inilah peluang anda untuk menjadi kreatif, memikirkan permainan baru dan bagaimana bahagiannya berkelakuan.
## Kuiz Pasca Kuliah
[Kuiz Pasca Kuliah](https://nice-beach-0fe9e9d0f.azurestaticapps.net/quiz/30)
## Mengkaji & Belajar Sendiri
Ketahui lebih lanjut mengenai Pub/Sub dengan [membaca mengenainya](https://docs.microsoft.com/en-us/azure/architecture/patterns/publisher-subscriber).
## Tugasan
[Mockup permainan](assignment.ms.md)

View File

@@ -0,0 +1,12 @@
# Mock up permainan
## Arahan
Dengan menggunakan contoh kod dalam pelajaran, tulis representasi permainan yang anda nikmati. Ini mestilah permainan yang sederhana, tetapi tujuannya adalah menggunakan kelas atau corak komposisi dan corak pub / sub untuk menunjukkan bagaimana permainan dapat dilancarkan. Dapatkan kreatif!
## Rubrik
| Kriteria |
Contoh | Mencukupi | Usaha Lagi |
| -------- | ------------------------------------------------------- | ----------------------------------------------------- | --------------------------------------------------- |
| | Tiga elemen diletakkan di skrin dan dimanipulasi | Dua elemen diletakkan di skrin dan dimanipulasi | Satu elemen diletakkan di skrin dan dimanipulasi |

View File

@@ -0,0 +1,216 @@
# Bina Permainan Angkasa Bahagian 2: Menarik Wira dan Monster ke Kanvas
## Kuiz Pra Kuliah
[Kuiz Pra Kuliah](https://nice-beach-0fe9e9d0f.azurestaticapps.net/quiz/31)
## Kanvas
Kanvas adalah elemen HTML yang secara lalai tidak mempunyai isi; itu batu tulis kosong. Anda perlu menambahkannya dengan melukisnya.
✅ Baca [lebih lanjut mengenai Canvas API](https://developer.mozilla.org/en-US/docs/Web/API/Canvas_API) di MDN.
Inilah cara ia dinyatakan secara umum, sebagai bahagian badan halaman:
```html
<canvas id="myCanvas" width="200" height="100"></canvas>
```
Di atas kita menetapkan `id`, `lebar` dan `tinggi`.
- `id`: tetapkan ini supaya anda dapat memperoleh rujukan apabila anda perlu berinteraksi dengannya.
- `lebar`: ini adalah lebar elemen.
- `tinggi`: ini adalah ketinggian elemen.
## Melukis geometri ringkas
Canvas menggunakan sistem koordinat kartesian untuk menarik sesuatu. Oleh itu ia menggunakan paksi-x dan paksi-y untuk menyatakan di mana sesuatu berada. Lokasi `0,0` adalah kedudukan kiri atas dan kanan bawah adalah yang anda katakan sebagai Luas dan TINGGI kanvas.
![grid kanvas](../canvas_grid.png)
> Imej dari [MDN](https://developer.mozilla.org/en-US/docs/Web/API/Canvas_API/Tutorial/Drawing_shapes)
Untuk menggunakan elemen kanvas, anda perlu melalui langkah-langkah berikut:
1. **Dapatkan rujukan** ke elemen Kanvas.
1. **Dapatkan rujukan** pada elemen Konteks yang terletak di elemen kanvas.
1. **Lakukan operasi menggambar** menggunakan elemen konteks.
Kod untuk langkah di atas biasanya kelihatan seperti:
```javascript
// melukis sebuah segi empat tepat berwarna merah
// 1. dapatkan rujukan kanvas
canvas = document.getElementById("myCanvas");
//2. tetapkan konteks ke 2D untuk melukis bentuk asas
ctx = canvas.getContext("2d");
//3. isi dengan warna merah
ctx.fillStyle = 'red';
//4. dan lukis sebuah segi empat tepat dengan parameter ini, tetapkan lokasi dan ukuran
ctx.fillRect(0,0, 200, 200) // x,y,luas,tinggi
```
✅ Canvas API kebanyakannya memfokuskan pada bentuk 2D, tetapi anda juga dapat menarik elemen 3D ke laman web; untuk ini, anda mungkin menggunakan [WebGL API](https://developer.mozilla.org/en-US/docs/Web/API/WebGL_API).
Anda boleh menarik pelbagai perkara dengan Canvas API seperti:
- **Bentuk geometri**, kami sudah menunjukkan cara melukis segi empat tepat, tetapi masih banyak lagi yang dapat anda lukis.
- **Teks**, anda boleh menggambar teks dengan fon dan warna yang anda inginkan.
- **Imej**, anda boleh melukis gambar berdasarkan aset gambar seperti .jpg atau .png misalnya.
✅ Cubalah! Anda tahu melukis segi empat, bolehkah anda melukis bulatan ke halaman? Lihatlah beberapa lukisan Kanvas yang menarik di CodePen. Berikut adalah [contoh yang sangat mengagumkan](https://codepen.io/dissimulate/pen/KrAwx).
## Muat dan lukiskan aset gambar
Anda memuat aset gambar dengan membuat objek `Imej` dan menetapkan sifat `src`nya. Kemudian anda mendengar acara `load` untuk mengetahui kapan ia siap digunakan. Kodnya seperti ini:
### Muatkan aset
```javascript
const img = new Image();
img.src = 'path/to/my/image.png';
img.onload = () => {
// gambar dimuat dan siap digunakan
}
```
### Muatkan corak aset
Sebaiknya bungkus perkara di atas dengan konstruk seperti itu, jadi lebih mudah digunakan dan anda hanya mencuba memanipulasinya apabila dimuat sepenuhnya:
```javascript
function loadAsset(path) {
return new Promise((resolve) => {
const img = new Image();
img.src = path;
img.onload = () => {
// gambar dimuat dan siap digunakan
resolve(img);
}
})
}
// use like so
async function run() {
const heroImg = await loadAsset('hero.png')
const monsterImg = await loadAsset('monster.png')
}
```
Untuk menarik aset permainan ke skrin, kod anda akan kelihatan seperti ini:
```javascript
async function run() {
const heroImg = await loadAsset('hero.png')
const monsterImg = await loadAsset('monster.png')
canvas = document.getElementById("myCanvas");
ctx = canvas.getContext("2d");
ctx.drawImage(heroImg, canvas.width/2,canvas.height/2);
ctx.drawImage(monsterImg, 0,0);
}
```
## Kini tiba masanya untuk mula membina permainan anda
### Apa yang hendak dibina
Anda akan membina laman web dengan elemen Canvas. Ia harus menjadikan skrin hitam `1024*768` . Kami telah memberi anda dua gambar:
- Kapal wira
![Kapal wira](../solution/assets/player.png)
- 5 * 5 raksasa
![Monster ship](solution/assets/enemyShip.png)
### Langkah-langkah yang disarankan untuk memulakan pembangunan
Cari fail yang telah dibuat untuk anda dalam sub folder `your-work`. Ia harus mengandungi yang berikut:
```bash
-| assets
-| enemyShip.png
-| player.png
-| index.html
-| app.js
-| package.json
```
Buka salinan folder ini dalam Visual Studio Code. Anda perlu membuat persediaan persekitaran pembangunan tempatan, lebih baik dengan Visual Studio Code dengan NPM dan Node dipasang. Sekiranya anda tidak memasang `npm` di komputer anda, [berikut cara melakukannya](https://www.npmjs.com/get-npm).
Mulakan projek anda dengan menavigasi ke folder `your_work`:
```bash
cd your-work
npm start
```
Perkara di atas akan memulakan Pelayan HTTP pada alamat `http: // localhost: 5000`. Buka penyemak imbas dan masukkan alamat itu. Ini adalah halaman kosong sekarang, tetapi itu akan berubah
> Catatan: untuk melihat perubahan pada layar anda, muat semula penyemak imbas anda.
### Tambah Kod
Tambahkan kod yang diperlukan ke `your-work / app.js` untuk menyelesaikan perkara di bawah
1. ** Lukiskan kanvas dengan latar belakang hitam
> tip: tambahkan dua baris di bawah TODO yang sesuai di `/ app.js`, tetapkan elemen` ctx` menjadi hitam dan koordinat atas / kiri berada pada 0,0 dan tinggi dan lebarnya sama dengan kanvas .
2. ** Muatkan tekstur **
> tip: tambahkan gambar pemain dan musuh dengan menggunakan `menunggu loadTexture` dan melewati jalan gambar. Anda belum akan melihatnya di skrin!
3. ** Draw ** wira di tengah skrin di bahagian bawah
> tip: gunakan API `drawImage` untuk menarik heroImg ke skrin, tetapkan` canvas.width / 2 - 45` dan `canvas.height - canvas.height / 4)`;
4. ** Draw ** 5 * 5 monster
> tip: Sekarang anda boleh melepaskan kod untuk menarik musuh di layar. Seterusnya, pergi ke fungsi `createEnemies` dan bangunkan.
Pertama, sediakan beberapa pemalar:
```javascript
const MONSTER_TOTAL = 5;
const MONSTER_WIDTH = MONSTER_TOTAL * 98;
const START_X = (canvas.width - MONSTER_WIDTH) / 2;
const STOP_X = START_X + MONSTER_WIDTH;
```
kemudian, buat gelung untuk menarik susunan monster ke skrin:
```javascript
for (let x = START_X; x < STOP_X; x += 98) {
for (let y = 0; y < 50 * 5; y += 50) {
ctx.drawImage(enemyImg, x, y);
}
}
```
## Keputusan
Hasil akhirnya akan kelihatan seperti:
![Skrin hitam dengan wira dan 5 * 5 monster](../partI-solution.png)
## Penyelesaian
Cuba selesaikannya sendiri terlebih dahulu tetapi jika anda buntu, lihatlah [solution](../solution/app.js)
---
## 🚀 Cabaran
Anda telah belajar melukis dengan Canvas API 2D; lihatlah [WebGL API](https://developer.mozilla.org/en-US/docs/Web/API/WebGL_API), dan cuba lukis objek 3D.
## Kuiz Pasca Kuliah
[Kuiz Pasca Kuliah](https://nice-beach-0fe9e9d0f.azurestaticapps.net/quiz/32)
## Mengkaji & Belajar Sendiri
Ketahui lebih lanjut mengenai Canvas API dengan [membaca mengenainya](https://developer.mozilla.org/en-US/docs/Web/API/Canvas_API).
## Tugasan
[Main dengan Canvas API](assignment.ms.md)

View File

@@ -0,0 +1,11 @@
# Main dengan Canvas API
## Arahan
Pilih satu elemen API Canvas dan buat sesuatu yang menarik di sekitarnya. Bolehkah anda membuat galaksi kecil bintang berulang? Bolehkah anda membuat tekstur garis berwarna yang menarik? Anda boleh melihat CodePen untuk mendapatkan inspirasi (tetapi jangan menyalin)
## Rubrik
| Kriteria | Contoh | Mencukupi | Usaha Lagi |
| -------- | --------------------------------------------------------- | ----------------------------------- | --------------------- |
| | Kod dihantar menunjukkan tekstur atau bentuk yang menarik | Kod dihantar, tetapi tidak dijalankan | Kod tidak dihantar |

View File

@@ -0,0 +1,388 @@
# Bina Permainan Angkasa Bahagian 3: Menambah Gerakan
## Kuiz Pra Kuliah
[Kuiz Pra Kuliah](https://nice-beach-0fe9e9d0f.azurestaticapps.net/quiz/33)
Permainan tidak begitu menyeronokkan sehingga anda mempunyai makhluk asing di layar! Dalam permainan ini, kami akan menggunakan dua jenis pergerakan:
- **Pergerakan papan kekunci / Tetikus**: ketika pengguna berinteraksi dengan papan kekunci atau tetikus untuk menggerakkan objek di layar.
- **Pergerakan yang disebabkan oleh permainan**: ketika permainan menggerakkan objek dengan selang waktu tertentu.
Jadi bagaimana kita memindahkan sesuatu di skrin? Ini semua mengenai koordinat kartesian: kami menukar lokasi (x, y) objek dan kemudian melukis semula skrin.
Biasanya anda memerlukan langkah-langkah berikut untuk menyelesaikan *pergerakan* di skrin:
1. **Tetapkan lokasi baru** untuk objek; ini diperlukan untuk melihat objek sebagai bergerak.
2. **Kosongkan skrin**, skrin perlu dibersihkan di antara undian. Kita dapat membersihkannya dengan melukis sebuah segi empat tepat yang kita isi dengan warna latar belakang.
3. **Lukis semula objek** di lokasi baru. Dengan melakukan ini kita akhirnya dapat memindahkan objek dari satu lokasi ke lokasi lain.
Inilah rupa bentuknya dalam kod:
```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);
```
✅ Bolehkah anda memikirkan sebab mengapa menggambar semula pahlawan anda dengan banyak bingkai sesaat mungkin menambah kos prestasi? Baca mengenai [alternatif untuk corak ini](https://www.html5rocks.com/en/tutorials/canvas/performance/).
## Mengendalikan acara papan kekunci
Anda mengendalikan acara dengan melampirkan acara tertentu ke kod. Peristiwa papan kekunci dipicu di seluruh tetingkap sedangkan peristiwa tetikus seperti `click` dapat dihubungkan dengan mengklik elemen tertentu. Kami akan menggunakan acara papan kekunci sepanjang projek ini.
Untuk menangani suatu peristiwa, anda perlu menggunakan kaedah ``addEventListener()` tetingkap dan memberikannya dua parameter input. Parameter pertama adalah nama acara, misalnya `keyup`. Parameter kedua adalah fungsi yang harus dipanggil sebagai akibat dari peristiwa yang berlaku.
Inilah contohnya:
```javascript
window.addEventListener('keyup', (evt) => {
// `evt.key` = string representation of the key
if (evt.key === 'ArrowUp') {
// do something
}
})
```
Untuk acara utama terdapat dua sifat pada acara yang boleh anda gunakan untuk melihat kunci apa yang ditekan:
- `key`, ini adalah representasi rentetan dari kekunci yang ditekan, misalnya `ArrowUp`
- `keyCode`, ini adalah representasi angka, misalnya `37`, sesuai dengan `ArrowLeft`.
✅ Manipulasi acara utama berguna di luar pengembangan permainan. Apa kegunaan lain yang dapat anda fikirkan untuk teknik ini?
### Kekunci khas: peringatan
Terdapat beberapa *kunci* khas yang mempengaruhi tetingkap. Ini bermaksud bahawa jika anda sedang mendengar acara `keyup` dan anda menggunakan kekunci khas ini untuk menggerakkan wira anda, ia juga akan melakukan tatal mendatar. Untuk itu anda mungkin mahu *mematikan* tingkah laku penyemak imbas terbina dalam ini semasa anda membina permainan anda. Anda memerlukan kod seperti ini:
```javascript
let 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);
```
Kod di atas akan memastikan bahawa anak panah dan kekunci spasi mempunyai tingkah laku *lalai* mereka. Mekanisme *shut-off* berlaku apabila kita memanggil `e.preventDefault()`.
## Pergerakan yang disebabkan oleh permainan
Kita dapat membuat sesuatu bergerak dengan menggunakan pemasa seperti fungsi `setTimeout()` atau `setInterval()` yang mengemas kini lokasi objek pada setiap centang, atau selang waktu. Begini rupa:
```javascript
let id = setInterval(() => {
//move the enemy on the y axis
enemy.y += 10;
})
```
## Gelung permainan
Gelung permainan adalah konsep yang pada dasarnya adalah fungsi yang dipanggil pada selang waktu yang tetap. Ia dipanggil gelung permainan kerana segala sesuatu yang dapat dilihat oleh pengguna ditarik ke dalam gelung. Gelung permainan menggunakan semua objek permainan yang menjadi bagian dari permainan, menggambar semuanya kecuali untuk beberapa alasan tidak seharusnya menjadi bagian dari permainan lagi. Contohnya jika objek adalah musuh yang terkena laser dan meletup, ia bukan lagi bahagian dari gelung permainan semasa (anda akan mengetahui lebih lanjut mengenai perkara ini dalam pelajaran berikutnya).
Inilah rupa gelung permainan, yang dinyatakan dalam kod:
```javascript
let 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();
}, 200);
```
Gelung di atas dipanggil setiap `200` milisaat untuk menggambar semula kanvas. Anda mempunyai kemampuan untuk memilih selang terbaik yang sesuai untuk permainan anda.
## Meneruskan Permainan Angkasa
Anda akan mengambil kod yang ada dan memanjangkannya. Mulakan dengan kod yang anda lengkapkan semasa bahagian I atau gunakan kod di [Bahagian II- starter] (karya anda).
- **Memindahkan pahlawan**: anda akan menambah kod untuk memastikan anda dapat memindahkan pahlawan menggunakan kekunci anak panah.
- **Pindahkan musuh**: anda juga perlu menambahkan kod untuk memastikan musuh bergerak dari atas ke bawah pada kadar tertentu.
## Langkah yang disyorkan
Cari fail yang telah dibuat untuk anda dalam sub folder `your-work`. Ia harus mengandungi yang berikut:
```bash
-| assets
-| enemyShip.png
-| player.png
-| index.html
-| app.js
-| package.json
```
Anda memulakan projek anda folder `your_work` dengan mengetik:
```bash
cd your-work
npm start
```
Perkara di atas akan memulakan Pelayan HTTP pada alamat `http: // localhost: 5000`. Buka penyemak imbas dan masukkan alamat itu, sekarang ia harus menjadikan pahlawan dan semua musuh; tidak ada yang bergerak - namun!
### Tambah kod
1. **Tambahkan objek khusus** untuk `hero` dan `musuh` dan `objek permainan`, mereka harus mempunyai sifat `x` dan `y`. ( Ingat bahagian pada [Warisan atau komposisi](../../translations/README.ms.md) ).
*HINT* `objek permainan` harus menjadi objek dengan `x` dan `y` dan kemampuan untuk menarik dirinya ke kanvas.
> tip: mulakan dengan menambahkan kelas GameObject baru dengan konstruktornya digambarkan seperti di bawah, dan kemudian lukiskannya ke kanvas:
```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);
}
}
```
Sekarang, panjangkan GameObject ini untuk membuat Wira dan Musuh.
```javascript
class Hero extends GameObject {
constructor(x, y) {
...it needs an x, y, type, and speed
}
}
```
```javascript
class Enemy extends GameObject {
constructor(x, y) {
super(x, y);
(this.width = 98), (this.height = 50);
this.type = "Enemy";
let id = setInterval(() => {
if (this.y < canvas.height - this.height) {
this.y += 5;
} else {
console.log('Stopped at', this.y)
clearInterval(id);
}
}, 300)
}
}
```
2. **Tambahkan pengendali acara utama** untuk mengendalikan navigasi utama (pusing pahlawan ke atas / bawah kiri / kanan)
*INGAT* ini adalah sistem kartesian, kiri atas adalah `0,0`. Juga ingat untuk menambah kod untuk menghentikan *tingkah laku lalai*
> tip: buat fungsi onKeyDown anda dan pasangkannya ke tetingkap:
```javascript
let onKeyDown = function (e) {
console.log(e.keyCode);
...add the code from the lesson above to stop default behavior
}
};
window.addEventListener("keydown", onKeyDown);
```
Periksa konsol penyemak imbas anda pada ketika ini, dan perhatikan penekanan kekunci dicatat.
3. **Terapkan** the [Pub sub pattern](../../translations/README.ms.md), ini akan memastikan kod anda tetap bersih semasa anda mengikuti bahagian yang tinggal.
Untuk melakukan bahagian terakhir ini, anda boleh:
1. **Tambahkan pendengar acara** di tetingkap:
```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);
}
});
```
1. **Buat kelas EventEmitter** untuk menerbitkan dan melanggan mesej:
```javascript
class EventEmitter {
constructor() {
this.listeners = {};
}
on(message, listener) {
if (!this.listeners[message]) {
this.listeners[message] = [];
}
this.listeners[message].push(listener);
}
emit(message, payload = null) {
if (this.listeners[message]) {
this.listeners[message].forEach((l) => l(message, payload));
}
}
}
```
1. **Tambah pemalar** dan sediakan 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();
```
1. **Memulakan permainan**
```javascript
function initGame() {
gameObjects = [];
createEnemies();
createHero();
eventEmitter.on(Messages.KEY_EVENT_UP, () => {
hero.y -=5 ;
})
eventEmitter.on(Messages.KEY_EVENT_DOWN, () => {
hero.y += 5;
});
eventEmitter.on(Messages.KEY_EVENT_LEFT, () => {
hero.x -= 5;
});
eventEmitter.on(Messages.KEY_EVENT_RIGHT, () => {
hero.x += 5;
});
}
```
1. **Siapkan gelung permainan**
Memfaktorkan semula fungsi window.onload untuk memulakan permainan dan mengatur gelung permainan pada selang waktu yang baik. Anda juga akan menambah sinar laser:
```javascript
window.onload = async () => {
canvas = document.getElementById("canvas");
ctx = canvas.getContext("2d");
heroImg = await loadTexture("assets/player.png");
enemyImg = await loadTexture("assets/enemyShip.png");
laserImg = await loadTexture("assets/laserRed.png");
initGame();
let gameLoopId = setInterval(() => {
ctx.clearRect(0, 0, canvas.width, canvas.height);
ctx.fillStyle = "black";
ctx.fillRect(0, 0, canvas.width, canvas.height);
drawGameObjects(ctx);
}, 100)
};
```
5. **Tambahkan kod** untuk memindahkan musuh pada selang waktu tertentu
Refactor fungsi `createEnemies()` untuk membuat musuh dan mendorong mereka ke kelas gameObjects yang baru:
```javascript
function createEnemies() {
const MONSTER_TOTAL = 5;
const MONSTER_WIDTH = MONSTER_TOTAL * 98;
const START_X = (canvas.width - MONSTER_WIDTH) / 2;
const STOP_X = START_X + MONSTER_WIDTH;
for (let x = START_X; x < STOP_X; x += 98) {
for (let y = 0; y < 50 * 5; y += 50) {
const enemy = new Enemy(x, y);
enemy.img = enemyImg;
gameObjects.push(enemy);
}
}
}
```
dan tambahkan fungsi `createHero()` untuk melakukan proses yang serupa untuk wira.
```javascript
function createHero() {
hero = new Hero(
canvas.width / 2 - 45,
canvas.height - canvas.height / 4
);
hero.img = heroImg;
gameObjects.push(hero);
}
```
dan akhirnya, tambahkan fungsi `drawGameObjects()` untuk memulakan lukisan:
```javascript
function drawGameObjects(ctx) {
gameObjects.forEach(go => go.draw(ctx));
}
```
Musuh anda harus mula maju di kapal angkasa wira anda!
---
## 🚀 Cabaran
Seperti yang anda lihat, kod anda boleh berubah menjadi 'spaghetti code' apabila anda mula menambahkan fungsi dan pemboleh ubah dan kelas. Bagaimana anda dapat mengatur kod anda dengan lebih baik agar lebih mudah dibaca? Lakarkan sistem untuk mengatur kod anda, walaupun masih terdapat dalam satu fail.
## Kuiz Pasca Kuliah
[Kuiz Pasca Kuliah](https://nice-beach-0fe9e9d0f.azurestaticapps.net/quiz/34)
## Mengkaji & Belajar Sendiri
Semasa kami menulis permainan kami tanpa menggunakan kerangka kerja, ada banyak kerangka kanvas berdasarkan JavaScript untuk pengembangan permainan. Luangkan sedikit masa untuk melakukan [membaca mengenai perkara ini](https://github.com/collections/javascript-game-engines).
## Tugasan
[Komen kod anda](assignment.ms.md)

View File

@@ -0,0 +1,11 @@
# Komen Kod Anda
## Arahan
Periksa fail /app.js semasa anda di folder permainan anda, dan cari cara untuk mengomentarinya dan rapi. Sangat mudah bagi kod untuk tidak terkawal, dan sekarang adalah peluang yang baik untuk menambahkan komen untuk memastikan bahawa anda mempunyai kod yang dapat dibaca sehingga anda dapat menggunakannya kemudian.
## Rubrik
| Kriteria | Contoh | Mencukupi | Usaha Lagi |
| -------- | ------------------------------------------------------------------ | ------------------------------------- | -------------------------------------------------------------- |
| | Kod `app.js` dikomentari sepenuhnya dan disusun menjadi blok logik | Kod `app.js` diberi komen yang mencukupi | Kod `app.js` agak tidak teratur dan tidak mempunyai komen yang baik |

View File

@@ -0,0 +1,297 @@
# Bina Permainan Angkasa Bahagian 4: Menambah Laser dan Mengesan Perlanggaran
## Kuiz Pra Kuliah
[Kuiz Pra Kuliah](https://nice-beach-0fe9e9d0f.azurestaticapps.net/quiz/35)
Dalam pelajaran ini, anda akan belajar bagaimana menembak laser dengan JavaScript! Kami akan menambah dua perkara pada permainan kami:
- **Laser**: laser ini ditembak dari kapal wira anda dan menegak ke atas
- **Pengesanan perlanggaran**, sebagai bagian dari menerapkan kemampuan untuk *menembak* kami juga akan menambahkan beberapa peraturan permainan yang bagus:
- **Laser menyerang musuh**: Musuh mati jika terkena laser
- **Laser mencecah skrin atas**: Laser hancur jika memukul bahagian atas skrin
- **Pertempuran musuh dan pahlawan**: Musuh dan pahlawan musnah jika saling memukul
- **Musuh memukul bahagian bawah layar**: Musuh dan pahlawan hancur jika musuh memukul bahagian bawah layar
Pendek kata, anda - *pahlawan* - perlu memukul semua musuh dengan laser sebelum mereka berjaya bergerak ke bahagian bawah skrin.
✅ Lakukan sedikit kajian mengenai permainan komputer pertama yang pernah ditulis. Apa fungsinya?
Mari sama-sama menjadi wira!
## Pengesanan perlanggaran
Bagaimanakah kita melakukan pengesanan perlanggaran? Kita perlu memikirkan objek permainan kita sebagai segi empat tepat bergerak. Mengapa anda bertanya? Nah, gambar yang digunakan untuk menggambar objek permainan adalah persegi panjang: ia memiliki `x`, `y`, `width` dan` height`.
Sekiranya dua segi empat tepat, iaitu pahlawan dan musuh *berpotongan*, anda akan bertembung. Apa yang harus berlaku adalah mengikut peraturan permainan. Oleh itu, untuk melaksanakan pengesanan perlanggaran anda memerlukan perkara berikut:
1. Cara untuk mendapatkan representasi segi empat tepat dari objek permainan, seperti ini:
```javascript
rectFromGameObject() {
return {
top: this.y,
left: this.x,
bottom: this.y + this.height,
right: this.x + this.width
}
}
```
2. Fungsi perbandingan, fungsi ini boleh kelihatan seperti ini:
```javascript
function intersectRect(r1, r2) {
return !(r2.left > r1.right ||
r2.right < r1.left ||
r2.top > r1.bottom ||
r2.bottom < r1.top);
}
```
## Bagaimanakah kita memusnahkan perkara
Untuk menghancurkan sesuatu dalam permainan, anda perlu memberitahu permainan bahawa permainan ini tidak lagi harus melukis item ini dalam gelung permainan yang mencetuskan pada selang waktu tertentu. Cara untuk melakukannya adalah dengan menandakan objek permainan sebagai *mati* apabila sesuatu berlaku, seperti:
```javascript
// collision happened
enemy.dead = true
```
Kemudian anda meneruskan untuk menyusun *mati* objek sebelum mengecat semula skrin, seperti:
```javascript
gameObjects = gameObject.filter(go => !go.dead);
```
## Bagaimanakah kita menghidupkan laser
Menyalakan laser diterjemahkan untuk bertindak balas terhadap peristiwa penting dan membuat objek yang bergerak ke arah tertentu. Oleh itu, kita perlu melakukan langkah-langkah berikut:
1. **Buat objek laser**: dari bahagian atas kapal pahlawan kita, bahawa setelah penciptaan mula bergerak ke atas menuju bahagian atas layar.
2. **Lampirkan kod ke acara utama**: kita perlu memilih kunci pada papan kekunci yang mewakili pemain yang menembak laser.
3. **Buat objek permainan yang kelihatan seperti laser** apabila kekunci ditekan.
## Cooldown menggunakan laser kami
Laser perlu menyala setiap kali anda menekan kekunci, seperti *ruang* misalnya. Untuk mengelakkan permainan menghasilkan terlalu banyak laser dalam masa yang singkat, kita perlu memperbaikinya. Penyelesaiannya adalah dengan menerapkan *cooldown*, pemasa, yang memastikan bahawa laser hanya dapat dipecat begitu kerap. Anda boleh melaksanakannya dengan cara berikut:
```javascript
class Cooldown {
constructor(time) {
this.cool = false;
setTimeout(() => {
this.cool = true;
}, time)
}
}
class Weapon {
constructor {
}
fire() {
if (!this.cooldown || this.cooldown.cool) {
// menghasilkan laser
this.cooldown = new Cooldown(500);
} else {
// buat apa-apa - ia belum cooldown.
}
}
}
```
✅ Rujuk pelajaran 1 dalam siri permainan ruang untuk mengingatkan diri anda mengenai *cooldowns*.
## Apakah yang hendak dibina
Anda akan mengambil kod yang ada (yang seharusnya anda bersihkan dan refactored) dari pelajaran sebelumnya, dan memperpanjangnya. Mulakan dengan kod dari bahagian II atau gunakan kod di [Bahagian III-starter](/your-work)
> tip: laser yang akan anda gunakan sudah ada di folder aset anda dan dirujuk oleh kod anda
- **Tambahkan pengesanan perlanggaran**, apabila laser bertabrakan dengan sesuatu peraturan berikut harus berlaku:
1. **Laser memukul musuh**: musuh mati jika terkena laser
2. **Laser mencecah skrin atas**: Laser hancur jika menyentuh bahagian atas skrin kita
3. **Pertembungan musuh dan pahlawan**: musuh dan pahlawan musnah jika saling memukul
4. **Musuh memukul bahagian bawah skrin**: Musuh dan pahlawan hancur jika musuh memukul bahagian bawah skrin
## Langkah-langkah yang disyorkan
Cari fail yang telah dibuat untuk anda dalam sub folder `your-work`. Ia harus mengandungi yang berikut:
```bash
-| assets
-| enemyShip.png
-| player.png
-| laserRed.png
-| index.html
-| app.js
-| package.json
```
Anda memulakan projek anda folder `your_work` dengan mengetik:
```bash
cd your-work
npm start
```
Perkara di atas akan memulakan Pelayan HTTP pada alamat `http: // localhost: 5000`. Buka penyemak imbas dan masukkan alamatnya, sekarang ia harus menjadikan pahlawan dan semua musuh, tidak ada yang bergerak - namun :).
### Tambah kod
1. **Siapkan representasi segi empat tepat dari objek permainan anda, untuk menangani perlanggaran** Kod di bawah ini membolehkan anda mendapatkan representasi segi empat tepat dari `GameObject`. Edit kelas GameObject anda untuk memperluasnya:
```javascript
rectFromGameObject() {
return {
top: this.y,
left: this.x,
bottom: this.y + this.height,
right: this.x + this.width,
};
}
```
2. **Tambahkan kod yang memeriksa perlanggaran** Ini akan menjadi fungsi baru yang menguji sama ada dua segi empat tepat bersilang:
```javascript
function intersectRect(r1, r2) {
return !(
r2.left > r1.right ||
r2.right < r1.left ||
r2.top > r1.bottom ||
r2.bottom < r1.top
);
}
```
3. **Tambahkan keupayaan menembak laser**
1. **Tambah mesej peristiwa penting**. Kekunci *ruang* harus membuat laser tepat di atas kapal wira. Tambahkan tiga pemalar dalam objek Mesej:
```javascript
KEY_EVENT_SPACE: "KEY_EVENT_SPACE",
COLLISION_ENEMY_LASER: "COLLISION_ENEMY_LASER",
COLLISION_ENEMY_HERO: "COLLISION_ENEMY_HERO",
```
1. **Kendalikan kekunci ruang**. Edit fungsi kekunci `window.addEventListener` untuk menangani ruang:
```javascript
} else if(evt.keyCode === 32) {
eventEmitter.emit(Messages.KEY_EVENT_SPACE);
}
```
1. **Tambah pendengar**. Edit fungsi `initGame ()` untuk memastikan bahawa pahlawan dapat melepaskan tembakan ketika spasi terkena:
```javascript
eventEmitter.on(Messages.KEY_EVENT_SPACE, () => {
if (hero.canFire()) {
hero.fire();
}
```
and add a new `eventEmitter.on()` function to ensure behavior when an enemy collides with a laser:
```javascript
eventEmitter.on(Messages.COLLISION_ENEMY_LASER, (_, { first, second }) => {
first.dead = true;
second.dead = true;
})
```
1. **Pindahkan objek**, Pastikan laser bergerak ke bahagian atas skrin secara beransur-ansur. Anda akan membuat kelas Laser baru yang meluaskan `GameObject`, seperti yang telah anda lakukan sebelumnya:
```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. ** Tangani perlanggaran **, Terapkan peraturan perlanggaran untuk laser. Tambahkan fungsi `updateGameObjects ()` yang menguji objek bertembung untuk hits
```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);
}
```
Pastikan untuk menambah `updateGameObjects ()` ke gelung permainan anda di `window.onload`.
4. ** Terapkan cooldown ** pada laser, sehingga hanya dapat dipecat begitu kerap.
Akhir sekali, edit kelas Wira sehingga dapat dikembalikan:
```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;
}
}
```
Pada ketika ini, permainan anda mempunyai beberapa fungsi! Anda boleh menavigasi dengan kekunci anak panah anda, menembak laser dengan bar ruang anda, dan musuh hilang ketika anda memukulnya. Bagus!
---
## 🚀 Cabaran
Tambah letupan! Lihat aset permainan di [Space Art repo](../../solution/spaceArt/readme.txt) dan cuba tambahkan letupan ketika laser memukul makhluk asing
## Kuiz Pasca Kuliah
[Kuiz Pasca Kuliah](https://nice-beach-0fe9e9d0f.azurestaticapps.net/quiz/36)
## Mengkaji & Belajar Sendiri
Percubaan dengan selang permainan anda setakat ini. Apa yang berlaku apabila anda menukarnya? Baca lebih lanjut mengenai [acara pemasaan JavaScript](https://www.freecodecamp.org/news/javascript-timing-events-settimeout-and-setinterval/).
## Tugasan
[Menerokai Perlanggaran](assignment.ms.md)

View File

@@ -0,0 +1,11 @@
# Menorokai Perlanggaran
## Arahan
## Rubrik
Untuk lebih memahami bagaimana perlanggaran berfungsi, bina permainan yang sangat kecil dengan beberapa item yang bertembung. Buat mereka bergerak melalui menekan kekunci atau klik tetikus, dan membuat sesuatu berlaku pada salah satu item ketika dipukul. Ini mungkin seperti meteor yang menghantam bumi, atau kereta bumper. Dapatkan kreatif!
| Kriteria | Contoh | Mencukupi | Usaha Lagi |
| -------- | ------------------------------------------------------------------------------------------------------------------------ | ------------------------------ | ----------------- |
| | Sampel kod kerja lengkap dihasilkan, dengan item dilukis ke kanvas, perlanggaran asas berlaku, dan reaksi berlaku | Kod tidak lengkap dalam beberapa cara | Kod Tidak Berfungsi |

View File

@@ -0,0 +1,189 @@
# Membina Permainan Angkasa Bahagian 5: Pemarkahan dan Kehidupan
## Kuiz Pra Kuliah
[Kuiz Pra Kuliah](https://nice-beach-0fe9e9d0f.azurestaticapps.net/quiz/37)
Dalam pelajaran ini, anda akan belajar bagaimana menambahkan skor pada permainan dan mengira kehidupan.
## Lukis teks di skrin
Untuk dapat memaparkan skor permainan di layar, Anda harus tahu cara meletakkan teks di layar. Jawapannya adalah menggunakan kaedah `fillText()` pada objek kanvas. Anda juga dapat mengawal aspek lain seperti fon apa yang hendak digunakan, warna teks dan juga penjajarannya (kiri, kanan, tengah). Di bawah ini terdapat beberapa kod yang melukis beberapa teks di skrin.
```javascript
ctx.font = "30px Arial";
ctx.fillStyle = "red";
ctx.textAlign = "right";
ctx.fillText("show this on the screen", 0, 0);
```
✅ Baca lebih lanjut mengenai [cara menambahkan teks ke kanvas](https://developer.mozilla.org/en-US/docs/Web/API/Canvas_API/Tutorial/Drawing_text), dan jangan ragu untuk menjadikan teks anda kelihatan lebih menarik!
## Hidup, sebagai konsep permainan
Konsep mempunyai kehidupan dalam permainan hanya bilangan. Dalam konteks permainan ruang angkasa adalah biasa untuk menetapkan satu set nyawa yang dipotong satu demi satu ketika kapal anda mengalami kerosakan. Senang jika anda dapat menunjukkan gambaran grafik seperti miniships atau hati dan bukannya angka.
## Apakah yang anda perlu bina
Mari tambahkan yang berikut ke permainan anda:
- **Skor permainan**: Untuk setiap kapal musuh yang musnah, pahlawan harus diberikan beberapa mata, kami mencadangkan 100 mata setiap kapal. Skor permainan harus ditunjukkan di kiri bawah.
- **Kehidupan**: Kapal anda mempunyai tiga nyawa. Anda kehilangan nyawa setiap kali kapal musuh bertembung dengan anda. Skor hidup mesti dipaparkan di kanan bawah dan dibuat berdasarkan grafik berikut! [Gambar hidup](../solution/assets/life.png).
## Langkah yang disyorkan
Cari fail yang telah dibuat untuk anda dalam sub folder `your-work`. Ia harus mengandungi yang berikut:
```bash
-| assets
-| enemyShip.png
-| player.png
-| laserRed.png
-| index.html
-| app.js
-| package.json
```
Anda memulakan projek anda folder `your_work` dengan mengetik:
```bash
cd your-work
npm start
```
Perkara di atas akan memulakan Pelayan HTTP pada alamat `http://localhost:5000`. Buka penyemak imbas dan masukkan alamatnya, sekarang ia akan menjadikan pahlawan dan semua musuh, dan ketika anda menekan anak panah kiri dan kanan, pahlawan bergerak dan dapat menembak musuh.
### Tambahkan Kod
1. **Salin atas aset yang diperlukan** dari folder `solution/aset/` ke folder `your-work`; anda akan menambah aset `life.png`. Tambahkan lifeImg ke fungsi window.onload:
```javascript
lifeImg = await loadTexture("assets/life.png");
```
1. Tambahkan `lifeImg` ke senarai aset:
```javascript
let heroImg,
...
lifeImg,
...
eventEmitter = new EventEmitter();
```
2. **Tambah pemboleh ubah**. Tambahkan kod yang mewakili jumlah skor anda (0) dan tinggal (3), paparkan skor ini di skrin.
3. **Panjangkan fungsi `updateGameObjects ()`**. Panjangkan fungsi `updateGameObjects ()` untuk menangani perlanggaran musuh:
```javascript
enemies.forEach(enemy => {
const heroRect = hero.rectFromGameObject();
if (intersectRect(heroRect, enemy.rectFromGameObject())) {
eventEmitter.emit(Messages.COLLISION_ENEMY_HERO, { enemy });
}
})
```
4. **Tambahkan `life` dan` point`**.
1. **Memulakan pemboleh ubah**. Di bawah `this.cooldown = 0` di kelas `Hero`, tetapkan hidup dan mata:
```javascript
this.life = 3;
this.points = 0;
```
1. **Lukis pemboleh ubah pada skrin**. Lukiskan nilai-nilai ini ke skrin:
```javascript
function drawLife() {
// TODO, 35, 27
const START_POS = canvas.width - 180;
for(let i=0; i < hero.life; i++ ) {
ctx.drawImage(
lifeImg,
START_POS + (45 * (i+1) ),
canvas.height - 37);
}
}
function drawPoints() {
ctx.font = "30px Arial";
ctx.fillStyle = "red";
ctx.textAlign = "left";
drawText("Points: " + hero.points, 10, canvas.height-20);
}
function drawText(message, x, y) {
ctx.fillText(message, x, y);
}
```
1. ** Tambahkan kaedah ke gelung Permainan **. Pastikan anda menambahkan fungsi ini ke fungsi window.onload anda di bawah `updateGameObjects()`:
```javascript
drawPoints();
drawLife();
```
1. **Melaksanakan peraturan permainan**. Laksanakan peraturan permainan berikut:
1. **Untuk setiap pertembungan pahlawan dan musuh**, tolaklah nyawa.
Lanjutkan kelas `Hero` untuk melakukan pemotongan ini:
```javascript
decrementLife() {
this.life--;
if (this.life === 0) {
this.dead = true;
}
}
```
2. **Untuk setiap laser yang menyerang musu**, tingkatkan skor permainan dengan 100 mata.
Panjangkan kelas Wira untuk melakukan kenaikan ini:
```javascript
incrementPoints() {
this.points += 100;
}
```
Tambahkan fungsi ini ke Collision Event Emitter anda:
```javascript
eventEmitter.on(Messages.COLLISION_ENEMY_LASER, (_, { first, second }) => {
first.dead = true;
second.dead = true;
hero.incrementPoints();
})
eventEmitter.on(Messages.COLLISION_ENEMY_HERO, (_, { enemy }) => {
enemy.dead = true;
hero.decrementLife();
});
```
✅ Lakukan sedikit penyelidikan untuk mengetahui permainan lain yang dibuat menggunakan JavaScript/Canvas. Apakah sifat umum mereka?
Menjelang akhir kerja ini, anda akan melihat kapal-kapal kecil 'kehidupan' di kanan bawah, titik di kiri bawah, dan anda akan melihat pengurangan jumlah hayat anda semasa anda bertembung dengan musuh dan kenaikan mata anda ketika anda menembak musuh. Bagus! Permainan anda hampir selesai.
---
## 🚀 Cabaran
Kod anda hampir lengkap. Bolehkah anda membayangkan langkah seterusnya?
## Kuiz Pasca Kuliah
[Kuiz Pasca Kuliah](https://nice-beach-0fe9e9d0f.azurestaticapps.net/quiz/38)
## Mengkaji & Belajar Sendiri
Teliti beberapa cara yang boleh anda tambah dan mengurangkan skor dan kehidupan permainan. Terdapat beberapa enjin permainan yang menarik seperti [PlayFab](https://playfab.com). Bagaimana penggunaan salah satu daripadanya dapat meningkatkan permainan anda?
## Tugasan
[Bina Permainan Pemarkahan](assignment.ms.md)

View File

@@ -0,0 +1,11 @@
# Bina Permainan Pemarkahan
## Arahan
Buat permainan di mana anda menampilkan kehidupan dan mata dengan cara yang kreatif. Satu cadangan adalah untuk menunjukkan kehidupan sebagai hati dan poin sebagai angka yang besar di bahagian tengah bawah skrin. Lihat di sini [Sumber permainan percuma](https://www.kenney.nl/)
# Rubrik
| Kriteria | Contoh | Mencukupi | Usaha Lagi |
| -------- | ---------------------- | --------------------------- | -------------------------- |
| | permainan penuh dipersembahkan | permainan dipersembahkan sebahagiannya | permainan separa mengandungi pepijat |

View File

@@ -211,8 +211,7 @@ Aggiungere un suono! Si può aggiungere un suono per migliorare il gioco, magari
## Quiz Post-Lezione
[Quiz post-lezione](https://nice-beach-0fe9e9d0f.azurestaticapps.net/quiz/40?loc=it)
[Quiz post-lezione](https://nice-b
## Revisione e Auto Apprendimento
Il compito è creare un nuovo gioco di esempio, quindi esplorare alcuni dei giochi interessanti esistenti per vedere che tipo di gioco si potrebbe costruire.

View File

@@ -0,0 +1,222 @@
# Bina Permainan Angkasa Bahagian 6: Tamat dan Mulakan Semula
## Kuiz Pra Kuliah
[Kuiz Pra Kuliah](https://nice-beach-0fe9e9d0f.azurestaticapps.net/quiz/39)
Terdapat pelbagai cara untuk menyatakan dan *keadaan akhir* dalam permainan. Terserah anda sebagai pencipta permainan untuk mengatakan mengapa permainan ini berakhir. Berikut adalah beberapa sebab, jika kita menganggap bahawa kita sedang membincangkan permainan ruang angkasa yang anda buat sejauh ini:
- **Kapal musuh `N` telah hancur**: Sangat biasa jika anda membahagikan permainan ke dalam tahap yang berbeza yang anda perlukan untuk menghancurkan kapal `N` Musuh untuk menyelesaikan level
- **Kapal anda hancur**: Pasti ada permainan di mana anda kehilangan permainan jika kapal anda musnah. Pendekatan umum lain ialah anda mempunyai konsep kehidupan. Setiap kali kapal anda musnah, ia akan meragut nyawa. Setelah semua nyawa telah hilang maka anda akan kehilangan permainan.
- **Anda telah mengumpulkan mata `N`**: Syarat akhir yang umum ialah anda mengumpulkan mata. Cara anda memperoleh mata adalah bergantung kepada anda tetapi agak biasa untuk memberikan mata kepada pelbagai aktiviti seperti memusnahkan kapal musuh atau mungkin mengumpulkan barang-barang yang item *turun* ketika mereka musnah.
- **Lengkapkan tahap**: Ini mungkin melibatkan beberapa syarat seperti kapal musuh `X` musnah, mata `Y` dikumpulkan atau mungkin item tertentu telah dikumpulkan.
## Memulakan semula
Sekiranya orang menikmati permainan anda, mereka mungkin ingin memainkannya semula. Setelah permainan berakhir dengan alasan apa pun, anda harus menawarkan alternatif untuk dimulakan semula.
✅ Fikirkan sedikit dalam keadaan apa permainan anda berakhir, dan kemudian bagaimana anda diminta untuk memulakan semula
## Apakah yang anda perlu bina
Anda akan menambahkan peraturan ini ke permainan anda:
1. **Memenangi permainan**. Setelah semua kapal musuh musnah, anda memenangi permainan. Selain itu memaparkan semacam mesej kemenangan.
1. **Mulakan semula**. Setelah semua nyawa anda hilang atau permainan dimenangi, anda harus menawarkan cara untuk memulakan semula permainan. Ingat! Anda perlu memulakan semula permainan dan keadaan permainan sebelumnya harus dibersihkan.
## Langkah-langkah yang disyorkan
Cari fail yang telah dibuat untuk anda dalam sub folder `your-work`. Ia harus mengandungi yang berikut:
```bash
-| assets
-| enemyShip.png
-| player.png
-| laserRed.png
-| life.png
-| index.html
-| app.js
-| package.json
```
Anda memulakan projek anda folder `your_work` dengan mengetik:
```bash
cd your-work
npm start
```
Perkara di atas akan memulakan Pelayan HTTP pada alamat `http://localhost:5000`. Buka penyemak imbas dan masukkan alamat itu. Permainan anda mestilah dalam keadaan boleh dimainkan.
> tip: untuk mengelakkan amaran dalam Visual Studio Code, edit fungsi `window.onload` untuk memanggil `gameLoopId` sebagaimana adanya (tanpa `let`), dan nyatakan gameLoopId di bahagian atas fail, secara bebas: `let gameLoopId;`
### Tambahkan kod
1. **Keadaan hujung trek**. Tambahkan kod yang memantau jumlah musuh, atau jika kapal pahlawan telah musnah dengan menambahkan dua fungsi ini:
```javascript
function isHeroDead() {
return hero.life <= 0;
}
function isEnemiesDead() {
const enemies = gameObjects.filter((go) => go.type === "Enemy" && !go.dead);
return enemies.length === 0;
}
```
1. **Tambahkan logik ke pengendali mesej**. Edit `eventEmitter` untuk menangani keadaan berikut:
```javascript
eventEmitter.on(Messages.COLLISION_ENEMY_LASER, (_, { first, second }) => {
first.dead = true;
second.dead = true;
hero.incrementPoints();
if (isEnemiesDead()) {
eventEmitter.emit(Messages.GAME_END_WIN);
}
});
eventEmitter.on(Messages.COLLISION_ENEMY_HERO, (_, { enemy }) => {
enemy.dead = true;
hero.decrementLife();
if (isHeroDead()) {
eventEmitter.emit(Messages.GAME_END_LOSS);
return; // loss before victory
}
if (isEnemiesDead()) {
eventEmitter.emit(Messages.GAME_END_WIN);
}
});
eventEmitter.on(Messages.GAME_END_WIN, () => {
endGame(true);
});
eventEmitter.on(Messages.GAME_END_LOSS, () => {
endGame(false);
});
```
1. **Tambahkan jenis mesej baru**. Tambahkan Mesej ini ke objek pemalar:
```javascript
GAME_END_LOSS: "GAME_END_LOSS",
GAME_END_WIN: "GAME_END_WIN",
```
2. **Tambah kod restart** kod yang memulakan semula permainan dengan menekan butang yang dipilih.
1. **Dengarkan kekunci tekan `Enter`**. Edit eventListener tetingkap anda untuk mendengar akhbar ini:
```javascript
else if(evt.key === "Enter") {
eventEmitter.emit(Messages.KEY_EVENT_ENTER);
}
```
1. **Tambah semula mesej**. Tambahkan Mesej ini ke pemalar Mesej anda:
```javascript
KEY_EVENT_ENTER: "KEY_EVENT_ENTER",
```
1. **Melaksanakan peraturan permainan**. Laksanakan peraturan permainan berikut:
1. **Syarat kemenangan pemain**. Apabila semua kapal musuh hancur, tunjukkan mesej kemenangan.
1. Pertama, buat fungsi `displayMessage()`:
```javascript
function displayMessage(message, color = "red") {
ctx.font = "30px Arial";
ctx.fillStyle = color;
ctx.textAlign = "center";
ctx.fillText(message, canvas.width / 2, canvas.height / 2);
}
```
1. Buat fungsi `endGame()`:
```javascript
function endGame(win) {
clearInterval(gameLoopId);
// atur kelewatan supaya kami yakin sebarang cat telah selesai
setTimeout(() => {
ctx.clearRect(0, 0, canvas.width, canvas.height);
ctx.fillStyle = "black";
ctx.fillRect(0, 0, canvas.width, canvas.height);
if (win) {
displayMessage(
"Victory!!! Pew Pew... - Press [Enter] to start a new game Captain Pew Pew",
"green"
);
} else {
displayMessage(
"You died !!! Press [Enter] to start a new game Captain Pew Pew"
);
}
}, 200)
}
```
1. **Mulakan semula logik**. Apabila semua nyawa hilang atau pemain memenangi permainan, tunjukkan bahawa permainan dapat dimulakan semula. Selain itu mulakan semula permainan apabila butang * restart * dipukul (anda boleh menentukan kunci apa yang harus dipetakan untuk dimulakan semula).
1. Buat fungsi `resetGame ()`:
```javascript
function resetGame() {
if (gameLoopId) {
clearInterval(gameLoopId);
eventEmitter.clear();
initGame();
gameLoopId = setInterval(() => {
ctx.clearRect(0, 0, canvas.width, canvas.height);
ctx.fillStyle = "black";
ctx.fillRect(0, 0, canvas.width, canvas.height);
drawPoints();
drawLife();
updateGameObjects();
drawGameObjects(ctx);
}, 100);
}
}
```
1. Tambahkan panggilan ke `eventEmitter` untuk menetapkan semula permainan di `initGame()`:
```javascript
eventEmitter.on(Messages.KEY_EVENT_ENTER, () => {
resetGame();
});
```
1. Tambahkan fungsi `clear()` ke EventEmitter:
```javascript
clear() {
this.listeners = {};
}
```
👽 💥 🚀 Tahniah, Kapten! Permainan anda selesai! Bagus! 🚀 💥 👽
---
## 🚀 Cabaran
Tambahkan suara! Bolehkah anda menambahkan suara untuk meningkatkan permainan anda, mungkin ketika ada pancaran laser, atau wira mati atau menang? Lihatlah [sandbox](https://www.w3schools.com/jsref/tryit.asp?filename=tryjsref_audio_play) untuk belajar bagaimana memainkan suara menggunakan JavaScript
## Kuiz Pasca Kuliah
[Kuiz Pasca Kuliah](https://nice-beach-0fe9e9d0f.azurestaticapps.net/quiz/40)
## Mengkaji & Belajar Sendiri
Tugas anda adalah membuat permainan contoh baru, jadi terokai beberapa permainan menarik di luar sana untuk melihat jenis permainan yang mungkin anda bina.
## Tugasan
[Bina Contoh Permainan](assignment.ms.md)

View File

@@ -0,0 +1,19 @@
# Bina Contoh Permainan
## Arahan
Cuba buat permainan kecil di mana anda berlatih dengan keadaan akhir yang berbeza. Berbeza antara mendapatkan sejumlah mata, wira kehilangan semua nyawa atau semua raksasa dikalahkan. Bina sesuatu yang mudah seperti permainan pengembaraan berasaskan konsol. Gunakan aliran permainan di bawah sebagai inspirasi:
```
Wira> Serangan dengan pedang lebar - orc mengalami kerosakan 3p
Orc> Hits with club - wira mengalami kerosakan 2p
Wira> Tendangan - orc mengalami kerosakan 1p
Permainan> Orc dikalahkan - Hero mengumpulkan 2 syiling
Permainan> ****Tidak ada lagi raksasa, anda telah menakluki kubu jahat****
```
## Rubrik
| Kriteria | Contoh | Mencukupi | Usaha Lagi |
| -------- | ---------------------- | --------------------------- | -------------------------- |
| | permainan penuh dipersembahkan| permainan dipersembahkan sebahagiannya | permainan separa mengandungi pepijat |

View File

@@ -19,11 +19,11 @@
- 理論
- [JavaScript を使ったゲーム構築入門](../1-introduction/translations/README.ja.md)
- 実践
- [キャンバスへの描画](../2-drawing-to-canvas/translations/README.ja.md)
- [Canvas への描画](../2-drawing-to-canvas/translations/README.ja.md)
- [画面の周りの要素の移動](../3-moving-elements-around/translations/README.ja.md)
- [衝突の検出](../4-collision-detection/translations/README.ja.md)
- [スコアの保持](../5-keeping-score/translations/README.ja.md)
- [ゲームの終了と再](../6-end-condition/translations/README.ja.md)
- [ゲームの終了と再起動](../6-end-condition/translations/README.ja.md)
## クレジット

View File

@@ -0,0 +1,31 @@
# Bina Permainan Angkasa
Permainan ruang untuk mengajar asas-asas JavaScript yang lebih mendalam
Dalam pelajaran ini, anda akan belajar bagaimana membuat permainan ruang angkasa anda sendiri. Sekiranya anda pernah memainkan permainan "Space Invaders", permainan ini mempunyai idea yang sama: untuk mengarahkan kapal angkasa dan menembak monster yang turun dari atas. Beginilah rupa permainan yang sudah siap:
![Permainan selesai](../images/pewpew.gif)
Dalam enam pelajaran ini anda akan mempelajari perkara berikut:
- **Berinteraksi** dengan elemen Canvas untuk menarik sesuatu di skrin
- **Memahami** sistem koordinat kartesian
- **Pelajari** corak Pub-Sub untuk membuat seni bina permainan suara yang lebih mudah dijaga dan diperluas
- **Leverage** Async / Tunggu untuk memuatkan sumber permainan
- **Mengendalikan** acara papan kekunci
## Gambaran keseluruhan
- Theori
- [Pengenalan membina permainan dengan JavaScript](../1-introduction/README.md)
- Practice
- [Melukis ke kanvas](../2-drawing-to-canvas/README.md)
- [Menggerakkan elemen di sekitar skrin](../3-moving-elements-around/README.md)
- [Pengesanan perlanggaran](../4-collision-detection/README.md)
- [Menjaga skor](../5-keeping-score/README.md)
- [Menamatkan dan memulakan semula permainan](../6-end-condition/README.md)
## Kredit
Aset yang digunakan untuk ini berasal dari https://www.kenney.nl/.
Sekiranya anda suka membina permainan, ini adalah beberapa aset yang sangat baik, banyak percuma dan ada juga yang dibayar.