Hraní Rusta za 24 hodin: zkušenost s osobním rozvojem

Hraní Rusta za 24 hodin: zkušenost s osobním rozvojem

V tomto článku budu mluvit o své osobní zkušenosti s vývojem malé hry v Rustu. Vytvoření pracovní verze trvalo asi 24 hodin (většinou jsem pracoval po večerech nebo o víkendech). Hra není zdaleka dokončena, ale myslím, že zážitek bude odměňující. Podělím se o to, co jsem se naučil, a o několik postřehů, které jsem udělal při budování hry od nuly.

Skillbox doporučuje: Dvouletý praktický kurz "Jsem PRO webový vývojář".

Připomínáme: pro všechny čtenáře "Habr" - sleva 10 000 rublů při zápisu do jakéhokoli kurzu Skillbox pomocí propagačního kódu "Habr".

Proč Rust?

Vybral jsem si tento jazyk, protože jsem o něm slyšel spoustu dobrých věcí a vidím, že je ve vývoji her stále populárnější. Před psaním hry jsem měl málo zkušeností s vývojem jednoduchých aplikací v Rustu. To stačilo k tomu, abych měl pocit svobody při psaní hry.

Proč hra a jaký druh hry?

Vytváření her je zábava! Kéž by bylo více důvodů, ale pro „domácí“ projekty si vybírám témata, která s mojí běžnou prací příliš nesouvisí. co je to za hru? Chtěl jsem udělat něco jako tenisový simulátor, který kombinuje Cities Skylines, Zoo Tycoon, Prison Architect a tenis samotný. Obecně se ukázalo, že je to hra o tenisové akademii, kam lidé chodí hrát.

Technické školení

Chtěl jsem použít Rust, ale nevěděl jsem přesně, kolik základů bude zapotřebí k zahájení. Nechtěl jsem psát pixel shadery a používat drag-n-drop, takže jsem hledal co nejflexibilnější řešení.

Našel jsem užitečné zdroje, které s vámi sdílím:

Prozkoumal jsem několik herních enginů Rust, nakonec jsem si vybral Piston a ggez. Narazil jsem na ně při práci na předchozím projektu. Nakonec jsem zvolil ggez, protože se mi zdál vhodnější pro implementaci malé 2D hry. Modulární struktura Pistonu je pro začínajícího vývojáře (nebo někoho, kdo s Rustem pracuje poprvé) příliš složitá.

Struktura hry

Strávil jsem nějaký čas přemýšlením o architektuře projektu. Prvním krokem je udělat „země“, lidi a tenisové kurty. Lidé se musí pohybovat po kurtech a čekat. Hráči musí mít dovednosti, které se postupem času zlepšují. Navíc by měl existovat editor, který vám umožní přidávat nové lidi a soudy, ale to už není zadarmo.

Když jsem si vše promyslel, pustil jsem se do práce.

Tvorba hry

Začátek: Kruhy a abstrakce

Vzal jsem si příklad z ggez a dostal jsem na obrazovku kruh. Úžasné! Nyní nějaké abstrakce. Myslel jsem, že by bylo hezké abstrahovat od myšlenky herního objektu. Každý objekt musí 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 kus kódu mi dal pěkný seznam objektů, které jsem mohl aktualizovat a vykreslit ve stejně pěkné smyčce.

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 nezbytný, protože obsahuje všechny řádky kódu. Strávil jsem trochu času oddělením souborů a optimalizací adresářové struktury. Takhle to potom vypadalo:
zdroje -> zde jsou všechna aktiva (obrázky)
src
- entity
— game_object.rs
— kruh.rs
— main.rs -> hlavní smyčka

Lidé, podlahy a obrazy

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

Hraní Rusta za 24 hodin: zkušenost s osobním rozvojem

Tenisové kurty

Po prostudování toho, jak tenisové kurty vypadají, jsem se rozhodl je vyrobit z dlaždic 4*2. Zpočátku bylo možné vyrobit obraz této velikosti, nebo poskládat 8 samostatných dlaždic. Ale pak jsem si uvědomil, že jsou potřeba jen dvě unikátní dlaždice, a tady je důvod.

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

Každá část hřiště se skládá z dlaždice 1 nebo dlaždice 2. Mohou být rozloženy jako normální nebo otočené o 180 stupňů.

Hraní Rusta za 24 hodin: zkušenost s osobním rozvojem

Základní konstrukční (montážní) režim

Poté, co se mi podařilo dosáhnout vykreslení stránek, lidí a map, jsem si uvědomil, že je také potřeba základní režim sestavení. Implementoval jsem to takto: po stisknutí tlačítka se objekt vybere a kliknutím jej umístí na požadované místo. Tlačítko 1 tedy umožňuje výběr hřiště a tlačítko 2 umožňuje výběr hráče.

Stále si ale musíme pamatovat, co znamenají 1 a 2, takže jsem přidal drátěný model, aby bylo jasné, který objekt byl vybrán. Takhle to vypadá.

Hraní Rusta za 24 hodin: zkušenost s osobním rozvojem

Otázky architektury a refaktoringu

Nyní mám několik herních objektů: lidi, kurty a podlahy. Ale aby drátové modely fungovaly, musí být každé objektové entitě sděleno, zda jsou samotné objekty v demonstračním režimu, nebo zda je rámeček jednoduše nakreslen. To není příliš pohodlné.

Zdálo se mi, že je třeba architekturu přehodnotit způsobem, který odhalí některá omezení:

  • Mít entitu, která se sama vykresluje a aktualizuje, je problém, protože tato entita nebude schopna „vědět“, co má vykreslovat – obrázek a drátěný model;
  • chybí nástroj pro výměnu vlastností a chování mezi jednotlivými entitami (například vlastnost is_build_mode nebo vykreslování chování). Bylo by možné použít dědičnost, i když v Rustu neexistuje správný způsob, jak ji implementovat. Co jsem opravdu potřeboval, bylo rozložení;
  • k přidělování lidí k soudům byl zapotřebí nástroj pro interakci mezi subjekty;
  • samotné entity byly směsí dat a logiky, která se rychle vymkla kontrole.

Udělal jsem další průzkum a objevil architekturu ECS - Entity Component System, který se běžně používá ve hrách. Zde jsou výhody ECS:

  • data jsou oddělena od logiky;
  • složení místo dědictví;
  • datacentrická architektura.

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

  • entity - typ objektu, na který identifikátor odkazuje (může to být hráč, míč nebo něco jiného);
  • komponenty - entity jsou z nich tvořeny. Příklad - renderovací komponenta, umístění a další. Jedná se o datové sklady;
  • systémy – používají jak objekty, tak komponenty, navíc obsahují chování a logiku, které jsou založeny na těchto datech. Příkladem je vykreslovací systém, který prochází všemi entitami s vykreslovacími komponentami a provádí vykreslování.

Po prostudování se ukázalo, že ECS řeší následující problémy:

  • použití rozložení místo dědičnosti k systémové organizaci entit;
  • zbavit se změti kódu prostřednictvím řídicích systémů;
  • pomocí metod jako is_build_mode k udržení logiky drátěného modelu na stejném místě – v systému vykreslování.

To se stalo po implementaci ECS.

zdroje -> zde jsou všechna aktiva (obrázky)
src
- komponenty
—pozice.rs
— osoba.rs
— tennis_court.rs
— podlaha.rs
- wireframe.rs
— mouse_tracked.rs
- zdroje
—myš.rs
- systémy
— rendering.rs
— konstanty.rs
— utils.rs
— world_factory.rs -> funkce světové továrny
— main.rs -> hlavní smyčka

Přidělujeme lidi k soudům

ECS usnadnilo život. Nyní jsem měl systematický způsob, jak přidat data k entitám a přidat logiku založenou na těchto datech. A to zase umožnilo organizovat rozdělování lidí mezi soudy.

Co jsem udělal:

  • přidány údaje o přidělených soudech k osobě;
  • přidána data o distribuovaných lidech do TennisCourtu;
  • přidán CourtChoosingSystem, který umožňuje analyzovat lidi a soudy, zjišťovat dostupné kurty a distribuovat k nim hráče;
  • přidán PersonMovementSystem, který vyhledává osoby přidělené k soudům, a pokud tam nejsou, pošle je tam, kam potřebují.

Hraní Rusta za 24 hodin: zkušenost s osobním rozvojem

Sčítání

Práce na této jednoduché hře mě opravdu bavila. Navíc jsem rád, že jsem k jeho napsání použil Rust, protože:

  • Rust vám dává to, co potřebujete;
  • má výbornou dokumentaci, Rust je docela elegantní;
  • konzistence je chladná;
  • nemusíte se uchylovat ke klonování, kopírování nebo jiným podobným akcím, které jsem často dělal v C++;
  • Možnosti se velmi snadno používají a velmi dobře zvládají chyby;
  • Pokud se projekt podařilo sestavit, tak na 99 % funguje a přesně tak, jak má. Myslím, že chybové zprávy kompilátoru jsou nejlepší, jaké jsem kdy viděl.

Vývoj her v Rustu právě začíná. Ale už existuje stabilní a poměrně velká komunita, která se snaží otevřít Rust všem. Na budoucnost jazyka se proto dívám s optimismem a těším se na výsledky naší společné práce.

Skillbox doporučuje:

Zdroj: www.habr.com

Přidat komentář