2017-06-14 2 views
3

Je tente de tirer parti de la fonction init? (Codeur aDecoder: NSCoder) pour pouvoir sous-classer les sprites dans mon fichier sks.Configuration du corps physique à partir du code lors de l'utilisation de init (nscoder) requis

Je peux définir le corps de la physique dans le fichier sks, mais cela ne fonctionne pas très bien avec mes sprites rectangulaires que j'utilise qui ont également des coins arrondis. En raison des coins arrondis, avant d'utiliser la fonction init, je mettais en place le corps physique dans le code, et en définissant la largeur légèrement plus petite que la largeur des carrés (de cette façon, quand mon héros glisse du carré, le coin arrondi est ..

Je sais que je peux utiliser le corps de la physique des masques alpha pour avoir le même effet, sauf qu'avec ceci, il semble y avoir un écart de 1 px quand mon héros est sur les blocs, et il ne semble pas bon.

Vous vous demandez la raison pour laquelle je ne peux pas mettre le corps physique cela, et aussi comment je peux le faire ou contourner?

Merci pour toute aide !!!

Mise à jour:

required init?(coder aDecoder: NSCoder) { 
    super.init(coder: aDecoder) 
    if let p = userData?.value(forKey: "col") as? String { 
     setup(p) 
     print("working") 
    } 
} 
func setup(_ col: String) { 
    setupPhysics() 
    //allSprites.append(self) 

Dans les setupPhysics je:

override func setupPhysics() { 
    physicsBody = SKPhysicsBody(rectangleOf: CGSize(width: frame.width - 4, height: frame.height - 1)) 
...more code... 
} 

Ceci est mon code pour l'image-objet, et je l'ai correctement configuré dans le fichier SKS ...

J'ai commenté l'ajout à allSprites, afin que je puisse démontrer que cela ne fonctionne pas. Avec l'append décommentée, les sprites sont ajoutés à allSprites, puis dans ma fonction didMove dans le fichier de la scène, il boucle à travers allSprites et exécute les setupPhysics():

func setup(_ col: String) { 
    //setupPhysics() 
    allSprites.append(self) 

// scene file 
    func setupAllSpritesPhysics() { 
    for sprite in allSprites { sprite.setupPhysics() } 
} 

@ Knight0fDragon:

Vous mentionnez que c'est une solution laide. Je ne suis pas d'accord étant donné que cela ne fonctionnera pas de la manière «correcte». Et actuellement, je n'ai pas assez de sprites pour causer du retard dans le chargement de la scène. Je peux examiner cela à l'avenir si c'est le cas. Je vais admettre que je n'ai pas essayé la méthode que vous avez mentionnée car je ne veux pas créer un nœud enfant pour chaque sprite que je crée afin de contourner cela même si cela fonctionne. J'apprécie le conseil jusqu'ici cependant.

+0

cela aiderait si vous montriez plus d'informations. si la physique du héros est configurée en code, montrez ce code ou montrez une image montrant ce qui se passe quand les sprites interagissent. Plus vous pouvez fournir d'informations, plus il est facile de comprendre vos problèmes. –

+0

Merci pour les commentaires, je n'ai pas mon ordinateur en face de moi pour le moment mais je mettrai à jour la question quand j'aurai une chance. Je peux dire, que la fonction init fonctionne correctement et fonctionne, j'ai seulement 1 fonction init. La fonction qui configure la physique est appelée après l'appel de super.init. Je l'ai fait travailler aussi en utilisant un skating d'attente avec une fermeture d'achèvement ... donc je suppose que le super.init a besoin de plus de temps pour finir, mais cela semble un peu hacky ... – Discoveringmypath

+0

avez-vous même vérifié pour voir si cette ligne d'impression se passe – Knight0fDragon

Répondre

4

Pour faire ce travail avec le fichier SKS, je voudrais ajouter un SKNode enfant avec les dimensions du corps que vous voulez, puis dans le code de classe personnalisée, faites

required init(coder aDecoder:NSCoder){ 
    super.init(coder:aDecoder) 
    if let child = childNode(withName:"child"), let physicsBody = child.physicsBody{ 
     self.physicsBody = physicsBody 
     child.removeFromParent() 
    } 
} 

Ce que nous faisons ici est transférer le corps physique de l'enfant au parent, puis tuer l'enfant. Cela permet à notre code d'être un peu plus dynamique et de garder la conception séparée de la fonctionnalité.

Eh bien, joli petit bug de pomme. Ce qui se passe, c'est que physicsWorld n'existe pas au moment où NSCoder arrive, et au lieu de placer le corps physique attaché au corps des sprites dans le monde quand il existe, il décide de mettre en cache celui qui se trouve dans le fichier SKS et c'est pourquoi ça ne marche pas.Un moyen très pratique de contourner ce problème consiste à implémenter un worldNode (il est de bonne pratique de le faire quand même, surtout si vous voulez créer un écran de pause) et de le supprimer puis de le rajouter sceneLoad:

class GameScene: SKScene,SKPhysicsContactDelegate { 
    lazy var worldNode : SKNode = { self.childNode(withName:"//worldNode")!}() 

    override func sceneDidLoad() { 
     worldNode.removeFromParent() 
     addChild(worldNode) 
    } 
} 
+0

Merci pour la réponse. Je vais devoir essayer ça ... J'avais l'impression que super.init avait besoin de plus de temps pour terminer avant de configurer le corps de la physique, si vous lisez mon commentaire ci-dessus ... donc je suis un peu sceptique que cela fonctionnera , mais qui sait ... J'ai fini par trouver une solution. Je stocke tous les sprites qui m'intéressent, dans un tableau ... alors j'ai ajouté une fonction à mon fichier de scène de jeu pour faire une boucle dans le tableau et lancer la physique d'installation. J'ai appelé la fonction à la fin de la fonction didmove et tout va bien ... que pensez-vous de cette solution? – Discoveringmypath

+0

Rien ne fonctionne sur un thread d'arrière-plan, après super.init est fait, votre sprite est prêt – Knight0fDragon

+0

qui est une solution laide, si vous avez beaucoup de sprites, vous finirez par faire geler votre jeu momentanément. – Knight0fDragon