SpÄlÄjot Rust 24 stundu laikÄ: personÄ«gÄs attÄ«stÄ«bas pieredze
Å ajÄ rakstÄ es runÄÅ”u par savu personÄ«go pieredzi, izstrÄdÄjot nelielu spÄli Rust. Darba versijas izveide aizÅÄma aptuveni 24 stundas (pÄrsvarÄ strÄdÄju vakaros vai brÄ«vdienÄs). SpÄle ne tuvu nav pabeigta, taÄu domÄju, ka pieredze bÅ«s atalgojoÅ”a. PadalÄ«Å”os ar to, ko uzzinÄju un dažiem novÄrojumiem, ko izdarÄ«ju, veidojot spÄli no nulles.
IzvÄlÄjos Å”o valodu, jo esmu par to dzirdÄjis daudz laba un redzu, ka tÄ kļūst arvien populÄrÄka spÄļu izstrÄdÄ. Pirms spÄles rakstÄ«Å”anas man bija maz pieredzes vienkÄrÅ”u lietojumprogrammu izstrÄdÄ Rust. Tas bija tikai pietiekami, lai man radÄ«tu brÄ«vÄ«bas sajÅ«tu, rakstot spÄli.
KÄpÄc spÄle un kÄda veida spÄle?
SpÄļu veidoÅ”ana ir jautra! GribÄtos, lai bÅ«tu vairÄk iemeslu, bet āmÄjasā projektiem izvÄlos tÄmas, kas nav pÄrÄk cieÅ”i saistÄ«tas ar manu parasto darbu. Kas Ŕī ir par spÄli? Es gribÄju izveidot kaut ko lÄ«dzÄ«gu tenisa simulatoram, kas apvieno Cities Skylines, Zoo Tycoon, Prison Architect un paÅ”u tenisu. KopumÄ tÄ izvÄrtÄs spÄle par tenisa akadÄmiju, kur cilvÄki nÄk spÄlÄt.
TehniskÄ apmÄcÄ«ba
Es gribÄju izmantot Rust, bet es precÄ«zi nezinÄju, cik daudz pamata bÅ«s nepiecieÅ”ams, lai sÄktu. Es negribÄju rakstÄ«t pikseļu ÄnotÄjus un izmantot drag-n-drop, tÄpÄc meklÄju elastÄ«gÄkos risinÄjumus.
Es atradu noderīgus resursus, ar kuriem dalos ar jums:
Es izpÄtÄ«ju vairÄkus Rust spÄļu dzinÄjus, galu galÄ izvÄloties Piston un ggez. Ar tiem saskÄros, strÄdÄjot pie iepriekÅ”ÄjÄ projekta. BeigÄs izvÄlÄjos ggez, jo tas Ŕķita piemÄrotÄks nelielas 2D spÄles Ä«stenoÅ”anai. Virzuļa moduļu struktÅ«ra ir pÄrÄk sarežģīta iesÄcÄju izstrÄdÄtÄjam (vai kÄdam, kurÅ” pirmo reizi strÄdÄ ar Rust).
SpÄles struktÅ«ra
Es pavadÄ«ju kÄdu laiku, domÄjot par projekta arhitektÅ«ru. Pirmais solis ir izveidot "zemi", cilvÄkus un tenisa kortus. CilvÄkiem jÄpÄrvietojas pa tiesÄm un jÄgaida. SpÄlÄtÄjiem jÄbÅ«t prasmÄm, kas laika gaitÄ uzlabojas. TurklÄt vajadzÄtu bÅ«t redaktoram, kas ļauj pievienot jaunus cilvÄkus un tiesas, taÄu tas vairs nav bezmaksas.
PÄrdomÄjis visu, Ä·Äros pie darba.
SpÄles izveide
SÄkums: apļi un abstrakcijas
Es paÅÄmu piemÄru no ggez un ekrÄnÄ ieguvu apli. BrÄ«niŔķīgi! Tagad dažas abstrakcijas. Es domÄju, ka bÅ«tu jauki abstrahÄties no idejas par spÄles objektu. Katrs objekts ir jÄatveido un jÄatjaunina, kÄ norÄdÄ«ts Å”eit:
// 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(())
}
}
Å is koda fragments man sniedza jauku objektu sarakstu, kurus es varÄtu atjauninÄt un atveidot tikpat jaukÄ cilpÄ.
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 ir nepiecieÅ”ams, jo tajÄ ir visas koda rindas. Es pavadÄ«ju nedaudz laika, atdalot failus un optimizÄjot direktoriju struktÅ«ru. PÄc tam tas izskatÄ«jÄs Å”Ädi: resursi -> Å”eit atrodas visi lÄ«dzekļi (attÄli)
src
- vienības
ā game_object.rs
ā aplis.rs
ā main.rs -> galvenÄ cilpa
CilvÄki, stÄvi un attÄli
NÄkamais solis ir izveidot Personas spÄles objektu un ielÄdÄt attÄlus. Viss jÄbÅ«vÄ uz 32*32 flīžu bÄzes.
Tenisa korts
IzpÄtÄ«jis, kÄ izskatÄs tenisa korti, nolÄmu tos izgatavot no 4*2 flÄ«zÄm. SÄkotnÄji bija iespÄja izgatavot Å”Äda izmÄra attÄlu, vai arÄ« salikt kopÄ 8 atseviŔķas flÄ«zes. Bet tad es sapratu, ka vajadzÄ«gas tikai divas unikÄlas flÄ«zes, un lÅ«k, kÄpÄc.
KopumÄ mums ir divas Å”Ädas flÄ«zes: 1 un 2.
Katra laukuma sadaļa sastÄv no 1. vai 2. flÄ«zes. Tos var izklÄt kÄ parasti vai apgriezt par 180 grÄdiem.
Pamata uzbÅ«ves (montÄžas) režīms
Kad man izdevÄs panÄkt vietÅu, cilvÄku un karÅ”u renderÄÅ”anu, es sapratu, ka ir nepiecieÅ”ams arÄ« pamata montÄžas režīms. Es to Ä«stenoju Å”Ädi: nospiežot pogu, objekts tiek atlasÄ«ts, un klikŔķis novieto to vajadzÄ«gajÄ vietÄ. TÄtad, poga 1 ļauj izvÄlÄties laukumu, bet poga 2 ļauj izvÄlÄties spÄlÄtÄju.
Bet mums joprojÄm ir jÄatceras, ko nozÄ«mÄ 1 un 2, tÄpÄc es pievienoju karkasu, lai bÅ«tu skaidrs, kurÅ” objekts ir atlasÄ«ts. Tas izskatÄs Å”Ädi.
ArhitektÅ«ras un pÄrstrukturÄÅ”anas jautÄjumi
Tagad man ir vairÄki spÄles objekti: cilvÄki, laukumi un grÄ«das. Bet, lai stiepļu rÄmji darbotos, katrai objekta entÄ«tijai ir jÄpasaka, vai paÅ”i objekti atrodas demonstrÄcijas režīmÄ, vai arÄ« rÄmis ir vienkÄrÅ”i uzzÄ«mÄts. Tas nav Ä«paÅ”i Ärti.
Man Ŕķita, ka arhitektÅ«ra ir jÄpÄrdomÄ tÄ, lai atklÄtu dažus ierobežojumus:
EntÄ«tija, kas pati renderÄ un atjaunina, ir problÄma, jo Ŕī entÄ«tija nevarÄs āzinÄtā, kas tai ir jÄatveido ā attÄlu un karkasu;
rÄ«ka trÅ«kums rekvizÄ«tu un uzvedÄ«bas apmaiÅai starp atseviŔķÄm entÄ«tijÄm (piemÄram, rekvizÄ«ts is_build_mode vai uzvedÄ«bas renderÄÅ”ana). VarÄtu izmantot mantojumu, lai gan RustÄ nav pareizi to ieviest. Tas, kas man patieÅ”Äm bija vajadzÄ«gs, bija izkÄrtojums;
bija nepiecieÅ”ams instruments mijiedarbÄ«bai starp struktÅ«rÄm, lai norÄ«kotu cilvÄkus tiesÄs;
paÅ”as entÄ«tijas bija datu un loÄ£ikas sajaukums, kas Ätri izkļuva no kontroles.
Es veicu vÄl dažus pÄtÄ«jumus un atklÄju arhitektÅ«ru ECS ā entÄ«tijas komponentu sistÄma, ko parasti izmanto spÄlÄs. Å eit ir ECS priekÅ”rocÄ«bas:
dati ir atdalīti no loģikas;
sastÄvs mantojuma vietÄ;
uz datiem orientÄta arhitektÅ«ra.
ECS raksturo trÄ«s pamatjÄdzieni:
entÄ«tijas ā objekta veids, uz kuru attiecas identifikators (tas varÄtu bÅ«t spÄlÄtÄjs, bumba vai kas cits);
sastÄvdaļas ā entÄ«tijas veido no tÄm. PiemÄrs - renderÄÅ”anas komponents, atraÅ”anÄs vietas un citi. TÄs ir datu noliktavas;
sistÄmas - tÄs izmanto gan objektus, gan komponentus, kÄ arÄ« satur uzvedÄ«bu un loÄ£iku, kas ir balstÄ«ta uz Å”iem datiem. PiemÄrs ir renderÄÅ”anas sistÄma, kas atkÄrtojas caur visÄm entÄ«tijÄm ar renderÄÅ”anas komponentiem un veic renderÄÅ”anu.
PÄc tÄ izpÄtes kļuva skaidrs, ka ECS atrisina Å”Ädas problÄmas:
izkÄrtojuma izmantoÅ”ana mantojuma vietÄ, lai sistÄmiski organizÄtu entÄ«tijas;
atbrÄ«voÅ”anÄs no kodu jucekļa, izmantojot kontroles sistÄmas;
izmantojot tÄdas metodes kÄ is_build_mode, lai saglabÄtu karkasa loÄ£iku tajÄ paÅ”Ä vietÄ ā renderÄÅ”anas sistÄmÄ.
ECS ir padarÄ«jusi dzÄ«vi vieglÄku. Tagad man bija sistemÄtisks veids, kÄ pievienot datus entÄ«tijÄm un pievienot loÄ£iku, pamatojoties uz Å”iem datiem. Un tas savukÄrt ļÄva organizÄt cilvÄku sadali pa tiesÄm.
Ko es esmu darījis:
pievienoti dati par Personai pieŔķirtajÄm tiesÄm;
pievienoti dati par izplatÄ«tajiem cilvÄkiem TennisCourt;
pievienota CourtChoosingSystem, kas ļauj analizÄt cilvÄkus un laukumus, atklÄt pieejamos laukumus un izplatÄ«t tiem spÄlÄtÄjus;
pievienota PersonMovementSystem, kas meklÄ tiesÄm norÄ«kotos cilvÄkus un ja viÅu nav, tad sÅ«ta cilvÄkus, kur vajag.
Apkopojot
Man ļoti patika strÄdÄt pie Ŕīs vienkÄrÅ”Äs spÄles. TurklÄt es priecÄjos, ka rakstÄ«Å”anai izmantoju Rustu, jo:
Rūsa sniedz jums to, kas jums nepiecieŔams;
tai ir lieliska dokumentÄcija, Rust ir diezgan elegants;
konsistence ir forŔa;
jums nav jÄizmanto klonÄÅ”ana, kopÄÅ”ana vai citas lÄ«dzÄ«gas darbÄ«bas, ko es bieži darÄ«ju programmÄ C++;
Opcijas ir ļoti viegli lietojamas un ļoti labi tiek galÄ ar kļūdÄm;
ja projektu izdevÄs sastÄdÄ«t, tad 99% gadÄ«jumu tas strÄdÄ, un tieÅ”i tÄ, kÄ vajadzÄtu. Es domÄju, ka kompilatora kļūdu ziÅojumi ir vislabÄkie, ko esmu redzÄjis.
SpÄles izstrÄde RustÄ tikai sÄkas. Bet jau ir stabila un diezgan liela kopiena, kas strÄdÄ, lai atvÄrtu Rust ikvienam. TÄpÄc es ar optimismu raugos uz valodas nÄkotni, ar nepacietÄ«bu gaidot mÅ«su kopÄ«gÄ darba rezultÄtus.