Question

Je inséré le code de la question « à billes Collision boule - Détection et Manipulation » en Objective-C. Cependant, chaque fois que les billes entrent en collision à un angle leur vitesse augmente de façon spectaculaire. Tous les calculs de vecteur est fait en utilisant cocos2d-iphone , avec l'en-tête CGPointExtension.h. Quelle est la cause de cette accélération indésirable?

Ce qui suit est un exemple d'augmentation de la vitesse:

Entrée: masse == 12,56637
velocity.x == 1.73199439
velocity.y == -10,5695238

ball.mass == 12,56637
ball.velocity.x == 6.04341078
ball.velocity.y == 14.2686739

Sortie: masse == 12,56637
velocity.x == 110.004326
velocity.y == -10,5695238

ball.mass == 12,56637
ball.velocity.x == -102,22892
ball.velocity.y == -72,4030228

#import "CGPointExtension.h"
#define RESTITUTION_CONSTANT (0.75) //elasticity of the system

- (void) resolveCollision:(Ball*) ball
{
    // get the mtd (minimum translation distance)
    CGPoint delta = ccpSub(position, ball.position);
    float d = ccpLength(delta);
    // minimum translation distance to push balls apart after intersecting
    CGPoint mtd = ccpMult(delta, (((radius + ball.radius)-d)/d)); 


    // resolve intersection --
    // inverse mass quantities
    float im1 = 1 / [self mass]; 
    float im2 = 1 / [ball mass];

    // push-pull them apart based off their mass
    position = ccpAdd(position, ccpMult(mtd, (im1 / (im1 + im2))));
    ball.position = ccpSub(ball.position, ccpMult(mtd, (im2 / (im1 + im2))));

    // impact speed
    CGPoint v = ccpSub(velocity, ball.velocity);
    float vn = ccpDot(v,ccpNormalize(mtd));

    // sphere intersecting but moving away from each other already
    if (vn > 0.0f) return;

    // collision impulse
    float i = (-(1.0f + RESTITUTION_CONSTANT) * vn) / ([self mass] + [ball mass]);
    CGPoint impulse = ccpMult(mtd, i);


    // change in momentum
    velocity = ccpAdd(velocity, ccpMult(impulse, im1));
    ball.velocity = ccpSub(ball.velocity, ccpMult(impulse, im2));

}
Était-ce utile?

La solution

Je suis celui qui a écrit le code de rebond de la balle d'origine que vous avez mentionné. Si vous télécharger et essayer ce code, vous pouvez voir cela fonctionne très bien.

Le code suivant est correct (la façon dont vous avait à l'origine il):

// collision impulse
float i = (-(1.0f + RESTITUTION_CONSTANT) * vn) / (im1 + im2);
CGPoint impulse = ccpMult(mtd, i);

Ceci est du code de la physique très courante et vous pouvez le voir presque exactement mis en œuvre comme celui-ci dans les exemples suivants:

Ceci est correct, et il ~ ne ~ créer un Comité des régions sur 1.0 comme d'autres l'ont suggéré. Ce calcule le vecteur d'impulsion relative basée hors masse et coefficient de restitution.

Ignorer friction, un exemple simple 1d est la suivante:

J = -Vr(1+e) / {1/m1 + 1/m2}  

Où e est votre CdR, Vr est votre vitesse normalisée et J est une valeur scalaire de la vitesse d'impulsion.

Si vous projetez de faire quoi que ce soit plus avancé que cela, je vous suggère d'utiliser l'une des nombreuses bibliothèques de physique déjà là-bas. Quand je le code ci-dessus était bien pour quelques balles, mais quand je rampe vers le haut de plusieurs centaines il a commencé à étouffer. Je l'ai utilisé le moteur physique Box2D et son solveur pourrait gérer plus de balles et il est beaucoup plus précis.

Quoi qu'il en soit, je regardais votre code et à première vue il semble bien (il est une jolie traduction fidèle). Il est probablement une petite erreur et subtile d'une mauvaise valeur transmise, ou un problème de mathématiques de vecteur.

Je ne sais pas quoi que ce soit en ce qui concerne le développement de l'iPhone, mais je suggère la fixation d'un point d'arrêt au sommet de cette méthode et de suivi chaque étape valeur résultante et de trouver où le coup-up est. Assurez-vous que le MTD est calculé correctement, les vitesses d'impact, etc, etc jusqu'à ce que vous voyez où la forte augmentation est introduit se.

Rapport de retour avec les valeurs de chaque étape de cette méthode et nous allons voir ce que nous avons.

Autres conseils

Après avoir examiné le code original et les commentaires de l'affiche originale, le code semble être le même, donc si l'original est une mise en œuvre correcte, je soupçonne une bibliothèque mauvais vecteur ou une sorte de variable non initialisée.

Pourquoi vous ajoutez 1,0 au coefficient de restitution?

De: http://en.wikipedia.org/wiki/Coefficient_of_restitution

Le COR est généralement un nombre dans l'intervalle [0,1]. Qualitativement, la figure 1 représente une collision parfaitement élastique, tandis que 0 représente une collision parfaitement inélastique. Un COR supérieur à un est théoriquement possible, ce qui représente une collision qui génère de l'énergie cinétique, comme les mines terrestres jetés ensemble et exploser.

Un autre problème est le suivant:

/ (im1 + im2)

Vous divisant par la somme des masses inverses des impulsions pour obtenir le long du vecteur de contacts - vous devriez probablement en divisant par la somme des masses elles-mêmes. Ceci est votre ourlé d'impulsion ( «c'est ce qu'elle a dit »).

Dans cette ligne:

CGPoint impulse = ccpMult(mtd, i);

mtd doit avoir été normalisé. L'erreur est survenue parce que dans le mtd de code d'origine a été normalisée dans une ligne précédente, mais pas dans votre code. Vous pouvez le réparer en faisant quelque chose comme ceci:

CGPoint impulse = ccpMult(ccpNormalize(mtd), i);
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top