Ok, depois de duas horas de conserto, consegui fazer isso, mas é preciso adicionar alguns corpos extras. Você provavelmente desejará extrair essas coisas em um método / classe, mas a idéia básica é a seguinte:
Crie o que chamo de corpos "detentores" para seus objetos. Esses corpos compartilham o tamanho e a posição dos seus "objetos", mas não participam de colisões. Essencialmente, eles são clones.
//Create "Main" (center) body
_bodyMain = BodyFactory.CreateRectangle(World, 5f, 5f, 1f);
_bodyMain.BodyType = BodyType.Dynamic;
_bodyMain.Position = new Vector2(2, 2);
//Create "MainHolder"
_bodyMainHolder = BodyFactory.CreateRectangle(World, 5f, 5f, 1f);
_bodyMainHolder.BodyType = BodyType.Dynamic;
_bodyMainHolder.CollisionCategories = Category.None; //Prevents collisions
_bodyMainHolder.Position = new Vector2(2, 2);
_bodyMainHolder.IsSensor = true;
//See http://farseerphysics.codeplex.com/discussions/222524 for why they're sensors
_bodyMainHolder.FixedRotation = true;
//Note: Only add FixedRotation for the main one, leave it off of the other
// holders. I'll explain later.
Anexe cada suporte ao "mainHolder" usando a WeldJoint
. Isso impedirá que eles se afastem um do outro. O FixedRotation
no suporte principal impede que eles girem. Não sei se há um bug no clarividente, mas se você adicionar um
WeldJoint
e os dois corpos tiverem FixedRotation == true
, a articulação não funcionará corretamente. É por isso que apenas o titular principal possui .FixedRotation = true
.
//Weld the holders together so they don't move. Assumes another holder is defined
// for the object on the right side (bodyRightHolder).
JointFactory.CreateWeldJoint(World, _bodyMainHolder, _bodyRightHolder,
_bodyRightHolder.Position - _bodyMainHolder.Position, Vector2.Zero);
Anexe seus corpos de "objetos" aos respectivos proprietários usando RevoluteJoint
s. Isso bloqueia seus objetos nos suportes, mas permite que eles girem livremente.
//Lock the actual bodies to the holders
JointFactory.CreateRevoluteJoint(World, _bodyMainHolder, _bodyMain, Vector2.Zero);
JointFactory.CreateRevoluteJoint(World, _bodyRightHolder, _bodyRight, Vector2.Zero);
Faça as rotações dos seus objetos reais se encaixarem, anexando uma junta angular. Nota: você não precisa anexar uma junta angular a cada par de objetos. Basta adicionar uma junta angular ao corpo principal e ao outro corpo e as rotações serão traduzidas em todos os objetos.
//Make them rotate the same as each other
JointFactory.CreateAngleJoint(World, _bodyMain, _bodyRight);
É isso aí! Basta adicionar o código extra para o outro objeto / suporte de objeto que você deseja e ele cuidará do resto. Aqui está uma imagem para ilustrar meu teste:
Aqui você verá que os corpos verdes são os detentores. Eles não giram ou colidem e são soldados juntos. Os corpos amarelo e vermelho são seus "objetos" (o amarelo é o principal). Você pode ver que eles são girados na mesma quantidade e estão girando em torno de seus respectivos suportes. Além disso, apenas os corpos vermelho e amarelo participam de colisões. Acredito que isso atenda às três condições acima.
Exemplo de trabalho
Se você carregar a solução Farseer "Samples XNA" e encontrar o SimpleDemo1.cs (projeto "Samples XNA"> pasta "Samples"), eu o reescrevi ( código aqui ) para testar.
Espero que isto ajude. Deixe-me saber se você tiver alguma dúvida.