Spylje Rust yn 24 oeren: ûnderfining fan persoanlike ûntwikkeling

Spylje Rust yn 24 oeren: ûnderfining fan persoanlike ûntwikkeling

Yn dit artikel sil ik prate oer myn persoanlike ûnderfining fan it ûntwikkeljen fan in lyts spultsje yn Rust. It duorre sawat 24 oeren om in wurkferzje te meitsjen (ik wurke meast jûns of yn it wykein). It spultsje is fier fan klear, mar ik tink dat de ûnderfining sil wêze beleanjend. Ik sil diele wat ik learde en wat observaasjes dy't ik makke by it bouwen fan it spultsje fanôf it begjin.

Skillbox advisearret: Twa jier praktyske kursus "Ik bin in PRO webûntwikkelder".

Wy herinnerje: foar alle lêzers fan "Habr" - in koarting fan 10 roebel by it ynskriuwen fan in Skillbox-kursus mei de promoasjekoade "Habr".

Wêrom Rust?

Ik haw dizze taal keazen om't ik der in protte goede dingen oer heard haw en ik sjoch dat it hieltyd populêrder wurdt yn spultsje-ûntwikkeling. Foardat ik it spul skreau, hie ik net folle ûnderfining mei it ûntwikkeljen fan ienfâldige applikaasjes yn Rust. Dit wie krekt genôch om my in gefoel fan frijheid te jaan by it skriuwen fan it spultsje.

Wêrom it spultsje en hokker soarte fan spultsje?

Spultsjes meitsje is leuk! Ik winskje dat der mear redenen wiene, mar foar "thús" projekten kies ik ûnderwerpen dy't net te nau besibbe binne oan myn gewoane wurk. Hokker spultsje is dit? Ik woe wat meitsje as in tennissimulator dy't Cities Skylines, Zoo Tycoon, Prison Architect en tennis sels kombineart. Yn it algemien waard it in spultsje oer in tennisakademy dêr't minsken komme te spyljen.

Technyske training

Ik woe Rust brûke, mar ik wist net krekt hoefolle grûnwurk it soe nimme om te begjinnen. Ik woe gjin pixel-shaders skriuwe en drag-n-drop brûke, dus ik socht nei de meast fleksibele oplossingen.

Ik fûn nuttige boarnen dy't ik mei jo diel:

Ik ferkende ferskate Rust game motors, úteinlik kieze Piston en ggez. Ik kaam se tsjin doe't ik wurke oan in earder projekt. Op it lêst keas ik ggez om't it mear geskikt like foar it útfieren fan in lyts 2D-spiel. De modulêre struktuer fan Piston is te kompleks foar in begjinnende ûntwikkelder (as ien dy't foar it earst mei Rust wurket).

Spultsjestruktuer

Ik haw wat tiid trochbrocht oan it tinken oer de arsjitektuer fan it projekt. De earste stap is it meitsjen fan "lân", minsken en tennisbanen. Minsken moatte om de rjochtbanken hinne en wachtsje. Spilers moatte feardichheden hawwe dy't oer de tiid ferbetterje. Plus, d'r moat in bewurker wêze wêrmei jo nije minsken en rjochtbanken kinne tafoegje, mar dit is net langer fergees.

Nei alles trochtocht, kaam ik oan it wurk.

Game skepping

Begjin: sirkels en abstraksjes

Ik naam in foarbyld fan ggez en krige in sirkel op it skerm. Prachtich! No wat abstraksjes. Ik tocht dat it moai wêze soe om fuort te abstraheren fan it idee fan in spultsje-objekt. Elk objekt moat wurde werjûn en bywurke lykas hjirboppe oanjûn:

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

Dit stikje koade joech my in moaie list mei objekten dy't ik koe bywurkje en werjaan yn in like moaie loop.

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 is nedich omdat it alle rigels fan koade befettet. Ik haw in bytsje tiid trochbrocht om de bestannen te skieden en de mapstruktuer te optimalisearjen. Dit is hoe't it der dêrnei útseach:
boarnen -> dit is wêr't alle aktiva binne (ôfbyldings)
src
- entiteiten
— game_object.rs
- sirkel.rs
— main.rs -> haadloop

Minsken, flierren en bylden

De folgjende stap is in meitsje in persoan spultsje foarwerp en laden ôfbyldings. Alles moat boud wurde op basis fan 32*32 tegels.

Spylje Rust yn 24 oeren: ûnderfining fan persoanlike ûntwikkeling

Tennisbanen

Nei it bestudearjen fan hoe tennisbanen der útsjen, besleat ik se te meitsjen fan 4 * 2 tegels. Yn it earstoan wie it mooglik om in ôfbylding fan dizze grutte te meitsjen, of om 8 aparte tegels te kombinearjen. Mar doe realisearre ik dat der mar twa unike tegels nedich wiene, en hjir is wêrom.

Yn totaal hawwe wy twa sokke tegels: 1 en 2.

Elts diel fan 'e rjochtbank bestiet út tegel 1 of tegel 2. Se kinne wurde oanlein as normaal of flipped 180 graden.

Spylje Rust yn 24 oeren: ûnderfining fan persoanlike ûntwikkeling

Basis konstruksje (gearkomste) modus

Nei't ik it slagge om rendering fan siden, minsken en kaarten te berikken, realisearre ik dat in basismontagemodus ek nedich wie. Ik ymplementearre it sa: as de knop wurdt yndrukt, wurdt it objekt selektearre, en de klik pleatst it op it winske plak. Sa, knop 1 kinne jo selektearje in rjochtbank, en knop 2 kinne jo selektearje in spiler.

Mar wy moatte noch betinke wat 1 en 2 betsjutte, dus ik tafoege in wireframe om dúdlik te meitsjen hokker objekt selektearre is. Dit is wat it liket.

Spylje Rust yn 24 oeren: ûnderfining fan persoanlike ûntwikkeling

Arsjitektuer en refactoring fragen

No haw ik ferskate spultsje objekten: minsken, rjochtbanken en flierren. Mar om wireframes te wurkjen, moat elke objektentiteit ferteld wurde oft de objekten sels yn demonstraasjemodus binne, of oft in frame gewoan tekene is. Dit is net hiel handich.

It like my ta dat de arsjitektuer opnij betocht wurde moast, sadat guon beheiningen iepenbiere waarden:

  • In entiteit hawwe dy't himsels werjaan en bywurkje is in probleem, om't dy entiteit net kin "witte" wat it moat werjaan - in ôfbylding en in wireframe;
  • gebrek oan in helpmiddel foar it útwikseljen fan eigenskippen en gedrach tusken yndividuele entiteiten (Bygelyks, de is_build_mode eigendom of gedrach rendering). It soe mooglik wêze om erfenis te brûken, hoewol d'r gjin goede manier is om it yn Rust út te fieren. Wat ik echt nedich wie de yndieling;
  • in ark foar ynteraksje tusken entiteiten wie nedich om minsken oan rjochtbanken ta te jaan;
  • de entiteiten sels wiene in mingsel fan gegevens en logika dy't gau út 'e kontrôle kaam.

Ik die wat mear ûndersyk en ûntduts de arsjitektuer ECS - Entity Component System, dat wurdt faak brûkt yn spultsjes. Hjir binne de foardielen fan ECS:

  • gegevens wurde skieden fan logika;
  • komposysje ynstee fan erfenis;
  • data-sintraal arsjitektuer.

ECS wurdt karakterisearre troch trije basisbegripen:

  • entiteiten - it type objekt dat de identifier ferwiist nei (it kin in spiler, in bal, of wat oars wêze);
  • komponinten - entiteiten besteane út har. Foarbyld - rendering komponint, lokaasjes en oare. Dit binne datapakhuzen;
  • systemen - se brûke sawol objekten as komponinten, plus befetsje gedrach en logika dy't basearre binne op dizze gegevens. In foarbyld is in rendering systeem dat iterearret troch alle entiteiten mei rendering komponinten en docht de rendering.

Nei it studearjen waard it dúdlik dat ECS de folgjende problemen oplost:

  • gebrûk fan yndieling ynstee fan erfskip om entiteiten systemysk te organisearjen;
  • kwyt te reitsjen fan koade gemienskip troch kontrôle systemen;
  • gebrûk fan metoaden lykas is_build_mode om de wireframe-logika op itselde plak te hâlden - yn it renderingsysteem.

Dit is wat barde nei ymplemintaasje fan ECS.

boarnen -> dit is wêr't alle aktiva binne (ôfbyldings)
src
- komponinten
-posysje.rs
- persoan.rs
— tennis_court.rs
- ferdjipping.rs
- wireframe.rs
- mouse_tracked.rs
- boarnen
-mûs.rs
- systemen
- rendering.rs
- konstanten.rs
— utils.rs
- world_factory.rs -> wrâldfabrykfunksjes
— main.rs -> haadloop

Wy jouwe minsken oan 'e rjochtbanken

ECS hat it libben makliker makke. No hie ik in systematyske manier om gegevens ta te foegjen oan entiteiten en logika ta te foegjen op basis fan dy gegevens. En dit, op syn beurt, makke it mooglik om te organisearjen de ferdieling fan minsken ûnder de rjochtbanken.

Wat haw ik dien:

  • tafoege gegevens oer tawiisd rjochtbanken oan Persoan;
  • tafoege gegevens oer ferspraat minsken oan TennisCourt;
  • tafoege CourtChoosingSystem, wêrmei jo te analysearjen minsken en rjochtbanken, detect beskikber rjochtbanken en fersprieden spilers oan harren;
  • tafoege in PersonMovementSystem, dat siket foar minsken tawiisd oan de rjochtbanken, en as se binne der net, dan stjoert minsken wêr't se moatte wêze.

Spylje Rust yn 24 oeren: ûnderfining fan persoanlike ûntwikkeling

Omheech op

Ik haw echt genoaten fan wurkjen oan dit ienfâldige spultsje. Boppedat bin ik bliid dat ik Rust brûkte om it te skriuwen, om't:

  • Rust jout jo wat jo nedich hawwe;
  • it hat poerbêst dokumintaasje, Rust is hiel elegant;
  • konsistinsje is cool;
  • jo hoege net ta cloning, kopiearjen of oare ferlykbere aksjes, dy't ik faak dien yn C ++;
  • Opsjes binne hiel maklik te brûken en omgean flaters hiel goed;
  • as it projekt koe wurde gearstald, dan 99% fan 'e tiid it wurket, en krekt sa't it moat. Ik tink dat de kompilator flater berjochten binne de bêste Ik haw sjoen.

Spultsjeûntwikkeling yn Rust begjint krekt. Mar der is al in stabile en frij grutte mienskip dwaande om Rust foar elkenien te iepenjen. Dêrom sjoch ik mei optimisme nei de takomst fan de taal, sjoch út nei de resultaten fan ús mienskiplik wurk.

Skillbox advisearret:

Boarne: www.habr.com

Add a comment