2010-04-14 13 views
3

J'ai essayé de mettre en œuvre une architecture simple objet de jeu à base de composants en utilisant Objective-C, bien le long des lignes de l'article 'Evolve Your Hierarchy' par Mick Ouest. A cette fin, j'ai utilisé avec succès quelques idées comme décrit dans l'article 'Objective-C Message Forwarding' par Mike Ash, c'est-à-dire en utilisant la méthode -(id)forwardingTargetForSelector:.architecture jeu à base de composants C-OBJ et le transfert des messages

La configuration de base est J'ai une classe GameObject conteneur, qui contient trois instances de classes de composants comme variables d'instance: GCPositioning, GCRigidBody et GCRendering. La méthode -(id)forwardingTargetForSelector: renvoie le composant qui répondra au sélecteur concerné, déterminé à l'aide de la méthode -(BOOL)respondsToSelector:.

Tout cela, en quelque sorte, fonctionne comme un charme: Je peux appeler une méthode sur l'instance gameobject dont la mise en œuvre se trouve dans l'un des composants, et il fonctionne. Bien sûr, le problème est que le compilateur donne des avertissements "ne peut pas répondre à ..." pour chaque appel. Maintenant, ma question est, comment puis-je éviter cela? Et spécifiquement en ce qui concerne le fait que chaque instance de GameObject aura un ensemble de composants différent? Peut-être un moyen d'enregistrer des méthodes avec les objets conteneurs, sur un objet par objet? Tels que, puis-je créer une sorte de -(void)registerMethodWithGameObject: méthode, et comment ferais-je cela? Maintenant, il peut ou peut ne pas être évident que je suis assez nouveau à Cocoa et Objective-C, et juste à cheval, fondamentalement, et tout cela peut être très étranger ici. Bien sûr, bien que j'aimerais beaucoup connaître une solution à mon problème spécifique, toute personne qui voudrait expliquer une façon plus élégante de le faire serait également la bienvenue.

très apprécié, -Bastiaan

+1

Malheureusement je pense que les avertissements resteront, puisqu'ils sont techniquement corrects. Le compilateur ne peut pas déterminer si votre objet répondra réellement ou non, sauf si une méthode correspondante est déclarée dans l'interface. Cela dit, vous pourriez être en mesure de lancer votre GameObject à 'id' pour l'éviter (moche) ou désactiver l'avertissement comme une option de configuration (moche). :/ –

+0

Voir la réponse de bbum à cette question très similaire: http://stackoverflow.com/questions/2259012/avoiding-compiler-warnings-when-doing-message-forwarding. Fondamentalement: déclarez une catégorie sur votre classe et placez les méthodes transférées dans cette catégorie. – Felixyz

Répondre

2

Je ne pense pas que l'envoi de l'objet conteneur tous les messages de ses composants est ce que Mick Ouest a laissé entendre - qui ne permet pas d'éliminer l'idée d'un « objet entité de jeu monolithique ».

L'objectif final est que les composants communiquent directement entre eux, sans aucun objet conteneur. Jusque-là, l'objet conteneur agit comme un lien entre l'ancien code qui attend un seul objet pour chaque entité de jeu et le nouveau système de composant à composant. Autrement dit, vous ne devriez pas du tout utiliser le transfert de message dans le produit final, donc ignorer les avertissements, ou déclarer des variables comme id pour les calmer, n'est pas si moche. (Le plan tel que prévu par l'article est de supprimer éventuellement le code qui provoque vos avertissements!

0

Une façon simple d'avoir ces avertissements disparaissent serait de déclarer les variables d'instance de type id

Ce façon dont le compilateur suppose que vous savez ce que vous faites en ce qui concerne le type de l'objet et que l'objet répondra à tous les messages que vous lui envoyez, ou si cela ne vous dérange pas. Remplacez la méthode -respondsToSelector: de votre GameObject par la méthode

0

Votre implémentation doit à son tour envoyer un message respondsToSelector: à chacune de ses instances et renvoyer YES si l'une d'elles renvoie YES.

+0

... et bien sûr, utilisez 'id' comme type de données, comme d'autres l'ont suggéré. – jlehr

0

Vous pouvez utiliser le type de id - ou vous pourriez invoquer les méthodes utilisant des méthodes performSelector, ou créer un NSInvocation si les arguments sont complexes. Cependant, tout ceci est juste un moyen de contourner les avertissements du compilateur. Si vos objets répondent à plusieurs méthodes, il peut être utile de déclarer un protocole, bien que la même mise en garde s'applique.

0

Une autre option si je comprends correctement le problème est d'implémenter un protocole. Ce lien est une interface en Java et variables peuvent être déclarées comme ceci:

id anObjectRef

De cette façon, le compilateur comprend que l'objet désigné par anObjectRef est conforme au protocole.

Il existe également des méthodes qui peuvent vous indiquer si un objet particulier est conforme à un protocole spécifique avant de le lancer ou de l'assigner.