Hra v Rustu za 24 hodiny: osobní zkušenost z vývoje

Hra v Rustu za 24 hodiny: osobní zkušenost z vývoje

V tomto článku se podělím o osobní zkušenost s vývojem malé hry v Rustu. Vytvoření funkční verze trvalo přibližně 24 hodin (většinou jsem pracovala večer nebo o víkendech). Hra je ještě daleko od dokončení, ale myslím, že zkušenost bude užitečná. Povím vám, co jsem se naučila, a o některých poznatcích, které jsem udělala při stavbě hry od nuly.

Skillbox doporučuje: Dvouroční praktický kurz „Jsem webový vývojář PRO“.

Připomínáme: pro všechny čtenáře "Habra" – sleva 10 000 korun při registraci na jakýkoli kurz Skillbox s promokódem "Habr".

Proč Rust?

Zvolila jsem tento jazyk, protože jsem o něm slyšela hodně dobrého a vidím, že se stává stále oblíbenějším ve světě vývoje her. Před psaním hry jsem měla malou zkušenost s vývojem jednoduchých aplikací v Rustu. To bylo právě dost na to, abych pocítila určitou svobodu během psaní hry.

Proč právě hra a jaká hra?

Vytváření her je zábava! Chtěla bych, aby bylo více důvodů, ale pro „domácí“ projekty volím témata, která nejsou příliš úzce spjata s mou běžnou prací. Jaká hra? Chtěla jsem vytvořit něco jako tenisový simulátor, kde se mísí Cities Skylines, Zoo Tycoon, Prison Architect a samozřejmě tenis. V podstatě, stvořila jsem hru o tenisové akademii, kam lidé přicházejí hrát.

Technická příprava

Chtěla jsem použít Rust, ale nevěděla jsem přesně, jak moc „od nuly“ budu potřebovat začít. Nechtěla jsem psát pixelové shadery a používat drag-n-drop, takže jsem hledala co nejflexibilnější řešení.

Našla jsem užitečné zdroje, kterými se s vámi podělím:

Prozkoumala jsem několik herních enginů v Rustu a nakonec vybrala Piston a ggez. S nimi jsem se setkala při práci na předchozím projektu. Nakonec jsem zvolila ggez, protože se zdál být vhodnější pro realizaci malého 2D projektu. Modulární struktura Piston je příliš složitá pro začínajícího vývojáře (nebo pro toho, kdo poprvé pracuje s Rustem).

Struktura hry

Strávila jsem nějaký čas přemýšlením o architektuře projektu. První krok — vytvořit „zemi“, lidi a tenisové kurty. Lidé by se měli pohybovat po kurtech a čekat. Hráči by měli mít dovednosti, které se vyvíjejí s časem. Navíc by měli mít editor, který umožňuje přidávat nové lidi a kurty, ale to už není zdarma.

Po pečlivém promyšlení jsem se pustila do práce.

Vytvoření hry

Začátek: kruhy a abstrakce

Vzala jsem si příklad z ggez a dostala jsem kruh na obrazovce. Úžasné! Teď trochu abstrakce. Přišlo mi rozumné abstrahovat od myšlenky herního objektu. Každý objekt by měl být vykreslen a aktualizován, jak je uvedeno zde:

// 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(())
    }
}

Tento úsek kódu mi umožnil získat skvělý seznam objektů, které mohu aktualizovat a vykreslovat ve stejně skvělém cyklu.

mpl event::EventHandler pro MainState {
    fn update(&mut self, context: &mut Context) -> GameResult {
        // Aktualizovat všechny objekty
        for object in self.objects.iter_mut() {
            object.update(context)?;
        }
 
        Ok(())
    }
 
    fn draw(&mut self, context: &mut Context) -> GameResult {
        graphics::clear(context);
 
        // Vykreslit všechny objekty
        for object in self.objects.iter_mut() {
            object.draw(context)?;
        }
 
        graphics::present(context);
 
        Ok(())
    }
}

main.rs je nezbytný, protože obsahuje všechny řádky kódu. Strávila jsem nějaký čas rozdělením souborů a optimalizací struktury adresářů. Takto to nyní vypadá:
resources -> zde jsou všechny zdroje (obrázky)
src
— entities
— game_object.rs
— circle.rs
— main.rs -> hlavní smyčka

Lidé, místa a obrázky

Další krok je vytvoření herního objektu Person a načtení obrázků. Vše by mělo být postaveno na dlaždicích o rozměrech 32*32.

Hra v Rustu za 24 hodiny: osobní zkušenost z vývoje

Tenisové kurty

Po prozkoumání tvaru tenisových kurtů jsem se rozhodla udělat je z dlaždic 4*2. Zpočátku bylo možné udělat obrázek této velikosti buď jako jeden obrázek, nebo složením osmi samostatných dlaždic. Ale pak jsem si uvědomila, že potřebuji jen dvě unikátní dlaždice, a tady je důvod.

Celkem máme dvě takové dlaždice: 1 a 2.

Každá sekce kurtu se skládá z dlaždice 1 nebo dlaždice 2. Mohou být umístěny normálně nebo otočeny o 180 stupňů.

Hra v Rustu za 24 hodiny: osobní zkušenost z vývoje

Hlavní režim stavění (sestavování)

Po dosažení vykreslování kurtů, lidí a map jsem pochopila, že také potřebuji základní režim sestavování. Implementovala jsem to tak, že když je stisknuto tlačítko – objekt je vybrán a kliknutí ho umístí na správné místo. Takže tlačítko 1 umožňuje vybrat kurt a tlačítko 2 umožňuje vybrat hráče.

Ale musíme si také pamatovat, co znamená 1 a 2, takže jsem přidala drátový model, aby bylo jasné, který objekt je vybrán. Takto to vypadá.

Hra v Rustu za 24 hodiny: osobní zkušenost z vývoje

Otázky o architektuře a refaktoringu

Nyní mám několik herních objektů: lidi, kurty a patra. Ale aby drátové modely fungovaly, je třeba každému objektu říci, zda jsou v režimu zobrazení, nebo zda je pouze nakreslena rámeček. To není zrovna pohodlné.

Myslím, že by bylo dobré přepracovat architekturu, aby se objevila některá omezení:

  • existence entity, která se zobrazuje a aktualizuje sama, je problém, protože tato entita nemůže 'poznat', co má vykreslit — obrázek nebo drátový model;
  • absence nástroje pro sdílení vlastností a chování mezi jednotlivými entitami (příklad — vlastnost is_build_mode nebo vykreslení chování). Mohla by se použít dědičnost, ačkoli v Rustu není normální způsob, jak ji realizovat. Co jsem skutečně potřebovala — byla kompozice;
  • nástroj pro vzájemnou interakci entit byl potřebný k přidělení lidí na kurty;
  • samotné entity představovaly směs dat a logiky, což velmi rychle vyšlo z kontroly.

Provedla jsem další studii a objevila architekturu ECS — Systém komponent a entit, který se obvykle používá ve hrách. Zde jsou výhody ECS:

  • data jsou oddělena od logiky;
  • kompozice místo dědičnosti;
  • architektura zaměřená na data.

ECS se vyznačuje třemi základními koncepty:

  • entity — typ objektu, na který odkazuje identifikátor (to může být hráč, míč nebo něco jiného);
  • komponenty — z nich se entity skládají. Příklad — renderovací komponent, umístění a další. To jsou úložiště dat;
  • systémy — ty používají jak objekty, tak komponenty a obsahují chování a logiku, která se zakládá na těchto datech. Příklad — renderovací systém, který prochází všechny entity s komponenty pro vykreslení a stará se o vykreslování.

Po studiu bylo jasné, že ECS řeší následující problémy:

  • použití kompozice místo dědičnosti pro systémovou organizaci entit;
  • zbavení se chaosu kódu díky systémům řízení;
  • využití metod jako is_build_mode k uchování logiky drátového modelu na stejném místě — v renderovacím systému.

Toto je výsledek po zavedení ECS.

resources -> zde jsou všechny zdroje (obrázky)
src
— komponenty
— position.rs
— person.rs
— tennis_court.rs
— floor.rs
— wireframe.rs
— mouse_tracked.rs
— resources
— mouse.rs
— systémy
— rendering.rs
— constants.rs
— utils.rs
— world_factory.rs -> world factory functions
— main.rs -> hlavní smyčka

Přiřazujeme lidi na kurty

ECS mi usnadnila život. Nyní jsem měl systémovou cestu pro přidávání dat k entitám a přidávání logiky na základě těchto dat. To na oplátku umožnilo organizovat rozdělení lidí na kurty.

Co jsem udělala:

  • přidala jsem data o přiřazených kurtech do osoby;
  • přidala jsem data o rozdělených lidech do TennisCourt;
  • přidala jsem CourtChoosingSystem, který umožňuje analyzovat lidi a místa, objevovat dostupné kurty a rozdělovat hráče na ně;
  • přidala jsem systém PersonMovementSystem, který hledá lidi přiřazené na kurty, a pokud tam nejsou, posílá lidi tam, kam je třeba.

Hra v Rustu za 24 hodiny: osobní zkušenost z vývoje

Shrnutí

Práce na této jednoduché hře se mi velmi líbila. Navíc jsem ráda, že jsem pro její napsání použila Rust, protože:

  • Rust vám dává to, co potřebujete;
  • má skvělou dokumentaci, Rust je velmi elegantní;
  • stálost je skvělá;
  • nemusíte se uchylovat ke klonování, kopírování nebo jiným podobným věcem, které jsem často dělala v C++;
  • Options jsou velmi pohodlné na práci, také skvěle zpracovávají chyby;
  • pokud se projekt podařilo zkompilovat, 99% šancí, že funguje, a to přesně tak, jak má. Chybové hlášení překladače se mi zdá být nejlepší, jaké jsem viděla.

Vývoj her na Rustu teprve začíná. Ale již existuje stabilní a poměrně velká komunita, která pracuje na tom, aby Rust otevřela všem. Takže se dívám do budoucnosti jazyka s optimismem, netrpělivě očekávající výsledky naší společné práce.

Skillbox doporučuje:

Zdroj: habr.com

Koupit spolehlivý hosting pro webové stránky s ochranou proti DDoS, VPS VDS servery 🔥 Koupit spolehlivý hosting pro webové stránky s ochranou proti DDoS, VPS VDS servery | ProHoster