Spill pÄ Rust pÄ 24 timer: personlig utviklingserfaring

Spill pÄ Rust pÄ 24 timer: personlig utviklingserfaring

I denne artikkelen vil jeg dele min personlige erfaring med utviklingen av et lite spill i Rust. Det tok omtrent 24 timer Ă„ lage en fungerende versjon (jeg jobbet hovedsakelig om kveldene eller i helgene). Spillet er fortsatt langt fra ferdig, men jeg mener erfaringen vil vĂŠre nyttig. Jeg vil fortelle hva jeg har lĂŠrt og om noen observasjoner jeg har gjort mens jeg bygde spillet fra bunnen av.

Skillbox anbefaler: ToÄrig praktisk kurs «Jeg er PRO webutvikler».

Vi minner om: for alle lesere av «Habr» — 10 000 rubler rabatt ved pĂ„melding til hvilket som helst Skillbox-kurs med kampanjekoden «Habr».

Hvorfor Rust?

Jeg valgte dette sprÄket fordi jeg har hÞrt mye positivt om det og ser at det blir stadig mer populÊrt innen spillutvikling. FÞr jeg begynte med spillet, hadde jeg noe erfaring med Ä utvikle enkle applikasjoner i Rust. Dette var akkurat nok til Ä fÞle en viss frihet mens jeg skrev spillet.

Hvorfor spill og hvilket spill?

Å lage spill er gĂžy! Jeg skulle Ăžnske det var flere grunner, men for «hjemme» prosjekter velger jeg temaer som ikke er alltför nĂŠrt knyttet til min vanlige jobb. Hvilket spill? Jeg Ăžnsket Ă„ lage noe som lignet pĂ„ en tennissimulator, hvor Cities Skylines, Zoo Tycoon, Prison Architect og selve tennis blandes. Totalt sett ble det et spill om en tennisskole der folk kommer for Ă„ spille.

Teknisk forberedelse

Jeg Þnsket Ä bruke Rust, men jeg visste ikke nÞyaktig hvor mye jeg mÄtte begynne fra «bunnen» av. Jeg ville ikke skrive pikselshadere eller bruke dra-og-slipp, sÄ jeg lette etter de mest fleksible lÞsningene.

Jeg fant nyttige ressurser som jeg deler med deg:

Jeg utforsket flere spillmotorer i Rust og endte til slutt opp med Piston og ggez. Jeg hadde stÞtt pÄ dem da jeg jobbet med et tidligere prosjekt. Til slutt valgte jeg ggez fordi det virket mer passende for Ä lage et lite 2D-spill. Den modulÊre strukturen i Piston er for komplisert for en nybegynner (eller for de som jobber med Rust for fÞrste gang).

Spillstrukturen

Jeg brukte litt tid pÄ Ä tenke over prosjektets arkitektur. Det fÞrste steget er Ä lage «jorden», folk og tennisbaner. Folk skal bevege seg rundt pÄ banene og vente. Spillerne skal ha ferdigheter som forbedres over tid. I tillegg bÞr det vÊre en redaktÞr som lar deg legge til nye folk og baner, men det er ikke gratis.

Etter Ă„ ha tenkt over alt, begynte jeg arbeidet.

Spilling av spillet

Start: sirkler og abstraksjoner

Jeg tok et eksempel fra ggez og fikk en sirkel pÄ skjermen. Fantastisk! NÄ litt abstraksjoner. Jeg mente det var en god idé Ä abstrahere fra tanken om et spillobjekt. Hvert objekt mÄ bli gjengitt og oppdatert, som angitt her:

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

Denne koden ga meg en flott liste over objekter jeg kan oppdatere og gjengi i en minst like flott lĂžkke.

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

main.rs er nÞdvendig fordi det inneholder alle kodebitene. Jeg brukte litt tid pÄ Ä dele opp filene og optimalisere mappestrukturen. Her er hvordan alt sÄ ut etter dette:
resources -> dette er hvor alle ressursene er (bilder)
src
— enheter
— game_object.rs
— circle.rs
— main.rs -> hovedlþkken

Mennesker, baner og bilder

Neste steg er Ä lage spillobjektet Person og laste opp bilder. Alt mÄ bygges pÄ 32*32 fliser.

Spill pÄ Rust pÄ 24 timer: personlig utviklingserfaring

Tennisbaner

Etter Ä ha sett hvordan tennisbaner ser ut, bestemte jeg meg for Ä lage dem med 4*2 fliser. Jeg kunne opprinnelig lage et bilde av den stÞrrelsen eller sette sammen 8 separate fliser. Men sÄ innsÄ jeg at bare to unike fliser er nÞdvendige, og her er hvorfor.

Vi har totalt to slike fliser: 1 og 2.

Hver seksjon av banen bestÄr av flis 1 eller flis 2. De kan plasseres vanlig eller vÊre snudd 180 grader.

Spill pÄ Rust pÄ 24 timer: personlig utviklingserfaring

Grunnleggende bygge-modus

Etter Ä ha fÄtt til gjengivelsen av baner, mennesker og kart, forstod jeg at vi ogsÄ trenger en grunnleggende byggemodus. Jeg implementerte det slik: nÄr knappen trykkes, blir objektet valgt, og et klikk plasserer det pÄ riktig sted. Dermed lar knapp 1 oss velge banen, mens knapp 2 lar oss velge spilleren.

Men vi mÄ ogsÄ huske hva 1 og 2 betyr, sÄ jeg la til et wireframe for Ä vise hvilket objekt som er valgt. Slik ser det ut.

Spill pÄ Rust pÄ 24 timer: personlig utviklingserfaring

SpÞrsmÄl om arkitektur og refaktorering

NÄ har jeg flere spillobjekter: mennesker, baner og etasjer. Men for at rammeverkene skal fungere, mÄ hver objekt enhet informere om de selv er i demonstrasjonsmodus eller om det bare er et rammeverk tegnet. Det er ikke veldig praktisk.

Jeg fĂžlte at det var nĂždvendig Ă„ revurdere arkitekturen slik at noen begrensninger ble avslĂžrt:

  • tilstedevĂŠrelsen av en enhet som viser og oppdaterer seg selv er et problem, siden denne enheten ikke vil kunne «vite» hva den skal rendere — bilde og rammeverk;
  • mangel pĂ„ et verktĂžy for utveksling av egenskaper og atferd mellom separate enheter (for eksempel egenskapen is_build_mode eller rendering av atferd). Man kunne ha brukt arv, selv om Rust ikke har en ordentlig mĂ„te Ă„ implementere det pĂ„. Det jeg virkelig trengte var komposisjon;
  • et verktĂžy for interaksjon mellom enheter var nĂždvendig for Ă„ tilordne mennesker til baner;
  • selve enhetene bestod av en blanding av data og logikk, noe som raskt kom ut av kontroll.

Jeg gjorde en ekstra studie og oppdaget arkitekturen ECS — Entity Component System, som vanligvis brukes i spill. Her er fordelene med ECS:

  • data er adskilt fra logikk;
  • komposisjon i stedet for arv;
  • dataorientert arkitektur.

For ECS er tre grunnleggende konsepter karakteristiske:

  • enheter — en type objekt som henvises til av en identifikator (dette kan vĂŠre en spiller, en ball, eller noe annet);
  • komponenter — de som enhetene bestĂ„r av. For eksempel — renderingskomponent, plassering og andre. Dette er datalagre;
  • systemer — de bruker bĂ„de objektene og komponentene, og inneholder atferd og logikk som er basert pĂ„ disse dataene. For eksempel — et renderingssystem som gĂ„r gjennom alle enheter med komponenter for rendering og hĂ„ndterer tegning.

Etter studien ble det klart at ECS lĂžser slike problemer:

  • bruk av komposisjon i stedet for arv for systematisk organisering av enheter;
  • fjerning av kodehermetikk gjennom styringssystemer;
  • bruk av metoder som is_build_mode for Ă„ lagre rammeverkatferd pĂ„ ett og samme sted - i renderingssystemet.

Slik ble det etter implementeringen av ECS.

resources -> dette er hvor alle ressursene er (bilder)
src
— komponenter
— position.rs
— person.rs
— tennis_court.rs
— floor.rs
— wireframe.rs
— mouse_tracked.rs
— ressurser
— mouse.rs
— systemer
— rendering.rs
— constants.rs
— utils.rs
— world_factory.rs -> world factory functions
— main.rs -> hovedlþkken

Vi har tildelt folk til banene

ECS har gjort livet enklere. NÄ hadde jeg en systemisk mÄte Ä legge til data til enheter og legge til logikk basert pÄ disse dataene. Dette har igjen gjort det mulig Ä organisere tildelingen av folk til banene.

Hva jeg gjorde:

  • la til data om tildelte baner i Person;
  • la til data om fordelte personer i TennisCourt;
  • la til CourtChoosingSystem som lar analysere folk og fasiliteter, oppdage tilgjengelige baner og fordele spillere til dem;
  • la til PersonMovementSystem som finner personer tildelt til banene, og hvis de ikke er der, sender dem dit de trenger Ă„ vĂŠre.

Spill pÄ Rust pÄ 24 timer: personlig utviklingserfaring

Oppsummering

Jeg likte veldig godt Ă„ jobbe med dette enkle spillet. Dessuten er jeg fornĂžyd med at jeg brukte Rust til Ă„ skrive det, fordi:

  • Rust gir deg det du trenger;
  • det har utmerket dokumentasjon, Rust er ganske elegant;
  • konstans er kult;
  • jeg trenger ikke Ă„ ty til kloning, kopiering eller andre lignende handlinger, som jeg ofte gjorde i C++;
  • Options er veldig praktiske Ă„ jobbe med, de hĂ„ndterer ogsĂ„ feil pĂ„ en utmerket mĂ„te;
  • hvis prosjektet klarte Ă„ kompilere, sĂ„ fungerer det i 99% av tilfellene, nĂžyaktig slik det skal. Kompilatork feilmeldinger er, etter min mening, de beste jeg har sett.

Spillutvikling pÄ Rust er bare i gang. Men det finnes allerede et stabilt og ganske stort fellesskap som jobber med Ä Äpne Rust for alle. Derfor ser jeg optimistisk pÄ framtiden for sprÄket, og ser frem til resultatene av vÄrt felles arbeid.

Skillbox anbefaler:

Kilde: habr.com

KjĂžp pĂ„litelig hosting for nettsteder med DDoS-beskyttelse, VPS VDS-servere đŸ”„ KjĂžp pĂ„litelig hosting for nettsteder med DDoS-beskyttelse, VPS VDS-servere | ProHoster