اذهب إلى المحتوى

في مقال بناء لعبة نرد بسيطة بلغة بايثون استخدمنا بايثون لبرمجة لعبة نرد بسيطة معتمدة على النص، وفي مقالنا السابق تعلمنا كيفية تجهيز بيئة لعبة رسومية من الصفر أيضًا بلغة بايثون، والآن سنطوّر هذه اللعبة ونضيف إليها شخصية تلعب دور اللاعب أو بطل اللعبة.

يمكنك مطالعة المقال ضمن السلسلة:

  1. بناء لعبة نرد بسيطة بلغة بايثون.
  2. بناء لعبة رسومية باستخدام بايثون ووحدة الألعاب PyGame.
  3. إضافة لاعب إلى اللعبة المطورة باستخدام بايثون و Pygame.
  4. تحريك شخصية اللعبة باستخدام PyGame.
  5. إضافة شخصية العدو للعبة.
  6. إضافة المنصات إلى لعبة بايثون باستخدام الوحدة Pygame.
  7. محاكاة أثر الجاذبية في لعبة بايثون.
  8. إضافة خاصية القفز والركض إلى لعبة بايثون.
  9. إضافة الجوائز إلى اللعبة المطورة بلغة بايثون.
  10. تسجيل نتائج اللعبة المطورة بلغة بايثون وعرضها على الشاشة.
  11. إضافة آليات القذف إلى اللعبة المطورة بلغة بايثون.

يُطلق اسم الكائن أو الشخصية sprite على الأفاتار أو أيقونة الشخصية التي يتحكم بها اللاعب في Pygame، إن كنت لم تجهز له صورةً بعد، فيمكنك تنزيل الصور walk.png ذوات الأرقام 0 و2 و4 و5 من موقع SuperTux الخاصة بلعبة Supertux وهي مفتوحة المصدر أو من الملفات المرفقة، ومن ثم إعادة تسميتها لتصبح hero1.png إلى hero4.png، أو استخدام كريتا أو إنكسكيب لتصميم صور مناسبة، أو الاستعانة بمنصة OpenGameArt مفتوحة المصدر لخياراتٍ أخرى، واحفظ كافة الصور التي ستعتمدها في المجلد images الموجود ضمن مجلد مشروعك، وإن لم يكن موجودًا أنشئ واحدًا.

لتجعل لعبتك مثيرة وحقيقية استخدم كائنًا متحركًا، وتحتاج لذلك عدة رسومات للكائن في وضعيات مختلفة لتعطي وهم الحركة، أشهر الحركات المتعارف عليها في الرسوم المتحركة هي دورة المشي وتتطلب أربع صور لتحقق المطلوب.

img-01-walk-cycle-poses.jpg

تنويه: كود اللعبة المستخدم هنا يصلح للكائنات الثابتة والمتحركة.

سمي صورة كائن اللعبة بالاسم hero.png وإن رغبت بجعله متحركًا فسمي الصور الخاصة بدورة المشي بأرقامٍ متتابعة بدءً من hero1.png، واحفظها جميعًا في المجلد images الموجود ضمن مجلد مشروعك.

إنشاء صنف بايثون

يتطلب إظهار كائن بايثون Object على الشاشة إنشاء صنف class.

إن كنت تستخدم كائنًا ثابتًا ليمثل شخصية بطل اللعبة، فاكتب التعليمات التالية في المقطع الخاص بكائنات بايثون في ملفك:

'''
Objects
'''

class Player(pygame.sprite.Sprite):
    """
    Spawn a player
    """

    def __init__(self):
        pygame.sprite.Sprite.__init__(self)
        self.images = []

        img = pygame.image.load(os.path.join('images', 'hero.png')).convert()
        self.images.append(img)
        self.image = self.images[0]
        self.rect = self.image.get_rect()

ستُنشئ هذه التعليمات كائن بايثون افتراضي object يشير إلى بطل لعبتك، والكائنات في لغات البرمجة الكائنية تُشتق دومًا من الأصناف.

توفر Pygame قوالب جاهزة للكائنات مثل:

 pygame.sprite.Sprite 

وهو ما يتيح لك اختيار الصورة التي تريدها لتمثل بطل لعبتك، وبدون هذه القوالب كنت ستحتاج لمعرفة ممتازة بلغة بايثون لتبرمج الكائن من الصفر، وهذه ميزة استخدام مكتبة جاهزة مثل Pygame.

أما في حال أردت استخدام دورة المشي لإنشاء شخصية متحركة، فاحفظ صور وضعيات المشي الأربع لبطل اللعبة بأربع صور منفصلة سمّها hero1.png إلى hero4.png ضمن مجلد الصور ومن ثم استخدم حلقة التكرار لينتقل بايثون من صورة إلى أخرى، في الواقع أن يكون لكل صنف مهمة محددة لا تؤثر "بعالم اللعبة" هو واحد من أفضل ميزات البرمجة الكائنية، ففي حالتنا سيعطي الانتقال بين وضعيات المشي وهم الحركة للمشاهد، وسيحدث ذلك بغض النظر أن كل ما يجري في المحيط.

'''
Objects
'''


class Player(pygame.sprite.Sprite):
    """
    Spawn a player
    """

    def __init__(self):
        pygame.sprite.Sprite.__init__(self)
        self.images = []
        for i in range(1, 5):
            img = pygame.image.load(os.path.join('images', 'hero' + str(i) + '.png')).convert()
            self.images.append(img)
            self.image = self.images[0]
            self.rect = self.image.get_rect()

إحضار شخصية اللاعب إلى عالم اللعبة

بعد أن جهزنا الصنف الذي يشير إلى بطل اللعبة، يتعين علينا استدعائه ضمن اللعبة ليظهر في عالمها، فلو حاولت تشغيل لعبتك الآن ستجدها فارغة كما كانت عليه في نهاية مقالنا السابق، فالكائن الذي يشير لبطل اللعبة لم يرتبط بها بعد ولم يُضاف إلى مجموعة كائنات Pygame.

لتنجز ذلك اكتب التعليمات التالية في مقطع الإعدادات ضمن برنامجك:

player = Player()   # إنتاج اللاعب
player.rect.x = 0   # X توجه إلى 
player.rect.y = 0   # Y توجه إلى
player_list = pygame.sprite.Group()
player_list.add(player)

حاول الآن تشغيل اللعبة، لن تجد أي فرق، إذ إنك لن تلحظ بطل اللعبة فقد ظهر لأجزاء من الثانية فقط واختفى، تذكر ما شرحناه في مقالنا السابق لجهة أن إتاحة أي شيء باستمرار على الشاشة يستلزم إضافته إلى حلقة اللعبة الرئيسية، وبذلك سيرسمه بايثون مع كل تكرار للحلقة.

أضف إذًا التعليمات التالية للحلقة:

    world.blit(backdrop, backdropbox)
    player_list.draw(world) # draw player
    pygame.display.flip()
    clock.tick(fps)

ومن ثم شغل اللعبة، ستجد شخصية اللاعب فيها.

ضبط قناة الشفافية ألفا لشخصية اللعبة

اعتمادًا على الطريقة التي أنشأت بها كائن اللعبة ستظهر حوله مساحة ملونة تحيط به تسمى في الألعاب الحديثة صندوق التصادم hit box، هذه المساحة تشغلها القناة ألفا ويفترض أن تكون غير مرئية، لكن بايثون لا يملك التوجيهات الخاصة بذلك بعد.

img-02-greenscreen.jpg

يمكنك إخبار بايثون باللون الذي تعدّه غير مرئي عبر ضبط إعدادات القناة ألفا باستخدام قيم النظام اللوني RGB، إذا كنت لا تعرف قيمة RGB التي يستخدمها رسمك للقناة ألفا فافتح الشخصية باستخدام أحد البرامج الاختصاصية مثل بينتا أو إنكسكيب واملأ المساحة الفارغة حوله بلونٍ مميز مثل ‎#00ff00 الذي يكافئ اللون الأخضر "للشاشة الخضراء" ثم سجل هذه القيمة المكتوبة بالترميز الست عشري واكتبها في كود بايثون لتشكل قيمة القناة ألفا.

أضف الآن السطرين التاليين إلى التعليمات الخاصة بإنشاء كائن اللعبة حتى تضبط القناة ألفا:

    img = pygame.image.load(os.path.join('images','hero' + str(i) + '.png')).convert()
            img.convert_alpha()     # تحسين ألفا
            img.set_colorkey(ALPHA) # تحديد قيمة ألفا

إذا كنت تعتقد أن الصورة التي تعتمدها تملك بالفعل قيمة لقناة ألفا فاضبط المتغير ALPHA على القيمة 0 أو 255 فكلاهما من القيم الشائعة، ولكن لخبرتي مجال المونتاج -يقول كاتب المقال- أفضل إنشاء قناة ألفا وضبطها بنفسي لتكون قيمتها أكيدة دون لبس.

أضف المتغير التالي في المقطع الخاص بالمتغيرات:

ALPHA = (0, 255, 0)

تكافئ القيمة 0,255,0 في نظام RGB اللون الأخضر، ويمكنك على الحصول قيم كافة الألوان باستخدام برنامج رسومات جيد مثل جيمب أو كريتا أو إنكسكيب، أو الاستعانة بأحد نظم اختيار الألوان الشهيرة مفتوحة المصدر مثل KColorChooser أو ColourPicker.

img-04-kcolor.jpg

إذا كانت الصور التي تعتمدها تملك قيمة مغايرة للقناة ألفا فاختر للمتغير قيمة مناسبة وفق ما يستلزم الأمر، ودائمًا القيم التي تضعها لألفا ستصبح غير مرئية أيًا كانت، ففي حال وضعت قيمة ألفا 000 مثلًا (وهي تعني اللون الأسود) فاجعل عندها خطوط رسمك التي تكون سوداء بالعادة باللون 111 وهو أقرب ما يمكن للأسود ولن يلاحظ المستخدم الفرق.

شغل لعبتك الآن ولاحظ النتائج.

img-05-alpha.jpg

أما الشكل النهائي للكود بعد كل هذه التعديلات سيكون كما يلي:

#!/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/>.
from typing import Tuple

import pygame
import sys
import os

'''
Variables
'''

worldx = 960
worldy = 720
fps = 40  # frame rate
ani = 4  # animation cycles
world = pygame.display.set_mode([worldx, worldy])

BLUE = (25, 25, 200)
BLACK = (23, 23, 23)
WHITE = (254, 254, 254)
ALPHA = (0, 255, 0)

'''
Objects
'''


class Player(pygame.sprite.Sprite):
    """
    Spawn a player
    """

    def __init__(self):
        pygame.sprite.Sprite.__init__(self)
        self.images = []
        for i in range(1, 5):
            img = pygame.image.load(os.path.join('images', 'hero' + str(i) + '.png')).convert()
            img.convert_alpha()  # optimise alpha
            img.set_colorkey(ALPHA)  # set alpha
            self.images.append(img)
            self.image = self.images[0]
            self.rect = self.image.get_rect()


'''
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 = 0  # go to y
player_list = pygame.sprite.Group()
player_list.add(player)


'''
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
    world.blit(backdrop, backdropbox)
    player_list.draw(world)
    pygame.display.flip()
    clock.tick(fps)

تابع معنا المقال التالي لتضيف بعض الإثارة وتتعلم كيفية تحريك الكائن.

ترجمة -وبتصرف- للمقال How to add a player to your Python game لصاحبه Seth Kenlon.

اقرأ أيضًا


تفاعل الأعضاء

أفضل التعليقات

لا توجد أية تعليقات بعد



انضم إلى النقاش

يمكنك أن تنشر الآن وتسجل لاحقًا. إذا كان لديك حساب، فسجل الدخول الآن لتنشر باسم حسابك.

زائر
أضف تعليق

×   لقد أضفت محتوى بخط أو تنسيق مختلف.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   جرى استعادة المحتوى السابق..   امسح المحرر

×   You cannot paste images directly. Upload or insert images from URL.


×
×
  • أضف...