ఈ వ్యాసంలో నేను రస్ట్లో ఒక చిన్న ఆటను అభివృద్ధి చేసిన నా వ్యక్తిగత అనుభవం గురించి మాట్లాడతాను. పని చేసే సంస్కరణను రూపొందించడానికి దాదాపు 24 గంటలు పట్టింది (నేను ఎక్కువగా సాయంత్రం లేదా వారాంతాల్లో పని చేస్తాను). ఆట పూర్తి కాలేదు, కానీ అనుభవం బహుమతిగా ఉంటుందని నేను భావిస్తున్నాను. నేను నేర్చుకున్న వాటిని మరియు మొదటి నుండి గేమ్ను రూపొందించేటప్పుడు నేను చేసిన కొన్ని పరిశీలనలను పంచుకుంటాను.
మేము గుర్తు చేస్తున్నాము:Habr పాఠకులందరికీ - Habr ప్రోమో కోడ్ని ఉపయోగించి ఏదైనా Skillbox కోర్సులో నమోదు చేసుకున్నప్పుడు 10 రూబుల్ తగ్గింపు.
ఎందుకు రస్ట్?
నేను ఈ భాషను ఎంచుకున్నాను ఎందుకంటే నేను దీని గురించి చాలా మంచి విషయాలు విన్నాను మరియు గేమ్ డెవలప్మెంట్లో ఇది మరింత జనాదరణ పొందడాన్ని నేను చూస్తున్నాను. ఆట రాయడానికి ముందు, రస్ట్లో సాధారణ అప్లికేషన్లను అభివృద్ధి చేయడంలో నాకు తక్కువ అనుభవం ఉంది. ఆట రాసేటప్పుడు నాకు స్వేచ్ఛను అందించడానికి ఇది సరిపోతుంది.
ఎందుకు ఆట మరియు ఎలాంటి ఆట?
ఆటలు తయారు చేయడం సరదాగా ఉంటుంది! మరిన్ని కారణాలు ఉన్నాయని నేను కోరుకుంటున్నాను, కానీ "హోమ్" ప్రాజెక్ట్ల కోసం నేను నా సాధారణ పనికి చాలా దగ్గరి సంబంధం లేని అంశాలను ఎంచుకుంటాను. ఇది ఏ ఆట? నేను సిటీస్ స్కైలైన్స్, జూ టైకూన్, ప్రిజన్ ఆర్కిటెక్ట్ మరియు టెన్నిస్ని కలిపి టెన్నిస్ సిమ్యులేటర్ లాంటిది తయారు చేయాలనుకున్నాను. సాధారణంగా, ఇది ప్రజలు ఆడటానికి వచ్చే టెన్నిస్ అకాడమీకి సంబంధించిన గేమ్గా మారింది.
సాంకేతిక శిక్షణ
నేను రస్ట్ని ఉపయోగించాలనుకున్నాను, కానీ ప్రారంభించడానికి ఎంత గ్రౌండ్వర్క్ పడుతుందో నాకు ఖచ్చితంగా తెలియదు. నేను పిక్సెల్ షేడర్లను వ్రాయాలని మరియు డ్రాగ్-ఎన్-డ్రాప్ని ఉపయోగించాలనుకోలేదు, కాబట్టి నేను అత్యంత సౌకర్యవంతమైన పరిష్కారాల కోసం వెతుకుతున్నాను.
నేను మీతో పంచుకునే ఉపయోగకరమైన వనరులను కనుగొన్నాను:
నేను అనేక రస్ట్ గేమ్ ఇంజిన్లను అన్వేషించాను, చివరికి పిస్టన్ మరియు గెజ్లను ఎంచుకున్నాను. మునుపటి ప్రాజెక్ట్లో పని చేస్తున్నప్పుడు నేను వాటిని చూశాను. చివరికి, నేను ggezని ఎంచుకున్నాను ఎందుకంటే ఇది ఒక చిన్న 2D గేమ్ని అమలు చేయడానికి మరింత అనుకూలంగా అనిపించింది. పిస్టన్ యొక్క మాడ్యులర్ నిర్మాణం అనుభవం లేని డెవలపర్కు (లేదా మొదటిసారి రస్ట్తో పని చేస్తున్న వ్యక్తికి) చాలా క్లిష్టంగా ఉంటుంది.
గేమ్ నిర్మాణం
నేను ప్రాజెక్ట్ యొక్క నిర్మాణం గురించి ఆలోచిస్తూ కొంత సమయం గడిపాను. మొదటి దశ "భూమి", ప్రజలు మరియు టెన్నిస్ కోర్టులను తయారు చేయడం. ప్రజలు కోర్టుల చుట్టూ తిరుగుతూ వేచి ఉండాల్సిందే. ఆటగాళ్ళు కాలక్రమేణా మెరుగుపడే నైపుణ్యాలను కలిగి ఉండాలి. అదనంగా, కొత్త వ్యక్తులను మరియు న్యాయస్థానాలను జోడించడానికి మిమ్మల్ని అనుమతించే ఎడిటర్ ఉండాలి, కానీ ఇది ఇకపై ఉచితం కాదు.
అంతా ఆలోచించి, నేను పనిలో పడ్డాను.
గేమ్ సృష్టి
ప్రారంభం: వృత్తాలు మరియు సంగ్రహణలు
నేను ggez నుండి ఒక ఉదాహరణ తీసుకున్నాను మరియు స్క్రీన్పై సర్కిల్ని పొందాను. అద్భుతం! ఇప్పుడు కొన్ని సారాంశాలు. గేమ్ ఆబ్జెక్ట్ ఆలోచన నుండి దూరంగా ఉండటం మంచిది అని నేను అనుకున్నాను. ఇక్కడ పేర్కొన్న విధంగా ప్రతి వస్తువు తప్పనిసరిగా రెండర్ చేయబడి, నవీకరించబడాలి:
// 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(())
}
}
ఈ కోడ్ ముక్క నేను అప్డేట్ చేయగల మరియు సమానమైన లూప్లో రెండర్ చేయగల మంచి వస్తువుల జాబితాను నాకు అందించింది.
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 అవసరం ఎందుకంటే ఇది కోడ్ యొక్క అన్ని లైన్లను కలిగి ఉంటుంది. నేను ఫైల్లను వేరు చేయడానికి మరియు డైరెక్టరీ నిర్మాణాన్ని ఆప్టిమైజ్ చేయడానికి కొంత సమయం గడిపాను. ఆ తర్వాత ఇలా కనిపించింది: వనరులు -> ఇక్కడే అన్ని ఆస్తులు ఉన్నాయి (చిత్రాలు)
src
- ఎంటిటీలు
— game_object.rs
- సర్కిల్.ఆర్ఎస్
— main.rs -> ప్రధాన లూప్
వ్యక్తులు, అంతస్తులు మరియు చిత్రాలు
తదుపరి దశ వ్యక్తి ఆట వస్తువును సృష్టించడం మరియు చిత్రాలను లోడ్ చేయడం. ప్రతిదీ 32 * 32 టైల్స్ ఆధారంగా నిర్మించబడాలి.
టెన్నిస్ కోర్టులు
టెన్నిస్ కోర్టులు ఎలా ఉంటాయో అధ్యయనం చేసిన తర్వాత, నేను వాటిని 4*2 టైల్స్ నుండి తయారు చేయాలని నిర్ణయించుకున్నాను. ప్రారంభంలో, ఈ పరిమాణంలో చిత్రాన్ని రూపొందించడం లేదా 8 వేర్వేరు పలకలను కలపడం సాధ్యమైంది. కానీ రెండు ప్రత్యేకమైన టైల్స్ మాత్రమే అవసరమని నేను గ్రహించాను మరియు ఇక్కడ ఎందుకు ఉంది.
మొత్తంగా మనకు అలాంటి రెండు పలకలు ఉన్నాయి: 1 మరియు 2.
కోర్టులోని ప్రతి విభాగం టైల్ 1 లేదా టైల్ 2ని కలిగి ఉంటుంది. వాటిని సాధారణంగా వేయవచ్చు లేదా 180 డిగ్రీలు తిప్పవచ్చు.
ప్రాథమిక నిర్మాణ (అసెంబ్లీ) మోడ్
నేను సైట్లు, వ్యక్తులు మరియు మ్యాప్ల రెండరింగ్ను సాధించగలిగిన తర్వాత, ప్రాథమిక అసెంబ్లీ మోడ్ కూడా అవసరమని నేను గ్రహించాను. నేను దీన్ని ఇలా అమలు చేసాను: బటన్ నొక్కినప్పుడు, ఆబ్జెక్ట్ ఎంపిక చేయబడుతుంది మరియు క్లిక్ అది కావలసిన స్థలంలో ఉంచుతుంది. కాబట్టి, బటన్ 1 కోర్టును ఎంచుకోవడానికి మిమ్మల్ని అనుమతిస్తుంది మరియు బటన్ 2 ఆటగాడిని ఎంచుకోవడానికి మిమ్మల్ని అనుమతిస్తుంది.
కానీ 1 మరియు 2 అంటే ఏమిటో మనం ఇంకా గుర్తుంచుకోవాలి, కాబట్టి ఏ వస్తువు ఎంపిక చేయబడిందో స్పష్టం చేయడానికి నేను వైర్ఫ్రేమ్ను జోడించాను. ఇది ఇలా కనిపిస్తుంది.
ఆర్కిటెక్చర్ మరియు రీఫ్యాక్టరింగ్ ప్రశ్నలు
ఇప్పుడు నా దగ్గర అనేక ఆట వస్తువులు ఉన్నాయి: వ్యక్తులు, కోర్టులు మరియు అంతస్తులు. కానీ వైర్ఫ్రేమ్లు పని చేయడానికి, ప్రతి వస్తువు ఎంటిటీకి వస్తువులు ప్రదర్శన మోడ్లో ఉన్నాయా లేదా ఫ్రేమ్ కేవలం డ్రా చేయబడిందా అని చెప్పాలి. ఇది చాలా సౌకర్యవంతంగా లేదు.
కొన్ని పరిమితులను వెల్లడించే విధంగా వాస్తుశిల్పం పునరాలోచించాల్సిన అవసరం ఉందని నాకు అనిపించింది:
రెండర్ మరియు అప్డేట్ చేసే ఎంటిటీని కలిగి ఉండటం ఒక సమస్య ఎందుకంటే ఆ ఎంటిటీ అది ఏమి అందించాలో "తెలుసుకోదు" - ఒక చిత్రం మరియు వైర్ఫ్రేమ్;
వ్యక్తిగత ఎంటిటీల మధ్య లక్షణాలు మరియు ప్రవర్తనను మార్పిడి చేయడానికి సాధనం లేకపోవడం (ఉదాహరణకు, is_build_mode ఆస్తి లేదా ప్రవర్తన రెండరింగ్). రస్ట్లో దానిని అమలు చేయడానికి సరైన మార్గం లేనప్పటికీ, వారసత్వాన్ని ఉపయోగించడం సాధ్యమవుతుంది. నాకు నిజంగా అవసరమైనది లేఅవుట్;
వ్యక్తులను న్యాయస్థానాలకు కేటాయించడానికి ఎంటిటీల మధ్య పరస్పర చర్య కోసం ఒక సాధనం అవసరం;
ఎంటిటీలు డేటా మరియు లాజిక్ల మిశ్రమంగా ఉంటాయి, అవి త్వరగా నియంత్రణలో లేవు.
మరికొంత పరిశోధన చేసి ఆర్కిటెక్చర్ని కనుగొన్నాను ECS - ఎంటిటీ కాంపోనెంట్ సిస్టమ్, ఇది సాధారణంగా ఆటలలో ఉపయోగించబడుతుంది. ECS యొక్క ప్రయోజనాలు ఇక్కడ ఉన్నాయి:
డేటా తర్కం నుండి వేరు చేయబడింది;
వారసత్వానికి బదులుగా కూర్పు;
డేటా-సెంట్రిక్ ఆర్కిటెక్చర్.
ECS మూడు ప్రాథమిక భావనల ద్వారా వర్గీకరించబడుతుంది:
ఎంటిటీలు - ఐడెంటిఫైయర్ సూచించే వస్తువు రకం (అది ఆటగాడు, బంతి లేదా మరేదైనా కావచ్చు);
భాగాలు - ఎంటిటీలు వాటితో రూపొందించబడ్డాయి. ఉదాహరణ - రెండరింగ్ భాగం, స్థానాలు మరియు ఇతరులు. ఇవి డేటా గిడ్డంగులు;
సిస్టమ్లు - అవి ఆబ్జెక్ట్లు మరియు కాంపోనెంట్లు రెండింటినీ ఉపయోగిస్తాయి, అంతేకాకుండా ఈ డేటాపై ఆధారపడిన ప్రవర్తన మరియు లాజిక్లను కలిగి ఉంటాయి. ఒక ఉదాహరణ రెండరింగ్ సిస్టమ్, ఇది రెండరింగ్ భాగాలతో అన్ని ఎంటిటీల ద్వారా పునరావృతమవుతుంది మరియు రెండరింగ్ చేస్తుంది.
దానిని అధ్యయనం చేసిన తరువాత, ECS క్రింది సమస్యలను పరిష్కరిస్తుందని స్పష్టమైంది:
వ్యవస్థలను వ్యవస్థాగతంగా నిర్వహించడానికి వారసత్వానికి బదులుగా లేఅవుట్ను ఉపయోగించడం;
నియంత్రణ వ్యవస్థల ద్వారా కోడ్ గందరగోళాన్ని వదిలించుకోవడం;
వైర్ఫ్రేమ్ లాజిక్ను ఒకే చోట ఉంచడానికి is_build_mode వంటి పద్ధతులను ఉపయోగించడం - రెండరింగ్ సిస్టమ్లో.
ఇసిఎస్ని అమలు చేసిన తర్వాత ఇదే జరిగింది.
వనరులు -> ఇక్కడే అన్ని ఆస్తులు ఉన్నాయి (చిత్రాలు)
src
- భాగాలు
-స్థానం.rs
— person.rs
— tennis_court.rs
- ఫ్లోర్.ఆర్ఎస్
- wireframe.rs
— mouse_tracked.rs
- వనరులు
— mouse.rs
- వ్యవస్థలు
- rendering.rs
— స్థిరాంకాలు.rs
— utils.rs
— world_factory.rs -> ప్రపంచ ఫ్యాక్టరీ విధులు
— main.rs -> ప్రధాన లూప్
మేము ప్రజలను కోర్టులకు కేటాయించాము
ECS జీవితాన్ని సులభతరం చేసింది. ఇప్పుడు నేను ఎంటిటీలకు డేటాను జోడించడానికి మరియు ఆ డేటా ఆధారంగా లాజిక్ను జోడించడానికి ఒక క్రమబద్ధమైన మార్గాన్ని కలిగి ఉన్నాను. మరియు ఇది, కోర్టుల మధ్య ప్రజల పంపిణీని నిర్వహించడం సాధ్యం చేసింది.
నేను ఏమి చేసాను:
వ్యక్తికి కేటాయించిన కోర్టుల గురించి డేటా జోడించబడింది;
టెన్నిస్కోర్ట్కు పంపిణీ చేయబడిన వ్యక్తుల గురించి డేటా జోడించబడింది;
వ్యక్తులు మరియు కోర్టులను విశ్లేషించడానికి, అందుబాటులో ఉన్న కోర్టులను గుర్తించడానికి మరియు వారికి ఆటగాళ్లను పంపిణీ చేయడానికి మిమ్మల్ని అనుమతించే కోర్ట్చూసింగ్సిస్టమ్ జోడించబడింది;
ఒక PersonMovementSystemని జోడించారు, ఇది న్యాయస్థానాలకు కేటాయించబడిన వ్యక్తుల కోసం వెతుకుతుంది మరియు వారు అక్కడ లేకుంటే, వారు ఉండవలసిన వ్యక్తులను పంపుతుంది.
సారాంశం
నేను ఈ సాధారణ గేమ్లో పని చేయడం నిజంగా ఆనందించాను. అంతేకాకుండా, నేను దానిని వ్రాయడానికి రస్ట్ని ఉపయోగించుకున్నందుకు నేను సంతోషిస్తున్నాను, ఎందుకంటే:
రస్ట్ మీకు అవసరమైనది ఇస్తుంది;
ఇది అద్భుతమైన డాక్యుమెంటేషన్ కలిగి ఉంది, రస్ట్ చాలా సొగసైనది;
స్థిరత్వం చల్లగా ఉంటుంది;
మీరు C++లో నేను తరచుగా చేసే క్లోనింగ్, కాపీయింగ్ లేదా ఇతర సారూప్య చర్యలను ఆశ్రయించాల్సిన అవసరం లేదు;
ఐచ్ఛికాలు ఉపయోగించడం చాలా సులభం మరియు లోపాలను బాగా నిర్వహించడం;
ప్రాజెక్ట్ కంపైల్ చేయగలిగితే, అది 99% సమయం పని చేస్తుంది మరియు సరిగ్గా చేయాలి. కంపైలర్ ఎర్రర్ మెసేజ్లు నేను చూసిన వాటిలో ఉత్తమమైనవి అని నేను భావిస్తున్నాను.
రస్ట్లో గేమ్ డెవలప్మెంట్ ఇప్పుడే ప్రారంభమైంది. కానీ ప్రతి ఒక్కరికీ రస్ట్ను తెరవడానికి ఇప్పటికే స్థిరమైన మరియు చాలా పెద్ద సంఘం పని చేస్తోంది. అందువల్ల, నేను భాష యొక్క భవిష్యత్తును ఆశావాదంతో చూస్తాను, మా ఉమ్మడి పని ఫలితాల కోసం ఎదురు చూస్తున్నాను.