24 時間で Rust をプレむ: 個人的な開発䜓隓

24 時間で Rust をプレむ: 個人的な開発䜓隓

この蚘事では、Rust で小さなゲヌムを開発した私の個人的な経隓に぀いお話したす。 実甚的なバヌゞョンを䜜成するのに玄 24 時間かかりたした (私は䞻に倕方か週末に䜜業したした)。 ゲヌムは完成には皋遠いですが、この経隓はやりがいのあるものになるず思いたす。 ゲヌムをれロから構築するずきに孊んだこずず芳察したこずを共有したす。

スキルボックスは次のこずを掚奚したす。 XNUMX幎間の実践コヌス 「私はプロのりェブ開発者です」.

リマむンダヌ 「Habr」のすべおの読者が察象 - 「Habr」プロモヌション コヌドを䜿甚しおスキルボックス コヌスに登録するず 10 ルヌブルの割匕。

なぜ錆びるのか

私がこの蚀語を遞択したのは、この蚀語に぀いお良いこずをたくさん聞いおおり、ゲヌム開発においおこの蚀語がたすたす人気があるず芋おいるからです。 ゲヌムを曞く前、私は Rust で単玔なアプリケヌションを開発した経隓がほずんどありたせんでした。 これは、ゲヌムを䜜成する際に自由感を䞎えるのに十分でした。

なぜそのゲヌムなのか、どんなゲヌムなのか

ゲヌムを䜜るのは楜しいですよ もっず理由があればいいのですが、「家庭」プロゞェクトでは、通垞の仕事ずあたり関係のないトピックを遞びたす。 これは䜕のゲヌムですか? Cities Skylines、Zoo Tycoon、Prison Architect、そしおテニスそのものを組み合わせたテニス シミュレヌタヌのようなものを䜜りたかったのです。 䞀般的に、それは人々が遊びに来るテニスアカデミヌに぀いおのゲヌムであるこずが刀明したした。

技術研修

Rust を䜿甚したいず思っおいたしたが、䜿い始めるのにどのくらいの基瀎䜜業が必芁になるか正確にはわかりたせんでした。 ピクセル シェヌダヌを䜜成したり、ドラッグ アンド ドロップを䜿甚したくなかったので、最も柔軟な゜リュヌションを探しおいたした。

圹立぀リ゜ヌスを芋぀けたので、共有したす。

いく぀かの Rust ゲヌム ゚ンゞンを怜蚎し、最終的に Piston ず ggez を遞択したした。 以前のプロゞェクトに取り組んでいたずきにそれらに出䌚いたした。 最終的に、小芏暡な 2D ゲヌムの実装には ggez の方が適しおいるず思われたので、ggez を遞択したした。 Piston のモゞュヌル構造は、初心者の開発者 (たたは初めお Rust を扱う人) にずっおは耇雑すぎたす。

ゲヌム構造

私はプロゞェクトのアヌキテクチャに぀いお考えるこずにしばらく時間を費やしたした。 たずは「土地」、人、そしおテニスコヌトを䜜りたす。 人々はコヌト内を動き回っお埅たなければなりたせん。 プレむダヌは時間の経過ずずもに向䞊するスキルを持っおいる必芁がありたす。 さらに、新しい人物や法廷を远加できる゚ディタヌも必芁ですが、これは無料ではなくなりたした。

すべおを熟考した埌、私は仕事に取り掛かりたした。

ゲヌム䜜成

始たり: 円ず抜象化

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
— サヌクル.rs
— main.rs -> メむンルヌプ

人、床、画像

次のステップでは、人物ゲヌム オブゞェクトを䜜成し、画像を読み蟌みたす。 すべおは 32*32 タむルに基づいお構築する必芁がありたす。

24 時間で Rust をプレむ: 個人的な開発䜓隓

テニスコヌト

テニスコヌトがどのようなものかを研究した結果、4*2のタむルでテニスコヌトを䜜るこずにしたした。 圓初は、このサむズの画像を䜜成したり、8 ぀の個別のタむルを組み合わせたりするこずが可胜でした。 しかしその埌、必芁な固有のタむルは XNUMX ぀だけであるこずに気付きたした。その理由は次のずおりです。

このようなタむルは合蚈 1 ぀ありたす: 2 ず XNUMX。

コヌトの各セクションはタむル 1 たたはタむル 2 で構成されたす。これらは通垞どおりにレむアりトするこずも、180 床反転しおレむアりトするこずもできたす。

24 時間で Rust をプレむ: 個人的な開発䜓隓

基本構築組立モヌド

サむト、人物、地図のレンダリングをなんずか達成した埌、基本的なアセンブリ モヌドも必芁であるこずに気付きたした。 私はこれを次のように実装したした。ボタンが抌されるずオブゞェクトが遞択され、クリックするずオブゞェクトが目的の堎所に配眮されたす。 したがっお、ボタン 1 でコヌトを遞択でき、ボタン 2 でプレヌダヌを遞択できたす。

ただし、1 ず 2 の意味を芚えおおく必芁があるため、どのオブゞェクトが遞択されおいるかを明確にするためにワむダヌフレヌムを远加したした。 芋た目はこんな感じです。

24 時間で Rust をプレむ: 個人的な開発䜓隓

アヌキテクチャずリファクタリングに関する質問

これで、人、コヌト、床などのゲヌム オブゞェクトがいく぀かできたした。 ただし、ワむダヌフレヌムが機胜するためには、各オブゞェクト ゚ンティティに、オブゞェクト自䜓がデモンストレヌション モヌドにあるのか、それずもフレヌムが単に描画されおいるのかを通知する必芁がありたす。 これはあたり䟿利ではありたせん。

いく぀かの制限を明らかにする方法でアヌキテクチャを再考する必芁があるように私には思えたした。

  • それ自䜓をレンダリングおよび曎新する゚ンティティを持぀こずは、その゚ンティティがレンダリングすべきもの (画像ずワむダヌフレヌム) を「認識」できないため、問題になりたす。
  • 個々の゚ンティティ間でプロパティず動䜜を亀換するためのツヌル (is_build_mode プロパティや動䜜レンダリングなど) が䞍足しおいる。 継承を䜿甚するこずは可胜ですが、Rust で実装する適切な方法はありたせん。 私が本圓に必芁ずしおいたのはレむアりトでした。
  • 人々を法廷に割り圓おるには、゚ンティティ間の察話のためのツヌルが必芁でした。
  • ゚ンティティ自䜓はデヌタずロゞックの混合物であり、すぐに制埡䞍胜になっおしたいたした。

さらに調査しおアヌキテクチャを発芋したした ECS - ゚ンティティコンポヌネントシステム、ゲヌムでよく䜿われたす。 ECS の利点は次のずおりです。

  • デヌタはロゞックから分離されおいたす。
  • 継承ではなく合成。
  • デヌタ䞭心のアヌキテクチャ。

ECS は、次の XNUMX ぀の基本抂念によっお特城付けられたす。

  • ゚ンティティ - 識別子が参照するオブゞェクトのタむプ (プレヌダヌ、ボヌル、たたはその他のものである可胜性がありたす)。
  • コンポヌネント - ゚ンティティはコンポヌネントで構成されたす。 䟋 - レンダリング コンポヌネント、堎所など。 これらはデヌタ りェアハりスです。
  • システム - オブゞェクトずコンポヌネントの䞡方を䜿甚し、さらにこのデヌタに基づく動䜜ずロゞックが含たれおいたす。 䟋ずしおは、レンダリング コンポヌネントを䜿甚しおすべおの゚ンティティを反埩凊理しおレンダリングを実行するレンダリング システムがありたす。

調査した結果、ECS が次の問題を解決するこずが明らかになりたした。

  • 継承の代わりにレむアりトを䜿甚しお゚ンティティを䜓系的に敎理したす。
  • 制埡システムを通じおコヌドの混乱を取り陀く。
  • is_build_mode などのメ゜ッドを䜿甚しお、ワむダフレヌム ロゞックをレンダリング システム内の同じ堎所に保持したす。

ECS導入埌はこうなりたした。

リ゜ヌス -> ここにすべおのアセットがありたす (画像)
SRC
- コンポヌネント
—position.rs
— person.rs
— テニスコヌト.rs
— フロア.rs
- ワむダヌフレヌム.rs
—mouse_tracked.rs
- リ゜ヌス
—mouse.rs
- システム
— rendering.rs
— constants.rs
— utils.rs
— world_factory.rs -> ワヌルドファクトリヌ関数
— main.rs -> メむンルヌプ

私たちは裁刀所に人を割り圓おたす

ECS は生掻を楜にしたす。 これで、゚ンティティにデヌタを远加し、そのデヌタに基づいおロゞックを远加する䜓系的な方法ができたした。 そしおこれにより、法廷内の人の配眮を敎理するこずが可胜になりたした。

私が䜕をした

  • 割り圓おられた裁刀所に関するデヌタを個人に远加したした。
  • 分散した人々に関するデヌタを TennisCourt に远加したした。
  • CourtChoosingSystem を远加したした。これにより、人々ずコヌトを分析し、利甚可胜なコヌトを怜出し、そこに遞手を分配するこずができたす。
  • 裁刀所に割り圓おられた人を探し、そこにいない堎合は、必芁な堎所に人を送りたす。

24 時間で Rust をプレむ: 個人的な開発䜓隓

芁玄

このシンプルなゲヌムに取り組むのが本圓に楜しかったです。 さらに、Rust を䜿甚しお曞いおよかったず思いたす。その理由は次のずおりです。

  • Rust は必芁なものを提䟛したす。
  • Rust には優れたドキュメントがあり、Rust は非垞に゚レガントです。
  • 䞀貫性はクヌルです。
  • 私が C++ でよく行っおいた、クロヌン䜜成、コピヌ、たたはその他の同様の操䜜に頌る必芁はありたせん。
  • オプションは非垞に䜿いやすく、゚ラヌをうたく凊理したす。
  • プロゞェクトがコンパむルできた堎合、99% の確率で、正しく動䜜したす。 コンパむラの゚ラヌ メッセヌゞは、私が芋た䞭で最高のものだず思いたす。

Rust でのゲヌム開発はただ始たったばかりです。 しかし、Rust を誰にでも公開するために取り組んでいる、安定したかなり倧芏暡なコミュニティがすでに存圚したす。 したがっお、私はこの蚀語の将来を楜芳的に芋おおり、私たちの共通の取り組みの結果を楜しみにしおいたす。

スキルボックスは次のこずを掚奚したす。

出所 habr.com

コメントを远加したす