Playing Rust in 24 hours: sperienza di sviluppu persunale

Playing Rust in 24 hours: sperienza di sviluppu persunale

In questu articulu, parraraghju di a mo sperienza persunale di sviluppà un picculu ghjocu in Rust. Pigliò circa 24 ore per creà una versione di travagliu (aghju travagliatu soprattuttu in a sera o in u weekend). U ghjocu hè luntanu da esse finitu, ma pensu chì l'esperienza serà gratificante. Aghju sparte ciò chì aghju amparatu è alcune osservazioni chì aghju fattu mentre custruisce u ghjocu da zero.

Skillbox consiglia: Corso praticu di dui anni "Sò un sviluppatore web PRO".

Ramintemu: per tutti i lettori di "Habr" - un scontu di 10 000 rubles quandu si iscrizzione in ogni cursu Skillbox cù u codice promozionale "Habr".

Perchè Rust?

Aghju sceltu sta lingua perchè aghju intesu assai cose boni è vecu chì diventa sempre più populari in u sviluppu di u ghjocu. Prima di scrive u ghjocu, aghju avutu pocu sperienza in u sviluppu di applicazioni simplici in Rust. Questu era solu abbastanza per dà un sensu di libertà mentre scrive u ghjocu.

Perchè u ghjocu è chì tipu di ghjocu?

Fà ghjochi hè divertente! Vulariu chì ci era più ragiuni, ma per i prughjetti di "casa" sceglite temi chì ùn sò micca troppu in relazione cù u mo travagliu regulare. Chì ghjocu hè questu? Vuliu fà qualcosa cum'è un simulatore di tennis chì combina Cities Skylines, Zoo Tycoon, Prison Architect è u tennis stessu. In generale, hè diventatu un ghjocu nantu à una accademia di tennis induve a ghjente vene à ghjucà.

Formazione tecnica

Vuliu usà Rust, ma ùn sapia micca esattamente quantu travagliu di basi ci vole à principià. Ùn vulia micca scrive pixel shaders è aduprà drag-n-drop, cusì cercava e soluzioni più flessibili.

Aghju trovu risorse utili chì sparte cun voi:

Aghju esploratu parechji motori di ghjocu Rust, in fine di sceglie Piston è ggez. L'aghju scontru mentre travagliava in un prughjettu precedente. In fine, aghju sceltu ggez perchè pareva più adattatu per implementà un picculu ghjocu 2D. A struttura modulare di Piston hè troppu cumplessa per un sviluppatore principiante (o qualchissia chì travaglia cù Rust per a prima volta).

Struttura di ghjocu

Aghju passatu qualchì tempu à pensà à l'architettura di u prugettu. U primu passu hè di fà "terra", ghjente è campi di tennis. A ghjente hà da spustà intornu à i tribunali è aspittà. I ghjucatori anu da avè cumpetenze chì migliurà cù u tempu. In più, ci deve esse un editore chì permette di aghjunghje novi persone è tribunale, ma questu ùn hè più liberu.

Dopu avè pensatu tuttu, aghju avutu à travaglià.

Creazione di ghjocu

Principiu: Cerchi è Astrazioni

Aghju pigliatu un esempiu da ggez è aghju avutu un cerculu nantu à u screnu. Meravigliosa! Avà qualchi astrazioni. Pensu chì saria bonu per astrattu da l'idea di un ughjettu di ghjocu. Ogni ughjettu deve esse rende è aghjurnatu cum'è dichjaratu quì:

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

Stu pezzu di codice m'hà datu una bella lista di l'uggetti chì puderia aghjurnà è rende in un loop ugualmente bellu.

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 hè necessariu perchè cuntene tutte e linee di codice. Aghju passatu un pocu di tempu per separà i schedari è ottimizendu a struttura di u cartulare. Eccu ciò chì pareva dopu:
risorse -> quì hè quì tutti l'assi sò (imaghjini)
src
- entità
- game_object.rs
- circulu.rs
- main.rs -> loop principale

Persone, piani è imagine

U prossimu passu hè di creà un oggettu di ghjocu Persona è carica images. Tuttu deve esse custruitu nantu à a basa di 32 * 32 tile.

Playing Rust in 24 hours: sperienza di sviluppu persunale

Campi di tennis

Dopu avè studiatu ciò chì i campi di tennis sò, decisu di fà da 4 * 2 tile. In principiu, era pussibule di fà una maghjina di questa dimensione, o di mette inseme 8 tile separati. Ma poi aghju realizatu chì solu duie tile uniche eranu necessarie, è eccu perchè.

In totale, avemu dui tile: 1 è 2.

Ogni rùbbrica di u tribunale hè custituitu da tile 1 o tile 2. Puderanu esse disposti cum'è normale o flipped 180 gradi.

Playing Rust in 24 hours: sperienza di sviluppu persunale

Modu di custruzzione basica (assemblea).

Dopu avè riesciutu à ottene u rendering di siti, persone è carte, aghju realizatu chì un modu di assemblea di basa era ancu necessariu. L'aghju implementatu cusì: quandu u buttone hè premutu, l'ughjettu hè sceltu, è u clicu u mette in u locu desideratu. Allora, u buttone 1 permette di selezziunà un tribunale, è u buttone 2 permette di sceglie un ghjucatore.

Ma avemu sempre bisognu di ricurdà ciò chì significanu 1 è 2, cusì aghju aghjustatu un wireframe per fà chjaru quale ughjettu hè statu sceltu. Questu hè ciò chì pare.

Playing Rust in 24 hours: sperienza di sviluppu persunale

Quistioni di architettura è refactoring

Avà aghju parechji ogetti di ghjocu: persone, tribunali è pavimenti. Ma per u funziunamentu di i wireframes, ogni entità di l'ughjettu deve esse dichjaratu s'ellu l'uggetti stessi sò in modu di dimostrazione, o se un quadru hè simplicemente disegnatu. Questu ùn hè micca assai convenientu.

Mi paria chì l'architettura avia da esse ripensata in una manera chì palesa certi limitazioni:

  • Avè una entità chì rende è aghjurnà stessu hè un prublema perchè quella entità ùn serà micca capaci di "sapè" ciò chì deve esse rende - una maghjina è un wireframe;
  • mancanza di un strumentu per scambià pruprietà è cumportamentu trà entità individuali (per esempiu, a pruprietà is_build_mode o rendering di cumpurtamentu). Puderia esse usà l'eredità, ancu s'ellu ùn ci hè micca manera propria di implementà in Rust. Ciò chì aghju veramente bisognu era u layout;
  • un strumentu per l'interazzione trà e entità era necessariu per assignà e persone à i tribunali;
  • l'entità stesse eranu una mistura di dati è di logica chì s'era prestu fora di cuntrollu.

Aghju fattu un pocu di ricerca è scupertu l'architettura ECS - Entity Component System, chì hè comunmente usatu in ghjochi. Eccu i benefici di ECS:

  • i dati sò separati da a logica;
  • cumpusizioni invece di l'eredità;
  • architettura centrata in i dati.

ECS hè carattarizatu da trè cuncetti basi:

  • entità - u tipu d'ughjettu chì l'identificatore si riferisce à (pò esse un ghjucatore, una bola, o qualcosa altru);
  • cumpunenti - entità sò custituiti da elli. Esempiu - cumpunenti di rendering, locu è altri. Quessi sò magazzini di dati;
  • sistemi - usanu tramindui l'uggetti è i cumpunenti, più cuntenenu cumportamentu è logica chì sò basati nantu à sti dati. Un esempiu hè un sistema di rendering chì itera per tutte e entità cù cumpunenti di rendering è face u rendering.

Dopu avè studiatu, hè diventatu chjaru chì ECS risolve i seguenti prublemi:

  • utilizendu u layout invece di l'eredità per urganizà entità sistemicamente;
  • sbarazzarsi di codice jumble attraversu sistemi di cuntrollu;
  • utilizendu metudi cum'è is_build_mode per mantene a logica wireframe in u stessu locu - in u sistema di rendering.

Questu hè ciò chì hè accadutu dopu l'implementazione di ECS.

risorse -> quì hè quì tutti l'assi sò (imaghjini)
src
- cumpunenti
—posizione.rs
- persona.rs
— tennis_court.rs
- pianu.rs
- wireframe.rs
- mouse_tracked.rs
- risorse
-mouse.rs
- sistemi
— rendering.rs
- custanti.rs
- utils.rs
- world_factory.rs -> funzioni di fabbrica mundiale
- main.rs -> loop principale

Assignemu persone à i tribunali

ECS hà facilitatu a vita. Avà aghju avutu un modu sistematicu per aghjunghje dati à l'entità è aghjunghje logica basatu annantu à quella dati. È questu, à u turnu, hà permessu di urganizà a distribuzione di e persone trà i tribunali.

Chì aghju fattu:

  • aghjustatu dati nantu à i tribunali assignati à Persona;
  • aghjustatu dati nantu à e persone distribuite à TennisCourt;
  • aghjustatu CourtChoosingSystem, chì permette di analizà e persone è i tribunali, detectà i tribunali dispunibuli è distribuisce i ghjucatori à elli;
  • aghjunghjia un PersonMovementSystem, chì cerca e persone assignate à i tribunali, è s'ellu ùn sò micca quì, allora manda a ghjente induve deve esse.

Playing Rust in 24 hours: sperienza di sviluppu persunale

Riunione

Mi piace assai di travaglià in stu ghjocu simplice. Inoltre, sò felice chì aghju utilizatu Rust per scrive, perchè:

  • Rust vi dà ciò chì avete bisognu;
  • hà una documentazione eccellente, Rust hè abbastanza elegante;
  • a cunsistenza hè fresca;
  • ùn avete micca bisognu à a clonazione, copia o altre azzioni simili, chì aghju spessu fattu in C++;
  • L'opzioni sò assai faciuli d'utilizà è trattà l'errori assai bè;
  • s'è u prugettu hà pussutu esse cumpilatu, allura 99% di u tempu si travaglia, è esattamente cum'è deve. Pensu chì i missaghji di errore di u compilatore sò i migliori chì aghju vistu.

U sviluppu di u ghjocu in Rust hè appena principiatu. Ma ci hè digià una cumunità stabile è abbastanza grande chì travaglia per apre Rust à tutti. Per quessa, fighjulu l’avvene di a lingua cun ottimisimu, aspittendu i risultati di u nostru travagliu cumunu.

Skillbox consiglia:

Source: www.habr.com

Add a comment