Buat game berbasis browser dengan Vanilla JS dan CSS – beragampengetahuan – Beragampengetahuan
Hari -hari ini tampaknya luar biasa untuk dikembangkan untuk web. Ada berbagai perpustakaan dan kerangka kerja yang hampir tidak terbatas untuk dipilih.
Anda mungkin juga perlu menerapkan langkah -langkah build, kontrol versi, dan pipa penyebaran. Sebelum Anda menulis satu baris kode. Bagaimana dengan saran yang menarik? Mari kita mundur selangkah dan ingatkan diri kita bahwa tidak perlu fitur tambahan yang mengkilap menjadi sederhana, JavaScript modern dan CSS.
Tertarik? Kemudian ikuti saya dalam perjalanan untuk membuat game berbasis browser hanya menggunakan Vanilla JS dan CSS.
Contents
Ide ini
Kami akan membangun permainan menebak. Pemain memiliki daftar jawaban dengan logo dan beberapa pilihan.
Langkah 1. Struktur dasar
Pertama, kita akan membutuhkan daftar negara dan bendera masing -masing. Untungnya, kita dapat menggunakan kekuatan emoji untuk menunjukkan bendera, yang berarti kita tidak perlu mendapatkannya, atau bahkan lebih buruk, membuatnya sendiri. Saya sudah menyiapkan ini dalam bentuk JSON.
Antarmuka paling sederhana akan menampilkan emoji logo dan lima tombol:

Gunakan kisi untuk menjepit pengukur semua CS ke tengah dan pusat ukuran relatif, sehingga ditampilkan dengan baik dari layar terkecil ke layar terbesar.
Sekarang ambil salinan paking starter kami dan kami akan membangun fondasi di seluruh proses
Tutorial.
Struktur file proyek kami terlihat seperti ini:
step1.html
step2.html
js/
data.json
helpers/
css/
i/
Di akhir setiap bagian, kode kami akan diarahkan dalam keadaan saat ini.
Langkah 2. Prototipe sederhana
Mari kita mulai retak. Pertama, kita perlu mendapatkan file data.json kami.
async function loadCountries(file) {
try {
const response = await fetch(file);
return await response.json();
} catch (error) {
throw new Error(error);
}
}
loadCountries('./js/data.json')
.then((data) => {
startGame(data.countries)
});
Sekarang kami memiliki data, kami dapat memulai permainan. Kode berikut membuat komentar murah hati pada kode berikut. Luangkan beberapa menit untuk membaca dan menangani apa yang sedang terjadi.
function startGame(countries) {
shuffle(countries);
let answer = countries.shift();
let selected = shuffle([answer, ...countries.slice(0, 4)]);
document.querySelector('h2.flag').innerText = answer.flag;
document.querySelectorAll('.suggestions button')
.forEach((button, index) => {
const countryName = selected[index].name;
button.innerText = countryName;
button.dataset.correct = (countryName === answer.name);
button.onclick = checkAnswer;
})
}
Ada juga beberapa logika untuk memeriksa jawabannya:
function checkAnswer(e) {
const button = e.target;
if (button.dataset.correct === 'true') {
button.classList.add('correct');
alert('Correct! Well done!');
} else {
button.classList.add('wrong');
alert('Wrong answer try again');
}
}
Anda mungkin telah memperhatikan kami startGame Fungsi memanggil fungsi shuffle. Ini adalah implementasi sederhana dari algoritma Fisher-Yates:
function shuffle(array) {
var m = array.length, t, i;
while (m) {
i = Math.floor(Math.random() * m--);
t = array[m];
array[m] = array[i];
array[i] = t;
}
return array;
}
Langkah 3. Pelajaran
Saatnya menjadi pembantu rumah tangga. Perpustakaan dan kerangka kerja modern sering kali memaksa konvensi tertentu yang membantu menerapkan struktur. Ketika hal -hal dimulai, ini masuk akal, dan dengan cepat menjadi berantakan untuk memasukkan semua kode dalam satu file.
Mari kita manfaatkan kekuatan modul untuk melestarikan kode, kesalahan, modularitas kita. Perbarui file HTML Anda dan ganti skrip Inline dengan yang berikut:
<script type="module" src="./js/step3.js"></script>
Sekarang, di JS/Step3.js kita dapat memuat penolong kita:
import loadCountries from "./helpers/loadCountries.js";
import shuffle from "./helpers/shuffle.js";
Pastikan untuk memindahkan fungsi shuffle dan memuat ke file masing -masing.
Catatan: Idealnya, kami juga akan mengimpor data kami. JSON digunakan sebagai modul, tetapi sayangnya, Firefox tidak mendukung klaim impor.
Anda juga perlu memulai setiap fitur dengan nilai default. Misalnya:
export default function shuffle(array) {
...
Kami juga akan merangkum logika game kami dalam kategori game. Ini membantu menjaga integritas data dan membuat kode lebih aman dan dapat dipelihara. Luangkan waktu sebentar untuk membaca komentar kode.
loadCountries('js/data.json')
.then((data) => {
const countries = data.countries;
const game = new Game(countries);
game.start();
});
class Game {
constructor(countries) {
this.masterCountries = countries;
this.DOM = {
flag: document.querySelector('h2.flag'),
answerButtons: document.querySelectorAll('.suggestions button')
}
this.DOM.answerButtons.forEach((button) => {
button.onclick = (e) => {
this.checkAnswer(e.target);
}
})
}
start() {
this.countries = shuffle([...this.masterCountries]);
const answer = this.countries.shift();
const selected = shuffle([answer, ...this.countries.slice(0, 4)]);
this.DOM.flag.innerText = answer.flag;
selected.forEach((country, index) => {
const button = this.DOM.answerButtons[index];
button.classList.remove('correct', 'wrong');
button.innerText = country.name;
button.dataset.correct = country.name === answer.name;
});
}
checkAnswer(button) {
const correct = button.dataset.correct === 'true';
if (correct) {
button.classList.add('correct');
alert('Correct! Well done!');
this.start();
} else {
button.classList.add('wrong');
alert('Wrong answer try again');
}
}
}
Langkah 4. Skor dan layar game
Mari kita perbarui konstruktor game untuk menangani beberapa putaran:
class Game {
constructor(countries, numTurns = 3) {
// number of turns in a game
this.numTurns = numTurns;
...
DOM kami perlu diperbarui sehingga kami dapat menangani permainan melalui status, menambahkan tombol replay dan menampilkan skor.
<main>
<div class="score">0</div>
<section class="play">
...
</section>
<section class="gameover hide">
<h2>Game Over</h2>
<p>You scored:
<span class="result">
</span>
</p>
<button class="replay">Play again</button>
</section>
</main>
Kami hanya menyembunyikan permainan di bagian ini sampai perlu.
Sekarang, tambahkan referensi ke elemen DOM baru ini di konstruktor game kami:
this.DOM = {
score: document.querySelector('.score'),
play: document.querySelector('.play'),
gameover: document.querySelector('.gameover'),
result: document.querySelector('.result'),
flag: document.querySelector('h2.flag'),
answerButtons: document.querySelectorAll('.suggestions button'),
replayButtons: document.querySelectorAll('button.replay'),
}
Kami juga akan mengatur metode start game kami, yang akan menunjukkan logika negara ke metode terpisah. Ini akan membantu menjaga kebersihan dan mudah dikelola.
start() {
this.countries = shuffle([...this.masterCountries]);
this.score = 0;
this.turn = 0;
this.updateScore();
this.showCountries();
}
showCountries() {
// get our answer
const answer = this.countries.shift();
// pick 4 more countries, merge our answer and shuffle
const selected = shuffle([answer, ...this.countries.slice(0, 4)]);
// update the DOM, starting with the flag
this.DOM.flag.innerText = answer.flag;
// update each button with a country name
selected.forEach((country, index) => {
const button = this.DOM.answerButtons[index];
// remove any classes from previous turn
button.classList.remove('correct', 'wrong');
button.innerText = country.name;
button.dataset.correct = country.name === answer.name;
});
}
nextTurn() {
const wrongAnswers = document.querySelectorAll('button.wrong')
.length;
this.turn += 1;
if (wrongAnswers === 0) {
this.score += 1;
this.updateScore();
}
if (this.turn === this.numTurns) {
this.gameOver();
} else {
this.showCountries();
}
}
updateScore() {
this.DOM.score.innerText = this.score;
}
gameOver() {
this.DOM.play.classList.add('hide');
this.DOM.gameover.classList.remove('hide');
this.DOM.result.innerText = `${this.score} out of ${this.numTurns}`;
}
Di bagian bawah metode konstruksi game, kami akan melakukannya
Dengarkan untuk mengklik tombol replay. ada
Klik acara dan kami restart dengan menelepon metode start.
this.DOM.replayButtons.forEach((button) => {
button.onclick = (e) => {
this.start();
}
});
Akhirnya, mari kita tambahkan sedikit gaya di tombol, tempatkan skor dan
Tambahkan kelas .Hide kami untuk beralih game sesuai kebutuhan.
button.correct { background: darkgreen; color: #fff; }
button.wrong { background: darkred; color: #fff; }
.score { position: absolute; top: 1rem; left: 50%; font-size: 2rem; }
.hide { display: none; }
kemajuan! Kami memiliki permainan yang sangat sederhana sekarang.
Namun, ini agak hambar. Mari kita selesaikan masalah ini
Di langkah berikutnya.
Kode dalam langkah ini
Langkah 5. Bawa kilau!
Animasi CSS adalah cara yang sangat sederhana dan ringkas
Menghidupkan elemen dan antarmuka statis.
Kerangka kerja utama
Memungkinkan kita untuk mendefinisikan kerangka kunci dari urutan animasi dengan mengubah
Properti CSS. Pertimbangkan ini sebagai gesek di dalam dan dalam daftar negara kami:
.slide-off { animation: 0.75s slide-off ease-out forwards; animation-delay: 1s;}
.slide-on { animation: 0.75s slide-on ease-in; }
@keyframes slide-off {
from { opacity: 1; transform: translateX(0); }
to { opacity: 0; transform: translateX(50vw); }
}
@keyframes slide-on {
from { opacity: 0; transform: translateX(-50vw); }
to { opacity: 1; transform: translateX(0); }
}
Kita bisa menerapkan efek geser saat memulai permainan …
start() {
// reset dom elements
this.DOM.gameover.classList.add('hide');
this.DOM.play.classList.remove('hide');
this.DOM.play.classList.add('slide-on');
...
}
… dan dalam metode NextTurn
nextTurn() {
...
if (this.turn === this.numTurns) {
this.gameOver();
} else {
this.DOM.play.classList.remove('slide-on');
this.DOM.play.classList.add('slide-off');
}
}
Setelah memeriksa jawabannya, kita juga perlu memanggil metode NextTurn. Perbarui metode checkanswer untuk mencapai ini:
checkAnswer(button) {
const correct = button.dataset.correct === 'true';
if (correct) {
button.classList.add('correct');
this.nextTurn();
} else {
button.classList.add('wrong');
}
}
Setelah animasi gesek selesai, kita perlu menggesek ke belakang dan memperbarui daftar negara. Kami dapat mengatur batas waktu berdasarkan panjang animasi dan melakukan logika ini. Untungnya, ada cara yang lebih mudah untuk menggunakan acara Animationend:
// listen to animation end events
// in the case of .slide-on, we change the card,
// then move it back on screen
this.DOM.play.addEventListener('animationend', (e) => {
const targetClass = e.target.classList;
if (targetClass.contains('slide-off')) {
this.showCountries();
targetClass.remove('slide-off', 'no-delay');
targetClass.add('slide-on');
}
});
Kode dalam langkah ini
Langkah 6. Sentuhan terakhir
Bukankah bagus untuk menambahkan layar judul? Dengan cara ini, pengguna akan mendapatkan beberapa konteks dan tidak akan secara langsung berinvestasi dalam permainan.
Tag kami terlihat seperti ini:
<div class="score hide">0</div>
<section class="intro fade-in">
<h1>
Guess the flag
</h1>
<p class="guess">π</p>
<p>How many can you recognize?</p>
<button class="replay">Start</button>
</section>
<section class="play hide">
...
Mari kita hubungkan layar Pendahuluan ke game.
Kita perlu menambahkan referensi ke elemen DOM:
this.DOM = {
intro: document.querySelector('.intro'),
....
Kemudian, sembunyikan saja saat Anda memulai permainan:
start() {
this.DOM.intro.classList.add('hide');
this.DOM.score.classList.remove('hide');
...
Juga, jangan lupa untuk menambahkan gaya baru:
section.intro p { margin-bottom: 2rem; }
section.intro p.guess { font-size: 8rem; }
.fade-in { opacity: 0; animation: 1s fade-in ease-out forwards; }
@keyframes fade-in {
from { opacity: 0; }
to { opacity: 1; }
}
Sekarang, bukankah menyenangkan memberikan peringkat kepada pemain berdasarkan skor mereka sendiri? Ini sangat mudah dicapai. Dapat dilihat bahwa dalam metode game yang diperbarui:
const ratings = ['π©','π€£','π΄','π€ͺ','π','π','π
','π','π€','π₯','β'];
const percentage = (this.score / this.numTurns) * 100;
const rating = Math.ceil(percentage / ratings.length);
this.DOM.play.classList.add('hide');
this.DOM.gameover.classList.remove('hide');
this.DOM.gameover.classList.add('fade-in');
this.DOM.result.innerHTML = `
${this.score} out of ${this.numTurns}
Your rating: ${this.ratings[rating]}
`;
}
Langkah terakhir; Kita dapat beralih ke animasi CSS lagi untuk mencapai efek ini.
button::before { content: ' '; background: url(../i/star.svg); height: 32px; width: 32px; position: absolute; bottom: -2rem; left: -1rem; opacity: 0; }
button::after { content: ' '; background: url(../i/star.svg); height: 32px; width: 32px; position: absolute; bottom: -2rem; right: -2rem; opacity: 0; }
button { position: relative; }
button.correct::before { animation: sparkle .5s ease-out forwards; }
button.correct::after { animation: sparkle2 .75s ease-out forwards; }
@keyframes sparkle {
from { opacity: 0; bottom: -2rem; scale: 0.5 }
to { opacity: 0.5; bottom: 1rem; scale: 0.8; left: -2rem; transform: rotate(90deg); }
}
@keyframes sparkle2 {
from { opacity: 0; bottom: -2rem; scale: 0.2}
to { opacity: 0.7; bottom: -1rem; scale: 1; right: -3rem; transform: rotate(-45deg); }
}
Kami menggunakan :::: gambar latar belakang yang digabungkan (star.svg) sebelum menggunakan :: π tetapi sembunyikan sebagai 0 dengan mengatur opacity. Kemudian, ketika tombol memiliki nama kelas yang benar, diaktifkan dengan memanggil animasi Sparkle. Ingatlah bahwa ketika jawaban yang benar dipilih, kami telah menerapkan kelas ini ke tombol.
Kode dalam langkah ini
Ringkasan dan beberapa pemikiran tambahan
Dalam kurang dari 200 baris javascript, kami memiliki lengkap
Bekerja, game ramah seluler. Dan tidak ada ketergantungan atau perpustakaan!
Tentu saja, kami dapat menambahkan fitur dan peningkatan permainan yang tidak terbatas.
Jika Anda menginginkan tantangan, berikut adalah beberapa ide:
- Tambahkan efek suara dasar untuk mendapatkan jawaban yang tepat dan jawaban yang salah.
- Game offline tersedia menggunakan pekerja web
- Simpan statistik seperti jumlah drama, peringkat keseluruhan dan tampilan LocalStorage
- Tambahkan cara untuk membagikan skor Anda dan menantang teman di media sosial.
rencana pengembangan website
metode pengembangan website
jelaskan beberapa rencana untuk pengembangan website, proses pengembangan website, kekuatan dan kelemahan bisnis pengembangan website
, jasa pengembangan website, tahap pengembangan website, biaya pengembangan website
#Buat #game #berbasis #browser #dengan #Vanilla #dan #CSS #beragampengetahuan