توسعه بازی‌های ساده با پايتون
آموزش کار با زبان برنامه‌نويسی پايتون (بخش نهم)
در این قسمت به طراحی و ساخت یک بازی بسیار ساده خواهیم پرداخت. در واقع برنامه‌ای خواهیم نوشت که یک کاراکتر دلخواه را روی صفحه بازی به فرمان کاربر جابه‌جا می‌کند. همانند بازی‌های پرطرفدار و مشهور که بر اساس یک موتور بازی توسعه داده می‌شوند، ما نیز در این بخش از مجموعه مقالات پایتون به بررسی یکی از ماجول‌های مخصوص توسعه بازی یعنی PyGame خواهیم پرداخت. هرچند برنامه ما عملاً یک «بازی» نخواهد بود، اما شما را با اصول اولیه کار آشنا خواهد کرد.

این مقاله یکی از قسمت‌های سلسله مقالاتی برای آشنایی و آموزش زبان پایتون است. این مجموع پیش از این در ماهنامه شبکه منتشر شده اما به سایت جدید منتقل نشده بود. با توجه به اهمیت موضوع و درخواست‌های مکرر خوانندگان، این مجموعه را به سایت مجله اضافه می‌کنیم و امیدواریم که مورد توجه علاقمندان قرار بگیرد.


برای مطالعه قسمت‌های قبلی سلسله مقالات آموزش زبان برنامه‌نویسی پایتون اینجا کلیک کنید


بازی‌های دیجیتال از ابتدای صنعت محاسبات کامپیوتری یکی از سودآورترین و پرطرفدارترین بازوهای این صنعت محسوب می‌شده‌اند. از دیگر سو، برنامه‌نویسی بازی‌های کامپیوتری به دلیل تعامل شدید با کاربر و همچنین به لحاظ نیاز به واکنش‌های سریع از سوی سیستم و در مواردی شبیه‌سازی هوش و رفتار انسانی از دشوارترین مواردی است که یک برنامه‌نویس می‌تواند در آن مهارت پیدا کند. اما این دشواری سبب نخواهد شد که ما این بخش را به‌صورت کامل کنار بگذاریم.

در این قسمت قصد داریم به بررسی Pygame بپردازیم. درواقع Pygame مجموعه‌ای از ماجول‌ها است که با هدف ساده‌سازی روند توسعه بازی‌های ساده طراحی‌شده‌اند. این ماجول‌ها از سایت www.pygame.org قابل دریافت هستند. به گفته توسعه‌دهندگان این مجموعه: «Pygame کتابخانه‌ای مستقل از پلتفرم است که برای ساده‌سازی توسعه نرم‌افزارهای مالتی‌مدیا نظیر، بازی‌ها، توسط زبان پایتون طراحی شده است. Pygame برای اجرا به زبان برنامه‌نویسی پایتون و کتابخانه مالتی‌مدیای SDL نیاز دارد.» برای نصب Pygame روی اوبونتو به سادگی می‌توانید با مراجعه به Synaptic بسته نرم‌افزاری آن را با نام python-pygame دانلود کنید یا در ترمینال دستور زیر را وارد کنید:

sudo apt-get install python-pygame

صفحه بازی

برای شروع کار، فهرست 1 را در ویرایشگر متن دلخواهتان وارد کنید و با نام game1.py آن را ذخیره کنید. در خط 3 این برنامه ما Pygame را import می‌کنیم تا توابع و مقادیر آن را در اختیار داشته باشیم. پس از آن و در خط 5 ماجول os را وارد می‌کنیم. هدف اصلی از به‌کار بردن ماجول os در خط 6 مشخص می‌شود. جایی که ما با مقداردهی یکی از مقادیر متغیر environment از ماجول os (که از جنس لیست است) تعیین می‌کنیم پنجره مربوط به برنامه بازی ما درست در وسط صفحه نمایش باز شود. پس از آن در خط 8 كد Pygame را راه‌اندازی یا به اصطلاح initialize می‌کنیم. این کار باعث می‌شود، پنجره مربوط به بازی ما تولید شده و در وسط صفحه به نمایش درآید. در مرحله بعد و در خط شماره 10 اندازه این پنجره را برابر 800×600 و در خط 11 عنوان پنجره را برابر عبارت “Pygame Test 1” تنظیم می‌کنیم. در نهایت، با اجرای یک حلقه به انتظار یک رویداد (در اینجا فشرده شدن کلیدهای ماوس یا کلیدی از صفحه کلید) می‌نشینیم. نخستين برنامه‌ای که ما با کمک Pygame نوشته‌ایم، هیچ عملیات خاصی انجام نمی‌دهد و تنها هدف ما از آوردن این مثال آشنایی با روش راه‌اندازی و تنظیم خصوصیات ابتدایی پنجره برنامه نظیر اندازه و عنوان پنجره بود. آنچه در این‌جا مهم است درک شیء screen به عنوان یک «ظرف» یا Container است. در اصطلاح Pygame به آن سطح یا Surface گفته می‌شود. این شیء به نوعی نقش یک برگه کاغذ را بازی خواهد کرد که ما ترسیمات مورد نظرمان را روی آن انجام می‌دهیم.

#! /usr/bin/env python
# importing modules
import pygame
from pygame.locals import *
import os
os.environ[‹SDL_VIDEO_CENTERED›]=›1›
# Initializing the game 
pygame.init()
# screen setup
screen = pygame.display.set_mode((800,600))
pygame.display.set_caption(‹Pygame Test 1›)
doloop=1
while doloop:
    if pygame.event.wait().type in (KEYDOWN ,\ MOUSEBUTTONDOWN):
        break

فهرست 1- كد ساده‌ای برای ايجاد يك صفحه Pygame

اکنون می‌توانیم به تدریج قابلیت‌ها و تنظیماتی را به این برنامه بیافزاییم. برای شروع از تغییر پس زمینه برنامه شروع می‌کنیم. برای تنظیم رنگ در ماجول‌های Pygame مجبور هستیم مقادیر RGB یا قرمز، سبز و آبی رنگ را تعیین کنیم. برای ساده‌تر شدن این کار می‌توانید از نرم‌افزاری به نام colorname استفاده کنید که از طریق مرکز نرم‌افزار اوبونتو قابل نصب است. به کمک این نرم‌افزار تعیین مقادیر RGB هر رنگ دلخواه از طریق یک چرخ رنگ به سادگی امکان‌پذیر خواهد شد. برای تنظیم رنگ پس‌زمینه کافی است، پس از دستور import خط زیر را اضافه کنید:

Background = 208 , 202 , 104

این کار رنگی آجری را به متغیر Background (که از جنس توپل است) نسبت خواهد داد. آن‌گاه پس از دستور  pygame.display.set_caption دو خط زیر را اضافه کنید:

screen.fill(Background)
screen.display.update()

متد ()screen.fill تنظیم رنگ صفحه را بر عهده دارد و متد ()update باعث اعمال تنظیم انجام شده به صفحه در حال نمایش خواهد شد. 

نمایش متن

اکنون زمان آن رسیده است که چند سطر متن را به پنجره برنامه اضافه کنیم. درست بعد از تعریف رنگ پس‌زمینه دستور زیر را برای تنظیم رنگ پیش‌زمینه به سفید وارد کنید:

FontForeground = 255 , 255 , 255

اگر برنامه را در این وضعیت اجرا کنید، اتفاق خاصی رخ نخواهد داد، زیرا ما تا‌کنون تنها رنگ متن را تعیین کرده‌ایم. برای نوشتن متن روی screen یا همان پنجره برنامه، خطوط زیر را بین دو دستور ()screen.fill  و ()pygame.display.update وارد کنید.

font = pygame.font.Font(None , 27)
text = font.render(‘Here is some text’ ,
True , FontForeground , Background)
textrect = text.get_rect()
screen.blit(text,textrect)

شکل 1- قراردادن متن روی يك صفحه Pygame

این برنامه را با عنوان game2.py ذخیره کرده و اجرا کنید. برنامه شما اکنون باید شبیه فهرست 2 باشد. برای نوشتن متن ما ابتدا در خط 15 متد Font را فراخوانده و 2 آرگومان را به آن پاس کرده‌ایم. نخستين آرگومان نام فونت و دومی اندازه آن خواهد بود. در اینجا ما از None برای نام فونت استفاده کرده‌ایم که باعث می‌شود سیستم از فونت پیش‌فرض خود استفاده کند.
پس از آن و در خط 16 متد ()font.render را به‌کار برده‌ایم که چهار آرگومان دارد. این چهار آرگومان به ترتیب عبارتند از متن موردنظر، استفاده یا عدم استفاده از anti-aliasing، رنگ پیش‌زمینه متن و در نهایت رنگ پس‌زمینه آن. برای قرار دادن متن روی screen از واسطی به نام مستطیل یا Rectangle استفاده می‌کنیم. در خط 18 با استفاده از تابع ()text.get_rect مستطیل مربوط به متن را ایجاد کرده‌ایم. درک این روند بسیار مهم است، زیرا اغلب اشیایی که از این به بعد با آن‌ها سروکار خواهیم داشت، مستطیل خواهند بود.
پس از آن ما مستطیل حاوی متن را روی screen قرار داده (خط 19) و تغییرات را اعمال کرد‌ه‌ایم. اما blit چیست و چرا از چنین نام عجیب و غریبی استفاده می‌شود؟ ریشه‌های این نام به سال‌های 1970 و دوران زیراکس پارک (جایی که بسیاری از تکنولوژی‌های امروزی را مدیون دانشمندان و نوآوران فعال در آن هستیم) باز می‌گردد. این اصطلاح در واقع خلاصه Bitmap Block Transfer است. وظیفه این دستور قرار دادن یک بلوک تصویری روی یک پس‌زمینه است.

#! /usr/bin/env python
# importing modules
import pygame
from pygame.locals import *
import os
os.environ[‹SDL_VIDEO_CENTERED›]=›1›
Background = 208,202,104
FontForeground = 255,255,255
# Initializing the game 
pygame.init()
# screen setup
screen = pygame.display.set_mode((800,600))
pygame.display.set_caption(‹Pygame Test 2›)
screen.fill(Background)
font=pygame.font.Font(None,27)
text=font.render(‹Here is some text›,True,\
FontForeground,Background)
textrect=text.get_rect()
screen.blit(text,textrect)
pygame.display.update()
doloop=1
while doloop:
    if pygame.event.wait().type in (KEYDOWN ,\ MOUSEBUTTONDOWN):
        break

فهرست 2

اما اگر بخواهیم متن ما درست در وسط پنجره برنامه ظاهر شود، چه باید کرد؟ در چنین صورتی کافی است بین دستور ()text.get_rect (خط‌ 18) و screen.blit (خط 19) اين دو خط را اضافه کنید:

textRect.centerx = screen.get_rect().centerx
textRect.centery = screen.get_rect().centery

همان‌گونه که مشاهده می‌کنید، خود screen هم در واقع یک مستطیل است که ما به کمک متد ()get_rect مشخصات آن و به ویژه x و y مرکز آن را استخراج کرده‌ایم و آن‌ها را به مختصات مرکز مستطیل متن نسبت داده‌ایم.
دوباره برنامه را اجرا کنید. این بار مشاهده خواهید کرد که همانند شکل‌1 پس از اجرای آن، متن Here is some text درست در وسط پنجره برنامه ظاهر می‌شود. با استفاده از متدهای (set_bold(True و (set_italic(True درست پس از قسمت pygame.font.Font می‌توانید به متن حالت توپر یا مایل را نیز نسبت دهید. اگر به خاطر داشته باشید، پیش‌تر گفتیم که برای تنظیم فونت متن از متد ()pygame.font.Font استفاده می‌کنیم که دو آرگومان فونت و اندازه را دریافت می‌کند. مشکل اینجا است که ما نمی‌توانیم از محل قرارگیری و نصب فونت‌های مختلف روی سیستم‌های متفاوت اطلاع پیدا کنیم یا درباره حالتی خاص مطمئن باشیم. خوشبختانه pygame این امکان را با پیش‌بینی متدی به نام match_font حل کرده است. در فهرست‌3 شما قطعه کدی را مشاهده می‌کنید که می‌تواند به عنوان مثال، محل قرارگیری فونت Courier New را برای ما چاپ کند. این کد در سیستم نگارنده آدرس usr/share/fonts/truetype/freefont/FreeMono.ttf را باز‌می‌گرداند که ممکن است در سیستم شما مقدار دیگری باشد. اگر فونت Courier New روی سیستم نصب نشده باشد، این کد مقدار None را بازخواهد گرداند. اما اگر فرض کنیم این فونت روی سیستم نصب شده باشد، می‌توان مقدار برگشتی این تابع را مانند قطعه کد زیر برای تنظیم فونت برنامه به کار برد:

courier = pygame.font.match_font(‘Courier New’)
font = pygame.font.Font(courier , 27)

این دو خط را نیز می‌توانید به عنوان آخرین تغییرات به کد برنامه game3.py خود اعمال کنید. در هنگام ایجاد یک بازی واقعی نهایت کار آن است که از یک فونت مشخص که مطمئن هستید روی سیستم‌های هدف موجود است، استفاده کنید یا فونت موردنظر را به همراه بسته نصب بازی عرضه کنید. 

گرافیک

اگرچه متن‌ها زیبا هستند، اما گرافیک‌ها از آن‌ها زیباترند. در اینجا به توضیح نحوه کار اسپرایت‌ها (Sprite) در pygame خواهیم پرداخت. اسپرایت‌ها تصاویر دو بعدی ساده‌ای هستند که در نرم‌افزارهای گرافیکی برای نمایش اجزای بازی مورد استفاده قرار می‌گیرند. برای استفاده از گرافیک‌ها در برنامه بازی خودتان، توسط نرم‌افزاری نظیر GIMP یا ابزارهای مشابه تصویری شبیه یک آدمک را در یک فایل 50 × 50 پیکسل ترسیم کنید. رنگ پس‌زمینه تصویر را به حالت شفاف (Transparent) تغییر دهید و فایل را با نام stick.png در پوشه‌ای که فایل‌های کد برنامه در آن قرار دارند، ذخیره کنید. توجه کنید که حتماً حالت پس‌زمینه تصویر را روی Transparent تنظیم کنید تا هنگام نمایش و حرکت اسپرایت روی پس‌زمینه تنها تصویر آدمک دیده شود، نه یک مربع 50 × 50 سفید رنگ.

import pygame
from pygame.locals import *
print pygame.font.match_font(‹Courier New›)

فهرست 3- كدی برای تعيين محل يك فونت خاص

هدف بعدی ما، طراحی بازی به گونه‌ای است که این اسپرایت روی صفحه بازی نمایش داده شود و با فشرده شدن کلیدهای جهت‌نما، آدمک نیز به چپ و راست و بالا و پایین حرکت کند. این حرکت باید در لبه‌های صفحه بازی متوقف شود و با فشرده شدن کلید q بازی خاتمه یابد. حرکت دادن اسپرایت روی صفحه به نسبت ساده است. تنها باید بدانید که برای این کار از دو اسپرایت؛ یکی اسپرایت آدمک و دیگری یک اسپرایت خالی استفاده خواهیم کرد. زمانی که کلیدی فشرده می‌شود، برنامه موقعیت جدید اسپرایت آدمک را محاسبه می‌کند، سپس ما اسپرایت خالی را در محل فعلی آدمک قرار می‌دهیم تا به اصطلاح آن را پاک کنیم، آن گاه اسپرایت آدمک را در محل جدید ظاهر می‌کنیم. 

#! /usr/bin/env python
# importing modules
import pygame
from pygame.locals import *
import os
import sys
os.environ[‹SDL_VIDEO_CENTERED›]=›1›
Background = 0,255,127
FontForeground = 255,255,255
# Initializing the game 
pygame.init()
# screen setup
screen = pygame.display.set_mode((400,300))
pygame.display.set_caption(‹Pygame Sprite Test›)
screen.fill(Background)
class Sprite(pygame.sprite.Sprite):
    def __init__(self,position):
        pygame.sprite.Sprite.__init__(self)
        # get the screen rectangle
        self.screen = pygame.display.get_surface().get_rect()
        # Variable to store privious position
        self.oldsprite=(0,0,0,0)
        self.image=pygame.image.load(‹stick.png›)
        self.rect=self.image.get_rect()
        self.rect.x=position[0]
        self.rect.y=position[1]
     def update(self,amount):
        # make a copy of current rectangle
        self.oldsprite = self.rect
        # Moving the rectangle
        self.rect = self.rect.move(amount)
        # Check the border
        if self.rect.x <0:
            self.rect.x=0
        elif self.rect.x > (self.screen.width - self.rect.width):
            self.rect.x = self.screen.width - self.rect.width
        if self.rect.y < 0:
            self.rect.y=0
        elif self.rect.y > (self.screen.height - self.rect.height):
            self.rect.y = self.screen.height - self.rect.height
character = Sprite((screen.get_rect().x , screen.get_rect().y))
screen.blit(character.image,character.rect)
blank=pygame.Surface((character.rect.width,character.rect.height))
blank.fill(Background)
pygame.display.update()
doloop=1
while doloop:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            sys.exit()
        elif event.type == pygame.KEYDOWN:
            if event.key == pygame.K_LEFT:
                character.update([-10,0])
            elif event.key == pygame.K_UP:
                character.update([0,-10])
            elif event.key == pygame.K_RIGHT:
                character.update([10,0])
            elif event.key == pygame.K_DOWN:
                character.update([0,10])
            elif event.key == pygame.K_q:
                doloop=0
        # Erase old position
        screen.blit(blank,character.oldsprite)
        # Draw new
        screen.blit(character.image,character.rect)
        # Update modified positions
        pygame.display.update([character.oldsprite,character.rect])

فهرست 4 - حركت دادن يك كاراكترروی صفحه Pygame

شکل 2- صفحه بازی ايجاد شده توسط كد فهرست 4

یک فایل جدید ایجاد کنید و محتویات فهرست 4 را در آن وارد کرده و آن را با نام game4.py  ذخیره کنید. با اجرای این کد شما آدمک متحرک را روی پس‌زمینه‌ای به رنگ سبز تیره مشاهده خواهید کرد که به کلیدهای جهت‌نما واکنش نشان داده و به دستور شما حرکت خواهد کرد.  بخش اول این کد، شبیه مثال‌های قبلی و شامل خطوطی برای import ماجول‌های موردنیاز و تنظیم رنگ و عنوان صفحه بازی است. پس از آن در خط 16 کلاسی را برای کنترل و مدیریت اسپرایت یا گرافیک دلخواهمان تعریف کرده‌ایم. در ابتدای کلاس و با تعریف تابع __init__ ما اسپرایت را راه‌اندازی می‌کنیم. غالب کارهای ساخت اسپرایت به کمک متد اصلی pygame.sprite.Sprite.__init__   که در خود pygame تعریف شده است (خط 18) به انجام می‌رسد. پس از آن در خط 20 سطح یا Surface بازی را تعریف کرده و آن را screen نامیده‌ایم. بعدها به کمک شیء screen می‌توانیم کنترل کنیم که اسپرایت از صفحه بازی خارج نشود. سپس در خط 23 با تابع pygame.image.load فایل تصویر آدمک ساخته شده را به اسپرایت نسبت داده‌ایم. اگر فایل برنامه و فایل تصویر در یک پوشه نباشند، باید آدرس کامل فایل تصویری در این تابع قید شود. پس از آن در خط‌های 25 و 26 موقعیت x , y  اسپرایت توسط متغیر position که به تابع پاس شده است،تنظیم می‌شود.
تابع update که در خط 27 تعریف شده است، وظیفه حرکت دادن اسپرایت و پرکردن محل قبلی آن با یک فضای خالی (پاک کردن اسپرایت) را برعهده خواهد داشت. این تابع همچنین عدم خروج اسپرایت از صفحه را کنترل می‌کند.  پس از پایان تعریف کلاس، ما نمونه‌ای از کلاس را در خط 41 با نام character ایجاد کرده و با تابع blit روی صفحه نمایش داده‌ایم (خط‌42). پس از آن شیء blank یا پاک کننده ایجاد شده و تابع update ماجول display  به اجرا در می‌آید. پس از آن در خطوط 47 تا 67 یک حلقه بی‌پایان ایجاد شده و با کنترل ورودی کاربر، آدمک ساخته شده روی صفحه نمایش به حرکت در خواهد آمد. کارهای بسیار پیچیده‌تری با pygame قابل انجام است  به عنوان مثال، اين ماجول داراي توابعی برای كنترل برخورد اسپرايت‌ها (مثلاً برخورد گلوله با شخصيت بازی)، نگه‌داری امتيازها و افزودن جلوه‌های صوتی و‌... نيز دارد. اما هدف ما آشنا‌کردن شما با مبانی کار با این ماجول بود و امیدواریم که توانسته باشیم حس کنجکاوی شما را برای آگاهی بیشتر برانگيخته باشیم.

ماهنامه شبکه را از کجا تهیه کنیم؟
ماهنامه شبکه را می‌توانید از کتابخانه‌های عمومی سراسر کشور و نیز از دکه‌های روزنامه‌فروشی تهیه نمائید.

ثبت اشتراک نسخه کاغذی ماهنامه شبکه     
ثبت اشتراک نسخه آنلاین

 

کتاب الکترونیک +Network راهنمای شبکه‌ها

  • برای دانلود تنها کتاب کامل ترجمه فارسی +Network  اینجا  کلیک کنید.

کتاب الکترونیک دوره مقدماتی آموزش پایتون

  • اگر قصد یادگیری برنامه‌نویسی را دارید ولی هیچ پیش‌زمینه‌ای ندارید اینجا کلیک کنید.

ایسوس

نظر شما چیست؟