Делаю небольшую real time strategy game в образовательных целях на java.
Есть класс Unit (общий interface для всех юнитов) — юниты. Они могут быть Movable (interface) — двигующиеся и Attackable (interface) — атакующие, комбинировать эти свойства или не обладать ими вообще. Movable юниты должны поддерживать 2 состояния — Moving и Stop. Для реализации состояния Moving могут использоваться разные стратегии движения. Attackable также должен поддерживать 2 состояния — Attack и Guard в каждом из них должна быть реализована своя стратегия поведения.
Здравствуйте, Burlaka, Вы писали:
B>Делаю небольшую real time strategy game в образовательных целях на java.
B>Есть класс Unit (общий interface для всех юнитов) — юниты. Они могут быть Movable (interface) — двигующиеся и Attackable (interface) — атакующие, комбинировать эти свойства или не обладать ими вообще. Movable юниты должны поддерживать 2 состояния — Moving и Stop. Для реализации состояния Moving могут использоваться разные стратегии движения. Attackable также должен поддерживать 2 состояния — Attack и Guard в каждом из них должна быть реализована своя стратегия поведения.
B>Как лучше организовать иерархию классов?
Советую рассмотреть такой подход: не представлять каждый тип поведения интерфейсом и не комбинировать, ибо это сильно запутает архитектуру, а представить каждый тип юнита (с различным поведением) как отдельный класс. Типу юнита будет соответствовать машина состояний (нарисованные на бумажке состояния и переходы между ними, например состояния "идет", "поворачивается", "падает", "озирается" и т.д., переходы между состояниями иницируются вызовами методов интерфейса данного типа юнита, только посредством этих методов можно влиять на состояние юнита, например turn, walk, kill...). Машина состояний будет реализована через паттерн State, у например у класса WarriorUnit будет private поле WarriorUnitState (абстрактный класс), в каждый конкретный момент времени это поле будет хранить ссылку на конкретное состояние, например WalkingState или DyingState, DiedState. Такой подход удобен тем, что можно с легкостью расширять машину состояний, а расширять её придется неизбежно непредусмотренными заранее состояниями, или чтобы ввести плавность переходов между ними, придется вводить промежуточные состояния типа "доставать оружие", "убирать оружие", "радоваться победе" и много-много других. "Комбинированный" же подход, мне кажется, в этом случае может запутать сложностью.
Также заранее нужно подумать о одно- или много-поточности, о типе ИИ (глобальный (классический, когда персонаж имеет доступ ко всем данным игрового мира) или перцептуальный (воплощенный, когда персонаж воспринимает мир только с помощью ограниченного набора методов)), дискретной или непрерывной модели, типе взаимодействия (event-driven или нет), будет ли разделение на вид-модель.
Здравствуйте, gyraboo, Вы писали:
G>Такой подход удобен тем, что можно с легкостью расширять машину состояний, а расширять её придется неизбежно непредусмотренными заранее состояниями, или чтобы ввести плавность переходов между ними, придется вводить промежуточные состояния типа "доставать оружие", "убирать оружие", "радоваться победе" и много-много других. "Комбинированный" же подход, мне кажется, в этом случае может запутать сложностью.
Я не спец в играх, но у меня возникает чувство, что машина состояний начнет давать сбои, когда понадобится радоваться победе убирая оружие на ходу.
Здравствуйте, Ziaw, Вы писали:
Z>Я не спец в играх, но у меня возникает чувство, что машина состояний начнет давать сбои, когда понадобится радоваться победе убирая оружие на ходу.
А зачем?
... << RSDN@Home 1.2.0 alpha rev. 745>>
Пусть это будет просто:
просто, как только можно,
но не проще.
(C) А. Эйнштейн
Здравствуйте, WolfHound, Вы писали:
Z>>Я не спец в играх, но у меня возникает чувство, что машина состояний начнет давать сбои, когда понадобится радоваться победе убирая оружие на ходу. WH>А зачем?
Действительно, зачем все навороты? Игроку ведь так нравится отвлечься и посмотреть как после очередной убитой птички его герой красиво убирает оружие, потом подпрыгивает и хлопает в ладоши радуясь победе и только после этого начинает движение в нужном игроку направлении.
Здравствуйте, Ziaw, Вы писали:
G>>Такой подход удобен тем, что можно с легкостью расширять машину состояний, а расширять её придется неизбежно непредусмотренными заранее состояниями, или чтобы ввести плавность переходов между ними, придется вводить промежуточные состояния типа "доставать оружие", "убирать оружие", "радоваться победе" и много-много других. "Комбинированный" же подход, мне кажется, в этом случае может запутать сложностью.
Z>Я не спец в играх, но у меня возникает чувство, что машина состояний начнет давать сбои, когда понадобится радоваться победе убирая оружие на ходу.
Я тоже не занимаюсь играми профессионально. Но как хобби — лет наверное 15. По моему опыту — использование машины состояний — наиболее оптимальное решение по соотношению простота реализации/эффективность. Причем машину состояний как модель первого приближения удобно использовать не только для описания персонажей, но и описания всей "инфраструктуры" игры (состояния "заставка"-"экран помощи"-"пауза"-"загрузка уровня"-"процесс игры"-"демо"), а также других элементов. На реализацию машины (в виде паттерна State) можно навесить механизм событий (оповещение об изменении состояния), и в этом случае машина состояний идеально ложится на архитектуру MVC.
Вообще же, если инициатор топика дойдет в реализации свой идеи до той стадии, когда понадобятся указанные вами, Ziaw, навороты в поведении персонажей, советую курить эту книгу: "Искусственный интеллект в компьютерных играх: как обучить виртуальные персонажи реагировать на внешние воздействия", Алекс Дж. Шампандар (http://www.kodges.ru/2007/10/07/iskusstvennyjj-intellekt-v.html)
Здравствуйте, gyraboo, Вы писали:
G>Я тоже не занимаюсь играми профессионально. Но как хобби — лет наверное 15. По моему опыту — использование машины состояний — наиболее оптимальное решение по соотношению простота реализации/эффективность. Причем машину состояний как модель первого приближения удобно использовать не только для описания персонажей, но и описания всей "инфраструктуры" игры (состояния "заставка"-"экран помощи"-"пауза"-"загрузка уровня"-"процесс игры"-"демо"), а также других элементов. На реализацию машины (в виде паттерна State) можно навесить механизм событий (оповещение об изменении состояния), и в этом случае машина состояний идеально ложится на архитектуру MVC.
Я думаю, что прислушаюсь к вашей рекомендации. Идея вообщем-то такая: сделать "экосистему" с расширяемым количеством существ живущих в ней, их состояний и их способностей. Чтобы потом, в последствии, можно было создавать новых, комбинировать существующих и т.д.
Здравствуйте, Burlaka, Вы писали:
B>Есть класс Unit (общий interface для всех юнитов) — юниты. Они могут быть Movable (interface) — двигующиеся и Attackable (interface) — атакующие, комбинировать эти свойства или не обладать ими вообще. Movable юниты должны поддерживать 2 состояния — Moving и Stop. Для реализации состояния Moving могут использоваться разные стратегии движения. Attackable также должен поддерживать 2 состояния — Attack и Guard в каждом из них должна быть реализована своя стратегия поведения.
B>Как лучше организовать иерархию классов?
1) Movable и Attackable переводятся как перемещаемые и атакуемые соотв. Пассивный залог, короче.
2) Правильный дизайн модели юнитов можно построить, только неплохо зная, какие операции с этой моделью нужно производить.
3) Абстрактно — идея менять у юнитов состояния не очень хороша, потому что потенциально порождает ошибки, связанные с нарушением инвариантов. Поэтому, ИМХО, стоит завести отдельную сущность UnitState, ссылающуюся на юнит.
4) Практически в любой современной игре набор юнитов расширяем. Так что, вполне возможно, никакой иерархии для юнитов и не нужно. Вместо этого юнит можно описывать специальными метаданными, его характеризующими, возможно дополненными какими то алгоритмами.
5) Стоит подумать в сторону декларативного, вместо императивного, описания юнитов. Например в виде набора правил, состоящих из предиката и тела, изменяющего состояние. Это, имхо, упростит создание юнитов и развяжет руки по реализации собственно движка.
... << RSDN@Home 1.2.0 alpha 4 rev. 1111 on Windows Vista 6.0.6001.65536>>
Здравствуйте, AndrewVK, Вы писали:
AVK>3) Абстрактно — идея менять у юнитов состояния не очень хороша, потому что потенциально порождает ошибки, связанные с нарушением инвариантов. Поэтому, ИМХО, стоит завести отдельную сущность UnitState, ссылающуюся на юнит.
А можно об этом поподробнее (или что можно почитать по этому поводу)?
И что подразумевается под инвариантом?