Gestion des collisions de masse balle à balle (comme dans beaucoup de balles))

mise à jour: J'ai découvert que j'utilisais le rayon comme diamètre, ce qui explique pourquoi le mtd surcompensait.

une autre mise à jour: la raison pour laquelle mes balles se chevauchent semble être parce qu'il n'y a qu'un seul chèque pour chaque collision. Après quelques recherches, certains disent que l'un des moyens que vous pourriez éviter le chevauchement avec les objets empilant est d'effectuer récursivement la vérification de collision. Cela fonctionne dans une certaine mesure, et je soupçonne que cela fonctionnerait encore mieux si le la physique était beaucoup plus précise. Je vais mettre à jour à nouveau si je trouve plus de solutions. J'utilise aussi le code de correction de collision de Simucal .

Salut, StackOverflow. J'ai écrit un programme de traitement il y a quelques temps en simulant la physique des balles. Fondamentalement, j'ai un grand nombre de boules (1000), avec la gravité allumée. La détection fonctionne très bien, mais mon problème est qu'ils commencent à agir bizarrement quand ils rebondissent contre d'autres balles dans toutes les directions.

je suis assez sûr que cela implique la manipulation. Pour la plupart, J'utilise le code de Jay Conrod. Une partie qui est différente est

if (distance > 1.0)
        return;

que j'ai changé en

if (distance < 1.0)
        return;

parce que la collision n'a même pas été faite avec le premier morceau de code, je suppose que c'est une faute de frappe.

les balles se chevauchent quand j'utilise son code, ce qui n'est pas ce que je cherchais. J'ai essayé de le réparer en déplaçant les couilles vers le bord de l'autre:

float angle = atan2(y - collider.y, x - collider.x);
float distance = dist(x,y, balls[ID2].x,balls[ID2].y);    
x = collider.x + radius * cos(angle);
y = collider.y + radius * sin(angle);

ce n'est pas correct, j'en suis assez sûr.

j'ai essayé l'algorithme de correction dans le sujet boule-à-boule précédent:

// get the mtd
Vector2d delta = (position.subtract(ball.position));
float d = delta.getLength();
// minimum translation distance to push balls apart after intersecting
Vector2d mtd = delta.multiply(((getRadius() + ball.getRadius())-d)/d); 


// resolve intersection --
// inverse mass quantities
float im1 = 1 / getMass(); 
float im2 = 1 / ball.getMass();

// push-pull them apart based off their mass
position = position.add(mtd.multiply(im1 / (im1 + im2)));
ball.position = ball.position.subtract(mtd.multiply(im2 / (im1 + im2)));

sauf que ma version n'utilise pas de vecteurs, et le poids de chaque balle est de 1. Le code que j'obtiens est le suivant:

PVector delta = new PVector(collider.x - x, collider.y - y);
float d = delta.mag();
PVector mtd = new PVector(delta.x * ((radius + collider.radius - d) / d), delta.y * ((radius + collider.radius - d) / d));

// push-pull apart based on mass
x -= mtd.x * 0.5;
y -= mtd.y * 0.5;
collider.x += mtd.x * 0.5;
collider.y += mtd.y * 0.5;

ce code semble sur-Corriger les collisions. Qui n'a pas de sens pour moi parce que dans aucune autre manière je ne modifier les valeurs x et y de chaque boule, d'autres que cela.

une autre partie de mon code pourrait être erronée, mais je ne sais pas. Voici un extrait de l'ensemble de la gestion de collision balle-à-balle que j'utilise:

if (alreadyCollided.contains(new Integer(ID2))) // if the ball has already collided with this, then we don't need to reperform the collision algorithm
  return;
Ball collider = (Ball) objects.get(ID2);
PVector collision = new PVector(x - collider.x, y - collider.y);
float distance = collision.mag();
if (distance == 0) {
  collision = new PVector(1,0);
  distance = 1; 
}
if (distance < 1)
  return;

PVector velocity = new PVector(vx,vy);  
PVector velocity2 = new PVector(collider.vx, collider.vy);
collision.div(distance); // normalize the distance

float aci = velocity.dot(collision);
float bci = velocity2.dot(collision);

float acf = bci;
float bcf = aci;

vx += (acf - aci) * collision.x;
vy += (acf - aci) * collision.y;

collider.vx += (bcf - bci) * collision.x;
collider.vy += (bcf - bci) * collision.y;
alreadyCollided.add(new Integer(ID2));
collider.alreadyCollided.add(new Integer(ID));

PVector delta = new PVector(collider.x - x, collider.y - y);
float d = delta.mag();
PVector mtd = new PVector(delta.x * ((radius + collider.radius - d) / d), delta.y * ((radius + collider.radius - d) / d));

// push-pull apart based on mass
x -= mtd.x * 0.2;
y -= mtd.y * 0.2;
collider.x += mtd.x * 0.2;
collider.y += mtd.y * 0.2;
3
demandé sur Community 2010-12-19 04:37:04

1 réponses

votre "code résultant" semble correct. Avez-vous un simple cas de test qui montre l'une surcorrection (par exemple x 1 =0, x 1 =3, y 1 =y 2 =0, r 1 =r 2 =2)?

aussi, est-ce que vous obtenez de bons résultats si vous négligez le chevauchement et garder tout le reste, comme si les balles étaient en caoutchouc souple?

EDIT:

Cette partie est mauvais:

PVector velocity = new PVector(vx,vy);  
...
collider.vy += (bcf - bci) * collision.y;

quand deux balles se rapprochent elles amortissent la vitesse de l'autre jusqu'à ce qu'elles s'arrêtent toutes les deux. Mais le bon côté, c'est que vous avez inventé les solides (je plaisante). Éteignez les choses de chevauchement et ne vous inquiétez pas à ce sujet jusqu'à ce que vous avez cette partie de travail.

obtenir cette partie de travail sera à peu près impossible sans une compréhension de physique de base. Avez-vous besoin d'un coup de main?

2
répondu Beta 2010-12-20 13:37:19