السلام عليكم ..
هذا مثال فيزيائي من اعداد F1 magazine .. المتميزة .
http://www.f1-mag.com/
المثال تقريبا من الاعداد الاولى من المجلة .
المثال على الفيجوال بيسك .
الشرح وهو كله من اعداد المجلة .. :
تصميم الألعاب و مراعاة الفيزياء
في تصميم الألعاب تعتبر مراعاة القوانين الفيزيائية حجر الأساس للحكم على مصداقية اللعبة ومطابقتها للواقع .
لاشك أن ألعاباً ضخمة كـ Splinter Cell أو Half Life 2 قد طورت بشكل كبير لجعلها تحاكي الواقع (الفيزياء) بشكل كبير لتؤثر في نفوس اللاعبين إلى درجة يقول فيها أحدهم "عندما أطلقت النار على الأعداء كان سقوطهم على الأرض حقيقاً جداً "، أما الآخر فيقول "أنا أيضاً عندما أطلقت النار على المصباح انطفئ الضوء وتغير ضوء الغرفة بشكل كلي .... رائع !!!" بالطبع يتطلب هذا طاقماً من المبرمجين المتمرسين ، ومشورة عدد من دارسي الفيزياء لكي ينجحوا هكذا عمل.
ما الذي سنقوم به الآن ؟
حسناً .. المثال الذي سنشرحه هو برنامج يبين لنا تأثير الفيزياء على ألعاب ككرة القدم أو المغامرات ، حيث يتأثر عناصر اللعبة ببعضها البعض عبر الاصطدام أو تغير سرعة الرياح.
ستقوم أنت بركل الكرة عن طريق تحريك زر الفأرة الأيسر ، في المنطقة المخصصة ، ثم
ستلاحظ أثناء حركة الكرة حوادث فيزيائية كثيرة و بحركة واقعيّة (صدم – جاذبية – ارتداد .... الخ) .
شرح الكود البرمجي الخاص بلعبتنا الفيزيائيّة :
في قسم التصريحات العام 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 حسب التغيير الذي تم على طول المستقيم .
الآن سنقوم بإنشاء أداتي مؤقت (تايمر) لهما وظيفتين منفصلتين و متكاملتين في آن واحد
كيف ذلك ؟
احد المؤقتين يقوم بمهمة تدوير الكرة حول نفسها، حيث يقوم بإظهار أربع صور مختلفة و متناظرة للكرة في تتابع زمني منتظم لتبدو الكرة و كأنها تدور حول نفسها (على طريقة الرسوم المتحركة تقريباً).
لاحظ الشكل التالي :
تتم العمليّة هذه عن طريق الكود البرمجي التالي :
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
الآن فهمنا أن الأكواد السابقة تقوم بمقارنة وضع كل من محتويات النموذج مع المحتويات الأخرى و في حال حصول أي تماس أو تصادم بين عنصرين متحركين يتم الارتداد في جهة معاكسة لجهة الحركة الأصلية و بما أن الأكواد موضوعة ضمن مؤقت (المقارنة مستمرة طول فترة عمل البرنامج) فهذا يعني أننا سوف نحصل على نتيجة واقعيّة بشكل مستمر .
واصل ؟؟؟؟؟؟؟؟؟؟ موفق .؟
ملف مرفق(ملفات)
PHYSICS.zip (4.32كيلو )