Advertisement
  1. Code
  2. HTML5

HTML5 Avoider permainan Tutorial: menjaga Skor

Scroll to top
Read Time: 21 min

Indonesian (Bahasa Indonesia) translation by Keti Pritania (you can also view the original English article)

Sejauh ini, kami telah mendapat aliran tidak pernah berakhir musuh yang avatar kami harus menghindari; satu sentuhan, dan it's permainan berakhir. Tapi jadi apa? Karena tidak ada cara untuk melacak kemajuan pemain, mereka memiliki tidak tahu apakah mereka melakukan lebih baik di terbaru mereka bulat daripada yang pernah mereka lakukan sebelumnya. Dalam tutorial ini, Anda akan belajar cara menjaga skor, cara menampilkannya di kanvas, dan cara membuat pemain tahu kapan mereka telah mengalahkan rekor mereka sendiri.


Penyegaran

Dalam bagian pertama dan kedua dari tutorial ini, kita telah membahas beberapa konsep: Menggambar Gambar ke kanvas, mendeteksi mouse tindakan, menggunakan jika dan ketika pernyataan, menyimpan variabel dalam array, dan gagasan lingkup variabel.

Anda dapat mendownload source file dari serial ke titik ini jika Anda ingin selam di sini, walaupun saya sarankan membaca semua bagian dalam urutan.

File JavaScript permainan kami menginisialisasi banyak variabel (termasuk dua array untuk menyimpan koordinat x dan y musuh) di luar semua fungsi, sehingga kontennya tersedia untuk semua fungsi. Ini juga berisi fungsi yang disebut setUpGame() yang dijalankan ketika pemain pertama kali mengklik kanvas; ini memuat gambar, mulai mendengarkan setiap gerakan mouse, dan mengatur fungsi 'centang' untuk dijalankan setiap 25 milidetik.

Ketika mouse tersebut akan dipindahkan, kita bergerak posisi avatar, sebagai disimpan dalam dua variabel - satu untuk koordinat x - dan satu untuk koordinat y- tetapi kita tidak segera redraw gambar avatar di lokasi ini baru; Menggambar ulang semua ditangani dalam fungsi kutu.

Fungsi kutu melakukan empat hal:

  • Ada kesempatan satu-di-dua puluh bahwa ini akan menambahkan musuh baru dengan menekan baru x - dan y-koordinat ke array relevan.
  • Ia bertambah koordinat y-setiap musuh dengan perulangan melalui array itu.
  • Itu menggambar ulang gambar avatar dan musuh sesuai dengan koordinat mereka saat ini.
  • Itu memeriksa tabrakan antara avatar dan setiap musuh, memberikan peringatan jika satu terjadi.

Semuanya jelas?


Hangat sampai tantangan

Jika sudah lama sejak Anda membaca bagian kedua dari seri (atau jika Anda hanya ingin memastikan bahwa Anda memahami apa yang sedang terjadi), cobalah latihan-latihan kecil ini. Mereka sudah benar-benar opsional dan terpisah untuk tutorial sebenarnya, jadi saya sarankan bekerja pada copy proyek Anda daripada yang asli. Anda dapat menyelesaikan semua latihan-latihan ini menggunakan hanya informasi dari seri sejauh ini.

Mudah

Tukar gambar avatar dan musuh di sekitar sehingga pemain mengontrol wajah tersenyum yang menghindari tengkorak yang jatuh.

(Berapa banyak cara yang berbeda Anda bisa mencari tahu bagaimana melakukan ini? Aku bisa memikirkan tiga, dari atas kepalaku.)

Media

Saat ini, ada flat satu-di-dua puluh kesempatan bahwa musuh baru akan dibuat di setiap centang yang diberikan. Saya ingin Anda untuk membuatnya sehingga ada kesempatan satu-di-satu pada centang pertama, satu-di-dua kesempatan kedua, kesempatan satu-di-tiga ketiga, dan seterusnya.

Untuk membuat ini lebih menantang, melakukannya terbalik: kesempatan satu-di-1,000 kutu pertama, satu-di-999 kesempatan kedua, kesempatan satu-di-998 ketiga, dan seterusnya. (Setelah membuat kutu, membuat kesempatan satu-di-satu mantap.)

Sulit

Daripada menunggu musuh untuk muncul satu memiliki awal permainan dengan dua puluh musuh sudah pada layar.

Untuk membuat ini lebih menantang, membuat mereka menyebar di sekitar kanvas, dan tidak memungkinkan mereka untuk tumpang tindih avatar atau satu sama lain.


Menjaga waktu

Apa adalah cara termudah untuk mengukur seberapa baik pemain melakukan putaran ini? Hal termudah bisa kupikirkan adalah untuk melacak berapa lama sudah sejak mereka memukul musuh. Dan karena memukul musuh berarti game over, kita hanya perlu melacak berapa lama mereka telah bermain.

Untuk melakukan ini, kita akan hanya membuat variabel, set ke 0 ketika putaran dimulai, dan kenaikan setiap centang. Mari kita sebut ticksSurvived variabel ini. Dan berpikir: karena kita perlu mengakses lagi dan lagi, itu perlu didefinisikan di luar semua fungsi, di bagian atas JS file:

1
var enemyYPositions = [];  //empty square brackets means new empty array

2
var enemyXPositions = [];
3
var avatarX = 0;
4
var avatarY = 0;
5
var avatarImage;
6
var enemyImage;
7
var ticksSurvived = 0;

Sekarang, kami akan memberikan handleTick() Namun lain tugas untuk dilakukan: kenaikan ticksSurvived. Menempatkan ini setelah deteksi tabrakan; setelah semua, jika avatar hits musuh, itu tidak benar-benar selamat kutu:

1
function handleTick() {
2
3
	//...

4
	
5
	currentEnemyNumber = 0;
6
	while (currentEnemyNumber < numberOfEnemies) {
7
		if ( ( (avatarX < enemyXPositions[currentEnemyNumber] && enemyXPositions[currentEnemyNumber] < avatarX + 30) || (enemyXPositions[currentEnemyNumber] < avatarX && avatarX < enemyXPositions[currentEnemyNumber] + 30) ) && ( (avatarY < enemyYPositions[currentEnemyNumber] && enemyYPositions[currentEnemyNumber] < avatarY + 33) || (enemyYPositions[currentEnemyNumber] < avatarY && avatarY < enemyYPositions[currentEnemyNumber] + 30) ) ) {
8
			alert("You hit an enemy!");
9
		}
10
		currentEnemyNumber = currentEnemyNumber + 1;
11
	}
12
	
13
	ticksSurvived = ticksSurvived + 1;
14
}

Untuk menampilkan ini, untuk saat ini, kami hanya akan mengubah peringatan yang muncul ketika avatar mengenai musuh:

1
function handleTick() {
2
3
	//...

4
	
5
	currentEnemyNumber = 0;
6
	while (currentEnemyNumber < numberOfEnemies) {
7
		if ( ( (avatarX < enemyXPositions[currentEnemyNumber] && enemyXPositions[currentEnemyNumber] < avatarX + 30) || (enemyXPositions[currentEnemyNumber] < avatarX && avatarX < enemyXPositions[currentEnemyNumber] + 30) ) && ( (avatarY < enemyYPositions[currentEnemyNumber] && enemyYPositions[currentEnemyNumber] < avatarY + 33) || (enemyYPositions[currentEnemyNumber] < avatarY && avatarY < enemyYPositions[currentEnemyNumber] + 30) ) ) {
8
			alert("You hit an enemy! Ticks survived: " + ticksSurvived);
9
		}
10
		currentEnemyNumber = currentEnemyNumber + 1;
11
	}
12
	
13
	ticksSurvived = ticksSurvived + 1;
14
}

Itulah sedikit aneh; kami telah menggunakan + operator untuk menambahkan string nomor. Kita dapat menambahkan string lainnya sampai akhir:

1
function handleTick() {
2
3
	//...

4
	
5
	currentEnemyNumber = 0;
6
	while (currentEnemyNumber < numberOfEnemies) {
7
		if ( ( (avatarX < enemyXPositions[currentEnemyNumber] && enemyXPositions[currentEnemyNumber] < avatarX + 30) || (enemyXPositions[currentEnemyNumber] < avatarX && avatarX < enemyXPositions[currentEnemyNumber] + 30) ) && ( (avatarY < enemyYPositions[currentEnemyNumber] && enemyYPositions[currentEnemyNumber] < avatarY + 33) || (enemyYPositions[currentEnemyNumber] < avatarY && avatarY < enemyYPositions[currentEnemyNumber] + 30) ) ) {
8
			alert("You hit an enemy! You survived " + ticksSurvived + " ticks.");
9
		}
10
		currentEnemyNumber = currentEnemyNumber + 1;
11
	}
12
	
13
	ticksSurvived = ticksSurvived + 1;
14
}

Mungkin ini tidak aneh bagi Anda, tetapi beberapa bahasa pemrograman membenci ini. JavaScript tidak peduli. Ia tahu bahwa 'some' + 'string' sama dengan 'somestring', dan mengasumsikan bahwa Anda ingin memperlakukan ticksSurvived sebagai string dalam situasi ini.

(Beberapa hal untuk mencoba:

12 + 6
"12" + "6"
"12" + 6
12 + "6"

Mereka semua lakukan apa yang Anda harapkan mereka untuk melakukan?)

Pokoknya, mari kita coba kode baru ini.

HTML5 avoider game tutorialHTML5 avoider game tutorialHTML5 avoider game tutorial
Klik untuk mencobanya.

Bagus!

Seperti sebelumnya, ketika Anda mengklik OK, alert kotak muncul lagi, karena semua hal ini adalah jeda kutu daripada benar-benar menghentikan mereka. Namun perlu dicatat bahwa nomor dalam kotak meningkat oleh satu; ini bukti bahwa JavaScript tidak mengubah nomor menjadi string itu hanya menggunakannya sebagai string untuk keperluan menambahkannya ke string lainnya.

Sementara kita pada subjek ini kotak peringatan: Jangan Anda menemukannya menjengkelkan?


Coba lagi

Saat ini, satu-satunya cara untuk memulai babak baru adalah menyegarkan halaman. Mari kita membuatnya lebih mudah dan lebih menjengkelkan untuk mencoba lagi, dengan membuat tombol 'OK' pada kotak peringatan mengatur ulang permainan.

Karena peringatan secara efektif berhenti permainan, apa pun yang kita meletakkan pada baris setelah waspada akan berjalan sekali pemain hits OK. Mari kita membuat itu memanggil fungsi baru, startNewGame():

1
	currentEnemyNumber = 0;
2
	while (currentEnemyNumber < numberOfEnemies) {
3
		if ( ( (avatarX < enemyXPositions[currentEnemyNumber] && enemyXPositions[currentEnemyNumber] < avatarX + 30) || (enemyXPositions[currentEnemyNumber] < avatarX && avatarX < enemyXPositions[currentEnemyNumber] + 30) ) && ( (avatarY < enemyYPositions[currentEnemyNumber] && enemyYPositions[currentEnemyNumber] < avatarY + 33) || (enemyYPositions[currentEnemyNumber] < avatarY && avatarY < enemyYPositions[currentEnemyNumber] + 30) ) ) {
4
			alert("You hit an enemy! You survived " + ticksSurvived + " ticks.");
5
			startNewGame();
6
		}
7
		currentEnemyNumber = currentEnemyNumber + 1;
8
	}

Jadi apa kita perlu startNewGame() untuk melakukan?

Mungkin kita harus hanya memanggil setUpGame() lagi - tapi tidak, tidak ada yang perlu melakukan dua kali: kita tidak perlu memuat gambar atau menambahkan pendengar acara mouse atau mengatur kutu lagi.

Pikirkan apa yang akan dibutuhkan, dan cobalah ide-ide Anda. Solusi saya di bawah ini; lihatlah ketika Anda siap.

1
function startNewGame() {
2
	enemyXPositions = [];
3
	enemyYPositions = [];
4
	ticksSurvived = 0;
5
}

Itu saja. Anda dapat melakukan lebih banyak jika Anda inginkan, tetapi ini adalah minimum yang diperlukan.

Perhatikan bahwa kita tidak harus melakukan sesuatu dengan kanvas - kita tidak perlu untuk membersihkan, atau menarik apa itu, atau memanipulasi gambar - karena ini semua dilakukan di handleTick(). Kita tidak harus pergi melalui semua elemen dalam array, satu demi satu, baik, karena array hanya daftar koordinat yang kita gunakan untuk stempel gambar musuh ke kanvas; musuh tidak ada sebagai objek yang sebenarnya.

HTML5 avoider game tutorialHTML5 avoider game tutorialHTML5 avoider game tutorial
Klik untuk mencobanya.

Jadi ini besar - pemain dapat bermain lagi dan lagi untuk terus mencoba untuk Skor yang lebih baik. Kecuali... bagaimana mereka tahu apakah mereka sudah mengalahkan Skor mereka sebelumnya? Saat ini, mereka hanya harus ingat mereka top Skor sejauh, atau menuliskannya. Kita bisa melakukan lebih dari itu.


Ingat Skor terbaik

Bagaimana seharusnya kita menyimpan skor teratas? Di variabel lain, tentu saja!

1
var enemyYPositions = [];	//empty square brackets means new empty array

2
var enemyXPositions = [];
3
var avatarX = 0;
4
var avatarY = 0;
5
var avatarImage;
6
var enemyImage;
7
var ticksSurvived = 0;
8
var mostTicksSurvived = 0;

Tentu saja, itu harus tinggal di luar fungsi; Sekarang, saya yakin Anda memahami mengapa.

Untuk mulai dengan, kita set ke 0, tentu saja-pemain bahkan belum menyelesaikan putaran. Ketika avatar hits musuh, mari kita memperbarui nilai baru yang diperlukan:

1
	while (currentEnemyNumber < numberOfEnemies) {
2
		if ( ( (avatarX < enemyXPositions[currentEnemyNumber] && enemyXPositions[currentEnemyNumber] < avatarX + 30) || (enemyXPositions[currentEnemyNumber] < avatarX && avatarX < enemyXPositions[currentEnemyNumber] + 30) ) && ( (avatarY < enemyYPositions[currentEnemyNumber] && enemyYPositions[currentEnemyNumber] < avatarY + 33) || (enemyYPositions[currentEnemyNumber] < avatarY && avatarY < enemyYPositions[currentEnemyNumber] + 30) ) ) {
3
			alert("You hit an enemy! You survived " + ticksSurvived + " ticks.");
4
			if (ticksSurvived > mostTicksSurvived) {
5
				mostTicksSurvived = ticksSurvived;
6
			}
7
			startNewGame();
8
		}
9
		currentEnemyNumber = currentEnemyNumber + 1;
10
	}

Mari kita juga memberitahu pemain bahwa mereka mengalahkan Skor tinggi mereka lama:

1
	while (currentEnemyNumber < numberOfEnemies) {
2
		if ( ( (avatarX < enemyXPositions[currentEnemyNumber] && enemyXPositions[currentEnemyNumber] < avatarX + 30) || (enemyXPositions[currentEnemyNumber] < avatarX && avatarX < enemyXPositions[currentEnemyNumber] + 30) ) && ( (avatarY < enemyYPositions[currentEnemyNumber] && enemyYPositions[currentEnemyNumber] < avatarY + 33) || (enemyYPositions[currentEnemyNumber] < avatarY && avatarY < enemyYPositions[currentEnemyNumber] + 30) ) ) {
3
			alert("You hit an enemy! You survived " + ticksSurvived + " ticks.");
4
			if (ticksSurvived > mostTicksSurvived) {
5
				alert("New high score!");
6
				mostTicksSurvived = ticksSurvived;
7
			}
8
			startNewGame();
9
		}
10
		currentEnemyNumber = currentEnemyNumber + 1;
11
	}

Perhatikan:

HTML5 avoider game tutorialHTML5 avoider game tutorialHTML5 avoider game tutorial
Klik untuk mencobanya.

Sangat baik. Sekarang mari kita memberi pemain sedikit lebih lanjut tentang berapa banyak lebih baik mereka lakukan:

1
	while (currentEnemyNumber < numberOfEnemies) {
2
		if ( ( (avatarX < enemyXPositions[currentEnemyNumber] && enemyXPositions[currentEnemyNumber] < avatarX + 30) || (enemyXPositions[currentEnemyNumber] < avatarX && avatarX < enemyXPositions[currentEnemyNumber] + 30) ) && ( (avatarY < enemyYPositions[currentEnemyNumber] && enemyYPositions[currentEnemyNumber] < avatarY + 33) || (enemyYPositions[currentEnemyNumber] < avatarY && avatarY < enemyYPositions[currentEnemyNumber] + 30) ) ) {
3
			alert("You hit an enemy! You survived " + ticksSurvived + " ticks.");
4
			if (ticksSurvived > mostTicksSurvived) {
5
				alert("You beat your old high score by " + (ticksSurvived - mostTicksSurvived) + " ticks!");
6
				mostTicksSurvived = ticksSurvived;
7
			}
8
			startNewGame();
9
		}
10
		currentEnemyNumber = currentEnemyNumber + 1;
11
	}

Perhatikan di sini bahwa ticksSurvived dan mostTicksSurvived diperlakukan sebagai nomor ketika mengurangi satu dari yang lain, tapi ekspresi dihasilkan (ticksSurvived - mostTicksSurvived) dianggap sebagai string ketika ditambahkan ke string lain! Ini bisa benar-benar membingungkan, jika Anda tidak hati-hati.

HTML5 avoider game tutorialHTML5 avoider game tutorialHTML5 avoider game tutorial
Klik untuk mencobanya.

Baiklah, jadi sekarang pemain tahu seberapa baik mereka lakukan, setelah mereka mendapatkan permainan berakhir, kita harus memberi mereka sebuah indikasi dari seberapa baik mereka lakukan, sementara mereka masih bermain.


Menggambar Skor ke kanvas

Sangat mudah untuk menulis teks ke kanvas - dan tidak, kita tidak perlu menyatukannya dari gambar berbeda dari berbagai huruf!

Ingat bahwa menggambar gambar kanvas kita sebut canvas.getContext("2d").drawImage(). Menulis teks ini sangat mirip: kita sebut canvas.getContext("2d").fillText().

Kita harus melewati tiga argumen untuk fillText():

  • String yang berisi teks untuk menulis.
  • Koordinat x di mana untuk menulis itu.
  • Koordinat y di mana untuk menulis itu.

Ada argumen keempat opsional:

  • Lebar maksimum yang teks diperbolehkan untuk mengambil pada layar.

... tapi kita tidak khawatir tentang hal itu sekarang.

Untuk menguji ini, kepala ke handleTick(), menemukan baris mana kita menarik avatar ke kanvas, dan menggambar garis contoh teks hanya setelah itu:

1
	gameCanvas.width = 400;		//this erases the contents of the canvas

2
	gameCanvas.getContext("2d").drawImage(avatarImage, avatarX, avatarY);
3
	gameCanvas.getContext("2d").fillText("Testing, testing, one, two, three.", 100, 100);

Mencobanya:

HTML5 avoider game tutorialHTML5 avoider game tutorialHTML5 avoider game tutorial
Klik untuk mencobanya.

Perhatikan bahwa, karena ini akan ditarik setelah avatar dan sebelum musuh, musuh diambil di atas, sementara avatar pergi di bawah:

HTML5 avoider game tutorialHTML5 avoider game tutorialHTML5 avoider game tutorial
Klik untuk mencobanya.

Seperti yang saya katakan, argumen pertama yang diperlukan adalah string, dan - seperti yang telah kita lihat - kita dapat membangun string dengan menambahkan string ke angka. Jadi, ini seharusnya bekerja:

1
	gameCanvas.width = 400;		//this erases the contents of the canvas

2
	gameCanvas.getContext("2d").drawImage(avatarImage, avatarX, avatarY);
3
	gameCanvas.getContext("2d").fillText("Score: " + ticksSurvived, 100, 100);

.. .dan memang itu!

HTML5 avoider game tutorialHTML5 avoider game tutorialHTML5 avoider game tutorial
Klik untuk mencobanya.

Tapi sedikit berantakan, mengambang ada di bawahnya musuh dengan font yang kecil. Mari kita jenis yang keluar.


Merapikan teks

Pertama, mari kita lanjutkan teks sehingga musuh bergerak di bawahnya. Ini hanya berarti menggambar setelah semua musuh tertarik, jadi bergerak relevan garis:

1
	gameCanvas.width = 400;		//this erases the contents of the canvas

2
	gameCanvas.getContext("2d").drawImage(avatarImage, avatarX, avatarY);
3
	
4
	currentEnemyNumber = 0;
5
	while (currentEnemyNumber < numberOfEnemies) {
6
		gameCanvas.getContext("2d").drawImage(enemyImage, enemyXPositions[currentEnemyNumber], enemyYPositions[currentEnemyNumber]);
7
		currentEnemyNumber = currentEnemyNumber + 1;
8
	}
9
10
	gameCanvas.getContext("2d").fillText("Score: " + ticksSurvived, 100, 100);

Sekarang, mari kita bergerak ke kiri atas layar. Itu, (0, 0) sehingga ini harus bekerja, kanan?

1
	gameCanvas.width = 400;		//this erases the contents of the canvas

2
	gameCanvas.getContext("2d").drawImage(avatarImage, avatarX, avatarY);
3
	
4
	currentEnemyNumber = 0;
5
	while (currentEnemyNumber < numberOfEnemies) {
6
		gameCanvas.getContext("2d").drawImage(enemyImage, enemyXPositions[currentEnemyNumber], enemyYPositions[currentEnemyNumber]);
7
		currentEnemyNumber = currentEnemyNumber + 1;
8
	}
9
10
	gameCanvas.getContext("2d").fillText("Score: " + ticksSurvived, 0, 0);

Hmm. Nope. Kita tidak melihat nilai sama sekali. Ini adalah karena menggunakan (0, 0) untuk menempatkan sudut kiri bawah teks. Kita perlu memindahkan teks turun sedikit, maka:

1
	gameCanvas.width = 400;		//this erases the contents of the canvas

2
	gameCanvas.getContext("2d").drawImage(avatarImage, avatarX, avatarY);
3
	
4
	currentEnemyNumber = 0;
5
	while (currentEnemyNumber < numberOfEnemies) {
6
		gameCanvas.getContext("2d").drawImage(enemyImage, enemyXPositions[currentEnemyNumber], enemyYPositions[currentEnemyNumber]);
7
		currentEnemyNumber = currentEnemyNumber + 1;
8
	}
9
10
	gameCanvas.getContext("2d").fillText("Score: " + ticksSurvived, 0, 10);

Coba lihat:

HTML5 avoider game tutorialHTML5 avoider game tutorialHTML5 avoider game tutorial
Klik untuk mencobanya.

Oke, jadi sejauh ini begitu baik. Sekarang, mari kita mengubah font itu sendiri. Kita melakukan ini dengan menetapkan kanvas konteks font properti ke string CSS dengan font. Jika Anda tidak familiar dengan CSS, jangan khawatir; pada tahap ini, semua yang perlu Anda ketahui adalah bahwa hal itu berisi ukuran font dan fontface:

1
	gameCanvas.width = 400;		//this erases the contents of the canvas

2
	gameCanvas.getContext("2d").drawImage(avatarImage, avatarX, avatarY);
3
	
4
	currentEnemyNumber = 0;
5
	while (currentEnemyNumber < numberOfEnemies) {
6
		gameCanvas.getContext("2d").drawImage(enemyImage, enemyXPositions[currentEnemyNumber], enemyYPositions[currentEnemyNumber]);
7
		currentEnemyNumber = currentEnemyNumber + 1;
8
	}
9
10
	gameCanvas.getContext("2d").font = "10px Impact";
11
	gameCanvas.getContext("2d").fillText("Score: " + ticksSurvived, 0, 10);

("px" singkatan "piksel".)

Perhatikan bahwa kita harus menetapkan font sebelum menggambar teks!

Perhatikan:

HTML5 avoider game tutorialHTML5 avoider game tutorialHTML5 avoider game tutorial
Klik untuk mencobanya.

Ini berfungsi - tetapi font Dampak sangat sulit dibaca pada ukuran itu. Mari kita buat lebih besar:

1
	gameCanvas.getContext("2d").font = "18px Impact";
2
	gameCanvas.getContext("2d").fillText("Score: " + ticksSurvived, 0, 10);
HTML5 avoider game tutorialHTML5 avoider game tutorialHTML5 avoider game tutorial
Klik untuk mencobanya.

Sayangnya, ini tidak bekerja begitu baik, karena font masih 10px dari atas kanvas, tetapi sekarang ini 16px tinggi!

Kita bisa terus berubah posisi y font untuk memperbaiki ini, tapi ada alternatif: kami akan membuatnya sehingga posisi kita menentukan menentukan sudut kiri atas teks, bukan sudut kiri bawah. Sangat mudah:

1
	gameCanvas.getContext("2d").font = "18px Impact";
2
	gameCanvas.getContext("2d").textBaseline = "top";
3
	gameCanvas.getContext("2d").fillText("Score: " + ticksSurvived, 0, 10);

Tentu saja, sekarang, ada kesenjangan 10px antara bagian atas teks dan atas kanvas:

HTML5 avoider game tutorialHTML5 avoider game tutorialHTML5 avoider game tutorial
Klik untuk mencobanya.

... tapi yang mudah untuk memperbaiki sekarang:

1
	gameCanvas.getContext("2d").font = "18px Impact";
2
	gameCanvas.getContext("2d").textBaseline = "top";
3
	gameCanvas.getContext("2d").fillText("Score: " + ticksSurvived, 0, 0);

Yah, sebenarnya, aku suka sedikit padding, jadi mari kita melakukan hal ini:

1
	gameCanvas.getContext("2d").font = "18px Impact";
2
	gameCanvas.getContext("2d").textBaseline = "top";
3
	gameCanvas.getContext("2d").fillText("Score: " + ticksSurvived, 5, 5);
HTML5 avoider game tutorialHTML5 avoider game tutorialHTML5 avoider game tutorial
Klik untuk mencobanya.

Jauh lebih baik.

Font yang berbeda

Mungkin Anda bertanya-tanya apakah ada daftar font yang bisa kita gunakan. Ya dan tidak. Lihat, jika Anda memilih font yang tidak diinstal pemain di komputer mereka, maka teks hanya akan ditampilkan dalam font default. Ingat, JavaScript adalah gambar teks pada lalat, menggunakan sumber daya komputer pemain.

Kami menggunakan dampak, baik karena itu adalah diinstal pada setiap komputer - tapi apakah itu berarti kita tidak dapat menggunakan font apapun selain beberapa di daftar ini?

Untungnya, tidak. Kita dapat menggunakan font apapun yang kita sukai, selama kita memberi akses pengguna ke itu entah bagaimana. Dan untuk ini, kita akan menggunakan yang CSS file - yang Anda tahu, yang kami belum menyentuh sejak awal seri.

Misalkan kita memiliki font yang disebut 'Really-Awesome'. Ini akan ada di komputer Anda, di suatu tempat, sebagai file - mungkin file .TFF ('True Type Font'). Misalkan file itu disebut ReallyAwesomeFont.ttf.

Sekarang seandainya Anda meng-upload font ini ke situs web - reallyawesomewebsite.com - jadi yang ada langsung URL untuk itu: http://reallyawesomewebsite.com/fonts/ReallyAwesomeFont.ttf.

Anda kemudian dapat membiarkan pemain browser tahu tentang hal itu dengan menambahkan ini ke file CSS Anda:

1
@font-face {
2
    font-family: 'Really-Awesome';
3
    src: url('http://reallyawesomewebsite.com/fonts/ReallyAwesomeFont.ttf');
4
}

Dengan baris ini di CSS Anda, Anda dapat mengubah kode seperti:

1
	gameCanvas.getContext("2d").font = "18px Really-Awesome";
2
	gameCanvas.getContext("2d").textBaseline = "top";
3
	gameCanvas.getContext("2d").fillText("Score: " + ticksSurvived, 5, 5);

.. .dan itu akan berhasil, karena browser mereka akan mencari font "Benar-benar-Awesome" dalam stylesheet, dan menemukan URL untuk TTF. Hebat!

Aku tidak akan menunjukkan hal ini karena saya tidak memiliki hak redistribusi font apapun; Jika saya meng-upload beberapa dan memberikan Anda link ke TTF sebagai bagian dari tutorial ini, itu tidak benar-benar adil. Tapi ada alternatif...

Google Web font

Google telah mengumpulkan koleksi besar font yang dapat Anda gunakan dalam proyek Anda dalam CSS Anda, menggunakan prinsip yang sama seperti di atas. Lihatlah koleksi.

Ada beberapa kriteria yang dapat digunakan untuk mencari font, dan Anda dapat memasukkan beberapa sampel teks untuk melihat bagaimana font itu ditampilkan:

HTML5 avoider game tutorialHTML5 avoider game tutorialHTML5 avoider game tutorial
Font Google Web.

Aku akan memilih Islandia. Ketika saya klik cepat menggunakan, itu memberi saya HTML ini:

1
<link href='http://fonts.googleapis.com/css?family=Iceland' rel='stylesheet' type='text/css'>

Jika Anda memuat http://fonts.googleapis.com/css?family=Iceland di browser Anda, Anda akan melihat bahwa itu adalah jenis hal yang sama seperti yang kita tulis dari awal sebelum:

1
@media screen {
2
@font-face {
3
  font-family: 'Iceland';
4
  font-style: normal;
5
  font-weight: 400;
6
  src: local('Iceland'), local('Iceland-Regular'), url('http://themes.googleusercontent.com/static/fonts/iceland/v1/F6LYTZLHrG9BNYXRjU7RSw.woff') format('woff');
7
}
8
}

Ini memiliki beberapa rincian lebih lanjut, dan font yang dalam WOFF format daripada TTF, tetapi Anda mendapatkan ide.

Anda dapat menggunakan font apapun yang Anda suka (dan tidak harus Google Web Font), tetapi untuk tutorial ini saya akan menganggap bahwa Anda menggunakan Islandia. Jadi, mengedit game.html dan paste referensi font ke dalamnya:

1
<!DOCTYPE html>
2
<html>
3
	<head>
4
		<title>HTML5 Avoider Game</title>
5
		<script src="js/main.js"></script>
6
		<link rel="stylesheet" href="css/style.css" />
7
		<link href='http://fonts.googleapis.com/css?family=Iceland' rel='stylesheet' type='text/css'>
8
	</head>
9
	<body>
10
		<canvas id="gameCanvas" onclick="setUpGame();" width="400" height="300"></canvas>
11
		<p>Click inside the box to play. Warning: extremely basic!</p>
12
		<p>Make sure you have <a href="http://google.com/chrome/" rel="external">Chrome</a>.</p>
13
		<p>From <a href="http://active.tutsplus.com/tutorials/html5/html5-avoider-game-tutorial-keeping-score">HTML5 Avoider Game Tutorial: Keeping Score</a>.</p>
14
	</body>
15
</html>

Sekarang, kembali di main.js, mengubah font dari dampak ke Islandia:

1
	gameCanvas.getContext("2d").font = "18px Iceland";
2
	gameCanvas.getContext("2d").textBaseline = "top";
3
	gameCanvas.getContext("2d").fillText("Score: " + ticksSurvived, 5, 5);

Perhatikan:

HTML5 avoider game tutorialHTML5 avoider game tutorialHTML5 avoider game tutorial
Klik untuk mencobanya.

Cool!

Tantangan: Tampilkan Skor terbaik

Sekarang bahwa nilai saat ini adalah layar setiap saat, itu hanya alam yang pemain akan ingin melihat apa yang mereka berusaha untuk mengalahkan.

Menggunakan apa yang telah Anda pelajari, menggambar Skor terbaik mereka di kanan kanvas. Ini sedikit rumit daripada tampaknya: Anda harus memutuskan apa yang harus dilakukan (jika ada) ketika nilai saat ini menyusul saat ini top Skor!


Menyimpan nilai antara sesi

Anda mungkin telah memperhatikan oleh sekarang bahwa Skor tinggi reset ketika Anda reload halaman. Ini masuk akal - setelah semua, kami menjalankan baris ini tepat di awal:

1
var mostTicksSurvived = 0;

... tapi bahkan tanpa garis, Skor tinggi masih tidak akan bertahan. Semua variabel mendapatkan reset dan unassigned ketika Anda meninggalkan laman tersebut.

Namun, ada alternatif: setiap browser menyisihkan 5MB penyimpanan untuk setiap domain situs web. Anda dapat menyimpan string apapun yang Anda suka dalam ini 5MB penyimpanan, dan itu akan tinggal di sana bahkan jika pengguna menutup browser dan me-restart komputer mereka.

Ini disebut penyimpanan lokal, dan sangat mudah digunakan! Untuk menyimpan sesuatu, Anda hanya perlu memberinya dua string:

  • nama untuk item, dan
  • nilai item.

Untuk mengambilnya, Anda hanya perlu nama yang Anda semula digunakan.

Sebuah contoh cepat

Berikut adalah contoh cepat: Mari kita menambahkan sesuatu ke penyimpanan lokal tepat pada awal setUpGame() fungsi:

1
function setUpGame() {
2
	localStorage.setItem("exampleItem", "This is a great example.");

Simpan file, dan beban permainan Anda. Kemudian Tutup tab.

Sekarang, edit file JS Anda lagi, menghapus baris baru saja ditambahkan, dan menggantinya dengan garis yang harus mengambil item:

1
function setUpGame() {
2
	alert(localStorage.getItem("exampleItem"));

Jadi, hanya untuk memperjelas, sekarang tidak ada dalam kode yang menetapkan nilai "exampleItem".

Ketika Anda memuat permainan saat ini, Anda akan melihat peringatan dengan "Ini adalah contoh besar." - bukti bahwa string telah disimpan antara sesi.

Kami dapat menghapus item ini dari penyimpanan lokal yang menggunakan localStorage.removeItem():

1
function setUpGame() {
2
	localStorage.removeItem("exampleItem");

Saya sarankan Anda melakukannya sekarang, dan kemudian menghapus baris sepenuhnya.

Anda dapat juga menghapus segala sesuatu dalam penyimpanan lokal sekaligus, menggunakan localStorage.clear() (tidak ada argumen yang diperlukan). Oke - tidak cukup segalanya. Halaman Anda hanya dapat mempengaruhi ruang penyimpanan lokal yang ditugaskan ke domain di mana itu host; Saya tidak dapat menghapus penyimpanan lokal Anda untuk google.com dari halaman yang di-host di tutsplus.com, dan sebaliknya.

Menyimpan Skor terbaik

Sekarang bahwa kita telah melihat contoh, mari kita memasukkannya ke dalam praktek.

Kapan pun skor tinggi baru ditetapkan, mari kita simpan ke penyimpanan lokal. Itu hanya akan ditetapkan dalam satu tempat: Kapan avatar bertabrakan dengan musuh dan nilai saat ini lebih tinggi dari nilai terbaik. Jadi, menambahkan panggilan untuk localStorage.setItem() di tempat yang tepat:

1
	while (currentEnemyNumber < numberOfEnemies) {
2
		if ( ( (avatarX < enemyXPositions[currentEnemyNumber] && enemyXPositions[currentEnemyNumber] < avatarX + 30) || (enemyXPositions[currentEnemyNumber] < avatarX && avatarX < enemyXPositions[currentEnemyNumber] + 30) ) && ( (avatarY < enemyYPositions[currentEnemyNumber] && enemyYPositions[currentEnemyNumber] < avatarY + 33) || (enemyYPositions[currentEnemyNumber] < avatarY && avatarY < enemyYPositions[currentEnemyNumber] + 30) ) ) {
3
			alert("You hit an enemy! You survived " + ticksSurvived + " ticks.");
4
			if (ticksSurvived > mostTicksSurvived) {
5
				alert("You beat your old high score by " + (ticksSurvived - mostTicksSurvived) + " ticks!");
6
				mostTicksSurvived = ticksSurvived;
7
				localStorage.setItem("bestScore", mostTicksSurvived);
8
			}
9
			startNewGame();
10
		}
11
		currentEnemyNumber = currentEnemyNumber + 1;
12
	}

Ketika halaman pertama yang dimuat, kita harus memeriksa untuk melihat apakah sudah ada Skor tinggi disimpan dalam penyimpanan lokal, dan menetapkan mostTicksSurvived ke nilai, jika demikian. (Anda tidak perlu untuk mengulang ini memeriksa setelah halaman dibuka, kecuali jika Anda khawatir tentang pengguna bermain game di dua terpisah tab sekaligus.)

Bagaimana kita memeriksa apakah nilai yang ada? Semua harus kita lakukan adalah meletakkannya di dalam jika kondisi:

1
if (localStorage.getItem("thisItemDoesNotExist")) {
2
	alert("This alert will never appear!");
3
}

alert() di atas tidak akan disebut karena localStorage.getItem("thisItemDoesNotExist") tidak ada. Mudah, kan? Jadi pada awal setUpGame(), kita bisa saja menulis:

1
function setUpGame() {
2
	if (localStorage.getItem("bestScore")) {
3
		mostTicksSurvived = localStorage.getItem("bestScore");
4
	}

Memiliki pergi. Memuat halaman, menetapkan nilai tinggi, kemudian mengalahkan itu. Reload halaman, kemudian mendapatkan Skor yang lebih rendah - apakah ia memberitahu Anda Anda mengalahkan Skor lama Anda?

HTML5 avoider game tutorialHTML5 avoider game tutorialHTML5 avoider game tutorial
Klik untuk mencobanya.

Hebat! By the way, jika Anda mengambil tantangan sebelumnya maka Anda akan dapat melihat Skor terbaik Anda sebelumnya di sudut kanan atas kanvas, dan ini akan sekarang membawa dari sesi ke sesi.


Sidenote: Mengetik Kuat dan Lemah

Kami hampir selesai untuk bagian seri ini, tetapi saya hanya ingin menunjukkan bahwa, sekali lagi, kami telah memperlakukan string sebagai angka dan angka sebagai string: penyimpanan lokal hanya menyimpan nilai string, namun kami simpan nomor ketika kita menyimpan skor terbaik, dan gunakan nilai yang kita ambil sebagai nomor di kemudian hari.

Hal ini dapat diterima, karena JavaScript adalah apa yang disebut "lemah-mengetik". Bahasa pemrograman lain "sangat-mengetik", yang berarti bahwa jika Anda mengatakan bahwa sesuatu adalah nomor, kemudian tetap nomor; Jika Anda mengatakan sesuatu yang string, maka itu tetap sebuah string.

Dalam bahasa diketik kuat, jika Anda ingin menambahkan string "Skor:" Nomor 32, maka Anda harus memberitahukan secara eksplisit bahasa untuk mengobati 32 sebagai string, mungkin seperti:

'Skor:' + (32 sebagai String)

Juga, dalam bahasa diketik kuat, ketika Anda mendefinisikan sebuah variabel, Anda juga menentukan apa jenis ini:

1
var greeting:String = "Hello.";
2
var score:Number = 1000;

Tapi JavaScript tidak khawatir tentang hal-hal ini. Hal ini tidak membuatnya lebih baik atau lebih buruk daripada bahasa diketik kuat, hanya berbeda.


Membungkus

That's it untuk bagian ini tutorial. Sekarang permainan Anda memiliki permainan di atas kondisi dan sarana untuk menjaga Skor. Plus, Anda belajar tentang menggambar teks ke kanvas, memilih font, dan menggunakan penyimpanan lokal.

Jika Anda ingin menantang diri sebelum bagian berikutnya, memiliki pergi di membuat perubahan:

  • Mudah: Menggambar Skor terbaik pada kanvas, sebelum pemain klik.
  • Medium: Menyimpan lima skor teratas pemain.
  • Sulit: Menyimpan posisi semua musuh ke penyimpanan lokal, dan memulihkan mereka dalam sidang (Anda mungkin harus melakukan penelitian tambahan di sini! Petunjuk: melihat ke dalam JSON.)

Nikmati!

Advertisement
Did you find this post useful?
Want a weekly email summary?
Subscribe below and we’ll send you a weekly email summary of all new Code tutorials. Never miss out on learning about the next big thing.
Advertisement
Looking for something to help kick start your next project?
Envato Market has a range of items for sale to help get you started.