Создать поведенческую / компонентную систему для игр

11

Фон

Я занимаюсь разработкой игр как хобби и ищу лучший способ их дизайна. В настоящее время я использую стандартный подход ООП (я занимаюсь разработкой предприятия 8 лет, так что это происходит в обычном порядке). Взять, к примеру, «злодея»

public class Baddie:AnimatedSprite //(or StaticSprite if needed, which inherit Sprite)
{
    //sprite base will have things like what texture to use, 
    //what the current position is, the base Update/Draw/GetInput methods, etc..
    //an AnimatedSprite contains helpers to animated the player while 
    //a StaticSprite is just one that will draw whatever texture is there
}

Эта проблема

Допустим, я делаю 2D-платформер, и мне нужен злодей, чтобы иметь возможность прыгать. Обычно я добавляю соответствующий код в методы Update / GetInput. Тогда, если мне нужно заставить игрока ползать, нырять, лазить и т. Д., Код будет там.

Если я не буду осторожен, эти методы будут загромождены, поэтому я в итоге создаю пары методов, подобные этой

CheckForJumpAction(Input input) и DoJump()

CheckforDuckAction(Input input) и DoDuck()

так выглядит GetInput

public void DoInput(Input input)
{
    CheckForJumpAction(input);
    CheckForDuckAction(input);
}

и обновление выглядит

public void Update()
{
    DoJump();
    DoDuck();
}

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

Решение?

Мне действительно нравится, как у Blend есть поведение, которое я могу прикрепить к элементу. Я думал об использовании той же концепции в моих играх. Итак, давайте посмотрим на те же примеры.

Я бы создал базовый объект Behavior

public class Behavior
{
    public void Update()
    Public void GetInput()
}

И я могу создать поведение, используя это. JumpBehavior:BehaviorиDuckBehavior:Behavior

Затем я могу добавить коллекцию поведений в базу Sprite и добавить то, что мне нужно, к каждой сущности.

public class Baddie:AnimatedSprite
{
    public Baddie()
    {
        this.behaviors = new Behavior[2];
        this.behaviors[0] = new JumpBehavior();
        //etc...
    }

    public void Update()
    {
        //behaviors.update
    }

    public GetInput()
    {
        //behaviors.getinput
    }
}

Так что теперь, если бы я хотел использовать Jump and Duck во многих играх, я могу просто перенести поведение. Я мог бы даже сделать библиотеку для обычных.

Это работает?

Что я не могу понять, так это как разделить состояние между ними. Глядя на Jump и Duck, они влияют не только на текущую часть рисуемой текстуры, но и на состояние игрока. (Прыжок будет со временем применять уменьшающуюся восходящую силу, в то время как утка просто остановит движение, изменит текстуру и размер столкновения злодея.

Как я могу связать это вместе, чтобы это работало? Должен ли я создать свойства зависимости между поведением? Должен ли я иметь каждое поведение ноу о родителе и непосредственно изменить его? Одна вещь, о которой я думал, была возможность передавать делегат в каждое поведение, чтобы оно выполнялось при его запуске.

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

Так что я передаю это вам. Не хочешь объяснить, как / если это можно сделать? У тебя есть идея получше? Я весь во внимании.


источник
Это может быть лучше спросить на gamedev.stackexchange.com ?
rcapote
Мне нравится, куда ты идешь, но я не уверен, как решать проблемы, которые ты поднимаешь. Очень интересно и имеет значение не только для разработки игр.
Эдвард Стрендж,
@rcapote не этот сайт для доски объявлений?
2
@ Джо - нет, нет. Даже не упоминайте "обсуждение" здесь, или вы будете лишены существования. Этот сайт предназначен только для вопросов-> Ответ-> Готово.
Эдвард Стрендж
Что ж, системы сущностей на основе компонентов - это то, что в последнее время стало популярным в сообществе разработчиков игр, поэтому я подумал, что вы могли бы получить больше внимания там, но в любом случае вы, вероятно, получите здесь хорошие ответы. Вот интересная дискуссия по GameDev.net об этой проблеме , что вы могли бы найти интересное: gamedev.net/topic/...
rcapote

Ответы:

1

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

Nieldy
источник
9

Для меня это звучит почти как учебник для использования шаблона стратегии . В этом паттерне ваше общее поведение может быть определено в интерфейсах, которые позволят вам менять различные реализации поведения во время выполнения (подумайте о том, как усиление может повлиять на способность вашего персонажа к прыжкам или бегу).

Для (надуманного) примера:

// The basic definition of the jump behavior
public interface IJumpBehavior {
    void Jump();
}

Теперь вы можете реализовывать различные типы прыжков, которые может использовать ваш персонаж, не обязательно зная детали каждого конкретного прыжка:

// This is the jump the character may have when first starting
public class NormalJump : IJumpBehavior {

     public void Jump() {
         Console.WriteLine("I am jumping, and being pretty boring about it!");
     }

}

// This is the jump of a character who has consumed a power-up
public class SuperJump : IJumpBehavior {
    public void Jump() { 
         Console.WriteLine("I am all hopped up on star power, now my jumps can do damage!");
     }
}

Любые символы, которые вы хотите иметь возможность прыгать, могут теперь содержать ссылку на IJumpable и могут начать потреблять ваши различные реализации

public class HeroCharacter {

    // By default this hero can perform normal jump.
    private IJumpBehavior _jumpBehavior = new NormalJump();

    public void Jump() {
        _jumpBehvaior.Jump();
    }

    // If you want to change the hero's IJumpable at runtime
    public void SetJump(IJumpBehavior jumpBehavior) {
      _jumpBehavior = jumpBehavior;
    }

}

Тогда ваш код может выглядеть примерно так:

HeroCharacter myHero = new HeroCharacer();

// Outputs: "I am jumping, and being pretty boring about it!"
myHero.Jump()

// After consuming a power-up
myHero.SetJump(new SuperJump());

// Outputs: "I am all hopped up on star power, now my jumps can do damage!"
myHero.Jump();

Теперь вы можете легко использовать эти варианты поведения или даже расширить их позже, если хотите добавить больше типов переходов, или создать больше игр, созданных на одной платформе боковой прокрутки.

mclark1129
источник
хотя не совсем то, что я ищу, это очень близко и нравится. Я собираюсь поиграть с этим, чтобы убедиться. благодаря!
1

Взгляните на архитектуру DCI - интересный подход к программированию ОО, который может помочь.

Реализация архитектуры стиля DCI в C # требует использования простых классов домена и использования объектов Context (поведения) с методами расширения и интерфейсами, чтобы позволить классам домена взаимодействовать под различными ролями. Интерфейсы используются для выделения ролей, необходимых для сценария. Классы домена реализуют интерфейсы (роли), которые применяются к их предполагаемому поведению. Сотрудничество между ролями происходит в контексте (поведении) объектов.

Вы можете создать библиотеку с общими поведениями и ролями, которые могут совместно использоваться объектами домена из отдельных проектов.

Смотрите DCI в C # для примеров кода в C #.

Эд Джеймс
источник
0

Как насчет передачи объекта контекста в поведение, которое предоставляет методы для изменения состояния спрайтов / объектов, на которые воздействует поведение? Теперь, если объект имеет несколько поведений, каждый из них вызывается в цикле, что дает им возможность изменить контекст. Если определенная модификация свойства исключает / ограничивает модификацию других свойств, объект контекста может предоставить методы для установки каких-либо флагов, чтобы указать этот факт, или он может просто запретить нежелательные модификации.

Джонни Ди
источник