2016-08-16 2 views
0

Je me bats ici avec les soi-disant collisions fantômes sur une simple carte à base de mosaïque avec un cercle comme personnage de joueur.Box2D: Comment utiliser b2ChainShape pour une carte en mosaïque avec des carrés

Lors de l'application d'une impulsion au cercle, il commence par rebondir correctement, puis tôt ou tard il rebondit mal (mauvais angle).

En regardant sur Internet, j'ai lu un problème dans Box2D (j'utilise iOS Swift avec le port Box2d pour Swift). L'utilisation de b2ChainShape n'aide pas, mais il semble que je l'ai mal compris. J'ai aussi besoin d'utiliser les propriétés "prevVertex" et "nextVertex" pour configurer les sommets fantômes.

Mais im confused. J'ai une carte simple composée de cases (carré simple), toutes placées l'une à côté de l'autre formant une pièce fermée. A l'intérieur de mon cercle j'applique une impulsion voyant le problème.

Maintenant O WH placer ces vertex fantômes pour chaque carré/boîte que j'ai placé sur la vue afin de résoudre ce problème? Ai-je besoin de placer n'importe quel sommet près du dernier et premier vertice de chainShape ou doit-il être l'un des sommets de la case suivante à l'actuel? Je ne comprends pas. Le manuel de Box2D n'explique pas d'où viennent ces coordonnées de sommets fantômes.

Ci-dessous vous pouvez voir une image décrivant le problème.

enter image description here

Une partie du code montrant les parties de physique pour les murs et le cercle:

D'abord la partie de mur:

let bodyDef = b2BodyDef() 
bodyDef.position = self.ptm_vec(node.position+self.offset) 
let w = self.ptm(Constants.Config.wallsize) 
let square = b2ChainShape() 
var chains = [b2Vec2]() 
chains.append(b2Vec2(-w/2,-w/2)) 
chains.append(b2Vec2(-w/2,w/2)) 
chains.append(b2Vec2(w/2,w/2)) 
chains.append(b2Vec2(w/2,-w/2)) 
square.createLoop(vertices: chains) 

let fixtureDef = b2FixtureDef() 
fixtureDef.shape = square 
fixtureDef.filter.categoryBits = Constants.Config.PhysicsCategory.Wall 
fixtureDef.filter.maskBits = Constants.Config.PhysicsCategory.Player 

let wallBody = self.world.createBody(bodyDef) 
wallBody.createFixture(fixtureDef) 

La partie du cercle:

let bodyDef = b2BodyDef() 
bodyDef.type = b2BodyType.dynamicBody 
bodyDef.position = self.ptm_vec(node.position+self.offset) 

let circle = b2CircleShape() 
circle.radius = self.ptm(Constants.Config.playersize) 
let fixtureDef = b2FixtureDef() 
fixtureDef.shape = circle 
fixtureDef.density = 0.3 
fixtureDef.friction = 0 
fixtureDef.restitution = 1.0 
fixtureDef.filter.categoryBits = Constants.Config.PhysicsCategory.Player 
fixtureDef.filter.maskBits = Constants.Config.PhysicsCategory.Wall 

let ballBody = self.world.createBody(bodyDef) 
ballBody.linearDamping = 0 
ballBody.angularDamping = 0 
ballBody.createFixture(fixtureDef) 
+0

Je suis un peu confus. Vous avez remplacé tous les bords de la boîte par un seul b2ChainShape, et vous rencontrez toujours ce problème de collision? – user2647513

+0

Si c'est le cas, avez-vous retiré les caisses ou les collisions désactivées? J'ai eu un problème similaire avec Farseer, qui est basé sur Box2d, et ma solution consistait simplement à écrire un algorithme pour construire manuellement chaque ligne de boîtes en un seul objet, car je n'avais que des murs verticaux et horizontaux dans mes cartes. – user2647513

+0

la physique devrait être bien, les collisions et le rebond fonctionnent, ayant seulement ce problème de fantôme vertice qui ne semble pas être résolu par EdgeShapes ou ChainShapes. Je suppose que c'est parce que ma boîte est une boucle de 4 sommets. Les sommets de coin se chevauchent avec les sommets des autres cases, alors comment résoudre ceci avec des sommets de fantômes? – NovumCoder

Répondre

0

Non sûr que je connais une solution simple dans le cas où chaque carreau c potentiellement avoir une physique différente. Si vos murs sont tous horizontaux et/ou verticaux, vous pouvez écrire une classe pour prendre une rangée de boîtes, créer un seul corps de bord ou de rectangle, et ensuite sur une collision, < x < b test) doit interagir avec l'objet en collision et appliquer la physique de manière appropriée, en appelant manuellement la méthode OnCollision que vous spécifieriez autrement comme rappel pour chaque boîte individuelle.

0

Alternativement, pour éviter le problème de tester manuellement l'intersection avec différentes boîtes, vous pouvez toujours fusionner toutes les boîtes droites courantes en un seul corps de bord pour des réflexions précises. Cependant, vous conserverez toujours les corps pour les boîtes individuelles. Étendez les boîtes de sorte qu'elles chevauchent le bord.

Maintenant, voici l'astuce: tous les gestionnaires de collision de boîte renvoient la valeur false, mais ils basculent les indicateurs sur l'objet en collision (en activant les indicateurs sur OnCollision et en désactivant OnSeparation). La méthode OnCollision pour le corps de bord traite ensuite la collision en fonction des indicateurs définis. Assurez-vous que le corps en collision traverse toujours une boîte avant de pouvoir toucher un bord. Cela devrait être simple.