mirror of
https://github.com/microsoft/Web-Dev-For-Beginners.git
synced 2025-08-26 16:14:56 +02:00
Merge branch 'main' into loc-query-strings-fix
This commit is contained in:
@@ -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
|
||||
|
||||
|
@@ -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)
|
@@ -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) और अधिक जानें .
|
||||
|
||||
## असाइनमेंट
|
||||
|
||||
|
@@ -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)。
|
||||
|
||||
## 課題
|
||||
|
||||
|
@@ -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에 대해 조금 더 배워봅시다.
|
||||
|
||||
## 과제
|
||||
|
||||
|
224
6-space-game/1-introduction/translations/README.ms.md
Normal file
224
6-space-game/1-introduction/translations/README.ms.md
Normal file
@@ -0,0 +1,224 @@
|
||||
# Membina Permainan Angkasa Bahagian 1: Pengenalan
|
||||
|
||||

|
||||
|
||||
## 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)
|
12
6-space-game/1-introduction/translations/assignment.ms.md
Normal file
12
6-space-game/1-introduction/translations/assignment.ms.md
Normal 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 |
|
216
6-space-game/2-drawing-to-canvas/translations/README.ms.md
Normal file
216
6-space-game/2-drawing-to-canvas/translations/README.ms.md
Normal 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.
|
||||
|
||||

|
||||
> 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
|
||||
|
||||

|
||||
|
||||
- 5 * 5 raksasa
|
||||
|
||||

|
||||
|
||||
### 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:
|
||||
|
||||

|
||||
|
||||
## 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)
|
@@ -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 |
|
388
6-space-game/3-moving-elements-around/translations/README.ms.md
Normal file
388
6-space-game/3-moving-elements-around/translations/README.ms.md
Normal 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)
|
@@ -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 |
|
297
6-space-game/4-collision-detection/translations/README.ms.md
Normal file
297
6-space-game/4-collision-detection/translations/README.ms.md
Normal 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)
|
@@ -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 |
|
189
6-space-game/5-keeping-score/translations/README.ms.md
Normal file
189
6-space-game/5-keeping-score/translations/README.ms.md
Normal 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)
|
11
6-space-game/5-keeping-score/translations/assignment.ms.md
Normal file
11
6-space-game/5-keeping-score/translations/assignment.ms.md
Normal 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 |
|
@@ -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.
|
||||
|
222
6-space-game/6-end-condition/translations/README.ms.md
Normal file
222
6-space-game/6-end-condition/translations/README.ms.md
Normal 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)
|
19
6-space-game/6-end-condition/translations/assignment.ms.md
Normal file
19
6-space-game/6-end-condition/translations/assignment.ms.md
Normal 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 |
|
@@ -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)
|
||||
|
||||
## クレジット
|
||||
|
||||
|
31
6-space-game/translations/README.ms.md
Normal file
31
6-space-game/translations/README.ms.md
Normal 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:
|
||||
|
||||

|
||||
|
||||
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.
|
Reference in New Issue
Block a user