|
|
1 month ago | |
|---|---|---|
| .. | ||
| solution | 3 months ago | |
| your-work | 3 months ago | |
| README.md | 1 month ago | |
| assignment.md | 1 month ago | |
README.md
Izgradnja svemirske igre, dio 6: Kraj i ponovno pokretanje
Svaka sjajna igra treba jasne uvjete završetka i glatki mehanizam za ponovno pokretanje. Izgradili ste impresivnu svemirsku igru s kretanjem, borbom i bodovanjem - sada je vrijeme da dodate završne dijelove koji će je učiniti potpunom.
Vaša igra trenutno traje beskonačno, poput sondi Voyager koje je NASA lansirala 1977. godine - još uvijek putuju svemirom desetljećima kasnije. Iako je to u redu za istraživanje svemira, igre trebaju definirane završetke kako bi pružile zadovoljavajuće iskustvo.
Danas ćemo implementirati odgovarajuće uvjete pobjede/poraza i sustav za ponovno pokretanje. Do kraja ove lekcije imat ćete uglađenu igru koju igrači mogu završiti i ponovno igrati, baš poput klasičnih arkadnih igara koje su definirale medij.
Kviz prije predavanja
Razumijevanje uvjeta završetka igre
Kada bi vaša igra trebala završiti? Ovo temeljno pitanje oblikovalo je dizajn igara još od ranih dana arkadnih igara. Pac-Man završava kada vas uhvate duhovi ili očistite sve točke, dok Space Invaders završava kada vanzemaljci stignu do dna ili ih sve uništite.
Kao kreator igre, vi definirate uvjete pobjede i poraza. Za našu svemirsku igru, evo provjerenih pristupa koji stvaraju zanimljivu igru:
- Uništeno je
Nneprijateljskih brodova: Često se događa da, ako podijelite igru na različite razine, morate uništitiNneprijateljskih brodova kako biste završili razinu. - Vaš brod je uništen: Postoje igre u kojima gubite igru ako je vaš brod uništen. Drugi uobičajeni pristup je koncept života. Svaki put kada je vaš brod uništen, oduzima se jedan život. Kada izgubite sve živote, gubite igru.
- Prikupili ste
Nbodova: Još jedan uobičajeni uvjet završetka je prikupljanje bodova. Kako ćete dobiti bodove ovisi o vama, ali često se bodovi dodjeljuju za razne aktivnosti poput uništavanja neprijateljskog broda ili prikupljanja predmeta koje neprijatelji ispuste kada su uništeni. - Završili ste razinu: To može uključivati nekoliko uvjeta, kao što su uništenje
Xneprijateljskih brodova, prikupljanjeYbodova ili možda prikupljanje određenog predmeta.
Implementacija funkcionalnosti za ponovno pokretanje igre
Dobre igre potiču ponovnu igrivost kroz glatke mehanizme za ponovno pokretanje. Kada igrači završe igru (ili dožive poraz), često žele odmah pokušati ponovno - bilo da poboljšaju svoj rezultat ili izvedbu.
Tetris je savršen primjer: kada blokovi dosegnu vrh, možete odmah započeti novu igru bez navigacije kroz složene izbornike. Izgradit ćemo sličan sustav za ponovno pokretanje koji čisto resetira stanje igre i brzo vraća igrače u akciju.
✅ Razmišljanje: Razmislite o igrama koje ste igrali. Pod kojim uvjetima završavaju i kako vas potiču na ponovno pokretanje? Što čini iskustvo ponovnog pokretanja glatkim, a što frustrirajućim?
Što ćete izgraditi
Implementirat ćete završne značajke koje će vaš projekt pretvoriti u cjelovito iskustvo igre. Ovi elementi razlikuju uglađene igre od osnovnih prototipova.
Evo što danas dodajemo:
- Uvjet pobjede: Uništite sve neprijatelje i dobijte zasluženu proslavu!
- Uvjet poraza: Ostajete bez života i suočavate se s porazom na ekranu.
- Mehanizam za ponovno pokretanje: Pritisnite Enter za povratak u igru - jer jedna igra nikad nije dovoljna.
- Upravljanje stanjem: Čista ploča svaki put - bez preostalih neprijatelja ili čudnih grešaka iz prethodne igre.
Početak rada
Pripremimo vaše razvojno okruženje. Trebali biste imati sve datoteke svoje svemirske igre iz prethodnih lekcija spremne.
Vaš projekt trebao bi izgledati otprilike ovako:
-| assets
-| enemyShip.png
-| player.png
-| laserRed.png
-| life.png
-| index.html
-| app.js
-| package.json
Pokrenite svoj razvojni server:
cd your-work
npm start
Ova naredba:
- Pokreće lokalni server na
http://localhost:5000 - Ispravno poslužuje vaše datoteke
- Automatski osvježava kada napravite promjene
Otvorite http://localhost:5000 u svom pregledniku i provjerite radi li vaša igra. Trebali biste se moći kretati, pucati i komunicirati s neprijateljima. Kada to potvrdite, možemo nastaviti s implementacijom.
💡 Profesionalni savjet: Kako biste izbjegli upozorenja u Visual Studio Codeu, deklarirajte
gameLoopIdna vrhu svoje datoteke kaolet gameLoopId;umjesto da ga deklarirate unutar funkcijewindow.onload. Ovo slijedi moderne najbolje prakse deklaracije varijabli u JavaScriptu.
Koraci implementacije
Korak 1: Kreiranje funkcija za praćenje uvjeta završetka
Potrebne su nam funkcije koje će pratiti kada bi igra trebala završiti. Poput senzora na Međunarodnoj svemirskoj postaji koji stalno prate kritične sustave, ove funkcije će kontinuirano provjeravati stanje igre.
function isHeroDead() {
return hero.life <= 0;
}
function isEnemiesDead() {
const enemies = gameObjects.filter((go) => go.type === "Enemy" && !go.dead);
return enemies.length === 0;
}
Što se događa u pozadini:
- Provjerava je li naš junak ostao bez života (au!)
- Broji koliko je neprijatelja još uvijek živo
- Vraća
truekada je bojno polje čisto od neprijatelja - Koristi jednostavnu logiku true/false za jednostavnost
- Filtrira sve objekte igre kako bi pronašao preživjele
Korak 2: Ažuriranje rukovatelja događajima za uvjete završetka
Sada ćemo povezati ove provjere uvjeta s sustavom događaja igre. Svaki put kada se dogodi sudar, igra će procijeniti hoće li to pokrenuti uvjet završetka. Ovo stvara trenutnu povratnu informaciju za ključne događaje u igri.
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);
});
Što se ovdje događa:
- Laser pogađa neprijatelja: Oboje nestaju, dobivate bodove i provjeravamo jeste li pobijedili.
- Neprijatelj pogađa vas: Gubite život i provjeravamo jeste li još uvijek u igri.
- Pametno redoslijed: Prvo provjeravamo poraz (nitko ne želi pobijediti i izgubiti u isto vrijeme!)
- Trenutne reakcije: Čim se dogodi nešto važno, igra to odmah registrira.
Korak 3: Dodavanje novih konstanti poruka
Morat ćete dodati nove vrste poruka u svoj objekt Messages. Ove konstante pomažu u održavanju dosljednosti i sprječavanju tipografskih pogrešaka u vašem sustavu događaja.
GAME_END_LOSS: "GAME_END_LOSS",
GAME_END_WIN: "GAME_END_WIN",
U gore navedenom, mi smo:
- Dodali konstante za događaje završetka igre radi održavanja dosljednosti
- Koristili opisne nazive koji jasno označavaju svrhu događaja
- Slijedili postojeću konvenciju imenovanja za vrste poruka
Korak 4: Implementacija kontrola za ponovno pokretanje
Sada ćete dodati kontrole tipkovnice koje omogućuju igračima ponovno pokretanje igre. Tipka Enter prirodan je izbor jer se obično povezuje s potvrđivanjem radnji i pokretanjem novih igara.
Dodajte detekciju tipke Enter u postojeći slušatelj događaja pritiska tipki:
else if(evt.key === "Enter") {
eventEmitter.emit(Messages.KEY_EVENT_ENTER);
}
Dodajte novu konstantu poruke:
KEY_EVENT_ENTER: "KEY_EVENT_ENTER",
Što trebate znati:
- Proširuje vaš postojeći sustav rukovanja događajima na tipkovnici
- Koristi tipku Enter kao okidač za ponovno pokretanje radi intuitivnog korisničkog iskustva
- Emitira prilagođeni događaj koji drugi dijelovi vaše igre mogu slušati
- Održava isti obrazac kao i vaše ostale kontrole tipkovnice
Korak 5: Kreiranje sustava za prikaz poruka
Vaša igra treba jasno komunicirati rezultate igračima. Kreirat ćemo sustav poruka koji prikazuje stanja pobjede i poraza koristeći tekst u boji, slično terminalskim sučeljima ranih računalnih sustava gdje je zelena označavala uspjeh, a crvena signalizirala pogreške.
Kreirajte funkciju displayMessage():
function displayMessage(message, color = "red") {
ctx.font = "30px Arial";
ctx.fillStyle = color;
ctx.textAlign = "center";
ctx.fillText(message, canvas.width / 2, canvas.height / 2);
}
Korak po korak, evo što se događa:
- Postavlja veličinu i obitelj fonta za jasan, čitljiv tekst
- Primjenjuje parametar boje s "crvenom" kao zadanim za upozorenja
- Centrira tekst horizontalno i vertikalno na platnu
- Koristi moderne JavaScript zadane parametre za fleksibilne opcije boja
- Koristi 2D kontekst platna za izravno prikazivanje teksta
Kreirajte funkciju endGame():
function endGame(win) {
clearInterval(gameLoopId);
// Set a delay to ensure any pending renders complete
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)
}
Što ova funkcija radi:
- Zamrzava sve na mjestu - nema više kretanja brodova ili lasera
- Uzima kratku pauzu (200ms) kako bi se posljednji kadar završio
- Briše ekran i boji ga crno za dramatičan efekt
- Prikazuje različite poruke za pobjednike i gubitnike
- Kodira vijesti bojama - zeleno za dobro, crveno za... pa, ne tako dobro
- Govori igračima kako se vratiti u igru
Korak 6: Implementacija funkcionalnosti za resetiranje igre
Sustav za resetiranje mora potpuno očistiti trenutno stanje igre i inicijalizirati novu sesiju igre. To osigurava da igrači započnu svježe, bez preostalih podataka iz prethodne igre.
Kreirajte funkciju resetGame():
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);
}
}
Razumijmo svaki dio:
- Provjerava je li trenutna petlja igre aktivna prije resetiranja
- Briše postojeću petlju igre kako bi zaustavila sve trenutne aktivnosti igre
- Uklanja sve slušatelje događaja kako bi spriječila curenje memorije
- Ponovno inicijalizira stanje igre s novim objektima i varijablama
- Pokreće novu petlju igre sa svim bitnim funkcijama igre
- Održava isti interval od 100ms za dosljedne performanse igre
Dodajte rukovatelja događajem za tipku Enter u svoju funkciju initGame():
eventEmitter.on(Messages.KEY_EVENT_ENTER, () => {
resetGame();
});
Dodajte metodu clear() u svoju klasu EventEmitter:
clear() {
this.listeners = {};
}
Ključne točke za zapamtiti:
- Povezuje pritisak tipke Enter s funkcionalnošću za resetiranje igre
- Registrira ovog slušatelja događaja tijekom inicijalizacije igre
- Pruža čist način za uklanjanje svih slušatelja događaja tijekom resetiranja
- Sprječava curenje memorije čišćenjem rukovatelja događaja između igara
- Resetira objekt slušatelja na prazno stanje za svježu inicijalizaciju
Čestitamo! 🎉
👽 💥 🚀 Uspješno ste izgradili kompletnu igru od temelja. Poput programera koji su stvorili prve video igre 1970-ih, transformirali ste linije koda u interaktivno iskustvo s odgovarajućim mehanikama igre i povratnim informacijama korisnika. 🚀 💥 👽
Postigli ste:
- Implementirali potpune uvjete pobjede i poraza s povratnim informacijama korisnika
- Kreirali besprijekoran sustav za ponovno pokretanje za kontinuiranu igrivost
- Dizajnirali jasnu vizualnu komunikaciju za stanja igre
- Upravljali složenim prijelazima stanja igre i čišćenjem
- Sastavili sve komponente u koherentnu, igrivu igru
Izazov GitHub Copilot Agent 🚀
Koristite Agent mode za dovršavanje sljedećeg izazova:
Opis: Poboljšajte svemirsku igru implementacijom sustava napredovanja kroz razine s povećanjem težine i dodatnim značajkama.
Zadatak: Kreirajte sustav svemirske igre s više razina gdje svaka razina ima više neprijateljskih brodova s povećanom brzinom i zdravljem. Dodajte množitelj bodova koji se povećava sa svakom razinom i implementirajte pojačanja (poput brzog pucanja ili štita) koja se nasumično pojavljuju kada se neprijatelji unište. Uključite bonus za završetak razine i prikaz trenutne razine na ekranu uz postojeći rezultat i živote.
Saznajte više o agent mode ovdje.
🚀 Izazov za dodatno poboljšanje
Dodajte zvuk svojoj igri: Poboljšajte iskustvo igranja implementacijom zvučnih efekata! Razmislite o dodavanju zvuka za:
- Pucanje lasera kada igrač puca
- Uništenje neprijatelja kada su brodovi pogođeni
- Oštećenje heroja kada igrač primi udarac
- Pobjedničku glazbu kada je igra osvojena
- Zvuk poraza kada je igra izgubljena
Primjer implementacije zvuka:
// Create audio objects
const laserSound = new Audio('assets/laser.wav');
const explosionSound = new Audio('assets/explosion.wav');
// Play sounds during game events
function playLaserSound() {
laserSound.currentTime = 0; // Reset to beginning
laserSound.play();
}
Što trebate znati:
- Kreira audio objekte za različite zvučne efekte
- Resetira
currentTimekako bi omogućio brzo ponavljanje zvučnih efekata - Rukuje pravilima automatske reprodukcije preglednika pokretanjem zvukova iz korisničkih interakcija
- Upravlja glasnoćom i vremenom zvuka za bolje iskustvo igre
💡 Resurs za učenje: Istražite ovaj audio sandbox kako biste saznali više o implementaciji zvuka u JavaScript igrama.
Kviz nakon predavanja
Pregled i samostalno učenje
Vaš zadatak je stvoriti novu uzornu igru, pa istražite neke zanimljive igre kako biste vidjeli kakvu biste igru mogli izgraditi.
Zadatak
Izjava o odricanju odgovornosti:
Ovaj dokument je preveden pomoću AI usluge za prevođenje Co-op Translator. Iako nastojimo osigurati točnost, imajte na umu da automatski prijevodi mogu sadržavati pogreške ili netočnosti. Izvorni dokument na izvornom jeziku treba smatrati autoritativnim izvorom. Za ključne informacije preporučuje se profesionalni prijevod od strane čovjeka. Ne preuzimamo odgovornost za nesporazume ili pogrešna tumačenja koja proizlaze iz korištenja ovog prijevoda.