السلام عليكم ..
هذا مثال فيزيائي من اعداد F1 magazine .. المتميزة .
المثال تقريبا من الاعداد الاولى من المجلة .
المثال على الفيجوال بيسك .
الشرح وهو كله من اعداد المجلة .. :
تصميم الألعاب و مراعاة الفيزياء
في تصميم الألعاب تعتبر مراعاة القوانين الفيزيائية حجر الأساس للحكم على مصداقية اللعبة ومطابقتها للواقع .
لاشك أن ألعاباً ضخمة كـ Splinter Cell أو Half Life 2 قد طورت بشكل كبير لجعلها تحاكي الواقع (الفيزياء) بشكل كبير لتؤثر في نفوس اللاعبين إلى درجة يقول فيها أحدهم "عندما أطلقت النار على الأعداء كان سقوطهم على الأرض حقيقاً جداً "، أما الآخر فيقول "أنا أيضاً عندما أطلقت النار على المصباح انطفئ الضوء وتغير ضوء الغرفة بشكل كلي .... رائع !!!" بالطبع يتطلب هذا طاقماً من المبرمجين المتمرسين ، ومشورة عدد من دارسي الفيزياء لكي ينجحوا هكذا عمل.
ما الذي سنقوم به الآن ؟
حسناً .. المثال الذي سنشرحه هو برنامج يبين لنا تأثير الفيزياء على ألعاب ككرة القدم أو المغامرات ، حيث يتأثر عناصر اللعبة ببعضها البعض عبر الاصطدام أو تغير سرعة الرياح.
ستقوم أنت بركل الكرة عن طريق تحريك زر الفأرة الأيسر ، في المنطقة المخصصة ، ثم
ستلاحظ أثناء حركة الكرة حوادث فيزيائية كثيرة و بحركة واقعيّة (صدم – جاذبية – ارتداد .... الخ) .
.jpg)
شرح الكود البرمجي الخاص بلعبتنا الفيزيائيّة :
في قسم التصريحات العام General نقوم بتعريف بعض المتغيّرات التي سوف نتعامل معها .
Dim Force As Integer Dim Wind As Integer Dim Bounc As Integer Dim Bounce As String Dim PiC As Integer Dim bForce As Integer Dim bWind As Integer
في حدث التحميل للنموذج Form Load نضع الأسطر التالية
MsgBox "لتحريك الكرة قم بالنقر باستمرار ضمن المربّع جانباً", 64, "F1 Magazine" lnWind.X1 = Picture5.Width / 2 lnWind.Y1 = Picture5.Height / 2 lnWind.X2 = lnWind.X1 + 1000 lnWind.Y2 = lnWind.Y1 Bounce = 0.3 Wind = (lnWind.X1 - lnWind.X2) / 15 Force = (lnWind.Y1 - lnWind.Y2) / 15
يقوم السطر الأول من الأسطر السابقة بإظهار مربّع رسالة (مسج بوكس) يحتوي على تعليمات لكيفية اللعب كما هو واضح .
أما الأسطر الأربعة التي تلي هذا السطر تقوم برسم المستقيم الذي سوف تركل عن طريقه الكرة و هذا المستقيم يمر بالنقطتين التاليتين :
النقطة الأولى ذات الإحداثيات
X1 , Y1
تقع في منتصف الأداة
Picture5
و النقطة الثانية ذات الإحداثيات المعلومة ...
X2 =X1+100
Y2=Y1
كما تلاحظ النقطتان تقعان على خط أفقي واحد لأن إحداثياتهما الشاقوليّة متساوية (العينات متساوية) .
توضيح :
كما نعلم يتم رسم المستقيم بتحديد نقطتين منه (في جملة ديكارتيّة نظاميّة) عموماً
نتابع الآن شرح الكود
بعد أن قمنا برسم المستقيم أسندنا قيماً مناسبةً للمتغيرات التي قمنا بتعريفها سابقاً .
الآن في أحداث ضغط زر الفأرة نضع الأسطر التالية التي تقوم بتغيير موضع نقطة النهاية
للمستقيم السابق إلى مكان النقر (عبر تمرير إحداثيات النقطة التي تم النقر عليها)
Private Sub Picture5_MouseDown(Button As Integer, Shift As Integer, X As Single, Y As Single) lnWind.X2 = X lnWind.Y2 = Y End Sub Private Sub Picture5_MouseMove(Button As Integer, Shift As Integer, X As Single, Y As Single) If Button <> 0 Then lnWind.X2 = X lnWind.Y2 = Y End If End Sub
حتّى نجعل قيمة قوّة ركل الكرة تتناسب مع مقدار التغيير في طول المستقيم (الذي يعبّر أصلاً عن قوّة الركل) نكتب الأسطر البرمجية التالية
Private Sub Picture5_MouseUp(Button As Integer, Shift As Integer, X As Single, Y As Single) lnWind.X2 = X lnWind.Y2 = Y Wind = (lnWind.X1 - lnWind.X2) / 15 Force = (lnWind.Y2 - lnWind.Y1) / 15 End Sub
لاحظ أننا قمنا في الأسطر الأخيرة بإسناد قيم جديدة للمتغيرات Wind و Force حسب التغيير الذي تم على طول المستقيم .
الآن سنقوم بإنشاء أداتي مؤقت (تايمر) لهما وظيفتين منفصلتين و متكاملتين في آن واحد
كيف ذلك ؟
احد المؤقتين يقوم بمهمة تدوير الكرة حول نفسها، حيث يقوم بإظهار أربع صور مختلفة و متناظرة للكرة في تتابع زمني منتظم لتبدو الكرة و كأنها تدور حول نفسها (على طريقة الرسوم المتحركة تقريباً).
لاحظ الشكل التالي :
.jpg)
تتم العمليّة هذه عن طريق الكود البرمجي التالي :
Private Sub Timer2_Timer() If PiC = 1 Then PiC = 2 Ball.Picture = Picture3.Picture Exit Sub End If If PiC = 2 Then PiC = 3 Ball.Picture = Picture4.Picture Exit Sub End If If PiC = 3 Then PiC = 0 Ball.Picture = Picture1.Picture Exit Sub End If If PiC = 0 Then PiC = 1 Ball.Picture = Picture2.Picture End If End Sub
المؤقت الآخر يحتوي على مجموعة من التعليمات الخاصة بالأمور الفيزيائيّة
لنقرئ معاً
Timer2.Interval = Abs(Wind) * 5
في البداية جعلنا المؤقت يكرر الأكواد الموجودة فيه كل مدّة معينة
حيث Abs دالة مبيتة في فيجوال بيسك تعيد القيمة المطلقة (الموجبة) للرقم بعدها .
لاحظ أن حادثة الصدم والارتداد سوف تتم على عدّة احتمالات :
- بين الصندوق و حواف النافذة .
- بين الصندوق و الكرة .
- بين الكرة و حواف النافذة .
- بين كلٍّ من الكرة و الصندوق و الأرض .
فمثلاً في الأسطر التالية سوف نناقش حالة الصندوق و حواف النافذة
If Box.Left + Box.Width > Me.Width Then bWind = -(bWind * Bounce) Box.Left = Me.Width - Box.Width End If If Box.Left < 0 Then bWind = -(bWind * Bounce) Box.Left = 0 End If
نلاحظ أن الأسطر السابقة تقوم بالتحقق من موضع الصندوق (صورة الصندوق في المثال)
فعندما يلامس حواف النافذة فإنّه سوف يقوم بالارتداد إلى الجهة المعاكسة (يتابع الحركة بجهة عكسيّة) و هذا ما تعبّر عنه الإشارة السالبة.
الآن عندما يحصل الصدم بين الكرة و الصندوق يتم الارتداد بنفس الآلية و هذا ما تقوم به الأسطر التالية حيث تقوم بالتحقق بنفس الآلية السابقة التي تم شرحها في الأعلى
If Ball.Left + Ball.Width > Box.Left And Ball.Left < Box.Left + Box.Width And Ball.Top + Ball.Height > Box.Top And Ball.Top < Box.Top + Box.Height Then If Box.Top + Box.Height < Ball.Top + Box.Height / 8 Then bForce = -(bForce * Bounce) Box.Top = Ball.Top - Box.Height - 1 Exit Sub End If If Ball.Top + Ball.Height < Box.Top + Box.Height / 3 Then Force = -(Force * Bounce) If Wind > 0 Then Wind = Wind - 1 End If If Wind < 0 Then Wind = Wind + 1 End If Ball.Top = Box.Top - Ball.Height - 1 Exit Sub End If
قد يبدو الكود السابق معقّد بالنسبة للبعض لكنه سيغدو في منتهى البساطة إذا قمتم بقراءة نبذة قصيرة عن جملة IF في الفيجوال بيسك .
جملة IF كما هو واضح جملة شرطيّة أي يتم تنفيذ عدد من الأسطر البرمجية في حال حصول شرط معيّن و مهما تشعّبت فالأساس واحد....و هي تكتب على الشكل
IF شرط Then
أوامر
End if
ملحوظة 2 :
تستطيع تضمين أكثر من شرط عن طريق استخدام المعاملين AND و OR
If شرط1 AND شرط2OR شرط3 then
أوامر
End if
بقي أمر واحد و هو عملية الارتداد نتيجة التصادم بين الكرة و حواف النافذة و بين كل من الكرة و الصندوق و الأرض..... و هذا ما تقوم به بضع أسطر أخرى
'للطرف الأيسر If Abs(Ball.Left + Ball.Width - Box.Left) < Abs(Ball.Left - Box.Left - Box.Width) Then Ball.Left = Box.Left - Ball.Width - 2 Wind = -(Wind * Bounce) / 2 bWind = bWind + Wind * 3 If Force > 0 Then bForce = (bForce + Force) * 2 Else bForce = (bForce - Force) / 2 End If Exit Sub End If 'للطرف الأيمن If Ball.Left < Box.Left + Box.Width Then Ball.Left = Box.Left + Box.Width + 2 Wind = -(Wind * Bounce) bWind = bWind + Wind * 3 bForce = -((bForce + Force) * 0.2) If Force > 0 Then bForce = (bForce + Force) * 2 Else bForce = (bForce - Force) / 2 End If Exit Sub End If End If If Box.Top + Box.Height >= Line1.Y1 Then bForce = -(bForce * Bounce) Box.Top = Line1.Y1 - Box.Height Else bForce = bForce + 1 End If Box.Top = Box.Top + bForce Box.Left = Box.Left + bWind If bWind > 0 Then bWind = bWind - 1 End If If bWind < 0 Then bWind = bWind + 1 End If If Slider1.Value = 10 Then Slider1.Value = 9 If Slider1.Value < 10 Then Bounce = "0." & Slider1.Value Else Bounce = Slider1.Value Bounce = Right(Bounce, Len(Bounce) - 1) End If If Ball.Left + Ball.Width > Me.Width Then Ball.Left = Me.Width - Ball.Width Wind = -(Wind * Bounce) End If If Ball.Left < 0 Then Ball.Left = 0 Wind = -(Wind * Bounce) End If Force = Force + 1 Ball.Left = Ball.Left - Wind Ball.Top = Ball.Top + Force If Ball.Top + Ball.Height >= Line1.Y1 Then If Force <= 1 Then Force = 0 If Wind > 0 Then Wind = Wind - 1 End If If Wind < 0 Then Wind = Wind + 1 End If Ball.Top = Line1.Y1 - Ball.Height Exit Sub End If Ball.Top = Line1.Y1 - Ball.Height Force = -(Force * Bounce) End If
الآن فهمنا أن الأكواد السابقة تقوم بمقارنة وضع كل من محتويات النموذج مع المحتويات الأخرى و في حال حصول أي تماس أو تصادم بين عنصرين متحركين يتم الارتداد في جهة معاكسة لجهة الحركة الأصلية و بما أن الأكواد موضوعة ضمن مؤقت (المقارنة مستمرة طول فترة عمل البرنامج) فهذا يعني أننا سوف نحصل على نتيجة واقعيّة بشكل مستمر .
واصل ؟؟؟؟؟؟؟؟؟؟ موفق .؟
