Страницы

Поиск по вопросам

пятница, 24 января 2020 г.

Как изменить улучшить код?

#c_sharp #разработка_игр #инспекция_кода


Есть игра, много персонажей. У каждого есть свои уникальные приемы, например

Бутылка шампанского

1. метнуть пробкой сквозь противника перекручиваясь через себя
2. залить пол алкоголем, заставив противника подскользнуться упасть


или 

Варвар

1. Кинуть топор вверх, через секунду топор прилетит в голову сопернику
2. Усыпить соперника рогом шляпы в глаз


Для каждого персонажа для кастомных приемов есть свой класс, в котором есть три метода:
beforeAttack, afterAttack, UpdateAttack. Где beforeAttack и  afterAttack вызываются
лишь один раз до приема и после, а UpdateAttack обновляется 1 раз в кадр (то есть много).
Эти классы наследуются от главного, который и контролирует процесс, примерно выглядит так:

abstract class CommonCustom {

    public virtual void beforeAttack() {}
    public virtual void afterAttack() {}
    public virtual void UpdateAttack() {}

    public virtual void ApplyAll() {
        // тут некое условие, чтоб этот метод вызывался лишь раз!
        beforeAttack();

        // вызывается много раз пока идет прием
        UpdateAttack();

        // тут некое условие, чтоб этот метод вызывался лишь раз!
        afterAttack();
    }
}


Суть проблемы: т.к. у меня есть три метода и у каждого персонажа может быть несколько
приемов, то получается так, что в каждом методе я пишу switch/case, например:

class Test : CommonCustom {
    public virtual void beforeAttack() {
        switch attackType {
            case beerAttack: //do smth
                 break;
            case capAttack: //do smth
                 break;
            // и т.д.
        }
    }
    public virtual void afterAttack() {
        switch attackType {
            case beerAttack: //do smth
                 break;
            case capAttack: //do smth
                 break;
            // и т.д.
        }
    }
    public virtual void UpdateAttack() {
        switch attackType {
            case beerAttack: //do smth
                 break;
            case capAttack: //do smth
                 break;
            // и т.д.
        }
    }
}


Можно ли что-то как-то сделать, чтоб не писать в каждом методе swith, а как-то единообразить
всё это дело? Может быть как-то добавить еще классы, которые надо имплементировать
или еще что-то.
    


Ответы

Ответ 1



Я бы сделал интерфейс IAttack: public interface IAttack { public void PreAttack(); public void Attack(); public void PostAttack(); } BeerAttack и другие реализуют этот интерфейс: public class BeerAttack : IAttack { public void PreAttack() { //специфическая логика пива } public void Attack() { //специфическая логика пива } public void PostAttack() { //специфическая логика пива } } Потом вот так: class Test : CommonCustom { public virtual void beforeAttack(IAttack attack) { attack.PreAttack(); } public virtual void afterAttack(IAttack attack) { attack.PostAttack(); } public virtual void UpdateAttack(IAttack attack) { attack.Attack(); }

Ответ 2



При любом раскладе вам придется расписать эту пару сотен сценариев, в скриптах ли, классах, кейсах.. Ваша задача найти такой вариант, который будет максимально удобным, с минимумом повторений и возможностей ошибиться, с необходимой вам степенью кастомизации и масштабируемости. Напишите десять сценариев, вычлените все общее. Выберите вариант. Кейсы, и как их развитие - Полиморфизм Сделать класс действия, отнаследовать от него классы действий (по типам). Использовать классы действий согласно типам действий прописанным в данных. Удобно кодить, но неудобно настраивать. Дата-дривен Когда вы все действия пропишите в данных игры и будет один класс который будет их выполнять. Достаточно жесткая структура. Что-то среднее межды хардкодом и скриптами (см. ниже) Скриптовые языки, типа Lua. Отличные возможности по моддингу игры и масштабируемости. Не нужно перекомпилировать чтобы изменить какую-то мелочь.

Комментариев нет:

Отправить комментарий