Igranje Rusta u 24 sata: iskustvo osobnog razvoja

Igranje Rusta u 24 sata: iskustvo osobnog razvoja

U ovom ću članku govoriti o svom osobnom iskustvu razvijanja male igre u Rustu. Za izradu radne verzije bilo je potrebno oko 24 sata (radio sam uglavnom navečer ili vikendom). Igra je daleko od završene, ali mislim da će iskustvo biti korisno. Podijelit ću ono što sam naučio i neka zapažanja koja sam napravio dok sam gradio igru ​​od nule.

Skillbox preporučuje: Dvogodišnji praktični tečaj "Ja sam PRO web programer".

Podsjećamo: za sve čitatelje "Habra" - popust od 10 000 rubalja pri upisu na bilo koji tečaj Skillbox koristeći promotivni kod "Habr".

Zašto Rust?

Izabrao sam ovaj jezik jer sam čuo mnogo dobrih stvari o njemu i vidim da postaje sve popularniji u razvoju igara. Prije pisanja igre, imao sam malo iskustva u razvoju jednostavnih aplikacija u Rustu. Ovo je bilo dovoljno da mi pruži osjećaj slobode dok pišem igru.

Zašto igra i kakva igra?

Pravljenje igara je zabavno! Volio bih da je više razloga, ali za “kućne” projekte biram teme koje nisu previše vezane uz moj redovni posao. Koja je ovo igrica? Htio sam napraviti nešto poput teniskog simulatora koji kombinira Cities Skylines, Zoo Tycoon, Prison Architect i sam tenis. Općenito, ispala je igra o teniskoj akademiji u koju ljudi dolaze igrati.

Tehnički trening

Htio sam koristiti Rust, ali nisam točno znao koliko će temelja biti potrebno za početak. Nisam želio pisati shadere piksela i koristiti drag-n-drop, pa sam tražio najfleksibilnija rješenja.

Pronašao sam korisne resurse koje dijelim s vama:

Istražio sam nekoliko Rust motora za igre, na kraju sam odabrao Piston i ggez. Naišao sam na njih radeći na prethodnom projektu. Na kraju sam odabrao ggez jer mi se činio prikladnijim za implementaciju male 2D igre. Pistonova modularna struktura je presložena za programera početnika (ili nekoga tko prvi put radi s Rustom).

Struktura igre

Proveo sam neko vrijeme razmišljajući o arhitekturi projekta. Prvi korak je napraviti "zemlju", ljude i teniske terene. Ljudi se moraju kretati po sudovima i čekati. Igrači moraju imati vještine koje se s vremenom poboljšavaju. Osim toga, trebao bi postojati uređivač koji vam omogućuje dodavanje novih ljudi i sudova, ali to više nije besplatno.

Nakon što sam sve dobro razmislio, prionuo sam na posao.

Stvaranje igre

Početak: Krugovi i apstrakcije

Uzeo sam primjer iz ggez i dobio krug na ekranu. Predivno! Sada neke apstrakcije. Mislio sam da bi bilo lijepo apstrahirati se od ideje objekta igre. Svaki objekt mora se prikazati i ažurirati kako 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 dao mi je lijep popis objekata koje sam mogao ažurirati i prikazati u jednako lijepoj petlji.

mpl event::EventHandler for MainState {
    fn update(&mut self, context: &mut Context) -> GameResult<()> {
        // Update all objects
        for object in self.objects.iter_mut() {
            object.update(context)?;
        }
 
        Ok(())
    }
 
    fn draw(&mut self, context: &mut Context) -> GameResult<()> {
        graphics::clear(context);
 
        // Draw all objects
        for object in self.objects.iter_mut() {
            object.draw(context)?;
        }
 
        graphics::present(context);
 
        Ok(())
    }
}

main.rs je neophodan jer sadrži sve linije koda. Proveo sam malo vremena odvajajući datoteke i optimizirajući strukturu direktorija. Ovako je to izgledalo nakon toga:
resursi -> ovdje su sva sredstva (slike)
src
- entiteta
— game_object.rs
— krug.rs
— main.rs -> glavna petlja

Ljudi, podovi i slike

Sljedeći korak je stvaranje objekta igre Person i učitavanje slika. Sve treba graditi na bazi pločica 32*32.

Igranje Rusta u 24 sata: iskustvo osobnog razvoja

Teniski tereni

Nakon što sam proučio kako izgledaju teniski tereni, odlučio sam ih napraviti od pločica 4*2. U početku je bilo moguće napraviti sliku ove veličine ili sastaviti 8 zasebnih pločica. Ali onda sam shvatio da su potrebne samo dvije jedinstvene pločice, a evo i zašto.

Ukupno imamo dvije takve pločice: 1 i 2.

Svaki dio igrališta sastoji se od pločice 1 ili pločice 2. Mogu se rasporediti normalno ili okrenuti za 180 stupnjeva.

Igranje Rusta u 24 sata: iskustvo osobnog razvoja

Osnovni način gradnje (montaže).

Nakon što sam uspio postići renderiranje mjesta, ljudi i karata, shvatio sam da je potreban i osnovni način sklapanja. Ja sam to implementirao ovako: kada se pritisne gumb, objekt se selektira, a klik ga postavlja na željeno mjesto. Dakle, gumb 1 omogućuje vam odabir terena, a gumb 2 omogućuje odabir igrača.

Ali još uvijek moramo zapamtiti što znače 1 i 2, pa sam dodao okvir da bude jasno koji je objekt odabran. Ovako to izgleda.

Igranje Rusta u 24 sata: iskustvo osobnog razvoja

Arhitektura i pitanja refaktoriranja

Sada imam nekoliko objekata za igru: ljude, terene i podove. Ali kako bi žičani okviri radili, svakom entitetu objekta treba reći jesu li sami objekti u demonstracijskom načinu rada ili je okvir jednostavno nacrtan. Ovo nije baš zgodno.

Činilo mi se da arhitekturu treba ponovno promisliti na način koji otkriva neka ograničenja:

  • Imati entitet koji sam sebe renderira i ažurira je problem jer taj entitet neće moći "znati" što bi trebao renderirati - sliku i okvir;
  • nedostatak alata za razmjenu svojstava i ponašanja između pojedinačnih entiteta (na primjer, svojstvo is_build_mode ili renderiranje ponašanja). Bilo bi moguće koristiti nasljeđivanje, iako ne postoji odgovarajući način da se to implementira u Rustu. Ono što mi je stvarno trebalo je raspored;
  • bio je potreban alat za interakciju između entiteta kako bi se ljudi raspoređivali u sudove;
  • sami entiteti bili su mješavina podataka i logike koja je brzo izmakla kontroli.

Još sam malo istraživao i otkrio sam arhitekturu ECS - Sustav entitetskih komponenti, koji se obično koristi u igrama. Evo prednosti ECS-a:

  • podaci su odvojeni od logike;
  • sastav umjesto nasljedstva;
  • data-centric arhitektura.

ECS karakteriziraju tri osnovna koncepta:

  • entiteti - vrsta objekta na koji se identifikator odnosi (može biti igrač, lopta ili nešto drugo);
  • komponente – od njih se sastoje entiteti. Primjer - komponenta renderiranja, lokacije i ostalo. To su skladišta podataka;
  • sustavi - koriste i objekte i komponente, plus sadrže ponašanje i logiku koji se temelje na tim podacima. Primjer je sustav prikazivanja koji ponavlja sve entitete s komponentama prikazivanja i izvodi prikazivanje.

Nakon proučavanja postalo je jasno da ECS rješava sljedeće probleme:

  • korištenje rasporeda umjesto nasljeđivanja za sustavnu organizaciju entiteta;
  • rješavanje zbrke koda kroz sustave upravljanja;
  • koristeći metode kao što je is_build_mode da zadrži wireframe logiku na istom mjestu - u sustavu renderiranja.

To se dogodilo nakon implementacije ECS-a.

resursi -> ovdje su sva sredstva (slike)
src
- komponente
—položaj.rs
— osoba.rs
— tennis_court.rs
— kat.rs
- wireframe.rs
— mouse_tracked.rs
- resursi
—miš.rs
- sustavi
— prikazivanje.rs
— konstante.rs
— utils.rs
— world_factory.rs -> funkcije svetske fabrike
— main.rs -> glavna petlja

Mi raspoređujemo ljude na sudove

ECS je olakšao život. Sada sam imao sustavan način dodavanja podataka entitetima i dodavanja logike na temelju tih podataka. A to je zauzvrat omogućilo organiziranje raspodjele ljudi po dvorovima.

Što sam učinio:

  • dodani podaci o dodijeljenim sudovima Osobi;
  • dodao podatke o raspoređenim ljudima na TennisCourt;
  • dodan CourtChoosingSystem, koji vam omogućuje analizu ljudi i terena, otkrivanje dostupnih terena i raspodjelu igrača na njih;
  • dodao PersonMovementSystem, koji traži osobe dodijeljene sudovima, a ako ih nema, šalje ljude gdje trebaju biti.

Igranje Rusta u 24 sata: iskustvo osobnog razvoja

Sažimanje

Zaista sam uživao radeći na ovoj jednostavnoj igrici. Štoviše, drago mi je što sam koristio Rust da ga napišem, jer:

  • Rust vam daje ono što trebate;
  • ima izvrsnu dokumentaciju, Rust je prilično elegantan;
  • konzistencija je hladna;
  • ne morate pribjegavati kloniranju, kopiranju ili drugim sličnim radnjama, što sam često radio u C++;
  • Opcije su vrlo jednostavne za korištenje i vrlo dobro rješavaju pogreške;
  • Ako se projekt uspio kompajlirati, onda 99% vremena radi, i to točno onako kako treba. Mislim da su poruke o pogrešci prevoditelja najbolje što sam vidio.

Razvoj igre u Rustu tek počinje. Ali već postoji stabilna i prilično velika zajednica koja radi na otvaranju Rusta svima. Stoga s optimizmom gledam u budućnost jezika, radujući se rezultatima zajedničkog rada.

Skillbox preporučuje:

Izvor: www.habr.com

Dodajte komentar