سؤال

أنا أعمل على لعبة 2D حيث أحاول الإسراع كائن إلى سرعة قصوى باستخدام بعض الفيزياء الأساسية رمز.

وهنا شبة الكود هو:


const float acceleration = 0.02f;
const float friction     = 0.8f;  // value is always 0.0..1.0
      float velocity     = 0;
      float position     = 0;

move()
{
   velocity += acceleration;
   velocity *= friction;
   position += velocity;
}

هذا هو مبسط جدا النهج التي لا تعتمد على كتلة أو الاحتكاك الفعلي (في رمز الاحتكاك هو مجرد العامة قوة تعمل ضد الحركة).أنه يعمل بشكل جيد مثل "السرعة *= الاحتكاك;" جزء تحافظ على سرعة من تجاوز نقطة معينة.ومع ذلك ، فمن هذه أعلى سرعة وعلاقته التسارع والاحتكاك أين أنا فقدت قليلا.

ما أود القيام به هو تحديد السرعة القصوى ، ومقدار الوقت الذي يستغرقه للوصول إلى ذلك ، ثم استخدامها لاستخلاص التسارع والاحتكاك القيم.

أي


const float max_velocity = 2.0; 
const int   ticks;       = 120; // If my game runs at 60 FPS, I'd like a 
                                // moving object to reach max_velocity in 
                                // exactly 2 seconds.
const float acceleration = ?
const float friction     = ?
هل كانت مفيدة؟

المحلول

لقد وجدت هذا السؤال مثيرة جدا للاهتمام حيث كنت مؤخرا قد فعلت بعض العمل على النمذجة قذيفة الحركة مع السحب.

النقطة 1: أنت أساسا تحديث الموقف وسرعة باستخدام صريح/إلى الأمام يولر التكرار حيث كل قيمة جديدة لهذه الدول أن تكون وظيفة من القيم القديمة.في مثل هذه الحالة ، يجب أن يكون تحديث الموقف أولا, ثم تحديث السرعة.

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


يذكي' drag:

المعادلة تحديث سرعة ليكون:

velocity += acceleration - friction*velocity

الذي يمثل المعادلة التفاضلية التالية:

dv/dt = a - f*v

باستخدام الإدخال الأول في هذا الجدول جزءا لا يتجزأ من, يمكن أن نجد الحل (على افتراض v = 0 t = 0):

v = (a/f) - (a/f)*exp(-f*t)

أقصى (أيمحطة) سرعة يحدث عندما t >> 0, حتى أن المصطلح الثاني في المعادلة هو قريب جدا من الصفر:

v_max = a/f

بخصوص الوقت اللازم للوصول إلى أقصى سرعة ، علما بأن المعادلة لا حقا تصل إلى ذلك, ولكن بدلا من ذلك المتقاربان نحو ذلك.ومع ذلك ، عندما حجة الهائل يساوي -5, سرعة حوالي 98% من السرعة القصوى ، ربما قريبة بما فيه الكفاية للنظر في ذلك على قدم المساواة.ثم يمكنك الوقت التقريبي إلى السرعة القصوى كما يلي:

t_max = 5/f

ثم يمكنك استخدام هذه المعادلات اثنين إلى حل f و a نظرا المطلوب vmax و tmax.


الدرجة الثانية drag:

المعادلة تحديث سرعة ليكون:

velocity += acceleration - friction*velocity*velocity

الذي يمثل المعادلة التفاضلية التالية:

dv/dt = a - f*v^2

باستخدام الإدخال الأول في هذا الجدول جزءا لا يتجزأ من, يمكن أن نجد الحل (على افتراض v = 0 t = 0):

v = sqrt(a/f)*(exp(2*sqrt(a*f)*t) - 1)/(exp(2*sqrt(a*f)*t) + 1)

أقصى (أيمحطة) سرعة يحدث عندما t >> 0, بحيث الهائل من حيث هي أكبر بكثير من 1 و المعادلة النهج:

v_max = sqrt(a/f)

بخصوص الوقت اللازم للوصول إلى أقصى سرعة ، علما بأن المعادلة لا حقا تصل إلى ذلك, ولكن بدلا من ذلك المتقاربان نحو ذلك.ومع ذلك ، عندما حجة الهائل يساوي 5, سرعة حوالي 99% من السرعة القصوى ، ربما قريبة بما فيه الكفاية للنظر في ذلك على قدم المساواة.ثم يمكنك الوقت التقريبي إلى السرعة القصوى كما يلي:

t_max = 2.5/sqrt(a*f)

وهو أيضا ما يعادل:

t_max = 2.5/(f*v_max)

المطلوب vmax و tmax, الثانية المعادلة tmax سوف اقول لكم ما f يجب أن تكون, ثم يمكنك توصيل هذا في المعادلة vmax للحصول على قيمة a.


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

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

position += velocity_function(timeSinceStart)

حيث "velocity_function" هو واحد من اثنين من الصيغ v(t) وأنت لم تعد بحاجة إلى سرعة متغيرة.في عام ، هناك مفاضلة هنا:حساب v(t) قد تكون أكثر مكلفة حسابيا من مجرد تحديث السرعة مع مخطط تكراري (بسبب الأسي) ، ولكن من يضمن أن تظل مستقرة و يحدها.في ظل ظروف معينة (مثل محاولة للحصول على قصيرة جدا tmax) ، التكرار يمكن أن تصبح غير مستقرة و تفجير, مشكلة شائعة إلى الأمام مع يولر الأسلوب.ولكن المحافظة على حدود المتغيرات (مثل 0 < f < 1) أن تمنع هذه عدم الاستقرار.

وبالإضافة إلى ذلك, إذا كنت تشعر إلى حد ما ماسوشي, كنت قد تكون قادرة على دمج صيغة v(t) للحصول على شكل مغلق الحل p(t), وبالتالي ما سبق ضرورة نيوتن التكرار تماما.سأترك هذا للآخرين محاولة.=)

نصائح أخرى

تحذير:حلا جزئيا

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

كبديل, النظر في اثنين من القوى المؤثرة على الكائن الخاص بك:

  • ثابت قوة خارجية ، F, هذا يميل إلى التعجيل به ،
  • قوة السحب ، d, الذي يتناسب مع سرعة يميل إلى إبطاء انتشاره.

وبالتالي فإن السرعة في التكرار n يصبح: vn = v0 + n F - dvn-1

كنت قد طلبت أن تختار السرعة القصوى ، vnmax, هذا يحدث في التكرار nmax.

علما أن المشكلة هي تحت المحدودة;وهذا هو ، F و d هي ذات الصلة ، بحيث يمكنك اختيار تعسفي قيمة واحد منهم ، ثم حساب الأخرى.

الآن الكرة المتداول هو أي شخص على استعداد لالتقاط الرياضيات ؟

تحذير: انها قبيحة و يتضمن سلسلة الطاقة!


تحرير:لماذا الفلاني تسلسل n**F** في المعادلة الأولى تظهر حرفيا ما لم يكن هناك مساحة بعد n?

velocity *= friction;

وهذا لا يمنع سرعة من الذهاب نحو نقطة معينة ...

وزيادة الاحتكاك أضعافا مضاعفة (لا اقتبس لي في ذلك) مع زيادة السرعة، وسوف يكون 0 في بقية. في نهاية المطاف، سوف تصل إلى نقطة حيث الاحتكاك = التسارع.

وهكذا كنت تريد شيئا من هذا القبيل:

velocity += (acceleration - friction);
position += velocity;
friction = a*exp(b*velocity);

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

وهذه ليست الإجابة على سؤالك، ولكن الشيء الوحيد الذي لا ينبغي القيام به في المحاكاة مثل هذا يتوقف على معدل الإطار ثابت. حساب الوقت منذ آخر تحديث، واستخدام دلتا-T في المعادلات الخاصة بك. شيء من هذا القبيل:

static double lastUpdate=0;
if (lastUpdate!=0) {
  deltaT = time() - lastUpdate;
  velocity += acceleration * deltaT;
  position += velocity * deltaT;
}
lastUpdate = time();

وكما انها جيدة للتحقق مما إذا كنت تفقد التركيز وإيقاف تحديث، وعند الحصول على تركيز مجموعة LASTUPDATE إلى 0. بهذه الطريقة لا تحصل على deltaT ضخمة لمعالجة عند العودة.

إذا كنت تريد أن ترى ما يمكن القيام به مع جدا نماذج الفيزياء بسيط باستخدام جدا الرياضيات البسيطة، نلقي نظرة على بعض المشاريع خدش على الموقع http://scratch.mit.edu/ - قد تحصل على بعض الأفكار المفيدة وسيكون لديك بالتأكيد متعة

وربما هذا هو ليس ما كنت تبحث عن ولكن اعتمادا على ما المحرك الذي تعمل عليه، فإنه قد يكون من الأفضل استخدام محرك بنيت من قبل بعض واحد آخر، مثل <وأ href = "HTTP: //www.codeplex. كوم / FarseerPhysics "يختلط =" نوفولو noreferrer "> farseer (ولC #). ملاحظة كود بلاكس باستمرار للصيانة.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top