این بازی یک نمونه از بازی T-Rex Chrome Dino Game یا همان بازی معروف دایناسور گوگل کروم است است. در این بازی، بازیکن باید از روی موانع بپرد و سعی کند به آن ها برخورد نکند. این موانع حلزون ها و پشه ها هستند. بازیکن هر قدر موانع بیشتری را پشت سر بگذارد امتیاز بالاتری هم به دست می آورد. کد بازی را می توانید از نشانی دانلود کنید.تصویر بازی نیز در زیر آمده است.
کد کامل بازی همراه با فایل ها و تصاویر مربوطه را می توانید از نشانی دانلود کنید.
ابتدا پوشه ای به نام runner درست می کنیم و یک فایل به نام main.py در آن می سازیم. سپس سه پوشه دیگر به نام های font ،audio ،graphics ایجاد می کنیم. مانند زیر:
برای ایجاد یک پنجره معمولی تا الان می دانیم که باید چه کنیم. ابتدا کتابخانه pygame و sys را وارد برنامه می کنیم.سپس شی نمایش سطح یا display surface object را می سازیم بعد از این کار، عنوان پنجره را تعیین می کنیم که runner game است و پس از آن شی Clock را می سازیم. سپس حلقه بازی و حلقه رویداد ها را می نویسیم.
import pygame,sys pygame.init() SCREEN=pygame.display.set_mode((800,400)) pygame.display.set_caption("runner game") Clock=pygame.time.Clock() while True: for event in pygame.event.get(): if event.type == pygame.QUIT: pygame.quit() sys.exit() pygame.display.update() Clock.tick(60)
کدهای بالا را وارد فایل main.py می کنیم و سپس برنامه را اجرا می کنیم. با این کار پنجره سیاه رنگی را خواهیم دید. خط آخر یعنی Clock.tick(60) مشخص می کند که دستورات حلقه در هر ثانیه شصت بار تکرار و اجرا می شوند.
اگر به تصویر ابتدایی در این بخش نگاه کنید متوجه خواهید شد که پنج تصویر اصلی داریم. تصویر بازیکن (runner)، تصویر حلزون، تصویر پشه، تصویر آسمان و تصویر زمین. فعلا تصویر زمین و آسمان را نمایش می دهیم. ابتدا باید تصویر آن ها را وارد برنامه کرده و سپس آن ها را در شی تصویر مربوط به خودشان ذخیره کنیم. از این شی تصویر برای نمایش تصویر آن ها استفاده می کنیم. کد بازی تا این جا به شکل زیر در خواهد آمد:
import pygame,sys pygame.init() SCREEN=pygame.display.set_mode((800,400)) pygame.display.set_caption("runner game") Clock=pygame.time.Clock() sky_surface=pygame.image.load("graphics/Sky.png") ground_surface=pygame.image.load("graphics/ground.png") while True: for event in pygame.event.get(): if event.type == pygame.QUIT: pygame.quit() sys.exit() SCREEN.blit(sky_surface,(0,0)) SCREEN.blit(ground_surface,(0,300)) pygame.display.update() Clock.tick(60)
با اجرای بازی تصویر زیر را خواهیم داشت:
سپس تصویر حلزون و بازیکن را وارد می کنیم:
player_surface=pygame.image.load("graphics/Player/player_walk_1.png") snail_surface=pygame.image.load("graphics/snail/snail1.png")
حالا باید تصاویر را در حلقه بازی نمایش دهیم:
SCREEN.blit(snail_surface,(600,250)) SCREEN.blit(player_surface,(400,200))
اگر برنامه را اجرا کنیم تصویر زیر را خواهیم دید:
در آینده جای بازیکن و حلزون را تغییر خواهیم داد. کد کامل بازی تا این جای کار به صورت زیر خواهد بود:
import pygame,sys pygame.init() SCREEN=pygame.display.set_mode((800,400)) pygame.display.set_caption("runner game") Clock=pygame.time.Clock() sky_surface=pygame.image.load("graphics/Sky.png") ground_surface=pygame.image.load("graphics/ground.png") player_surface=pygame.image.load("graphics/Player/player_walk_1.png") snail_surface=pygame.image.load("graphics/snail/snail1.png") while True: for event in pygame.event.get(): if event.type == pygame.QUIT: pygame.quit() sys.exit() SCREEN.blit(sky_surface,(0,0)) SCREEN.blit(ground_surface,(0,300)) SCREEN.blit(snail_surface,(600,250)) SCREEN.blit(player_surface,(400,200)) pygame.display.update() Clock.tick(60)
برای نمایش متن ابتدا باید شی فونت را ساخته سپس با استفاده از این شی متن را نمایش داده و جای آن روی صفحه نمایش را مشخص کنیم. برای نمایش امتیاز و پیام ها به بازیکن، از متن ها استفاده می کنیم. ابتدا شی فونت را ایجاد می کنیم. از این شی برای نمایش متن ها استفاده می کنیم.
game_font=pygame.font.Font('font/Pixeltype.ttf', 50)
این فونت را از پوشه font وارد برنامه می کنیم و اندازه آن را پنجاه پیکسل می دهیم. سپس باید آن را render کرده و رنگ و نوشته آن را تعیین کنیم:
score_surface=game_font.render(f'Score: {0}',False,(64,64,64))
در کد بالا امتیاز را نشان می دهیم. امتیاز فعلا ثابت است و صفر درنظر گرفته می شود. بعدا کاری می کنیم که با پیشروی بازیکن افزایش یابد. پارامتر دوم برای تعیین رنگ متن است. برای نمایش نهایی امتیاز باید کد زیر را اضافه کنیم:
SCREEN.blit(score_surface,(300,50))
محل قرار گیری متن در (300,50) است. با اجرای برنامه تصویر زیر را خواهیم داشت:
کد بازی تا این جای کار به صورت زیر خواهد بود:
import pygame,sys pygame.init() SCREEN=pygame.display.set_mode((800,400)) pygame.display.set_caption("runner game") Clock=pygame.time.Clock() game_font=pygame.font.Font('font/Pixeltype.ttf', 50) sky_surface=pygame.image.load("graphics/Sky.png") ground_surface=pygame.image.load("graphics/ground.png") player_surface=pygame.image.load("graphics/Player/player_walk_1.png") snail_surface=pygame.image.load("graphics/snail/snail1.png") score_surface=game_font.render(f'Score: {0}',False,(64,64,64)) while True: for event in pygame.event.get(): if event.type == pygame.QUIT: pygame.quit() sys.exit() SCREEN.blit(sky_surface,(0,0)) SCREEN.blit(ground_surface,(0,300)) SCREEN.blit(snail_surface,(600,250)) SCREEN.blit(player_surface,(400,200)) SCREEN.blit(score_surface,(300,50)) pygame.display.update() Clock.tick(60)
برای پویانمایی تصاویر از حلزون آغاز می کنیم. برای حرکت دادن حلزون به سمت چپ متغیر snail_x_position را تعریف می کنیم و سپس آن را با مقدار 600 مقداردهی می کنیم. برای نمایش تصویر حلزون از SCREEN.blit استفاده کرده ایم.
snail_x_position=600
باید شی تصویر (display surface object) حلزون را تغییر کوچکی بدهیم. مانند زیر:
snail_surface=pygame.image.load("graphics/snail/snail1.png").convert_alpha()
در بالا به شی snail_surface کد convert_alpha را افزوده ایم.کار convert_alpha تغییر فرمت پیکسلی یک تصویر به ازای هر پیکسل آن است. convert_alpha تضمین می کند هنگام نمایش تصاویر تبدیل یافته در صفحه نمایش، عملکرد pygame را از دست نخواهیم داد. convert_alpha هر کانال آلفا را نگه می دارد.برای تغییر مکان حلزون باید موقعیت یا مولفه x آن را تغییر بدهیم. کد زیر را در حلقه بازی وارد می کنیم تا در هر تکرار حلقه حلزون چهار پیکسل به سمت چپ حرکت کند:
snail_x_position -= 4 SCREEN.blit(snail_surface,(snail_x_position,250))
اگر بازی را اجرا کنیم می بینیم که حلزون به سمت چپ حرکت می کند و از صفحه خارج می شود. ما دوست داریم وقتی که حلزون از صفحه خارج می شود دوباره از سمت راست صفحه وارد برنامه شود. برای انجام این کار کدهای زیر را به برنامه می افزاییم:
snail_x_position -= 4 if snail_x_position < -100: snail_x_position=800 SCREEN.blit(snail_surface,(snail_x_position,250))
در شرط if بالا بررسی می شود اگر موقعیت x حلزون کمتر از 100- شود یعنی حلزون از سمت چپ صفحه خارج شده است و باید موقعیت x حلزون 800 شود. اگر بازی را اجرا کنیم می بینیم هنگامی که حلزون از سمت چپ خارج می شود دوباره از سمت راست وارد صفحه می گردد.
کد بازی تا این لحظه به صورت زیر است:
import pygame,sys pygame.init() SCREEN=pygame.display.set_mode((800,400)) pygame.display.set_caption("runner game") Clock=pygame.time.Clock() game_font=pygame.font.Font('font/Pixeltype.ttf', 50) sky_surface=pygame.image.load("graphics/Sky.png") ground_surface=pygame.image.load("graphics/ground.png") player_surface=pygame.image.load("graphics/Player/player_walk_1.png") snail_surface=pygame.image.load("graphics/snail/snail1.png") snail_x_position=600 score_surface=game_font.render(f'Score: {0}',False,(64,64,64)) while True: for event in pygame.event.get(): if event.type == pygame.QUIT: pygame.quit() sys.exit() SCREEN.blit(sky_surface,(0,0)) SCREEN.blit(ground_surface,(0,300)) snail_x_position -= 4 if snail_x_position < -100: snail_x_position=800 SCREEN.blit(snail_surface,(snail_x_position,250)) SCREEN.blit(player_surface,(400,200)) SCREEN.blit(score_surface,(300,50)) pygame.display.update() Clock.tick(60)
دلیل استفاده از اشیا rect یا مستطیل دو چیز است:
و برای هر تصویر دو چیز داریم:
برای شروع کار برای تصویر بازیکن شی rect را می سازیم:
player_surface=pygame.image.load("graphics/Player/player_walk_1.png") player_rect=player_surface.get_rect(midbottom=(80,300))
متد get_rect در بالا یک شی Rect را از تصویر برمی گرداند. در این مرحله موقعیت تصویر را تنظیم می کنیم که در تاپل (80,300) قرار می گیرد.سپس از شی rect بازیکن استفاده می کنیم و آن را جایگزین تاپل (400,200) در SCREEN.blit می کنیم مانند زیر:
SCREEN.blit(player_surface,player_rect)
اگر بازی را اجرا کنیم پاهای بازیکن روی زمین قرار می گیرد مانند زیر:
کد بازی تا این لحظه به صورت زیر خواهد بود:
import pygame,sys pygame.init() SCREEN=pygame.display.set_mode((800,400)) pygame.display.set_caption("runner game") Clock=pygame.time.Clock() game_font=pygame.font.Font('font/Pixeltype.ttf', 50) sky_surface=pygame.image.load("graphics/Sky.png") ground_surface=pygame.image.load("graphics/ground.png") player_surface=pygame.image.load("graphics/Player/player_walk_1.png") player_rect=player_surface.get_rect(midbottom=(80,300)) snail_surface=pygame.image.load("graphics/snail/snail1.png").convert_alpha() snail_x_position=600 score_surface=game_font.render(f'Score: {0}',False,(64,64,64)) while True: for event in pygame.event.get(): if event.type == pygame.QUIT: pygame.quit() sys.exit() SCREEN.blit(sky_surface,(0,0)) SCREEN.blit(ground_surface,(0,300)) snail_x_position -= 4 if snail_x_position < -100: snail_x_position=800 SCREEN.blit(snail_surface,(snail_x_position,250)) SCREEN.blit(player_surface,player_rect) SCREEN.blit(score_surface,(300,50)) pygame.display.update() Clock.tick(60)
در گام بعدی شی rect را برای حلزون ایجاد می کنیم .همه کارهای را که برای player انجام دادیم برای حلزون نیز انجام می دهیم:
snail_surface=pygame.image.load("graphics/snail/snail1.png").convert_alpha() snail_rect=snail_surface.get_rect(bottomright=(600,300))
سپس باید snail_rect را جایگزین تاپل موجود در SCREEN.blit کنیم:
SCREEN.blit(snail_surface,snail_rect)
اگر بازی را اجرا کنیم تصویر زیر را می بینیم:
حلزون و بازیکن هر دو روی زمین قرار دارند. برای حرکت حلزون کد پیشین را به صورت زیر را صلاح می کنیم و از شی rect حلزون برای این کار استفاده می کنیم:
snail_rect.x -= 4 if snail_rect.right <= 0: snail_rect.right=800
کد بازی تا این لحظه به صورت زیر خواهد بود:
import pygame,sys pygame.init() SCREEN=pygame.display.set_mode((800,400)) pygame.display.set_caption("runner game") Clock=pygame.time.Clock() game_font=pygame.font.Font('font/Pixeltype.ttf', 50) sky_surface=pygame.image.load("graphics/Sky.png") ground_surface=pygame.image.load("graphics/ground.png") player_surface=pygame.image.load("graphics/Player/player_walk_1.png") player_rect=player_surface.get_rect(midbottom=(80,300)) snail_surface=pygame.image.load("graphics/snail/snail1.png").convert_alpha() snail_rect=snail_surface.get_rect(bottomright=(600,300)) # snail_x_position=600 score_surface=game_font.render(f'Score: {0}',False,(64,64,64)) while True: for event in pygame.event.get(): if event.type == pygame.QUIT: pygame.quit() sys.exit() SCREEN.blit(sky_surface,(0,0)) SCREEN.blit(ground_surface,(0,300)) snail_rect.x -= 4 if snail_rect.right <= 0: snail_rect.right=800 SCREEN.blit(snail_surface,snail_rect) SCREEN.blit(player_surface,player_rect) SCREEN.blit(score_surface,(300,50)) pygame.display.update() Clock.tick(60)
برای امتیاز نیز شی rect را می سازیم تا نمایش بهتری از آن ارائه دهیم:
score_rect=score_surface.get_rect(center=(400,50))
سپس از شی rect امتیاز یعنی score_rect در SCREEN.blit استفاده می کنیم:
SCREEN.blit(score_surface,score_rect)
می خواهیم همه ورودی های کاربر مانند فشرده شدن یک کلید ویژه در صفحه کلید را دریافت کنیم و برای برخی از آن ها کارهای ویژه ای را انجام بدهیم. اول باید بررسی کنیم اصلا دکمه ای فشار داده شده است یا نه و اگر دکمه ای فشار داده شده باشد کدام دکمه بوده است. بازیکن با فشار دادن دکمه SPACE است که پرش را انجام می دهد. پس برای این که بفهمیم پرش داشته ایم یا نه باید مانند زیر عمل کنیم:
if event.type == pygame.KEYDOWN: if event.key == pygame.K_ESCAPE: print("jump")
اگر space فشار داده شود فعلا jump را چاپ می کنیم.پسان تر کد پرش را کامل می کنیم.
در دنیای واقعی هنگامی که سقوط می کنیم با گذشت هر لحظه سرعت سقوط بیش تر می شود و در واقع با یک سرعت ثابت سقوط نمی کنیم یعنی حرکت شتاب دار(شتاب ثابت g=9.8) است. بازیکن وقتی که به بالا می پرد باید به صورت واقع گرایانه پایین بیاید. برای پیاده سازی این واقعیت فیزیکی از متغیر player_gravity استفاده می کنیم:
player_gravity=0
برای پیاده سازی نیروی گرانش زمین و افزایش سرعت سقوط باید کاری کنیم که متغیر player_gravity در هر تکرار حلقه یک واحد افزایش یابد.
# player player_gravity += 1 player_rect.y += player_gravity SCREEN.blit(player_surface,player_rect)
اگر بازی را اجرا کنیم و space را فشار دهیم بازیکن پرش می کند. ولی اگر space را رها کنیم بازیکن از پایین صفحه خارج می شود.برای رفع این مشکل کد زیر را داریم:
# player player_gravity += 1 player_rect.y += player_gravity if player_rect.bottom >= 300: player_rect.bottom=300 SCREEN.blit(player_surface,player_rect)
حالا اگر بازی را اجرا کنیم و space را فشار دهیم پاهای بازیکن روی صفحه می ماند و دیگر از پایین صفحه سقوط نمی کند. اگر بازی را دوباره اجرا کنیم و space را پشت سر هم فشار دهیم این بار بازیکن از بالای صفحه خارج می شود.می خواهیم بازیکن تنها در صورتی پرش داشته باشد که پاهایش زمین را لمس کرده باشند و سرش از صفحه نیز خارج نشود. برای حل این مشکل داریم:
if event.type == pygame.KEYDOWN: if event.key == pygame.K_SPACE and player_rect.bottom >= 300: player_gravity = -20
کد بازی تا این لحظه به صورت زیر خواهد بود:
import pygame,sys from pygame.constants import K_ESCAPE, KEYDOWN pygame.init() SCREEN=pygame.display.set_mode((800,400)) pygame.display.set_caption("runner game") Clock=pygame.time.Clock() game_font=pygame.font.Font('font/Pixeltype.ttf', 50) sky_surface=pygame.image.load("graphics/Sky.png") ground_surface=pygame.image.load("graphics/ground.png") player_surface=pygame.image.load("graphics/Player/player_walk_1.png") player_rect=player_surface.get_rect(midbottom=(80,300)) snail_surface=pygame.image.load("graphics/snail/snail1.png").convert_alpha() snail_rect=snail_surface.get_rect(bottomright=(600,300)) # snail_x_position=600 score_surface=game_font.render(f'Score: {0}',False,(64,64,64)) score_rect=score_surface.get_rect(center=(400,50)) player_gravity=0 while True: for event in pygame.event.get(): if event.type == pygame.QUIT: pygame.quit() sys.exit() if event.type == pygame.KEYDOWN: if event.key == pygame.K_SPACE and player_rect.bottom >= 300: player_gravity = -20 SCREEN.blit(sky_surface,(0,0)) SCREEN.blit(ground_surface,(0,300)) snail_rect.x -= 4 if snail_rect.right <= 0: snail_rect.right=800 SCREEN.blit(snail_surface,snail_rect) # player player_gravity += 1 player_rect.y += player_gravity if player_rect.bottom >= 300: player_rect.bottom=300 SCREEN.blit(player_surface,player_rect) SCREEN.blit(score_surface,score_rect) pygame.display.update() Clock.tick(60)
اگر بازیکن و حلزون برخود داشته باشند بازی باید پایان یابد. پس تشخیص برخورد آن ها الزامی است. برای تشخیص برخورد دو شی rect باید از متد colliderect استفاده کنیم. این متد برخورد دو شی rect را بررسی می کند.
if player_rect.colliderect(snail_rect): pygame.quit() sys.exit()
در این بازی برای توقف بازی دو state (حالت) در نظر می گیریم:
game_active=True
سپس باید قسمت نمایش صفحه بازی را مشروط به درست بودن متغیر game_active کنیم. به عبارت دیگر کاربر تنها در صورتی باید بتواند بازی کند که game_active فعال یا True باشد.پس داریم:
if game_active: SCREEN.blit(sky_surface,(0,0)) SCREEN.blit(ground_surface,(0,300)) snail_rect.x -= 4 if snail_rect.right <= 0: snail_rect.right=800 SCREEN.blit(snail_surface,snail_rect) # player player_gravity += 1 player_rect.y += player_gravity if player_rect.bottom >= 300: player_rect.bottom=300 SCREEN.blit(player_surface,player_rect) SCREEN.blit(score_surface,score_rect) if player_rect.colliderect(snail_rect): pygame.quit() sys.exit()
کد بالا را تغییری جزئی می دهیم. به جای این که در هنگام برخورد بازیکن و حلزون از کل بازی خارج شویم دوست داریم یک صفحه رنگی نمایش بدهیم و سپس بازی را متوقف کنیم (یعنی از حالت دوم توقف بازی استفاده کنیم):
if player_rect.colliderect(snail_rect): game_active=False else: SCREEN.fill("Yellow")
اگر بازی را اجرا کنیم و پس از بازی کردن، بازیکن و حلزون با هم برخورد داشته باشند صفحه زرد رنگ زیر را خواهیم داشت:
پس از توقف بازی دوست داریم اگر دکمه space فشار داده شود، بازی از نو آغاز شود.پس داریم:
if game_active: if event.type == pygame.KEYDOWN: if event.key == pygame.K_SPACE and player_rect.bottom >= 300: player_gravity = -20 else: if event.type == pygame.KEYDOWN and event.key == pygame.K_SPACE: game_active = True
امتیاز بازیکن باید از آغاز بازی محاسبه شود. برای این کار ابتدا متغیر start_time را تعریف می کنیم:
start_time=0
برای نمایش امتیاز از تابع display_score استفاده می کنیم.این تابع به صورت زیر است:
def display_score(): current_time=int(pygame.time.get_ticks()/1000) - start_time score_surface=game_font.render(f'Score : {current_time}',False,(64,64,64)) score_rect=score_surface.get_rect(center=(400,50)) SCREEN.blit(score_surface,score_rect)
در خط اول متغیر current_time را برای محاسبه زمان فعلی تعریف می کنیم. در این تابع برای نمایش امتیاز از شی فونت برای ایجاد متن امتیاز استفاده می کنیم. سپس شی rect را برای آن ایجاد کرده و آن را نمایش می دهیم. پس از ایجاد تابع باید آن را فراخوانی کنیم. امتیاز در صورتی نشان داده می شود که بازی فعال باشد (یعنی game_active دارای مقدار True باشد) پس باید تابع display_score را در صورت فعال بودن بازی فراخوانی کنیم:
if game_active: SCREEN.blit(sky_surface,(0,0)) SCREEN.blit(ground_surface,(0,300)) display_score()
پیش از اجرای بازی متغیر start_time را دوباره مقداردهی می کنیم:
if event.type == pygame.KEYDOWN and event.key == pygame.K_SPACE: game_active = True snail_rect.left=800 start_time=int(pygame.time.get_ticks()/1000)
و خط های زیر را comment می کنیم:
# score_surface=game_font.render(f'',False,(64,64,64)) # score_rect=score_surface.get_rect(center=(400,50))
الان نوبت اجرای بازی است.اگر بازی را اجرا کنیم امتیاز در بالای آن نمایش داده می شود که با گذشت زمان افزایش می یابد:
کد بازی تا این لحظه به صورت زیر خواهد بود:
import pygame,sys def display_score(): current_time=int(pygame.time.get_ticks()/1000) - start_time score_surface=game_font.render(f'Score : {current_time}',False,(64,64,64)) score_rect=score_surface.get_rect(center=(400,50)) SCREEN.blit(score_surface,score_rect) pygame.init() SCREEN=pygame.display.set_mode((800,400)) pygame.display.set_caption("runner game") Clock=pygame.time.Clock() game_font=pygame.font.Font('font/Pixeltype.ttf', 50) sky_surface=pygame.image.load("graphics/Sky.png") ground_surface=pygame.image.load("graphics/ground.png") player_surface=pygame.image.load("graphics/Player/player_walk_1.png") player_rect=player_surface.get_rect(midbottom=(80,300)) snail_surface=pygame.image.load("graphics/snail/snail1.png").convert_alpha() snail_rect=snail_surface.get_rect(bottomright=(600,300)) # snail_x_position=600 # score_surface=game_font.render(f'',False,(64,64,64)) # score_rect=score_surface.get_rect(center=(400,50)) player_gravity=0 game_active=True start_time=0 while True: for event in pygame.event.get(): if event.type == pygame.QUIT: pygame.quit() sys.exit() if game_active: if event.type == pygame.KEYDOWN: if event.key == pygame.K_SPACE and player_rect.bottom >= 300: player_gravity = -20 else: if event.type == pygame.KEYDOWN and event.key == pygame.K_SPACE: game_active = True snail_rect.left=800 start_time=int(pygame.time.get_ticks()/1000) if game_active: SCREEN.blit(sky_surface,(0,0)) SCREEN.blit(ground_surface,(0,300)) display_score() snail_rect.x -= 4 if snail_rect.right <= 0: snail_rect.right=800 SCREEN.blit(snail_surface,snail_rect) # player player_gravity += 1 player_rect.y += player_gravity if player_rect.bottom >= 300: player_rect.bottom=300 SCREEN.blit(player_surface,player_rect) # SCREEN.blit(score_surface,score_rect) if player_rect.colliderect(snail_rect): game_active=False else: SCREEN.fill("Yellow") pygame.display.update() Clock.tick(60)
در این قسمت، به پرسشهای تخصصی شما دربارهی محتوای مقاله پاسخ داده نمیشود. سوالات خود را اینجا بپرسید.