«Самосознательные» классы? - PullRequest
8 голосов
/ 01 ноября 2011

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

Я жадно создаю игры на VB.net. Будучи хобби-программистом, я отдаю свои игры бесплатно. Поскольку я хобби без формального обучения, я стараюсь научить себя правильным принципам программирования и следовать им при программировании, таком как ООП. Однако есть некоторые вещи, которые я, очевидно, упустил, будучи самоучкой, и, возможно, я узнал бы, если бы получил формальное образование.

Однажды такая проблема, которая действительно была моей проблемой, заключается в том, как разные классы (отныне именуемые объектами) «узнают» друг о друге БЕЗ программирования определенного взаимодействия (оставайтесь со мной здесь ... пожалуйста ...)

Хорошо, представьте, у вас космическая игра и следующие объекты

  • clsShip
  • clsMissile
  • clsAsteroid
  • clsSpaceJunk

Теперь каждый из этих объектов имеет закрытые члены Health, X, Y и Z и свойства, которые все унаследованы от clsSpaceEntity для аргументации. Теперь одним из способов программирования столкновения между ними было бы закодировать следующую логику в основном игровом цикле

для каждого корабля в списке кораблей
проверьте каждый clsMissile в списке, чтобы увидеть, сталкивается ли он с ним, и если да, то уменьшить здоровье
проверьте каждый clsAsteroid в списке, чтобы увидеть, сталкивается ли он с ним, и если да, то уменьшить здоровье
проверьте каждый список clsSpaceJunka, чтобы увидеть, сталкивается ли он с ним, и если да, то уменьшить здоровье
... и так далее, и так далее для каждого объекта Следующий

ect ect ect ...

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

Теперь мой вопрос к опытным программистам.

Есть ли способ в ООП сделать следующее ...

для каждой вещи, которая наследуется от clsSpaceEntity
проверять все остальные объекты, которые наследуют этот тип (кроме себя), и если они сталкиваются, уменьшить здоровье
Следующий

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

Буду очень признателен за любую помощь / помощь или отзывы по этому вопросу. Спасибо за ваше время, простите за долгое чтение.

Ответы [ 2 ]

7 голосов
/ 01 ноября 2011

Вместо отдельного List(Of T) для каждого производного объекта, вы должны создать один List(Of SpaceEntity), который содержит все ваши сущности.

Затем можно создать вложенный цикл For Each, который проходит по каждой паре сущностей и выполняет проверку столкновения. (после проверки If x <> y)

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

Обратите внимание, что каждое столкновение будет отправлено обоим объектам, которые столкнулись отдельно; Вы должны справиться с этим в своей логике.

2 голосов
/ 01 ноября 2011

Если бы я писал логику, имеющую дело с одним кораблем или одной ракетой, астероидом и т. Д. Тогда эта логика должна явно принадлежать соответствующему классу.

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

Например, у вас может быть класс Universe, содержащий коллекцию SpaceEntity.И есть Universe.FindCollisions (), который возвращает коллекцию объектов Collision.

public class Universe {
    private IEnumerable<SpaceEntity> _entities;

    public IEnumerable<Collision> FindCollisions() {
        foreach(var e1 in _entities) {
            foreach(var e2 in _entities) {
                if (e1.CollidesWith(e2)) {
                    yield return new Collision(e1, e2);
                }
            }
        }
    }
}

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

public class CollisionCalculator {
    public IEnumerable<Collision> Collisions {get; set;}

    public CollisionCalculator(IEnumerable<SpaceEntity> entities) {
        // logic to build the Collisions collection goes here
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...