[Résolu] SpriteKit : Traiter le cas des collisions dans une sous-classe

berfisberfis Membre
juin 2014 modifié dans Objective-C, Swift, C, C++ #1

Bonjour,


 


Je m'amuse (des fois même je m'énerve) avec SpriteKit (en Objective-C pour ne pas courir deux lièvres à  la fois).


 


J'ai eu l'idée (vous me direz si elle est saugrenue) de traiter l'affaire des contacts/collisions à  l'intérieur de chaque classe, pour éviter une - (void)didBeginContact:(SKPhysicsContact *)contact à  rallonge. Le problème étant que les contacts A et B nous arrivent dans un ordre quelconque et parfois dupliqués.


 


Je crée donc une sous-classe abstraite de SKSpriteNode que j'appelle BFContactSpriteNode, et je la dote d'une méthode (vide) appelée didMakeContactWith :



@implementation BFContactSpriteNode

// - (void) didMakeContactWith: (SKPhysicsBody*) body
// {
// Abstract method does nothing and must be overridden.
NSLog(@Did make contact);
}

@end

Maintenant, toutes mes sprites ne dérivent pas de cette classe. Je souhaitais n'envoyer le message didMakeContactWith qu'à  des nodes qui dérivent de ma classe abstraite. J'essaie donc, pour la première fois, ce test:



if ([contact.bodyA.node respondsToSelector:@selector (didMakeContactWith:)]) [(BFContactSpriteNode*)contact.bodyA.node didMakeContactWith:contact.bodyB];

Comme mon programme part en confettis, j'essaie cela:



if ([contact.bodyA.node isKindOfClass:[BFContactSpriteNode class]]) [(BFContactSpriteNode*)contact.bodyA.node didMakeContactWith:contact.bodyB];

Ce qui m'amène au même résultat:



-[SKSpriteNode didMakeContactWith:]: unrecognized selector sent to instance 0x63800011a430
2014-06-22 18:50:20.454 Labyrinthe[10394:303] An uncaught exception was raised

Pourquoi mon code tente-t-il tout de même d'envoyer un message à  une classe dont, en principe, on sait qu'elle ne répondra pas?


 


Merci de m'éclairer sur ce point.


Mots clés:

Réponses

  • AliGatorAliGator Membre, Modérateur
    Etrange en effet.
    1) Tu es sûr que le code que tu mets là  est exactement celui que tu as dans ton projet ? Si tu l'as simplifié pour rédiger ce post dans le but de ne pas nous assommer avec du code, peut-être as-tu mal copié certains détails, comme par exemple tu as peut-être mis un ";" à  la fin de ton "if" avant le corps de ce if, ce qui fait qu'en vrai tu as un corps de "if" vide (";") et que le code après tout ça est exécuté sans aucune condition ?

    2) Peux-tu séparer ton code avec ton "if" en plusieurs lignes ? (je déteste au passage les "if" sans accolades, justement pour le risque de boulettes que cela peut engendrer ; même si le corps du "if" ne contient qu'une seule instruction, je mets toujours des accolades)
    En particulier cela te permettra aussi de mettre des NSLog pour afficher le résultat du if, pour afficher le contact.bodyA.node, sa class, etc.


    Sinon, pour le côté "Le problème étant que les contacts A et B nous arrivent dans un ordre quelconque et parfois dupliqués." tu as appliqué l'astuce classique qui consiste à  trier les nodes d'après leur catégorie, pour toujours les avoir dans le même ordre et éviter d'avoir à  tester à  la fois "A,B" et "B,A" ?

    Voir La vidéo des CocoaHeads Rennes de démo sur SpriteKit (en particulier à  T=20'40 pour les collisions, et à  T=24'25 pour l'astuce en question dans l'implémentation type de "didBeginContact:")
  • Merci Ali, c'était en effet dans la ligne qui suivait immédiatement celle que j'ai donnée, j'avais inversé bodyA et bodyB dans un paramètre. Le truc idiot.


     


    J'ai finalement fait dériver tous mes sprites de mon BFContactSpriteNode, ce qui fait que je pourrais me passer du test IF.


     


    P.S: La vidéo offre une bonne solution en effet. On ne manque pas d'imagination pour contourner la difficulté (d'ailleurs signalée dans la doc) de ces paramètres "en vrac" de didBeginContact...


Connectez-vous ou Inscrivez-vous pour répondre.