Компонентная игровая архитектура Obj-C и пересылка сообщений - PullRequest
3 голосов
/ 15 апреля 2010

Я пытался реализовать простую компонентную архитектуру игровых объектов, используя Objective-C, во многом по аналогии со статьей 'Evolve Your Hierarchy' Мика Уэста. С этой целью я успешно использовал некоторые идеи, изложенные в статье Майка Эша 'Пересылка сообщений Objective-C' , то есть используя метод -(id)forwardingTargetForSelector:.

Базовая настройка: у меня есть контейнерный класс GameObject, который содержит три экземпляра классов компонентов в качестве переменных экземпляра: GCPosition, GCRigidBody и GCRendering. Метод -(id)forwardingTargetForSelector: возвращает тот компонент, который ответит на соответствующий селектор, определенный с помощью метода -(BOOL)respondsToSelector:.

Все это, в некотором смысле, работает как чудо: я могу вызвать метод в экземпляре GameObject, реализация которого находится в одном из компонентов, и он работает. Конечно, проблема в том, что компилятор выдает предупреждения «возможно, не отвечает ...» для каждого вызова. Теперь мой вопрос: как мне избежать этого? И особенно в том, что дело в том, что каждый экземпляр GameObject будет иметь свой набор компонентов? Может быть, способ регистрации методов с объектами-контейнерами для каждого объекта в отдельности? Например, могу ли я создать какой-нибудь метод -(void)registerMethodWithGameObject:, и как бы я это сделал?

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

Очень ценится, -Bastiaan

Ответы [ 5 ]

2 голосов
/ 15 апреля 2010

Я не думаю, что отправка объекта-контейнера всех сообщений его компонентов - это то, что предлагал Мик Уэст, - это не помогает избавиться от идеи "объекта монолитной игровой сущности".

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

То есть вам вообще не нужно использовать пересылку сообщений в конечном продукте, поэтому игнорирование предупреждений или объявление переменных как id на данный момент не так уж и уродливо. (План, изложенный в статье, состоит в том, чтобы в конечном итоге удалить тот самый код, который вызывает ваши предупреждения!)

0 голосов
/ 15 апреля 2010

Другой вариант, если я правильно понимаю проблему, это реализовать протокол. Это ссылка на интерфейс в Java, и переменные могут быть объявлены следующим образом:

id anObjectRef

Таким образом, компилятор понимает, что объект, на который ссылается anObjectRef, соответствует протоколу.

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

0 голосов
/ 15 апреля 2010

Переопределите метод GameObject -respondsToSelector:. Ваша реализация должна, в свою очередь, отправить respondsToSelector: сообщение каждому из его экземпляров и вернуть YES, если любой из них вернет YES.

0 голосов
/ 15 апреля 2010

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

0 голосов
/ 15 апреля 2010

Простой способ удалить эти предупреждения - объявить переменные экземпляра типа id

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

...