Pull to refresh

Разработка мультижанровой игры (пока RPG составляющая) на Bevy, LDtk, и прочее, прочее…

Level of difficultyEasy
Вступление

Hello, Habr! Эта статья не является ни путеводителем, ни тем более полным руководством, я лишь хочу описать свой опыт общения с движком и другим софтом, который использую впервые - можно сказать свой путь.
Буду рад советам в комментах, особенно по тем вопросам, которые я прямо задаю!

Также, буду ждать обратной связи на тему, а интересен ли такой контент вообще)

Почему стайка

При выборе игрового движка я руководствовался предпочтениями к языку — бывало писал на плюсах, и про шарп кое‑что знаю, но в сердце запал именно Rust).

К тому же, погружаться в огромные Unity и Unreal, пусть и с огромным количеством туториалов и документации — дело объемное, а про остальные движки ничего не скажу — остались ведь в основном ребята под скриптовые ЯП? (не моя любимая тема). Так вот, мой путь — это относительно небольшой модульный набор библиотек, которые можно осваивать с ранних этапов развития.

В пользу вышесказанного играет и моя неопытность в игровой разработке, желание «прохавать» её с низов — поиграть с графическими дровами, посмотреть, загрузить пару спрайтов по пикселям через байт‑буфер).

Итого - берём Bevy. Я начал с чего-то вроде 0.10, но мигрировал вплоть до 0.14.

Первые спрайты

Я не художник, не музыкант и не кто бы то ни было ещё, кроме кодера, но мне важно хотя бы поверхностно разобраться в большинстве аспектов разработки (и других вещей) прежде чем я смогу делегировать этот самый аспект (сейчас речь о рисовании) на случайные спрайты с просторов сети или другие ресурсы. Рисовал я в Aseprite и Pixel Studio.

И встречайте мои первые наброски, вот они - слева направо!

Осторожно, вырвиглаз
Это цыпа
Это цыпа
Это просто помидор на ножках, который был нужен для теста слоёв
Это просто помидор на ножках, который был нужен для теста слоёв
Seems like archer
Seems like archer
Также был вот такой паренёк, я пытался играться с переодеванием персонажа в рантайме
Также был вот такой паренёк, я пытался играться с переодеванием персонажа в рантайме

Думаю, для начала неплохо)

Emotions, Calm, Sabotage

Знаю, из моих разговоров о расте не сделаешь вывод о том, что я закоренелый ООП разработчик, но это так...

Название этой главы отражает не только примерное положение дел и связей в настоящем ECS, но и опыт знакомства с этим стилем - было долго, тяжело, местами сущность эмоций с определённым компонентом спокойствия попадала в систему саботирования.

Пока с трудом представляю себе, как под капотом реализована система архетипов, но уже в какой-то мере получается определять компоненты, создавать на их основе сущности, и даже воздействовать на них через системы.

Я провёл аналогию между trait'ами и Component, и структурами (вернее будет сказать их экземплярами) и Entity. А системы в этой идее воспринимаются как функции, принимающие экземпляр чего-то вроде impl Component. Это сильно упрощает на ранних этапах, хотя хочется мыслить не на уровне аналогий, а со сдвигом парадигмы)

Первый код

Ну, что тут скажешь, знакомство...

Система для перемещения игрока

Сорри за хардкод и unused:)

fn sprite_movement(time: Res<Time>,  
    mut sprite_position: Query<(&mut Transform)>,
        movement_x: Res<Movement_X>,
        movement_y: Res<Movement_Y>) 
    {
    for mut transform in &mut sprite_position{
        match movement_y.get() {
            MovementY::Up => transform.translation.y += 5.,
            MovementY::Down => transform.translation.y -= 5.,
            _ => {}
        }
        match movement_x.get() {
            MovementX::Left => transform.translation.x -= 5.,
            MovementX::Right => transform.translation.x += 5.,
            _ => {}
        }
    }
}

Что у нас тут, моё изобретение из одинаково названных перечислений и компонентов, их скрывающих. А нет, это ресурсы...

В пару к этой системе вероятно должна идти та, которая принимает пользовательский ввод:

fn keyboard_input_system(
    keyboard_input: Res<ButtonInput<KeyCode>>,
    mut movement_x: ResMut<Movement_X>,
    mut movement_y: ResMut<Movement_Y>) 
    {
    match (keyboard_input.pressed(KeyCode::KeyS),keyboard_input.pressed(KeyCode::KeyW)) {
        (true, false)=>movement_y.set(MovementY::Down),
        (false, true)=>movement_y.set(MovementY::Up),
        _ => movement_y.set(MovementY::No),
    }
    match (keyboard_input.pressed(KeyCode::KeyA),keyboard_input.pressed(KeyCode::KeyD)) {
        (true, false)=>movement_x.set(MovementX::Left),
        (false, true)=>movement_x.set(MovementX::Right),
        _ => movement_x.set(MovementX::No),
    }
}

Система спавна игрока

Заспавнить обычный спрайт - одна строка кода. Я хотел чтобы у игрока, да и у любого персонажа в игре была возможность модификаций, сменить шляпку или ещё что - так родилась эта система

fn setup_character(
    mut commands: Commands, 
    asset_server: Res<AssetServer>,
    mut texture_atlas_layouts: ResMut<Assets<TextureAtlasLayout>>)
    {
    let texture = asset_server.load("goose/universal_man.png");
    let num_of_sprites = 8;
    let num_of_frames = 2;
    let layout = 
        TextureAtlasLayout::from_grid(
            Vec2::new(64.0,64.0), 
            num_of_frames, 
            num_of_sprites, 
            None, 
            None);
    let texture_atlas_layout= texture_atlas_layouts.add(layout);

    let transform = Transform{scale:Vec3::splat(3.0), translation: Vec3::new(100., 0., 0.),..default()};
    let sprite_bundle = SpriteBundle{
        texture,
        transform,
        ..default()
    };
    for i in 0..num_of_sprites {
        if i == 4 || i == 6 {
            continue
        }
        let animation_indices = AnimationIndices { first: i* num_of_frames, last:(i+1)* num_of_frames -1 };
        let k = (
            sprite_bundle.clone(),

            TextureAtlas {
                layout: texture_atlas_layout.clone(),
                index: animation_indices.first,
            },
            animation_indices,
            AnimationTimer(Timer::from_seconds(0.3, TimerMode::Repeating)),
            Direction::Up,
        );
        commands.spawn(k);

    }

}

Сейчас обеих систем не существует. То есть есть, конечно, система перемещений, но она переработана донельзя, и естественно допускает перемещение не только самого Игрока с большой буквы.

Задача трёх тел

Я специально не сильно комментировал вторую и последнюю описанную выше систему — к ней есть претензии.

Работает она, мягко говоря, плохо — вечно что‑то не на том слое отображается.
Кто знает, как грамотно загружает спрайты под отдельные элементы экипировки и инкапсулировать всё это в сущности персонажа, да так ещё чтобы это были спрайты анимированные — дайте знать)

Планы

В следующей статье будет описан опыт работы с LDtk, есть у меня пара нерешённых проблем и там - может как раз получится разобраться.

Насчет непосредственно планов на развитие проекта в ближайшей перспективе:

  • Добавить NPC и механику диалога

  • Механика инвентаря

  • Пофиксить наконец слоёные спрайты и их анимацию

  • Механика боя

  • Квесты

  • Генерация мира

  • Поиграть с коллизиями (спойлер)

  • Переименовать козу в помидор или перерисовать помидор в козу (спойлер)

  • ИИ, который не просто ходит в случайном направлении (спойлер)

  • Логичный переход по локациям (спойлер)

Скрин к спойлеру?

Tags:
Hubs:
You can’t comment this publication because its author is not yet a full member of the community. You will be able to contact the author only after he or she has been invited by someone in the community. Until then, author’s username will be hidden by an alias.