سلام.
خوب حق با شماست باید از فرمول های اثبات شده استفاده کرد.
این که b رو سرعتش رو تغییر ندادم چون یه تصور غلطی از روند کار داشتم.
در حال حاظر تابع limit رو باز نویسی کردم به این شکل که در برخورد دو جسم با هم سرعت هریک از اجسام بعد از برخورد به درستی محسابه بشه.
فرمول رو میشه از لینک زیر مشاهده و بررسی کرد:
http://www.convertalot.com/elastic_collision_calculator.html
(البته لینک رو قرار دادم شاید یه روزی چنین کاری رو افراد دیگه هم خواستن انجام بدن)
چون حرکت راست به چپ و چپ به راست در فرمول با تفاوت داشته باشه واسه همین منم داخل تابع از شرط هایی برای این کار استفاده کردم.
من از 2 تا متغیر برای وزن و 2 متغیر برای سرعت استفاده کردم:
کد:
float VA = 1, VB = 1;
float WA = 2, WB = 1.5F;
private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
CheckLimit(_ballA, _ballB, VA * (_ballA.Direction == Ball.Directions.LeftToRight ? 1 : -1));
CheckLimit(_ballB, _ballA, VB* (_ballB.Direction == Ball.Directions.LeftToRight ? 1 : -1));
pictureBox1.Invalidate();
}
خوب حالا کافیه ما بیام بگیم که وقتی 2 گلوله بهم برخورد کردند مطابق با فرمول بالا سرعتشون چغدر میشه!
:
کد:
private void CheckLimit(Ball a, Ball b, float x)
{
float v1, v2;
float limit;
switch (a.Direction)
{
case Ball.Directions.LeftToRight:
if (b.Right >= a.Left)
{
limit = b.Left;
}
else
{
limit = pictureBox1.Width;
}
if (a.Right + x >= limit)
{
if(limit==b.Left)
{
v1 = VA;
v2 = VB;
if (a == _ballA && b.Direction==Ball.Directions.RightToLeft)
{
VA = (((WA - WB) * v1) + (-1 * 2 * WB * v2)) / (WA + WB);
VB = ((2 * WA * v1) - ((WA - WB) * v2 * -1)) / (WA + WB);
}
if (a == _ballA && b.Direction == Ball.Directions.LeftToRight)
{
VA = (((WA - WB) * v1) + (2 * WB * v2)) / (WA + WB);
VB = ((2 * WA * v1) - ((WA - WB) * v2)) / (WA + WB);
}
if (a == _ballB && b.Direction == Ball.Directions.RightToLeft)
{
VA = (((WA - WB) * v1 * -1) + (2 * WB * v2)) / (WA + WB);
VB = ((2 * WA * v1 * -1) - ((WA - WB) * v2)) / (WA + WB);
}
if (a == _ballB && b.Direction == Ball.Directions.LeftToRight)
{
VA = (((WA - WB) * v1 * +1) + (2 * WB * v2)) / (WA + WB);
VB = ((2 * WA * v1 * +1) - ((WA - WB) * v2)) / (WA + WB);
}
MessageBox.Show(VA+","+VB);
backgroundWorker1.CancelAsync();
}
a.Right = limit - 1;
a.Direction = Ball.Directions.RightToLeft;
}
else
{
a.Offset(x, 0);
}
break;
default:
if (b.Left <= a.Right)
{
limit = b.Right;
}
else
{
limit = 0;
}
if (a.Left + x <= limit)
{
if (limit == b.Right)
{
v1 = VA;
v2 = VB;
if (a == _ballA && b.Direction == Ball.Directions.RightToLeft)
{
VA = (((WA - WB) * v1 * -1) + (-1 * 2 * WB * v2)) / (WA + WB);
VB = ((2 * WA * v1 * -1) - ((WA - WB) * v2 * -1)) / (WA + WB);
}
if (a == _ballA && b.Direction == Ball.Directions.LeftToRight)
{
VA = (((WA - WB) * v1 * -1) + (2 * WB * v2)) / (WA + WB);
VB = ((2 * WA * v1 * -1) - ((WA - WB) * v2)) / (WA + WB);
}
if (a == _ballB && b.Direction == Ball.Directions.RightToLeft)
{
VA = (((WA - WB) * v1 * -1) + (2 * WB * v2 * -1)) / (WA + WB);
VB = ((2 * WA * v1 * -1) - ((WA - WB) * v2 * -1)) / (WA + WB);
}
if (a == _ballB && b.Direction == Ball.Directions.LeftToRight)
{
VA = (((WA - WB) * v1 * +1) + (2 * WB * v2 * -1)) / (WA + WB);
VB = ((2 * WA * v1 * +1) - ((WA - WB) * v2 * -1)) / (WA + WB);
}
MessageBox.Show(VA + "," + VB);
MessageBox.Show(a.Bounds.Location.ToString());
backgroundWorker1.CancelAsync();
}
a.Left = limit + 1;
a.Direction = Ball.Directions.LeftToRight;
}
else
{
a.Offset(x, 0);
}
break;
}
}
خوب حالا برنامه رو که اجرا می کنم بهش گفتم که موقعه برخورد از طریقmessagebox سرعت گلوله رو بعد از بخورد نمایش بده و بعدش backgroundworker غیر فعال بشه.
که اتفاقی که می افته این هست که هنگام برخورد اعداد نا درستی رو نمایش میده
ولی خوب چون ما از async استفاده کردیم یک بار دیگه پیغام نمایش داده میشه که میشه فهمید این پیغام از ترد قبلی بوده که جاری شده
و داخل پیغام دومیه دقیقا سرعت درست بعد از برخورد دو گلوله رو نمایش میده.
من میدونم async چطور کار می کنه روالش چطوره ولی سوالی که دارم این هستش که
چطور هنوز برخورد اول محاسبه نشده برخورد دوم محاسبه شده؟(برخورد دوم فکر کنم همون اعداد نادرستی ه که گفتم نمایش داد بار اول)
من برای این که بیشتر متوجه کار بشم به برنامه گفتم که محل برخورد رو هم نمایش بده
حالا برنامه رو که اجرا می کنید بار اول همون محاسبه برخورد دوم نمایش داده میشه + محلش برخورد دوم که در محلی خارج از فرم هستش
بعدش پیغام دیگه نمایش داده میشه که محاسبه برخورد اول رو نمایش میده که سرعت ها بعد از برخود به درتس نشون میده + محل برخورد که در محلی داخل فرم هستش.
مطمئن هستم که متوجه شدین چی گفتم
با تشکر فراوان.
پروژه رو هم ضمیمه کردم که دیگه تمام و کمال توضیح داده باشم.
یورول ما