يتمحور المقال السادس من سلسلة (بناء لعبة من الصفر باستخدام بايثون) حول إضافة المنصات إلى عالم اللعبة لتتفاعل معها الشخصيات وتتنقل عبرها فهذه اللعبة أولًا وأخيرًا لعبة منصات، ولكن قبل أن نبدأ نذكرك بمقالات السلسلة.
- بناء لعبة نرد بسيطة بلغة بايثون.
- بناء لعبة رسومية باستخدام بايثون ووحدة الألعاب PyGame.
- إضافة لاعب إلى اللعبة المطورة باستخدام بايثون و Pygame.
- تحريك شخصية اللعبة باستخدام PyGame.
- إضافة شخصية العدو للعبة.
- إضافة المنصات إلى لعبة بايثون باستخدام الوحدة Pygame.
- محاكاة أثر الجاذبية في لعبة بايثون.
- إضافة خاصية القفز والركض إلى لعبة بايثون.
- إضافة الجوائز إلى اللعبة المطورة بلغة بايثون.
- تسجيل نتائج اللعبة المطورة بلغة بايثون وعرضها على الشاشة.
- إضافة آليات القذف إلى اللعبة المطورة بلغة بايثون.
المنصات في Pygame كائنات مثلها مثل الشخصيات، تُضاف إلى عالم اللعبة بالطريقة نفسها عبر برمجة كائن بايثون خاص بكل منصة وتحديد إحداثيات ظهورها على الشاشة، ويسهل هذا التشابه برمجة التفاعل بين الطرفين.
برمجة كائن المنصة
تمامًا مثل بناء كائن شخصية اللاعب فإن بناء كائن للمنصة يعني إنشاء صنف بلغة بايثون، سنسميه Platform
ويتطلب إنشائه عددًا من المعلومات عن المنصة مثل نوعها وصورتها وموقع ظهورها على الشاشة، قد لا تملك هذه المعلومات جميعها في لحظة بناء الصنف ولا بأس في ذلك فستُمررها له فيما بعد بالطريقة نفسها التي اتبعناها عند تحريك اللاعب فلم نحدد السرعة حتى نهاية المقال.
عرّف الصنف وفق الآتي:
# x الإحداثي, y الإحداثي, imgw عرض الصورة, imgh ارتفاع الصورة, img ملف الصورة class Platform(pygame.sprite.Sprite): def __init__(self, xloc, yloc, imgw, imgh, img): pygame.sprite.Sprite.__init__(self) self.image = pygame.image.load(os.path.join('images', img)).convert() self.image.convert_alpha() self.image.set_colorkey(ALPHA) self.rect = self.image.get_rect() self.rect.y = yloc self.rect.x = xloc
لابد أنك لاحظت تشابه التعليمات بين هذا الصنف وأصناف شخصيتي البطل والعدو، ومثلهما أيضًا سيؤدي استدعاؤه إلى إنشاء كائن المنصة وإظهار صورتها على الشاشة بالأبعاد المحددة ضمن الصنف وفي الموقع المحدد وفق الإحداثيات X و Y.
أنواع المنصات
هناك نوعان للمنصات وهي:
المنصات المبنية بطريقة قطع البلاط
تُذكرنا هذه المنصات بالألعاب الكلاسيكية الشهيرة مثل سوبر ماريو والقنفذ سونيك، ويعدّها البعض من أسهل طرق بناء المنصات من ناحية الصور المطلوبة -وإن لم تكن كذلك لجهة تعقيد الشيفرة والعمليات الحسابية- فكل ما تحتاجه هو مجموعة صور لقطع البلاط أو القرميد أو ما شابه، ومن ثم تبدأ بترتيبها بأشكالٍ مختلفة ضمن اللعبة، حوالي 8 أو 12 نمط تشكل بها الأرضية والمنصات العائمة وتكررها لتبني مستويات اللعبة.
المنصات المبنية بطريقة الرسم اليدوي
تعني هذه الطريقة رسم أو تصميم كل منصة بصورة منفصلة، وتتطلب منك بذل بعض الوقت والجهد في العمل على برامج التصميم الجرافيكي لإنشاء كل جزء من عالم اللعبة، إلاّ أنها بالمقابل تحتاج قدرًا أقل من العمليات الحسابية، إذ إن كافة الكائنات أو المنصات مجهزة وكاملة وكل ما عليك فعله هو إخبار بايثون بمكان إظهارها على الشاشة.
لكل طريقة مزايا وعيوب وأسلوب معين في كتابة التعليمات البرمجية، لذا سنشرح الطريقتين في الفقرات اللاحقة حتى تتمكن من استخدام الطريقة التي تناسبك أو تدمج الطريقتين معًا في مشروعك.
وضع مخطط المستوى
تعدّ هذه المرحلة جزءًا مهمًا من تصميم المستوى للعبة، يمكنك البدء باستخدام الورقة والقلم، ارسم مربعًا يمثل نافذة اللعبة وعليه المحورين الأفقي والعمودي، ومن ثم ابدأ برسم المنصات التي تريدها واحدةً تلو الأخرى وثبت على كل منها الإحداثيات X و Y وكذلك أبعاد الصورة عرض وارتفاع، لا داعِ لتكون المواقع على الورقة دقيقة جدًا لكن اجعلها منطقية، فمثلًا لا يمكنك وضع 8 قطع قياس كل منها 100 بكسل في شاشة واحدة حجمها 720 بكسل.
بعد إنجاز شاشتك الأولى، استمر بالرسم تجاه اليمين حتى تمثل الشاشات التالية التي سينتقل خلالها بطل اللعبة وهو يجتاز المستوى حتى يصل لنهايته.
ولو رغبت بتعزيز المخطط بمزيدٍ من الدقة استخدم أوراق الرسم البياني المقسمة إلى مربعات متساوية، فهي مفيدة خصيصًا في رسم منصات البلاط، إذ يمكنك تمثيل كل بلاطة بمربع.
الإحداثيات
كل ما تعلمته في المدرسة عن نظام الإحداثيات الديكارتي ينطبق هنا على إحداثيات Pygame باستثناء أن نقطة التقاء المحاور أو نقطة الصفر 0,0
تقع في الزاوية العلوية اليسرى للشاشة بدلًا من الوسط مثلما اعتدت سابقًا في دروس الهندسة.
يبدأ المحور X عند النقطة 0 في أقصى اليسار ويمتد لا نهائيًا نحو اليمين، كذلك يبدأ المحور Y عند النقطة 0 في أعلى الشاشة لكنه يمتد للأسفل.
أبعاد الصور
معرفة أبعاد الصور التي تمثل كلًا من الأبطال والأعداء والمنصات مهمة جدًا ليكتمل مخطط المستوى، فبدونها سيغدو مخططك دون فائدة تُذكر، فكيف تعرف هذه الأبعاد؟
لديك طريقتان، إما أن تفتح الصور باستخدام برنامج تصميم متخصص مثل كريتا وتستعلم عن خصائصها، أو تكتب برنامج بسيط بلغة بايثون يعطيك إياها وذلك بالاستفادة من الوحدة Pillow التي توفر مكتبة خاصة بالموضوع تسمى PIL، ولكن طبعًا بعد ذكر الوحدة ضمن ملف متطلبات المشروع requirements.txt وفق مايلي:
pygame~=1.9.6 Pillow
أنشئ ملفًا جديدًا ضمن Pycharm باسم identify
، واكتب فيه:
#!/usr/bin/env python3 # GNU All-Permissive License # Copying and distribution of this file, with or without modification, # are permitted in any medium without royalty provided the copyright # notice and this notice are preserved. This file is offered as-is, # without any warranty. from PIL import Image import os.path import sys if len(sys.argv) > 1: print(sys.argv[1]) else: sys.exit('Syntax: identify.py [filename]') pic = sys.argv[1] img = Image.open(pic) X = img.size[0] Y = img.size[1] print(X, Y)
والآن اضغط على تبويب الطرفية الموجود في أسفل شاشة Pycharm، الذي يفتح لك نافذة الطرفية في بيئتك الافتراضية واكتب فيها التالي حتى تثبت الوحدة Pillo.
(venv) pip install -r requirements.txt Requirement already satisfied: pygame~=1.9.6 [...] Installed Pillow [...]
وعند انتهاء التثبيت شغل البرنامج البسيط الذي كتبناه للحصول على الأبعاد، وشغله من مسار مجلد اللعبة.
(venv) python ./identify.py images/ground.png (1080, 97)
بذلك تكون قد حصلت على أبعاد صورة الأرضية، وهي في حالتنا 1080 عرض و97 ارتفاع.
كتل المنصة
إذا رغبت بتصميم صورة خاصة لكل مُكَوِّن من مكونات اللعبة مثل المنصات والأرضية وغيرها، فهذا يعني أنك ستخصص ملفُا منفصلًا لكل مُكَوِّن مثل الظاهر في الصورة:
ويمكنك إعادة استخدام كل منصة عدة مرات ضمن لعبتك، بشرط أن يتضمن كل الملف مُكَوِّن واحد فقط كما ذكرنا، فلا يجوز مثلًا أن تتواجد جميع المكونات المبينة أدناه في ملف واحد:
وعلى فرض أنك أنشأتها جميعًا في ملف واحد كبير يتضمن كل مكونات الصورة، فلن تملك عندها أي طريقة تجعلك تُمييز المنصة عن خلفية اللعبة، لذا إما أن ترسم المكونات التي تريدها كلٌ في ملفه الخاص أو أن تقصها من الملف الكبير الذي ترغب بالوصول إليه وتحفظها في ملفات منفصلة.
تنويه: يمكنك استخدام أحد برامج التصميم الجرافيكي جيمب أو كريتا أو إنكسكيب على سبيل المثال لا الحصر لتُصمم مكونات اللعبة.
تظهر المنصات في بداية كل مستوى لذا عليك إضافة دالة المنصة platform
إلى صنف المستوى Level
، أما المنصة التي تشكل الأرضية سنفرد لها دالة خاصة فهي تتمتع ببعض الخصوصية إذ إنها تبقى ثابتة في بعض الألعاب بينما تطفو فوقها المنصات الأخرى، أو تتحرك في بعضها الآخر أو تُمرر في أثناء سير اللعبة.
أضف إذًا الدوال التالية إلى صنف المستوى Level
:
def ground(lvl,x,y,w,h): ground_list = pygame.sprite.Group() if lvl == 1: ground = Platform(x,y,w,h,'block-ground.png') ground_list.add(ground) if lvl == 2: print("Level " + str(lvl) ) return ground_list def platform( lvl ): plat_list = pygame.sprite.Group() if lvl == 1: plat = Platform(200, worldy-97-128, 285,67,'block-big.png') plat_list.add(plat) plat = Platform(500, worldy-97-320, 197,54,'block-small.png') plat_list.add(plat) if lvl == 2: print("Level " + str(lvl) ) return plat_list
الدالة الأولى في التعليمات السابقة هي دالة الأرضية ground
، وتتطلب تحديد الإحداثيات X و Y لمعرفة موقع ظهور الأرضية على الشاشة وكذلك تحديد الأبعاد حتى يتبين للوحدة Pygame كيف ستمتد أرضيتك في كلا الاتجاهين، تستخدم هذه الدالة صنف المنصة Platform
لإنشاء كائن الأرضية على الشاشة وإضافته إلى مجموعة الأرضيات ground_list
.
أما الدالة الثانية دالة المنصة platform
فتماثل الأولى تمامًا باستثناء أنها تتضمن أكثر من عنصر في مجموعة المنصات، في حالتنا يوجد منصتين فقط لكن يمكنك إضافة القدر الذي تريده بشرط ضمها جميعًا لمجموعة المنصات plat_list
وإلاّ فإنها لن تظهر على الشاشة.
اقتباستلميح: إذا شعرت بالارتباك من كون الصفر في أعلى الشاشة والأرقام تزداد كلما هبطت للأسفل، فيمكنك استخدام الأرقام السالبة للتعبير عن الإحداثيات على المحور العمودي Y، وعندها ستقيس ارتفاع كل شيء بدءًا من الأرضية وليس من أعلى الشاشة.
نعطيك مثالًا للتوضيح: إذا علمت أن أخفض نقطة في لعبتك هي القيمة
worldy
وأن ارتفاع أرضية اللعبة هو 97 فإن نقطة سطح الأرضية التي سيقف عليها اللاعب ستكونworldy
مطروحًا منها 97، فلو كان طول اللاعب مثلًا هو 64 بكسل فإن سطح الأرضية مطروحًا منها 128 يعادل ضعفي طول اللاعب، ما يعني أن أي منصة تضعها عند هذه النقطة ستكون على ارتفاع يعلو طول اللاعب بمرتين، وأي منصة عند 320- ستعلو ذلك بثلاث مرات إضافية.
تعلمنا على طول مقالات السلسلة أن الدوال والأصناف لا تعمل ما لم تستدعيها في البرنامج وهذا ما ستفعله بكتابة هذه التعليمات ضمن مقطع الإعدادات في شيفرة لعبتك:
ground_list = Level.ground(1, 0, worldy-97, 1080, 97) plat_list = Level.platform(1)
واكتب أيضًا الأسطر التالية في الحلقة الرئيسية، مع العلم أن السطر الأول لمعرفة السياق فقط وهو موجود لديك مسبقًا:
enemy_list.draw(world) # تحديث الأعداء ground_list.draw(world) # تحديث الأرضية plat_list.draw(world) # تحديث المنصات
منصات البلاط
يعد استخدام قطع البلاط لبناء عالم الألعاب أسلوبًا أسهل من استخدام الصور الكاملة كما عرضنا في الفقرة السابقة، فكل ما يترتب عليك هنا هو تجهيز أو رسم بعض الكتل مقدمًا ومن ثم استخدامها مرارًا وتكرارًا في كل منصات اللعبة.
توفر مواقع مثل kenney.nl أو OpenGameArt.org مجموعاتٍ واسعة من قطع البلاط التي تتمتع برخص المشاع الإبداعي، يمكنك تحميلها واستخدامها، اعتمد مثالنا قطعًا من kenney.nl تبلغ مساحة كل قطعة 64 بكسل مربع، وفي حال اعتمدت قطعًا بأبعادٍ أخرى راعِ ذلك ضمن الشيفرة.
لن يتغير صنف المنصة platform
عمّا كتبنا في السابق، لكن الدوال platform
و ground
في صنف المستوى Level
ستتضمن حلقاتٍ خاصة بحساب عدد الكتل اللازمة لبناء كل منصة.
لنفترض أنك ترغب بإنشاء أرضية ثابتة عبر تكرار استخدام قطع البلاط على طول نافذة اللعبة، يمكنك إنجاز ذلك بعدة طرق إحداها إعداد قائمة يدوية بالإحداثيات X و Y لمواقع قطع البلاط على طول المسار المطلوب، وعندها سترسم حلقة التكرار قطعة بلاط في كل موقع، انظر السطر التالي لكن لا تكتبه في فهو مجرد مثال، إذ سنعتمد طريقة أخرى للتعامل مع الموضوع.
# لا تكتب هذا السطر في شيفرة اللعبة فهو مجرد مثال gloc = [0,656,64,656,128,656,192,656,256,656,320,656,384,656]
دقّق قليلًا في المصفوفة السابقة وستجد أن جميع القيم Y متماثلة وهي 656 دائمًا، بينما تزداد قيم X ازديادًا مطردًا بمقدار 64 في كل نقلة الذي يعادل عرض البلاطة الواحدة.
أتمتة هذا النوع من التكرار المنتظم سهلة نوعًا ما فهي تتطلب بعض المنطق الرياضي والعمليات الحسابية لتتم آليًا.
اكتب لذلك التعليمات التالية ضمن مقطع الإعدادات في برنامجك:
gloc = [] tx = 64 ty = 64 i=0 while i <= (worldx/tx)+tx: gloc.append(i*tx) i=i+1 ground_list = Level.ground( 1,gloc,tx,ty )
يُجري بايثون من خلال التعليمات السابقة عملية قسمة يُقسم فيها عرض عالم اللعبة على عرض المربع الواحد أو قطعة البلاط الواحدة، وينتج بذلك مصفوفة تتضمن كافة قيم X اللازمة أما قيم Y فهي ثابتة لا تتغير طالما أن أرضية لعبتك مستوية.
استخدم حلقة while
لتستثمر المصفوفة السابقة في دالة بناء الأرضية فهي ستضيف بلاطة إلى الأرضية في الموقع المقابل لكل قيمة من قيم المصفوفة.
وستصبح الدالة على الشكل التالي، اكتبها ضمن صنف المستوى Level
:
def ground(lvl,gloc,tx,ty): ground_list = pygame.sprite.Group() i=0 if lvl == 1: while i < len(gloc): ground = Platform(gloc[i],worldy-ty,tx,ty,'tile-ground.png') ground_list.add(ground) i=i+1 if lvl == 2: print("Level " + str(lvl) ) return ground_list
تتشابه هذه الدالة في الغرض مع دالة الأرضية ground
التي تعاملنا معها في الفقرة السابقة إلّا أنها تعتمد هنا على الحلقة while
.
المبادئ نفسها تقريبًا لدالة المنصات المتحركة، وسنعطيك بعض النصائح الكفيلة بتبسيط الموضوع، فبدلًا من تحديد مساحة كل منصة بالبكسل، يمكنك الاستعاضة عن ذلك بتحديد نقطة بداية المنصة (أو الإحداثي X) ومدى ارتفاعها عن الأرضية (أي الإحداثي Y) وأيضًا عدد قطع البلاط التي تحتويها، وبذلك لن تحتاج لتحديد أبعاد كل منصة.
برمجة هذه العملية معقدة بعض الشيء فهي تتضمن حلقتي while
الواحدة ضمن الأخرى، إذ إن إنشاء كل منصة يستلزم تحديد ثلاث محددات مقابل كل قيمة من قيم المصفوفة، في حالتنا مثلًا لا يوجد سوى ثلاث منصات تعرفها التعليمات ploc.append
لكن بوسعك إضافة القدر الذي تريده من المنصات، وستلاحظ أنها لن تظهر دفعة واحدة عند تنفيذ الشيفرة بل ستظهر المنصات الخاصة بالشاشة الحالية فقط ومع تمرير الشاشة أثناء اللعب ستظهر البقية تباعًا.
def platform(lvl,tx,ty): plat_list = pygame.sprite.Group() ploc = [] i=0 if lvl == 1: ploc.append((200,worldy-ty-128,3)) ploc.append((300,worldy-ty-256,3)) ploc.append((500,worldy-ty-128,4)) while i < len(ploc): j=0 while j <= ploc[i][2]: plat = Platform((ploc[i][0]+(j*tx)),ploc[i][1],tx,ty,'tile.png') plat_list.add(plat) j=j+1 print('run' + str(i) + str(ploc[i])) i=i+1 if lvl == 2: print("Level " + str(lvl) ) return plat_list
إذًا فقد أنشأت الدالة المسؤولة عن بناء المنصات، وعليك الآن استدعائها داخل البرنامج وفق الأمر التالي:
plat_list = Level.platform(1, tx, ty)
وأخيرًا اكتب التالي في الحلقة الرئيسية حتى تظهر المنصات في عالم لعبتك (السطر الأول للحفاظ على السياق فقط فلا داعي لكتابته):
enemy_list.draw(world) # تحديث الأعداء ground_list.draw(world) # تحديث الأرضية plat_list.draw(world) # تحديث المنصات
شغل اللعبة الآن، ولاحظ توضع المنصات وشكلها، وعدّل ما تريد، علمًا أنك لن تجد المنصات التي لا تنتمي للشاشة الأولى، لا تقلق سنتجاوز ذلك في المقالات اللاحقة عبر تمرير عالم اللعبة.
طبق المهارات التي تعلمتها في السابق
لم يذكر هذا المقال أين يتوضع العدو أو كيف، لذا طبق المهارات التي تعلمتها سابقًا وأظهره على الأرضية أو فوق إحدى المنصات فهي الأماكن الأنسب له، أما البطل دعه حاليًا فهو محكوم بقوى خاصة بعالم الرسوم المتحركة تحاكي قوى الجاذبية في العالم الحقيقي ستتعلمها في مقالاتنا التالية.
إليك الشكل النهائي للشيفرة حتى الآن:
#!/usr/bin/env python3 # by Seth Kenlon # GPLv3 # This program is free software: you can redistribute it and/or # modify it under the terms of the GNU General Public License as # published by the Free Software Foundation, either version 3 of the # License, or (at your option) any later version. # # This program is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see <http://www.gnu.org/licenses/>. import pygame import sys import os ''' Variables ''' worldx = 960 worldy = 720 fps = 40 ani = 4 world = pygame.display.set_mode([worldx, worldy]) BLUE = (25, 25, 200) BLACK = (23, 23, 23) WHITE = (254, 254, 254) ALPHA = (0, 255, 0) ''' Objects ''' # x location, y location, img width, img height, img file class Platform(pygame.sprite.Sprite): def __init__(self, xloc, yloc, imgw, imgh, img): pygame.sprite.Sprite.__init__(self) self.image = pygame.image.load(os.path.join('images', img)).convert() self.image.convert_alpha() self.image.set_colorkey(ALPHA) self.rect = self.image.get_rect() self.rect.y = yloc self.rect.x = xloc class Player(pygame.sprite.Sprite): """ Spawn a player """ def __init__(self): pygame.sprite.Sprite.__init__(self) self.movex = 0 self.movey = 0 self.frame = 0 self.health = 10 self.images = [] for i in range(1, 5): img = pygame.image.load(os.path.join('images', 'hero' + str(i) + '.png')).convert() img.convert_alpha() img.set_colorkey(ALPHA) self.images.append(img) self.image = self.images[0] self.rect = self.image.get_rect() def control(self, x, y): """ control player movement """ self.movex += x self.movey += y def update(self): """ Update sprite position """ self.rect.x = self.rect.x + self.movex self.rect.y = self.rect.y + self.movey # moving left if self.movex < 0: self.frame += 1 if self.frame > 3 * ani: self.frame = 0 self.image = pygame.transform.flip(self.images[self.frame // ani], True, False) # moving right if self.movex > 0: self.frame += 1 if self.frame > 3 * ani: self.frame = 0 self.image = self.images[self.frame // ani] hit_list = pygame.sprite.spritecollide(self, enemy_list, False) for enemy in hit_list: self.health -= 1 print(self.health) class Enemy(pygame.sprite.Sprite): """ Spawn an enemy """ def __init__(self, x, y, img): pygame.sprite.Sprite.__init__(self) self.image = pygame.image.load(os.path.join('images', img)) self.image.convert_alpha() self.image.set_colorkey(ALPHA) self.rect = self.image.get_rect() self.rect.x = x self.rect.y = y self.counter = 0 def move(self): """ enemy movement """ distance = 80 speed = 8 if self.counter >= 0 and self.counter <= distance: self.rect.x += speed elif self.counter >= distance and self.counter <= distance * 2: self.rect.x -= speed else: self.counter = 0 self.counter += 1 class Level: def ground(lvl, gloc, tx, ty): ground_list = pygame.sprite.Group() i = 0 if lvl == 1: while i < len(gloc): ground = Platform(gloc[i], worldy - ty, tx, ty, 'tile-ground.png') ground_list.add(ground) i = i + 1 if lvl == 2: print("Level " + str(lvl)) return ground_list def bad(lvl, eloc): if lvl == 1: enemy = Enemy(eloc[0], eloc[1], 'enemy.png') enemy_list = pygame.sprite.Group() enemy_list.add(enemy) if lvl == 2: print("Level " + str(lvl)) return enemy_list # x location, y location, img width, img height, img file def platform(lvl, tx, ty): plat_list = pygame.sprite.Group() ploc = [] i = 0 if lvl == 1: ploc.append((200, worldy - ty - 128, 3)) ploc.append((300, worldy - ty - 256, 3)) ploc.append((500, worldy - ty - 128, 4)) while i < len(ploc): j = 0 while j <= ploc[i][2]: plat = Platform((ploc[i][0] + (j * tx)), ploc[i][1], tx, ty, 'tile.png') plat_list.add(plat) j = j + 1 print('run' + str(i) + str(ploc[i])) i = i + 1 if lvl == 2: print("Level " + str(lvl)) return plat_list ''' Setup ''' backdrop = pygame.image.load(os.path.join('images', 'stage.png')) clock = pygame.time.Clock() pygame.init() backdropbox = world.get_rect() main = True player = Player() # spawn player player.rect.x = 0 # go to x player.rect.y = 30 # go to y player_list = pygame.sprite.Group() player_list.add(player) steps = 10 eloc = [] eloc = [300, 0] enemy_list = Level.bad(1, eloc) gloc = [] tx = 64 ty = 64 i = 0 while i <= (worldx / tx) + tx: gloc.append(i * tx) i = i + 1 ground_list = Level.ground(1, gloc, tx, ty) plat_list = Level.platform(1, tx, ty) ''' Main Loop ''' while main: for event in pygame.event.get(): if event.type == pygame.QUIT: pygame.quit() try: sys.exit() finally: main = False if event.type == pygame.KEYDOWN: if event.key == ord('q'): pygame.quit() try: sys.exit() finally: main = False if event.key == pygame.K_LEFT or event.key == ord('a'): player.control(-steps, 0) if event.key == pygame.K_RIGHT or event.key == ord('d'): player.control(steps, 0) if event.key == pygame.K_UP or event.key == ord('w'): print('jump') if event.type == pygame.KEYUP: if event.key == pygame.K_LEFT or event.key == ord('a'): player.control(steps, 0) if event.key == pygame.K_RIGHT or event.key == ord('d'): player.control(-steps, 0) world.blit(backdrop, backdropbox) player.update() player_list.draw(world) enemy_list.draw(world) ground_list.draw(world) plat_list.draw(world) for e in enemy_list: e.move() pygame.display.flip() clock.tick(fps)
ترجمة -وبتصرف- للمقال Put platforms in a Python game with Pygame لصاحبيه Seth Kenlon و Jess Weichler.
اقرأ أيضًا
- المقال السابق: إضافة شخصية العدو للعبة عبر مكتبة Pygame في بايثون
- النسخة العربية الكاملة من كتاب البرمجة بلغة بايثون
- دليلك الشامل إلى: أشهر لغات برمجة الألعاب
أفضل التعليقات
لا توجد أية تعليقات بعد
انضم إلى النقاش
يمكنك أن تنشر الآن وتسجل لاحقًا. إذا كان لديك حساب، فسجل الدخول الآن لتنشر باسم حسابك.