C # список или массив, который принимает все типы? - PullRequest
0 голосов
/ 17 апреля 2011

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

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

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

Моя вторая резервная копия - создать все объекты, которые будутиметь тени, производные от класса с именем ShadowObject или чего-то еще, и создать список этого типа.Это действительно простое решение, но причина, по которой я этого пока не делаю, заключается в том, что мне не нравится идея создания фиктивного класса просто для того, чтобы заставить что-то работать, но, может быть, мне стоит начать любить его.

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

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

Редактировать: я знаю об интерфейсах, но мой ответ на это содержится в комментариях к ответу xixonia и после прочтения немного больше об интерфейсах, я думаю, что иметь класс ShadowCaster было бы более подходящим.Он может обрабатывать все рисунки теней, потому что все тени нарисованы одинаково, мне не нужно определять его для каждого объекта индивидуально, как этого требует интерфейс.

Ответы [ 4 ]

2 голосов
/ 17 апреля 2011

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

Пока объект реализует этот интерфейс, вы знаете, что можете сказать ему нарисовать тень. Фактический рисунок тени будет оставлен на усмотрение самого объекта при условии правильного устройства для рисования.

Например:

class Program
{
    public static void Main()
    {
        var shadowCasters = new List<ICastShadow>();

        shadowCasters.Add(new Car());
        shadowCasters.Add(new Plane());

        var castShadows = true;

        if (castShadows)
        {
            foreach (var caster in shadowCasters)
            {
                caster.DrawShadow(null); 
            }
        }

        Console.Read();
    }

    public class Car : ICastShadow
    {
        public void DrawShadow(object device)
        {
            Console.WriteLine("Car Shadow!");
        }
    }

    public class Plane : ICastShadow
    {
        public void DrawShadow(object device)
        {
            Console.WriteLine("Plane Shadow!");
        }
    }

    public interface IShadowCaster
    {
        void DrawShadow(object device);
    }
}

Когда вам нужно проверить, способен ли ваш объект отбрасывать тени, вы можете использовать ключевое слово "is" ...

if(myTrain is ICastShadow)
{
    shadowCasters.Add(myTrain);
}

Надеюсь, это поможет! :)

редактировать

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

У вас есть BrickBuilding и GlassBuilding. Кирпичное здание должно отбрасывать тень, а стеклянное здание не должно. Они оба наследуются от Building, который наследуется от ShadowCaster. Даже если все ваши классы отбрасывания теней рисуют тени одинаково, вам все равно нужно сделать методы ShadowCaster виртуальными, чтобы GlassBuilding мог их переопределить и ничего не делать при вызове этого метода.

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

Так что же происходит, когда вы используете интерфейс и начинаете повторять одну и ту же логику снова и снова, потому что все ваши классы рисования теней рисуют тени одинаково? Очевидно, это не лучшая идея. Но если все они рисуют тени одинаково, вы можете использовать другой класс для рисования теней для их. Затем идет класс "ShadowCaster".

Реализация теневого рисования для каждого объекта затем вызывала бы метод этого ShadowCaster, чтобы нарисовать тень для него. Это позволяет каждому объекту параметр рисования теней по-своему, но также предоставляет способ для каждого объекта использовать реализацию рисования теней по умолчанию. Он также предоставляет возможность легко добавлять и удалять возможность рисовать тени для определенных объектов (просто не позволяйте объектам реализовывать интерфейс ICastShadow).

Чтобы сделать еще один шаг вперед, вы можете рассматривать отбрасывание теней как другой метод рисования и создавать обобщенный интерфейс для рисования теней / частиц / отражений / трон-свечения и т. Д., А также создавать различные «модули», которые выполняют эти разные функции. вещи. Вместо того, чтобы ваш класс реализовывал ICastShadows, он должен реализовывать «IDrawModules», а затем давать каждому классу правильные модули во время выполнения.

Другими словами, вы можете добавить модуль «CastShadow» в BrickBuilding и добавить модуль «Reflect» в GlassBuilding, и ваш код будет вызывать «DrawModules» для обоих объектов (из интерфейса IDrawModules).

Хорошо, это становится действительно очень долго, Надеюсь, это поможет, и это не слишком запутанно.

Я бы посоветовал прочесть первые пару глав «Head First Design Patterns». Это книга на Java, но принципы для большинства языков одинаковы.

2 голосов
/ 17 апреля 2011

Вместо "фиктивного класса" ShadowObject, почему бы вам просто не создать интерфейс IShadowObject, который бы выставлял все необходимые методы и использовал:

List<IShadowObject>
0 голосов
/ 17 апреля 2011

Вы можете использовать оператор "is" для проверки типа.

public bool check(object obj)
{
   return obj is ShadowStuff;
   // or obj.GetType() == ShadowStuff
}

на сотворение:

(ShawdowStuff) obj  ;
0 голосов
/ 17 апреля 2011

Я не знаю много о разработке игр, но похоже, что System.Generic.Collection.List поддерживается платформой XNA. Это был бы ваш список любого типа.

...