در این بخش با رسم پنجره و در قسمت بعدی با تغییر رنگ آن آشنا می شویم.این برنامه نخستین برنامه ما با pygame است.
در این بخش از یادگیری pygame می خواهیم با هم یک پنجره ساده را که به شکل بالا است، رسم کنیم. این بخش از بخش های پیشین اندکی طولانی تر است، پس توصیه می کنم هر وقت که زمان داشتید آن را بخوانید. همچنین از سرسری خواندن آن بپرهیزید زیرا در این بخش قرار است درس های مهمی را فرا گیریم. نکته دیگر این که اگر در خواندن آن ابهام داشتید دوباره و چندباره آن را بخوانید، چون این مفاهیم برای کسانی که pygame را برای اولین یاد می گیرند تازگی دارد و ممکن است که با یک بار خواندن این مفاهیم را به درستی یاد نگیرند.
پیش از رسم کردن پنجره بیایید کمی با مفهوم CLI و GUI آشنا شویم.
برنامه هایی را که با توابع پایتون می نویسیم تنها می توانند با متن هایی کار کنند که با توابع print و input دریافت و چاپ شده اند. برنامه شما می تواند متن های گوناگونی را نمایش دهد و کاربر هم چنین می تواند متن دل خواه خود را با صفحه کلید بنویسد. اینگونه از برنامه ها دارای رابط خط فرمان یا CLI(command line interface) هستند. این برنامه ها تا اندازه ای محدود هستند چون نمی توانند اشکال مختلف را ترسیم کنند، رنگ داشته باشند یا از موس استفاده کنند. برنامه های CLI تنها می توانند ورودی را با تابع input دریافت کنند. پس از این که برنامه ورودی را دریافت کرد، کاربر باید Enter را بزند تا برنامه بتواند ورودی بعدی را دریافت کند.از این گفته ها می توان این نتیجه را گرفت که ساخت بازی های واکنشی بی درنگ با CLI ناممکن است.
Pygame با داشتن توابع مخصوص برای ساخت برنامه هایی با رابط کاربری گرافیکی یا GUI(graphical user interface) همه مشکل های گفته شده در بالا را حل می کند. برنامه های ساخته شده با GUI برخلاف CLI می توانند پنجره ای را با تصاویر و رنگ های مختلف نشان دهند.
در انتهای این نوشته می خواهیم یاد بگیریم که چگونه پنجره زیر را رسم کنیم:
نخستین برنامه ای که با pygame می نویسیم برنامه کوچک بالا است که نام آن "!Hello World" است.برای شروع کار یک ویرایشگر کد را باز کنید. یک فایل جدید با نام helloworld.py ایجاد کنید و کدهای زیر را در آن بنویسید و سپس آن را ذخیره کنید. می توانید از هر ویرایشگر متنی که خواستید استفاده کنید. پیش از این که یاد بگیریم چگونه پنجره بالا را رسم کنیم بیایید نگاهی به کد آن بیندازیم.
import pygame, sys from pygame.locals import * pygame.init() DISPLAYSURF = pygame.display.set_mode((400, 300)) pygame.display.set_caption('Hello World!') while True: # main game loop for event in pygame.event.get(): if event.type == QUIT: pygame.quit() sys.exit() pygame.display.update()
همان طور که از پیش می دانیم برای استفاده از یک کتابخانه خارجی در پایتون باید آن را وارد برنامه کنیم یعنی آن را import کنیم. به عنوان نمونه اگر بخواهیم از ماژول math استفاده بکنیم باید آن را با دستور import math وارد برنامه کنیم.پس برای استفاده از pygame و sys باید آن ها را import کنیم. مانند زیر:
import pygame,sys
خط بالا در هر برنامه pygame وجود دارد. این خط یک import ساده است که ماژول های pygame و sys را وارد برنامه می کند تا برنامه ما بتواند از توابع موجود در آن ها استفاده کند. همه تابع های pygame که با گرافیک، صدا و... سر و کار دارند در ماژول pygame هستند. تنها چیزی که در مورد ماژول sys باید بدانید این است که حاوی متغیرها و توابع مربوط به مفسر پایتون است.
در خط بعدی pygame.locals را وارد برنامه می کنیم:
from pygame.locals import *
دلیل استفاده از pygame.locals این است که به ثابت های موجود در آن نیاز داریم. ماژول pygame.locals شامل 280 ثابت است. قرار دادن این عبارت در ابتدای برنامه، همه آن ها را وارد برنامه می کند. مانند QUIT که در برنامه خود از آن استفاده کرده ایم.
با خط زیر در واقع می خواهیم به پایتون بفهمانیم که قصد استفاده از pygame را داریم. برای این کار باید pygame را مقداردهی اولیه یا initialize کنیم. اگر این کار را نکنیم pygame کار نخواهد کرد. کد pygame.init همیشه باید بعد از ماژول pygame و قبل از سایر تابع ها بیاید. لازم نیست بدانید که این تابع چه کاری انجام می دهد، فقط بدانید برای این که توابع pygame بتوانند به درستی کار کنند، این تابع باید قبل از آن ها فراخوانی شود. پس داریم:
()pygame.init
خط بعدی فراخوانی تابع display.set_mode است که شی ای به نام pygame.Surface را برای پنجره برمی گرداند. (اشیا Surface در بخش های بعدی این سری آموزش توضیح داده خواهد شد پس نگران نباشید). در واقع set_mode یک شی Screen را برای نمایش پنجره مقداردهی می کند. یک تاپل دوتایی از دو عدد صحیح را به تابع می فرستیم: (400,300). این تاپل مشخص می کند که تابع set_mode برای ساخت پنجره باید چه مقدار طول و عرض داشته باشد. (400,300) یک پنجره با طول 400 پیکسل و عرض 300 پیکسل می سازد. پس عدد اول برای طول و عدد دوم برای عرض است و هر دو حتما باید صحیح یا int باشند.
از این دو عدد به تنهایی در تابع set_mode استفاده نکنید و مطمئن شوید که آن ها را در یک تاپل یا یک آرایه قرار می دهید. روش درست برای فراخوانی این تابع مانند زیر است:
DISPLAYSURF=pygame.display.set_mode((400,300))
استفاده از کد بالا به صورت pygame.display.set_mode(400, 300) باعث ایجاد خطایی به صورت زیر می شود:
خطای بالا می گوید که آرگومان ارسالی به تابع باید یک تاپل دوتایی یا یک آرایه با دو مقدار صحیح باشد. پس همیشه بیاد داشته باشید که اندازه پنجره را در یک تاپل یا آرایه قرار بدهید و سپس آن را در set_mode استفاده کنید. شی بازگشت داده شده از set_mode در متغیری به نام DISPLAYSURF ذخیره می شود.
در خط زیر با تابع pygame.display.set_caption نام پنجره را تعیین کرده ایم. نام پنجره در بالای آن ظاهر می شود. این تابع یک رشته را به عنوان پارامتر می گیرد. رشته '!Hello World' به این تابع فرستاده داده شده است:
pygame.display.set_caption('Hello World!')
while True: # main game loop for event in pygame.event.get():
خط بالا یک حلقه while است که شرط آن True است. این حلقه هرگز متوقف نمی شود مگر این که شرط آن False شود. تنها راه خروج از حلقه این است که یک break یا ()sys.exit اجرا شود. همه بازی های این سری آموزشی این حلقه while را دارند. به این حلقه حلقه اصلی بازی یا main loop می گوییم. کار آن اجرای بازی تا هنگام بستن شدن پنجره است. درون main loop حلقه ای دیگر قرار دارد که به آن حلقه مدیریت رویداد می گوییم. این حلقه مهم ترین بخش یک برنامه واکنشی مانند بازی ها است.حلقه مدیریت رویداد سه کار را انجام می دهد:
به شکل زیر خوب نگاه کنید تا بهتر متوجه نوشته های بالا شوید:
اگر تا به حال بازی انجام داده اید که به شما امکان ذخیره کردن مرحله های بازی را می دهد و در هر بار بازی کردن مجبور نیستید که از مرحله اول شروع کنید، می توانم بگویم که شما با وضعیت بازی آشنایی مختصری دارید.
وضعیت بازی راهی ساده برای مراجعه به همه متغیرهای موجود در یک بازی است. در بسیاری از بازی ها، وضعیت بازی مقادیر متغیرها را در خود دارد مانند تعداد جان ها، موقعیت بازیکنان و موقعیت دشمنان که معمولا در بالا یا پایین صفحه با شکلی ویژه نشان داده می شوند. هرگاه رویدادی مانند آسیب دیدن بازیکن (که یکی از جان های او را کم می کند)، حرکت کردن دشمن یا ... که مقدار متغیرهای بازی را تغییر می دهد رخ دهد، می گوییم وضعیت بازی تغییر کرده است.
وضعیت بازی در نقطه ای می ماند که شما آن را ذخیره کرده اید. در بیش تر بازی ها، درنگ در بازی یا pause کردن آن وضعیت بازی را تغییر نخواهد داد. از آن جایی که معمولا وضعیت بازی در پاسخ به رویدادها (مانند کلیک ماوس یا فشار دادن صفحه کلید) یا گذشت زمان به روز می شود، حلقه بازی باید در هر ثانیه برای هر رویداد جدیدی که رخ داده است، بررسی هایی را انجام دهد. pygame، این بررسی را با تابع pygame.event.get انجام می دهد. حلقه event (رویداد) کدی دارد که بر اساس رویداد ایجاد شده، وضعیت بازی را به روز می کند. به این کار رسیدگی به رویدادها یا مدیریت رویدادها گفته می شود. پس نام حلقه رویداد از کاری که انجام می دهد می آید.
شی های pygame.event.Event (بررسی رویدادها و مدیریت آن ها)
هربار که کاربر چند کار را با هم انجام می دهد مانند فشار دادن صفحه کلید یا حرکت موس روی پنجره برنامه، یک شی pygame.event.Event توسط کتابخانه pygame ایجاد می شود تا این رویدادها را ثبت کند. (شی Event در ماژول event است و خود ماژول event در ماژول pygame قرار دارد.) با فراخوانی تابع ()pygame.event.get می توانیم بفهمیم که کدام رویدادها رخ داده اند. این تابع آرایه ای از اشیا pygame.event.Event را برمی گرداند.
اعضای این آرایه دو حالت خواهند داشت :(دو جمله زیر را چندبار بخوانید)
حلقه for در آرایه event که توسط تابع pygame.event.get برگردانده شده است، حلقه می زند یعنی یک سری دستور را چندین بار تکرار می کند. در هر تکرار حلقه for، متغیر event رویدادی را در آرایه event مشخص می کند. آرایه event رویدادها را به همان ترتیبی که اتفاق افتاده اند برمی گرداند. (توجه کنید که متغیر event و آرایه event با هم تفاوت دارند.)
اگر کاربر روی موس کلیک کند و سپس یک کلید صفحه کلید را فشار دهد، شی event برای کلیک شدن موس عضو اول در آرایه و برای فشرده شدن صفحه کلید عضو دوم خواهد بود. یعنی:
شی رویداد برای کلیک شدن موس = [0]event
شی رویداد برای فشرده شدن دکمه = [1]event
اگر هیچ رویدادی رخ نداده باشد pygame.event.get یک آرایه خالی را برمی گرداند.
رویداد QUIT و تابع pygame.quit
if event.type==QUIT: pygame.quit() sys.exit()
اشیا event یک ویژگی به نام type دارند که مشخص کننده نوع رویداد است. pygame برای هر یک از این انواع موجود در ماژول pygame.locals یک ثابت دارد. خط کدبالا بررسی می کند که آیا نوع رویداد برابر با مقدار ثابت QUIT است یا نه.اگر یک رویداد quit داشته باشیم، آنگاه توابع pygame.quit و sys.exit فراخوانی می شوند. تابع pygame.quit به نوعی مخالف تابع pygame.init است.این تابع کدی را اجرا می کند که کتابخانه pygame را غیرفعال می کند.
تابع pygame.quit همیشه باید قبل از sys.exit باشد. در این جا هیچ شرطی برای بقیه رویدادها مانند حرکت موس و... نداریم بنابراین اگر روی پنجره کلیک کنید یا یکی از دکمه ها را فشار دهید، هیچ اتفاقی نمی افتد.
pygame.display.update()
تابع update(به روز آوری وضعیت بازی)
خط آخر تابع pygame.display.update را فراخوانی می کند. این تابع شی ای را که توسط pygame.display.set_mode برگردانده می شود، نمایش می دهد (به یاد داشته باشید که ما این شی را در متغیر DISPLAYSURF ذخیره کرده ایم). از آن جایی که شی DISPLAYSURF در بازی تغییر نمی کند، هر بار که تابع pygame.display.update فراخوانی می شود، همان تصویر سیاه دوباره نشان داده می شود. پس از اجرا شدن خط آخر، حلقه while دوباره کار خود را که نمایش پنجره سیاه است تکرار می کند. برای بسته شدن پنجره باید از گوشه پنجره روی دکمه X کلیک کنیم.
در آخر باید بگویم که همه برنامه های نوشته شده با pygame دارای سه بخش کلی و ثابت هستند:
این سه بخش در تصویر زیر نشان داده شده اند:
تا این جا دیدیم که چگونه سه کار اصلی حلقه رویداد که بررسی رویدادها، مدیریت آن ها و به روزرسانی وضعیت بازی بود انجام شد. این همه داستان رسم یک پنجره ساده با pygame بود. در این قسمت با سه بخش اصلی هر برنامه pygame نیز آشنا شدیم. در بخش بعدی در مورد رنگ ها نکاتی را یاد می گیریم و می فهمیم که چگونه رنگ پنجره را تغییر دهیم. سپس یاد می گیریم که چگونه با زدن یک دکمه خاص رنگ پنجره و هم چنین نام آن را تغییر دهیم.
در این قسمت، به پرسشهای تخصصی شما دربارهی محتوای مقاله پاسخ داده نمیشود. سوالات خود را اینجا بپرسید.