كيفية إضافة شخصيات اللعبة (البطل + الشرير) إلى لعبة بايثون Pygame
في الجزء الخامس من هذه السلسلة حول بناء لعبة بايثون من الصفر ، أضف شخصية سيئة الى جانب الطيب ليقاتله.
في المقالات السابقة في هذه السلسلة تعلمت كيفية استخدام Pygame
و Python لإنتاج شخصية بطل قابلة للعب في عالم ألعاب فيديو فارغ. لكن ما هو البطل بدون شرير؟
ستكون لعبة مملة جدًا إذا لم يكن لديك أعداء ، لذا في هذه المقالة ،
ستضيف عدوًا إلى لعبتك وستنشئ إطارًا لبناء المستويات.
قد يبدو من الغريب القفز إلى الأعداء عندما لا يزال هناك الكثير مما يتعين
القيام به لجعل كائن اللاعب يعمل بكامل طاقته ، لكنك تعلمت الكثير بالفعل ،
وإنشاء الأشرار يشبه إلى حد بعيد إنشاء كائن لاعب. لذا استرخ ، واستخدم
المعرفة التي لديك بالفعل ، وشاهد ما يلزم لإثارة بعض المشاكل.
في هذا التمرين ، أنت بحاجة إلى كائن عدو. إذا لم تقم بتنزيل أحدها بالفعل ،
فيمكنك العثور على أصول المشاع الإبداعي على OpenGameArt.org .
خلق كائن العدو "enemy sprite"
سواء كنت تدرك ذلك أم لا ، فأنت تعرف بالفعل كيفية تنفيذ الأعداء. تشبه العملية إنشاء كائن لاعب:
1- اصنع فئة حتى يتمكن الأعداء من التكاثر.
2- قم بإنشاء updateوظيفة للعدو ، وقم بتحديث العدو في الحلقة الرئيسية الخاصة بك.
3- قم بإنشاء moveوظيفة حتى يتمكن عدوك من التجول.
ابدأ بالفصل. من الناحية المفاهيمية ، غالبًا ما تكون نفس فئة اللاعب.
يمكنك تعيين صورة أو سلسلة من الصور ، وتعيين موضع بدء الكائن.
قبل المتابعة ، تأكد من أنك وضعت رسم العدو في images
دليل مشروع اللعبة (نفس الدليل الذي وضعت فيه صورة اللاعب).
في مثال التعليمات البرمجية لهذه المقالة ، تم تسمية رسم العدو enemy.png.
تبدو اللعبة أفضل كثيرًا عندما يتم تحريك كل شيء حي . يتم تحريك كائن العدو بنفس
طريقة تحريك كائن اللاعب. في الوقت الحالي ، على الرغم من ذلك ، اجعل الأمر بسيطًا ، واستخدم كائنًا غير متحرك.
في الجزء العلوي من objectsقسم التعليمات البرمجية الخاصة بك ،
قم بإنشاء فئة تسمى العدو بهذا الرمز:
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
إذا كنت ترغب في تحريك عدوك ، فافعل ذلك بنفس الطريقة التي حركت فيها لاعبك .
انفسام العدو "Spawning an enemy"
يمكنك جعل الفصل مفيدًا لتكاثر أكثر من عدو واحد من خلال السماح لنفسك
بإخبار الفصل بالصورة التي ستستخدمها للكائن وأين تريد ظهور الكائن في العالم.
هذا يعني أنه يمكنك استخدام نفس فئة العدو هذه لإنشاء أي عدد من نقوش
العدو في أي مكان في عالم اللعبة. كل ما عليك فعله هو إجراء مكالمة إلى الفصل
وإخباره بالصورة التي يجب استخدامها ، جنبًا إلى جنب مع إحداثيات X و Y لنقطة التكاثر المرغوبة.
Ao الذي قمت به عند إنتاج كائن لاعب ، أضف رمزًا لتعيين نقطة ولادة في
setup قسم البرنامج النصي الخاص بك:
enemy = Enemy(300,0,'enemy.png') # spawn enemy
enemy_list = pygame.sprite.Group() # create enemy group
enemy_list.add(enemy) # add enemy to group
في نموذج التعليمات البرمجية هذا ، يمكنك إنتاج عدو عن طريق
إنشاء كائن جديد (يسمى enemy) ، عند 300 بكسل على المحور X و 0 على المحور Y.
إن تفريخ العدو عند 0 على المحور Y يعني أن الزاوية اليسرى العلوية تقع
عند 0 ، مع أن الرسم نفسه ينزل إلى أسفل من تلك النقطة. قد تحتاج إلى تعديل
هذه الأرقام ، أو الأرقام الخاصة بشخصيتك البطل ، اعتمادًا على حجم النقوش
المتحركة الخاصة بك ، ولكن حاول أن تجعلها تتكاثر في مكان يمكنك الوصول
إليه باستخدام كائن لاعبك (وهو ما يمثل نقصًا في الوضع الرأسي الحالي في لعبتك حركة).
في النهاية ، وضعت عدوي على 0 بكسل على المحور Y ووضعت بطلي عند 30 بكسل
لجعلها تظهر على نفس المستوى. جرب نقاط التكاثر لنفسك ، مع الأخذ في
الاعتبار أن أرقام المحور Y الأكبر تكون أقل على الشاشة.
يحتوي الرسم البطل على صورة "مشفرة بشكل ثابت" في فئته لأنه
لا يوجد سوى بطل واحد ، ولكن قد ترغب في استخدام رسومات مختلفة لكل عدو ،
لذا فإن ملف الصورة هو شيء يمكنك تحديده عند إنشاء الرموز المتحركة.
الصورة المستخدمة لهذا العدو هو enemy.png.
رسم الكائن على الشاشة
إذا كنت ستطلق لعبتك الآن ، فستعمل ولكنك لن ترى عدوًا.
قد تتذكر نفس المشكلة عندما أنشأت كائن اللاعب الخاص بك. هل تتذكر كيف تصلحه؟
للحصول على كائن يظهر على الشاشة ، يجب عليك إضافته إلى الحلقة الرئيسية.
إذا لم يكن هناك شيء ما في الحلقة الرئيسية الخاصة بك ، فإنه يحدث مرة واحدة فقط ،
ولمدة جزء من الثانية فقط. إذا كنت تريد أن يستمر شيء ما في لعبتك ، فيجب أن يحدث في الحلقة الرئيسية.
يجب عليك إضافة رمز لرسم جميع الأعداء في مجموعة العدو (تسمى enemy_list) ،
والتي أنشأتها في قسم الإعداد الخاص بك ، على الشاشة. السطر الأوسط في رمز
المثال هذا هو السطر الجديد الذي تحتاج إلى إضافته:
player_list.draw(world)
enemy_list.draw(world) # refresh enemies
pygame.display.flip()
الآن ، لديك عدو واحد فقط ، ولكن يمكنك إضافة المزيد لاحقًا إذا أردت.
ما دمت تضيف عدوًا إلى مجموعة الأعداء ، فسيتم سحبه إلى الشاشة أثناء الحلقة الرئيسية.
ابدأ لعبتك. يظهر عدوك في عالم اللعبة في أي تنسيق X و Y اخترته.
المستوى الاول
لا تزال لعبتك في مهدها ، ولكن قد ترغب في إضافة سلسلة من المستويات في النهاية.
من المهم أن تخطط مسبقًا عند البرمجة حتى تنمو لعبتك كلما تعلمت المزيد عن البرمجة.
على الرغم من أنه ليس لديك حتى مستوى واحد كامل حتى الآن ، يجب عليك
الترميز كما لو كنت تخطط لامتلاك العديد من المستويات.
فكر في ماهية "المستوى". كيف تعرف أنك في مستوى معين في لعبة ما؟
يمكنك التفكير في المستوى على أنه مجموعة من العناصر. في لعبة المنصات ،
مثل تلك التي تبنيها هنا ، يتكون المستوى من ترتيب محدد للمنصات ، ووضع
الأعداء والنهب ، وما إلى ذلك. يمكنك بناء فصل دراسي يبني مستوى حول لاعبك.
في النهاية ، عندما تنشئ أكثر من مستوى ، يمكنك استخدام هذه الفئة لإنشاء
المستوى التالي عندما يصل لاعبك إلى هدف معين.
انقل الكود الذي كتبته لإنشاء عدو ومجموعته إلى وظيفة جديدة يتم استدعاؤها مع كل مستوى جديد.
يتطلب الأمر بعض التعديل بحيث في كل مرة تنشئ فيها مستوى جديدًا ،
يمكنك إنشاء العديد من الأعداء ووضعهم:
class Level():
def bad(lvl,eloc):
if lvl == 1:
enemy = Enemy(eloc[0],eloc[1],'enemy.png') # spawn enemy
enemy_list = pygame.sprite.Group() # create enemy group
enemy_list.add(enemy) # add enemy to group
if lvl == 2:
print("Level " + str(lvl) )
return enemy_list
يضمن return البيان أنه عند استخدام Level.bad
الوظيفة ، يتبقى enemy_list لك كل عدو حددته.
نظرًا لأنك تقوم بإنشاء أعداء كجزء من كل مستوى الآن ، فإن setup
القسم الخاص بك بحاجة إلى التغيير أيضًا. بدلاً من إنشاء عدو ، يجب عليك
تحديد المكان الذي سينتشر فيه العدو والمستوى الذي ينتمي إليه:
eloc = []
eloc = [300,0]
enemy_list = Level.bad( 1, eloc )
قم بتشغيل اللعبة مرة أخرى للتأكد من أن مستواك يولد بشكل صحيح.
يجب أن ترى لاعبك ، كالعادة ، والعدو الذي أضفته في هذا الفصل.
ضرب العدو
لا يعتبر العدو عدوًا كبيرًا إذا لم يكن له تأثير على اللاعب.
من الشائع أن يتسبب الأعداء في ضرر عندما يصطدم بهم اللاعب.
نظرًا لأنك ربما تريد تتبع صحة اللاعب ، فإن فحص التصادم يحدث في فئة اللاعب بدلاً من فئة العدو.
يمكنك تتبع صحة العدو أيضًا ، إذا كنت تريد ذلك. المنطق والرمز متماثلان إلى حد كبير ،
لكن في الوقت الحالي ، ما عليك سوى تتبع صحة اللاعب.
لتتبع صحة اللاعب ، يجب عليك أولاً إنشاء متغير لصحة اللاعب. السطر الأول في
نموذج التعليمات البرمجية هذا مخصص للسياق ، لذا أضف السطر الثاني إلى فئة المشغل :
self.frame = 0
self.health = 10
في update وظيفة فئة المشغل الخاصة بك ، أضف كتلة التعليمات البرمجية هذه:
hit_list = pygame.sprite.spritecollide(self, enemy_list, False)
for enemy in hit_list:
self.health -= 1
print(self.health)
ينشئ هذا الرمز كاشفًا للتصادم باستخدام وظيفة
Pygame sprite.spritecollide، المسماة enemy_hit.
يرسل كاشف الاصطدام إشارة في أي وقت يلامس صندوق الوصول الخاص
بكائنه الأصلي (كائن اللاعب ، حيث تم إنشاء هذا الكاشف) صندوق الوصول لأي كائن بداخله enemy_list.
يتم forتشغيل الحلقة عند تلقي مثل هذه الإشارة وتخصم نقطة من صحة اللاعب.
نظرًا لأن هذا الرمز يظهر في update وظيفة فئة اللاعب الخاص بك update
ويتم استدعاؤه في الحلقة الرئيسية الخاصة بك ، فإن Pygame
يتحقق من هذا التصادم مرة واحدة في كل ساعة.
تحريك العدو
يعد العدو الذي لا يزال قائما مفيدًا إذا كنت تريد ، على سبيل المثال ،
المسامير أو الفخاخ التي يمكن أن تضر بلاعبك ، ولكن اللعبة أكثر صعوبة إذا تحرك الأعداء قليلاً.
على عكس كائن اللاعب ، لا يتحكم المستخدم في كائن العدو. يجب أن تكون حركاتها آلية.
في النهاية ، سيتم تمرير عالم لعبتك ، فكيف يمكنك جعل عدو يتحرك ذهابًا وإيابًا داخل
عالم اللعبة عندما يتحرك عالم اللعبة نفسه؟
أنت تطلب من كائن عدوك أن يسير ، على سبيل المثال ، 10 خطوات إلى اليمين ، ثم 10 خطوات إلى اليسار.
كائن العدو لا يمكن أن يحسب ، لذلك عليك إنشاء متغير لتتبع عدد الخطوات التي
تحركها عدوك وبرمجة عدوك للتحرك إما يمينًا أو يسارًا اعتمادًا على قيمة متغير العد الخاص بك.
أولاً ، قم بإنشاء متغير العداد في فئة العدو. أضف السطر الأخير في نموذج التعليمات البرمجية هذا:
self.rect = self.image.get_rect()
self.rect.x = x
self.rect.y = y
self.counter = 0 # counter variable
بعد ذلك ، قم بإنشاء move وظيفة في صف العدو الخاص بك.
استخدم حلقة if-else لإنشاء ما يسمى الحلقة اللانهائية :
1- تحرك يمينًا إذا كان العداد على أي رقم من 0 إلى 100.
2- تحرك إلى اليسار إذا كان العداد على أي عدد من 100 إلى 200.
3- أعد ضبط العداد إلى 0 إذا كان العداد أكبر من 200.
الحلقة اللانهائية ليس لها نهاية ؛ إنها تدور إلى الأبد لأنه لا يوجد شيء
في الحلقة غير صحيح على الإطلاق. العداد ، في هذه الحالة ، يكون دائمًا إما بين
0 و 100 أو 100 و 200 ، لذلك يمشي كائن العدو من اليمين إلى
اليسار ومن اليمين إلى اليسار إلى الأبد.
الأرقام الفعلية التي تستخدمها لمدى تحرك العدو في أي من الاتجاهين اعتمادًا
على حجم شاشتك ، وربما ، في النهاية ، حجم المنصة التي يسير عليها عدوك.
ابدأ صغيرًا واعمل في طريقك مع التعود على النتائج. جرب هذا أولاً:
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
بعد إدخال هذا الرمز ، ستعرض PyCharm تبسيط "المقارنة المتسلسلة".
يمكنك قبول اقتراحه لتحسين التعليمات البرمجية الخاصة بك ، وتعلم بعض بناء
جملة Python المتقدم. يمكنك أيضًا تجاهل PyCharm بأمان. يعمل الرمز ، في كلتا الحالتين.
يمكنك ضبط المسافة والسرعة حسب الحاجة.
السؤال هو: هل يعمل هذا الرمز إذا أطلقت لعبتك الآن؟
بالطبع لا! وأنت تعرف السبب: يجب عليك استدعاء moveالوظيفة في الحلقة الرئيسية الخاصة بك.
السطر الأول في نموذج التعليمات البرمجية هذا مخصص للسياق ، لذا أضف آخر سطرين:
enemy_list.draw(world) #refresh enemy
for e in enemy_list:
e.move()
ابدأ لعبتك وشاهد ما يحدث عندما تضرب عدوك. قد تضطر إلى ضبط
مكان تفرخ النقوش بحيث يمكن للاعبك وكائن عدوك أن يصطدموا.
عندما تصطدم ، انظر في وحدة التحكم IDLE أو PyCharm
لمعرفة النقاط الصحية التي يتم خصمها.
مقالات ذات صلة :
الشخصيات : البطل و العدو
قد تلاحظ أنه يتم خصم صحتك عن كل لحظة يلمسها لاعبك وعدوك.
هذه مشكلة ، لكنها مشكلة ستحلها لاحقًا ، بعد أن تكون قد اكتسبت مزيدًا من التدرب على Python.
في الوقت الحالي ، حاول إضافة المزيد من الأعداء. تذكر أن تضيف كل عدو
إلى enemy_list. كتمرين ، انظر إذا كان بإمكانك التفكير في كيفية تغيير مدى تحرك نقوش العدو المختلفة.
كود الكامل هو :
بالنسبة لك كمرجع ، إليك الرمز حتى الآن:
#!/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