
U ovom članku ću pričati o osobnom iskustvu razvoja male igre na Rustu. Izrada funkcionalne verzije trajala je oko 24 sata (većinom sam radila navečer ili vikendom). Igra je još uvijek daleko od završetka, ali mislim da će iskustvo biti korisno. Ispričat ću što sam naučila i neka zapažanja koja sam stekla tijekom stvaranja igre od nule.
Skillbox preporučuje: Dvoipogodišnji praktični tečaj .
Podsjećamo: za sve čitatelje "Habra" — popust od 10 000 rubalja prilikom upisa na bilo koji tečaj Skillbox uz promo kod "Habr".
Zašto Rust?
Odabrala sam ovaj jezik jer sam čula mnogo dobrih stvari o njemu i vidim da postaje sve popularniji u području razvoja igara. Prije pisanja igre imala sam malo iskustva u razvoju jednostavnih aplikacija na Rustu. To je bilo dovoljno da osjetim određenu slobodu tijekom pisanja igre.
Zašto baš igra i koja igra?
Gradnja igara je zabavna! Voljela bih da razloga ima više, ali za „kućne“ projekte biram teme koje nisu previše povezane s mojim uobičajenim poslom. Koja je to igra? Htjela sam napraviti nešto poput teniskog simulatora, gdje se kombiniraju Cities Skylines, Zoo Tycoon, Prison Architect i, naravno, tenis. Ukratko, nastala je igra o teniskoj akademiji, gdje ljudi dolaze igrati.
Tehnička priprema
Željela sam koristiti Rust, ali nisam bila sigurna koliko „od nule“ ću trebati početi raditi. Nisam htjela pisati pikselne shadere i koristiti drag-n-drop, pa sam tražila najfleksibilnija rješenja.
Našla sam korisne izvore koje dijelim s vama:
- — popis potrebnih elemenata Rust za razvoj igara;
Istražila sam nekoliko Rust game engine-a, a na kraju sam odabrala Piston i ggez. S njima sam se susretala radeći na prethodnom projektu. Na kraju sam odabrala ggez jer mi se činilo prikladnijim za realizaciju male 2D igre. Modularna struktura Piston-a previše je složena za početnika (ili onoga tko prvi put radi s Rust-om).
Struktura igre
Provela sam malo vremena razmišljajući o arhitekturi projekta. Prvi korak je napraviti „zemlju“, ljude i teniske terene. Ljudi trebaju biti u mogućnosti kretati se po terenima i čekati. Igrači trebaju imati vještine koje se razvijaju s vremenom. Također, trebao bi postojati urednik koji omogućuje dodavanje novih ljudi i terena, ali to već nije besplatno.
Razmišljajući o svemu, počela sam s radom.
Izrada igre
Početak: krugovi i apstrakcije
Uzeo sam primjer iz ggez i dobio krug na ekranu. Nevjerojatno! Sada malo apstrakcija. Činilo mi se da bi bilo dobro apstrahirati se od ideje igračke objekta. Svaki objekt trebao bi biti renderiran i ažuriran, kao što je ovdje navedeno:
// the game object trait
trait GameObject {
fn update(&mut self, _ctx: &mut Context) -> GameResult<()>;
fn draw(&mut self, ctx: &mut Context) -> GameResult<()>;
}
// a specific game object - Circle
struct Circle {
position: Point2,
}
impl Circle {
fn new(position: Point2) -> Circle {
Circle { position }
}
}
impl GameObject for Circle {
fn update(&mut self, _ctx: &mut Context) -> GameResult<()> {
Ok(())
}
fn draw(&mut self, ctx: &mut Context) -> GameResult<()> {
let circle =
graphics::Mesh::new_circle(ctx, graphics::DrawMode::Fill, self.position, 100.0, 2.0)?;
graphics::draw(ctx, &circle, na::Point2::new(0.0, 0.0), 0.0)?;
Ok(())
}
}Ovaj dio koda omogućio mi je da dobijem izvrstan popis objekata koje mogu ažurirati i renderirati u ne manje odličnom ciklusu.
mpl event::EventHandler for MainState {
fn update(&mut self, context: &mut Context) -> GameResult {
// Ažuriraj sve objekte
for object in self.objects.iter_mut() {
object.update(context)?;
}
Ok(())
}
fn draw(&mut self, context: &mut Context) -> GameResult {
graphics::clear(context);
// Nacrtaj sve objekte
for object in self.objects.iter_mut() {
object.draw(context)?;
}
graphics::present(context);
Ok(())
}
} main.rs je potreban jer sadrži sve linije koda. Provela sam malo vremena kako bih razdvojila datoteke i optimizirala strukturu direktorija. Evo kako je sve izgledalo nakon toga:
resources -> ovdje su svi resursi (slike)
src
— entiteti
— game_object.rs
— circle.rs
— main.rs -> glavna petlja
Ljudi, tereni i slike
Sljedeći korak je stvaranje igračkog objekta Person i učitavanje slika. Sve bi se trebalo temeljiti na pločicama dimenzija 32*32.

Teniski tereni
Istražujući kako izgledaju teniski tereni, odlučila sam ih napraviti od pločica 4*2. Isprva se moglo napraviti sliku te veličine ili sastaviti 8 odvojenih pločica. No kasnije sam shvatila da su potrebne samo dvije jedinstvene pločice, i evo zašto.
Ima samo dvije takve pločice: 1 i 2.
Svaka sekcija terena sastoji se od pločice 1 ili pločice 2. Mogu se nalaziti obično ili biti okrenute za 180 stupnjeva.

Glavni način gradnje (sastavljanja)
Nakon što sam bila u mogućnosti postići renderiranje igrališta, ljudi i karata, shvatila sam da mi je potreban i osnovni način sastavljanja. Implementirala sam ga tako: kada se pritisne gumb — objekt se odabire, a klik ga postavlja na željeno mjesto. Tako gumb 1 omogućava odabir terena, a gumb 2 dopušta odabir igrača.
Ali potrebno je i zapamtiti što za nas 1 i 2 znače, pa sam dodala wireframe kako bi bilo jasno koji je objekt odabran. Evo kako to izgleda.

Pitanja o arhitekturi i refaktoringu
Sada imam nekoliko igraćih objekata: ljude, terene i etaže. No, kako bi wireframeovi funkcionirali, svakoj entiteti objekta treba reći jesu li sami objekti u načinu demonstracije ili je samo okvir nacrtan. To nije baš praktično.
Činilo mi se da treba preispitati arhitekturu kako bi se otkrila određena ograničenja:
- postojanje entiteta koji se prikazuje i ažurira samog sebe — to je problem, jer taj entitet ne može "znati" što treba renderirati — sliku i wireframe;
- nedostatak alata za razmjenu svojstava i ponašanja između pojedinačnih entiteta (primjer — svojstvo is_build_mode ili renderiranje ponašanja). Moglo bi se koristiti nasljeđivanje, iako u Rustu ne postoji normalan način njegove implementacije. Ono što mi je zaista trebalo — to je kompozicija;
- alat za međusobnu interakciju entiteta bio je potreban kako bi se ljudi dodijelili terenom;
- sami entiteti predstavljali su mješavinu podataka i logike, što je vrlo brzo izmaklo kontroli.
Provela sam dodatno istraživanje i otkrila arhitekturu , koji se obično koristi u igrama. Evo prednosti ECS-a:
- podaci su odvojeni od logike;
- kompozicija umjesto nasljeđivanja;
- arhitektura usmjerena na podatke.
Za ECS su karakteristične tri osnovne koncepcije:
- entiteti — tip objekta na koji se odnosi identifikator (to može biti igrač, loptica ili nešto drugo);
- komponente — od kojih se sastoje entiteti. Primjer — komponenta za renderiranje, pozicioniranje i druge. To su skladišta podataka;
- sustavi — oni koriste i objekte i komponente, plus sadrže ponašanje i logiku koja se temelji na tim podacima. Primjer — sustav za renderiranje koji prolazi kroz sve entitete s komponentama za renderiranje i bavi se crtanjem.
Nakon proučavanja, postalo je jasno da ECS rješava takve probleme:
- primjenu kompozicije umjesto nasljeđivanja za sistemsku organizaciju entiteta;
- uklanjanje neredovitosti koda pomoću sustava upravljanja;
- korištenje metoda poput is_build_mode za pohranu logike wireframea na istom mjestu — u sustavu za renderiranje.
Evo što je rezultiralo nakon implementacije ECS-a.
resources -> ovdje su svi resursi (slike)
src
— komponente
— position.rs
— person.rs
— tennis_court.rs
— floor.rs
— wireframe.rs
— mouse_tracked.rs
— resursi
— mouse.rs
— sustavi
— rendering.rs
— constants.rs
— utils.rs
— world_factory.rs -> funkcije svjetske tvornice
— main.rs -> glavna petlja
Dodeljujemo ljude na terene
ECS je olakšala život. Sada sam imala sistemski put za dodavanje podataka entitetima i dodavanje logike zasnovane na tim podacima. To je zauzvrat omogućilo organizaciju raspodele ljudi po terenima.
Šta sam uradila:
- dodala podatke o dodeljenim terenima u Person;
- dodala podatke o raspodeljenim ljudima u TennisCourt;
- dodala CourtChoosingSystem, koja omogućava analiziranje ljudi i terena, otkrivanje dostupnih terena i raspoređivanje igrača na njih;
- dodala sistem PersonMovementSystem, koji pronalazi ljude dodeljene terenom, i ako ih nema tamo, šalje ljude gde treba.

Zaključujemo
Vrlo mi je bilo drago raditi na ovoj jednostavnoj igri. Štaviše, zadovoljna sam što sam koristila Rust za njeno pisanje, jer:
- Rust vam pruža ono što je potrebno;
- ima odličnu dokumentaciju, Rust je veoma elegantan;
- postojanost je sjajna;
- ne moram pribegavati kloniranju, kopiranju ili sličnim radnjama, što sam često radila u C++;
- Options su veoma korisne za rad, takođe savršeno obrađuju greške;
- ako je projekat uspeo da se kompajlira, u 99% slučajeva funkcioniše onako kako treba. Smatram da su poruke grešaka kompajlera najbolje koje sam videla.
Razvoj igara na Rustu tek počinje. Ali postoji stabilna i prilično velika zajednica koja radi na tome da otvori Rust za sve. Zbog toga gledam na budućnost jezika s optimizmom, s nestrpljenjem očekujući rezultate našeg zajedničkog rada.
Skillbox preporučuje:
- Online tečaj .
- Praktični tečaj .
- Praktični godišnji tečaj .
Izvor: habr.com
