Domanda

ho implementato il codice dalla questione "Palla href="https://stackoverflow.com/questions/345838/ball-to-ball-collision-detection-and-handling"> " in Objective-C. Tuttavia, ogni volta che le sfere si scontrano con un angolo loro velocità aumenta drammaticamente. Tutta la matematica vettore è fatto utilizzando cocos2d-iphone , con l'intestazione CGPointExtension.h. Qual è la causa di questa accelerazione indesiderata?

Il seguente è un esempio di aumento della velocità:

ingresso:
== massa 12,56,637 mila
velocity.x == 1.73199439
velocity.y == -10,5695238

ball.mass == 12,56,637 mila
ball.velocity.x == 6.04341078
ball.velocity.y == 14.2686739

Output:
== massa 12,56,637 mila
velocity.x == 110.004326
velocity.y == -10,5695238

ball.mass == 12,56,637 mila
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));

}
È stato utile?

Soluzione

Sono io quello che ha scritto il codice di palla di rimbalzo originale si fa riferimento. Se scaricare e provare che il codice, si può vedere che funziona bene.

Il seguente codice è corretto (il modo in cui è stato originariamente aveva):

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

Questo è il codice di fisica molto comune e si può vedere quasi esattamente implementato come questo nei seguenti esempi:

Questo è corretto, e ~ ~ non è la creazione di un Comitato delle regioni sopra 1,0, come altri hanno suggerito. Questo è il calcolo del vettore relativo impulso riferiscono off massa e coefficiente di restituzione.

Ignorando attrito, un semplice esempio 1d è la seguente:

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

dove E è l'CdR, Vr è la vostra velocità normalizzata e J è un valore scalare della velocità d'impulso.

Se hai intenzione di fare qualcosa di più avanzato di questo vi consiglio di utilizzare una delle tante librerie di fisica già là fuori. Quando ho usato il codice precedente che andava bene per un paio di palle, ma quando ho dilagato fino a diverse centinaia cominciò a soffocare. Ho usato il motore fisico Box2D e il suo risolutore potuto gestire più palle ed è molto più accurata.

In ogni caso, ho guardato oltre il codice e, a prima vista tutto sembra a posto (si tratta di una bella traduzione fedele). Probabilmente è un piccolo e sottile errore di un valore errato essere passato in, o un problema di matematica vettoriale.

Non so tutto ciò che riguarda lo sviluppo iPhone, ma vorrei suggerire l'impostazione di un punto di interruzione nella parte superiore di tale metodo e monitoraggio di ogni passi con conseguente valore e trovare dove il blow-up è. Assicurarsi che il MTD è calcolato in modo corretto, le velocità di impatto, ecc, ecc fino a vedere dove il forte aumento è sempre introdotto.

Cronaca indietro con i valori di ogni passo di quel metodo e vedremo quello che abbiamo.

Altri suggerimenti

Dopo aver esaminato il codice originale e le osservazioni da parte del manifesto originale, il codice sembra lo stesso, quindi se l'originale è un corretta attuazione, ho il sospetto di una libreria vettore cattivo o un qualche tipo di variabile non inizializzata.

Perché si sta aggiungendo 1,0 al coefficiente di restituzione?

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

Il Comitato è in genere un numero compreso nell'intervallo [0,1]. Qualitativamente, 1 rappresenta una collisione perfettamente elastica, mentre 0 rappresenta una collisione anelastica perfettamente. Un COR maggiore di uno è teoricamente possibile, che rappresenta una collisione che genera energia cinetica, come ad esempio le mine gettati insieme e che esplodono.

Un altro problema è questo:

/ (im1 + im2)

Si sta dividendo dalla somma dei reciproci delle masse per ottenere l'impulso lungo il vettore di contatto - che probabilmente dovrebbe essere dividendo per il somma delle masse stesse. Questo è ingrandendo il vostro impulso ( "questo è quello che ha detto").

In questa riga:

CGPoint impulse = ccpMult(mtd, i);

MTD deve essere stato normalizzato. L'errore è accaduto perché nel MTD codice originale è stata normalizzata in una riga precedente, ma non nel codice. È possibile risolvere il problema facendo qualcosa di simile a questo:

CGPoint impulse = ccpMult(ccpNormalize(mtd), i);
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top