#vb.net #oop #class #object
#vb.net #ооп #класс #объект
Вопрос:
долгое время читал первый постер. Пожалуйста, будьте нежны.
Я с жадностью создаю игры в VB.net . Будучи программистом-хобби, я раздаю свои игры бесплатно. Поскольку я любитель без формального обучения, я стараюсь обучаться правильным принципам программирования и следовать им при программировании, например, ООП. Однако есть некоторые вещи, которые я, очевидно, пропустил, будучи самоучкой, которые, возможно, я бы знал, если бы получил формальное образование.
Однажды такая проблема, которая действительно была моим проклятием, заключается в том, как разные классы (отныне называемые объектами) «знают» друг о друге БЕЗ программирования конкретного взаимодействия (оставайтесь со мной здесь… пожалуйста …)
Хорошо, представьте это, у вас есть космическая игра и следующие объекты
- clsShip
- clsMissile
- clsAsteroid
- clsSpaceJunk
Теперь каждый из этих объектов имеет работоспособность, частные члены X, Y и Z и свойства, которые все наследуются от clsSpaceEntity для аргументации. Теперь одним из способов программирования столкновения между ними было бы закодировать следующую логику в основном игровом цикле
для каждого корабля в списке кораблей
проверьте каждый clsMissile в списке, чтобы увидеть, сталкивается ли он с ним, и если да, уменьшите работоспособность
проверьте каждый clsasteroid в списке, чтобы увидеть, сталкивается ли он с ним, и если да, уменьшите работоспособность проверьте каждый список clsSpaceJunka, чтобы увидеть, сталкивается ли он с ним, и если да, уменьшите работоспособность
проверьте каждый список clsSpaceJunka, чтобы увидеть, сталкивается ли он с ним, и если да,снижение работоспособности
… и так далее, и так далее для каждого следующего объекта
ect, ect, ect…
Теперь это может быть нормально, если вы говорите о простом примере выше, но в некоторых моих играх есть десятки или даже СОТНИ объектов, которые взаимодействуют таким базовым способом.
Теперь мой вопрос к опытным программистам.
Есть ли способ в ООП сделать следующее…
для каждой вещи, которая наследуется от clsSpaceEntity
, проверьте все другие объекты, которые наследуют этот тип (кроме самого себя), и если они сталкиваются, затем уменьшите работоспособность
?
Такая способность для типа объектов / класса или чего-либо еще «осознавать» другого и то, как они одинаковы / различны и взаимодействуют, сэкономила бы мне тонны, тонны и ТОННЫ кодирования.
Любая помощь / помощь или отзывы по этому поводу были бы очень признательны. Спасибо за ваше время, извините за долгое чтение.
Комментарии:
1. Не используйте венгерскую нотацию (
clsWhatever
).2. Похоже, вы пытаетесь добиться надлежащего разделения проблем. Используя еще несколько концепций ООП, вы можете создать красиво разделенную логику без гигантских методов, которые обрабатывают все типы объектов. Удачи!
3. Немного не по теме, но вы, кажется, немного смущены классами и объектами. Хотя они связаны, это не одно и то же. Это поле для комментариев немного маловато для полного объяснения, но чтение различий облегчит вам жизнь.
Ответ №1:
Вместо того, чтобы иметь отдельный List(Of T)
для каждого производного объекта, вы должны создать единый List(Of SpaceEntity)
, который содержит все ваши сущности.
Затем вы можете создать вложенный For Each
цикл, который перебирает каждую пару объектов и выполняет проверку на коллизию. (после If x <> y
проверки)
Вы можете еще больше улучшить свой дизайн, предоставив SpaceEntity
MustOverride
функцию для обработки столкновений с другими объектами, не загрязняя цикл столкновений отдельной логикой для каждого объекта.
Вероятно, вам следует использовать шаблон visitor, чтобы позволить объектам по-разному реагировать на столкновения с другими типами объектов.
Обратите внимание, что каждое столкновение будет отправлено обоим объектам, которые столкнулись отдельно; вам нужно обработать это в своей логике.
Ответ №2:
Если бы я писал логику, которая имела дело с одним кораблем или одной ракетой, астероидом и т. Д., Тогда эта логика явно должна принадлежать соответствующему классу.
Если я пишу логику, которая имеет дело с несколькими объектами или, что еще хуже, с несколькими объектами разных типов, я бы предпочел поместить эту логику в класс, представляющий концепцию более высокого уровня.
Например, у вас может быть класс юниверса, который содержит коллекцию SpaceEntity . И есть Вселенная.Функция 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
}
}
Комментарии:
1. Этот вложенный цикл foreach будет возвращать два столкновения для каждой перекрывающейся пары объектов. Один для ракеты, сталкивающейся с камнем, и один для камня, сталкивающегося с ракетой. Возможно, вам потребуется отфильтровать их, в зависимости от того, как обрабатывается разрешение конфликтов.
2. Возможно, стоит отметить, что двойной вложенный цикл for станет непрактичным, поскольку количество объектов становится большим (более нескольких сотен). Если между объектами есть некоторое расстояние, которое гарантирует, что они не могут столкнуться, может быть полезно разделить юниверс на блоки, которые больше этого, и сохранить список объектов, которые хотя бы частично находятся в каждом блоке. При использовании простого разбиения в трехмерном пространстве некоторые объекты могут отображаться в восьми списках, но тестирование 100 групп из десяти объектов на предмет коллизий будет быстрее, чем тестирование одной группы из 1000.
3. Между прочим, возможно и не слишком сложно разделить трехмерное пространство на области таким образом, чтобы ни один объект не попадал более чем в четыре области (а не в восемь). Если округление Y до ближайшего целого числа даст нечетное число, добавьте 0,5 к X. Если округление Z до ближайшего целого числа даст нечетное число, добавьте 0,5 к X и Y. Затем округлите все три координаты до целых чисел. Сопоставление пространственных координат и значений XY показало бы, что пространство было разделено на единичные кубы, размещенные так, чтобы не более четырех находились в пределах четверти единицы от любой точки.