Играње Rust за 24 часа: искуство за личен развој

Играње Rust за 24 часа: искуство за личен развој

Во оваа статија ќе зборувам за моето лично искуство за развој на мала игра во Rust. Беа потребни околу 24 часа за да се создаде работна верзија (најчесто работев навечер или за време на викендите). Играта е далеку од завршена, но мислам дека искуството ќе биде наградно. Ќе го споделам она што го научив и некои набљудувања што ги направив додека ја градев играта од нула.

Skillbox препорачува: Двегодишен практичен курс „Јас сум PRO веб-развивач“.

Потсетуваме: за сите читатели на „Хабр“ - попуст од 10 рубли при запишување на кој било курс Skillbox користејќи го промотивниот код „Хабр“.

Зошто 'рѓа?

Го избрав овој јазик бидејќи слушнав многу добри работи за него и гледам дека станува сè попопуларен во развојот на игри. Пред да ја напишам играта, имав мало искуство со развивање едноставни апликации во Rust. Ова беше доволно само за да ми даде чувство на слобода додека ја пишував играта.

Зошто играта и каква игра?

Правењето игри е забавно! Посакувам да има повеќе причини, но за „домашни“ проекти избирам теми кои не се премногу поврзани со мојата редовна работа. Каква игра е ова? Сакав да направам нешто како тениски симулатор што ги комбинира Cities Skylines, Zoo Tycoon, Prison Architect и самиот тенис. Во принцип, се покажа дека е игра за тениска академија каде што луѓето доаѓаат да играат.

Техничка обука

Сакав да го користам Rust, но не знаев точно колку основа ќе биде потребна за да се започне. Не сакав да пишувам шејдери на пиксели и да користам drag-n-drop, па ги барав најфлексибилните решенија.

Најдов корисни ресурси што ги споделувам со вас:

Истражував неколку мотори за игри Rust, на крајот избрав Piston и ggez. Наидов на нив додека работев на претходен проект. На крајот, го избрав ggez бидејќи ми се чинеше посоодветен за имплементација на мала 2D игра. Модуларната структура на 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 -> главна јамка

Луѓе, подови и слики

Следниот чекор е да се создаде објект на играта Person и да се вчитаат слики. Сè треба да биде изградено врз основа на плочки 32*32.

Играње Rust за 24 часа: искуство за личен развој

Тениско игралиште

Откако проучував како изгледаат тениските терени, решив да ги направам од плочки 4*2. Првично, беше можно да се направи слика со оваа големина или да се спојат 8 посебни плочки. Но, тогаш сфатив дека се потребни само две уникатни плочки, а еве зошто.

Вкупно имаме две такви плочки: 1 и 2.

Секој дел од теренот се состои од плочка 1 или плочка 2. Тие можат да бидат поставени како нормално или превртени за 180 степени.

Играње Rust за 24 часа: искуство за личен развој

Основен режим на конструкција (склопување).

Откако успеав да постигнам рендерирање на локации, луѓе и мапи, сфатив дека е потребен и основен режим на склопување. Јас го имплементирав вака: кога ќе се притисне копчето, објектот се избира, а кликнувањето го става на саканото место. Значи, копчето 1 ви овозможува да изберете терен, а копчето 2 ви овозможува да изберете играч.

Но, сепак треба да запомниме што значат 1 и 2, па додадов рамка за да разјаснам кој објект е избран. Вака изгледа.

Играње Rust за 24 часа: искуство за личен развој

Прашања за архитектура и рефакторирање

Сега имам неколку предмети за игра: луѓе, терени и подови. Но, за да функционираат жичаните рамки, на секој објект треба да му се каже дали самите објекти се во режим на демонстрација или дали рамката е едноставно нацртана. Ова не е многу погодно.

Ми се чинеше дека архитектурата треба да се преиспита на начин што открива некои ограничувања:

  • Да се ​​има ентитет што сам по себе рендерира и ажурира е проблем бидејќи тој ентитет нема да може да „знае“ што треба да рендерира - слика и рамка;
  • недостаток на алатка за размена на својства и однесување помеѓу поединечни ентитети (на пример, својството is_build_mode или рендерирање на однесување). Би било можно да се користи наследство, иако не постои соодветен начин да се имплементира во Rust. Она што навистина ми требаше беше распоредот;
  • беше потребна алатка за интеракција помеѓу субјектите за доделување луѓе во судовите;
  • самите ентитети беа мешавина од податоци и логика кои брзо излегоа од контрола.

Направив уште малку истражување и ја открив архитектурата ECS - Ентитет-компонентен систем, кој најчесто се користи во игрите. Еве ги придобивките од ECS:

  • податоците се одвоени од логиката;
  • состав наместо наследство;
  • архитектура фокусирана на податоци.

ECS се карактеризира со три основни концепти:

  • ентитети - тип на објект на кој се однесува идентификаторот (може да биде играч, топка или нешто друго);
  • компоненти - ентитетите се составени од нив. Пример - компонента за рендерирање, локации и други. Тоа се складишта на податоци;
  • системи - тие користат и објекти и компоненти, плус содржат однесување и логика што се засноваат на овие податоци. Пример е систем за рендерирање кој повторува низ сите ентитети со компоненти за рендерирање и го прави рендерирањето.

Откако го проучував, стана јасно дека ECS ги решава следниве проблеми:

  • користење на распоред наместо наследство за системско организирање на ентитетите;
  • ослободување од мешаницата на кодови преку контролните системи;
  • користејќи методи како is_build_mode за да ја задржите логиката на жичната рамка на истото место - во системот за рендерирање.

Ова е она што се случи по спроведувањето на ECS.

ресурси -> тука се сите средства (слики)
src
- компоненти
— позиција.rs
— лице.rs
— tennis_court.rs
— кат.рс
- wireframe.rs
— mouse_tracked.rs
- ресурси
— глушец.рс
- системи
— рендерирање.rs
— константи.rs
— utils.rs
— world_factory.rs -> светски фабрички функции
— main.rs -> главна јамка

Доделуваме луѓе во судовите

ECS го олесни животот. Сега имав систематски начин да додавам податоци на ентитети и да додавам логика врз основа на тие податоци. И ова, пак, овозможи да се организира распределба на луѓе меѓу судовите.

Што направив:

  • додадени податоци за доделените судови на Лицето;
  • додадени податоци за дистрибуирани луѓе на Тенискоурт;
  • додаде CourtChoosingSystem, кој ви овозможува да анализирате луѓе и терени, да откриете достапни терени и да ги дистрибуирате играчите до нив;
  • додаде PersonMovementSystem, кој бара луѓе доделени во судовите, а ако ги нема, тогаш ги испраќа луѓето каде што треба.

Играње Rust за 24 часа: искуство за личен развој

Сумирање

Навистина уживав да работам на оваа едноставна игра. Згора на тоа, мило ми е што го искористив Rust за да го напишам, бидејќи:

  • Рѓата ви го дава она што ви треба;
  • има одлична документација, Rust е доста елегантен;
  • конзистентноста е кул;
  • не мора да прибегнувате кон клонирање, копирање или други слични дејства, што често ги правев во C++;
  • Опциите се многу лесни за употреба и одлично се справуваат со грешките;
  • ако проектот можеше да се состави, тогаш 99% од времето работи, и точно како што треба. Мислам дека пораките за грешка на компајлерот се најдобрите што сум ги видел.

Развојот на играта во Rust само што започнува. Но, веќе постои стабилна и прилично голема заедница која работи на отворање на Rust за сите. Затоа, со оптимизам гледам на иднината на јазикот, очекувајќи ги резултатите од нашата заедничка работа.

Skillbox препорачува:

Извор: www.habr.com

Додадете коментар