سؤال

قمت بتنفيذ التعليمات البرمجية من السؤال "الكرة لتصادم الكرة - الكشف والمناولة"في الهدف - ج. ومع ذلك، كلما تصطدمت الكرات بزاوية، تزداد سرعتها بشكل كبير. تتم جميع الرياضيات المتجه باستخدام Cocos2D-iPhone., ، مع رأس cgpointextension.h. ما هو سبب هذا التسارع غير المرغوب فيه؟

فيما يلي مثال على الزيادة في السرعة:

إدخال:
كتلة == 12.56637.
Velocity.x == 1.73199439.
velocity.y == -10.5695238.

ball.mass == 12.56637.
ball.velocity.x == 6.04341078.
ball.velocity.y == 14.2686739.

انتاج:
كتلة == 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));

}
هل كانت مفيدة؟

المحلول

أنا الشخص الذي كتب رمز ترتد الكرة الأصلي الذي تمت الرجوع إليه. اذا أنت تحميل وجرب هذا الرمز، يمكنك أن ترى أنه يعمل بشكل جيد.

التعليمة البرمجية التالية صحيحة (الطريقة التي حصلت عليها في الأصل):

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

هذا رمز الفيزياء الشائع للغاية ويمكنك أن ترى أنه يتم تنفيذه تماما تماما مثل هذا في الأمثلة التالية:

هذا صحيح، وهذا ~ ليس ~ إنشاء كور أكثر من 1.0 كما اقترح الآخرون. هذا يحسب ناقلات الدافع النسبي يعتمد على الكتلة ومعامل الرد.

تجاهل الاحتكاك، مثال 1D بسيط هو كما يلي:

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

حيث e هو cor الخاص بك، VR هو السرعة الطبيعية و J هي قيمة عددية للسرعة الدافع.

إذا كنت تخطط للقيام بأي شيء أكثر تقدما من ذلك، أقترح عليك استخدام واحدة من العديد من مكتبات الفيزياء الموجودة بالفعل هناك. عندما استخدمت الكود أعلاه، كان على ما يرام لبضع كرات ولكن عندما صحبتها حتى عدة مئات، بدأت تخنقها. لقد استخدمت محرك الفيزياء Box2D وحلها يمكن أن يعالج المزيد من الكرات وهو أكثر دقة للغاية.

على أي حال، نظرت إلى التعليمات البرمجية الخاصة بك والوهلة الأولى تبدو جيدة (إنها ترجمة مخلصة جميلة). ربما يكون هناك خطأ صغير وخفيف من قيمة خاطئة يتم تمريرها، أو مشكلة في الرياضيات المتجهات.

لا أعرف أي شيء يتعلق بتطوير iPhone ولكني أقترح إعداد نقطة توقف في الجزء العلوي من تلك الطريقة ومراقبة كل خطوات مما يؤدي إلى قيمة وإيجاد حيث تفجير. تأكد من حساب MTD بشكل صحيح، وسرعات التأثير، إلخ، إلخ حتى ترى أين يتم تقديم الزيادة الكبيرة.

الإبلاغ عن قيم كل خطوة في هذه الطريقة وسنرى ما لدينا.

نصائح أخرى

بعد استعراض الكود الأصلي والتعليقات من الملصق الأصلي، يبدو الكود هو نفسه، لذلك إذا كان الأصل هو تطبيق صحيح، فسأظشى مكتبة ناقلات سيئة أو نوعا من المتغير غير المهيم.

لماذا تضيف 1.0 إلى معامل الرد؟

من: http://en.wikipedia.org/wiki/coeffiction_of_restitution.

COR هو عموما رقم في النطاق [0،1]. نوعيا، 1 يمثل تصادما مرن للغاية، بينما يمثل 0 تصادما غير مرن تماما. من الناحية النظرية من الناحية النظرية، تمثل الاصطدام الذي يولد طاقة حركية، مثل الألغام البرية التي يتم إلقاؤها معا وتنفجر.

مشكلة أخرى هي:

/ (im1 + im2)

أنت تقسم بمجموع المتبادلات في الجماهير للحصول على الدافع على طول متجه الاتصال - ربما يجب أن تكون تقسيم بمجموع الجماهير نفسها. هذا هو مكبرة دفعة الخاص بك ("هذا ما قالته").

في هذا الخط:

CGPoint impulse = ccpMult(mtd, i);

يجب أن تم تطبيع MTD. حدث الخطأ لأنه في الكود الأصلي MTD تم تطبيعه في السطر السابق ولكن ليس في التعليمات البرمجية الخاصة بك. يمكنك إصلاحه عن طريق القيام بشيء مثل هذا:

CGPoint impulse = ccpMult(ccpNormalize(mtd), i);
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top