بازی دایناسور گوگل (همچنین به عنوان دایناسور کروم نیز شناخته می شود) یک بازی مرورگر است که توسط گوگل توسعه یافته و در مرورگر وب گوگل کروم ساخته شده است. بازیکن یک تیرکس (Trex) پیکسلی را در یک اسکرول جانبی هدایت می کند و باید بکوشد تا تیرکس به موانع برخورد نکند امتیاز بالاتر را به دست دآورد. این بازی توسط اعضای تیم Chrome UX در سال 2014 ساخته شد.
هنگامی که کاربر آفلاین است و سعی می کند یک صفحه وب در Google Chrome را باز کند، مرورگر به کاربر اطلاع می دهد که به اینترنت متصل نیست، و سپس بازی تیرکس را روی صفحه نمایش می دهد. بازی را میتوان با فشار دادن Space راه اندازی کرد. علاوه بر این، با وارد کردن chrome://dino یا chrome://network-error/-106 در Omnibox میتوانید به بازی دسترسی پیدا کنید.
در طول بازی، تیرکس به طور مداوم از چپ به راست در یک منظره بیابانی سیاه و سفید حرکت می کند، و بازیکن باید از روی موانع پیش رو مانند کاکتوس ها و دایناسورهای پرنده بپرد. فشار دادن space، باعث می شود دایناسور «پرش» کند، در حالی که فشار دادن کلید ↓ باعث خم شدن دایناسور می شود. با پیشرفت بازی، سرعت بازی به تدریج افزایش مییابد تا زمانی که کاربر به مانعی برخورد کند و باعث میشود بازی تمام شود.
بازی دایناسور گوگل توسط اعضای تیم Chrome UX در سال 2014 ساخته شد که متشکل از سباستین گابریل، آلن بتس و ادوارد یونگ بود. توسعه دهندگان بازی دایناسور را به این علت طراحی کردند که یک شوخی باشد و متصل نبودن اینترنت به «عصر ماقبل تاریخ» اشاره کند! این بازی در سپتامبر 2014 منتشر شد. در ابتدا، روی دستگاههای قدیمیتر کار نمیکرد، بنابراین کد بهروزرسانی شد و در دسامبر همان سال دوباره منتشر شد.
در این جا قرار است که این بازی را نه بلکه برای مرورگر برای دسکتاپ خود بسازیم. بازی دایناسور گوگل با استفاده از python و pygame نوشته خواهد شد. برای ساخت آن، این مقاله را تا آخر بخوانید. تصویر این بازی در زیر آمده است:
برای ساخت بازی دایناسور گوگل به دانستن python و pygame نیاز داریم. در صورتی که با پایتون آشنایی چندانی ندارید می توانید با خواندن پست ما در خصوص پایتون چیست در ارتباط با این زبان برنامه نویسی کاربردی اطلاعات زیادی کسب کنید. همچنین باید python و pygame را در سیستم خود نصب کرده باشید. به یک ویرایشگر کد هم برای نوشتن و اجرای برنامه نیاز داریم. اگر با pygame آشنایی ندارید می توانید آن را از این نشانی فرابگیرید.
در ادامه با دو فایل objects.py و main.py نیاز داریم. فایل objects.py برای ساخت اشیا برنامه به کار می رود. این بازی به صورت شی گرا نوشته می شود. فایل main.py فایل اصلی برنامه است و برای اجرا شدن برنامه این فایل را باید run یا راه اندازی کنیم.
در این بازی از تصاویر و صداهایی گوناگون استفاده می شود.این تصاویر و صداها باید در پوشه های مخصوص در کنار فایل main.py قرار گیرند، مانند تصویر زیر:
کد کامل این بازی و همچنین فایل های مورد نیاز برای ساخت این بازی در این نشانی قرار دارد.
همان طور که قبلا هم گفتم این فایل برای ساخت اشیا گوناگون برای موجودیت های مختلف در بازی به کار می رود. برای زمین کلاس Ground، برای ابر Cloud، برای دایناسور Dino، برای ستاره Star، برای دایناسور پرنده Ptera و برای کاکتوس کلاس Cactus را داریم. کد کامل در زیر آمده است.
import pygame SCREEN = WIDTH, HEIGHT = (1000, 500) class Ground(): def __init__(self): self.image = pygame.image.load('Assets/ground.png') self.rect = self.image.get_rect() self.width = self.image.get_width() self.x1 = 0 self.x2 = self.width self.y = 250 def update(self, speed): self.x1 -= speed self.x2 -= speed if self.x1 <= -self.width: self.x1 = self.width if self.x2 <= -self.width: self.x2 = self.width def draw(self, win): win.blit(self.image, (self.x1, self.y)) win.blit(self.image, (self.x2, self.y)) class Dino(): def __init__(self, x, y): self.x, self.base = x, y self.run_list = [] self.duck_list = [] for i in range(1, 4): img = pygame.image.load(f'Assets/Dino/{i}.png') img = pygame.transform.scale(img, (52, 58)) self.run_list.append(img) for i in range(4, 6): img = pygame.image.load(f'Assets/Dino/{i}.png') img = pygame.transform.scale(img, (70, 38)) self.duck_list.append(img) self.dead_image = pygame.image.load(f'Assets/Dino/8.png') self.dead_image = pygame.transform.scale(self.dead_image, (52,58)) self.reset() self.vel = 0 self.gravity = 1 self.jumpHeight = 15 self.isJumping = False def reset(self): self.index = 0 self.image = self.run_list[self.index] self.rect = self.image.get_rect() self.rect.x = self.x self.rect.bottom = self.base self.alive = True self.counter = 0 def update(self, jump, duck): if self.alive: if not self.isJumping and jump: self.vel = -self.jumpHeight self.isJumping = True self.vel += self.gravity if self.vel >= self.jumpHeight: self.vel = self.jumpHeight self.rect.y += self.vel if self.rect.bottom > self.base: self.rect.bottom = self.base self.isJumping = False if duck: self.counter += 1 if self.counter >= 6: self.index = (self.index + 1) % len(self.duck_list) self.image = self.duck_list[self.index] self.rect = self.image.get_rect() self.rect.x = self.x self.rect.bottom = self.base self.counter = 0 elif self.isJumping: self.index = 0 self.counter = 0 self.image = self.run_list[self.index] else: self.counter += 1 if self.counter >= 4: self.index = (self.index + 1) % len(self.run_list) self.image = self.run_list[self.index] self.rect = self.image.get_rect() self.rect.x = self.x self.rect.bottom = self.base self.counter = 0 self.mask = pygame.mask.from_surface(self.image) else: self.image = self.dead_image def draw(self, win): win.blit(self.image, self.rect) class Cactus(pygame.sprite.Sprite): def __init__(self, type): super(Cactus, self).__init__() self.image_list = [] for i in range(5): scale = 0.65 img = pygame.image.load(f'Assets/Cactus/{i+1}.png') w, h = img.get_size() img = pygame.transform.scale(img, (int(w*scale), int(h*scale))) self.image_list.append(img) self.image = self.image_list[type-1] self.rect = self.image.get_rect() self.rect.x = WIDTH + 10 self.rect.bottom = 260 def update(self, speed, dino): if dino.alive: self.rect.x -= speed if self.rect.right <= 0: self.kill() self.mask = pygame.mask.from_surface(self.image) def draw(self, win): win.blit(self.image, self.rect) class Ptera(pygame.sprite.Sprite): def __init__(self, x, y): super(Ptera, self).__init__() self.image_list = [] for i in range(2): scale = 0.65 img = pygame.image.load(f'Assets/Ptera/{i+1}.png') w, h = img.get_size() img = pygame.transform.scale(img, (int(w*scale), int(h*scale))) self.image_list.append(img) self.index = 0 self.image = self.image_list[self.index] self.rect = self.image.get_rect(center=(x, y)) self.counter = 0 def update(self, speed, dino): if dino.alive: self.rect.x -= speed if self.rect.right <= 0: self.kill() self.counter += 1 if self.counter >= 6: self.index = (self.index + 1) % len(self.image_list) self.image = self.image_list[self.index] self.counter = 0 self.mask = pygame.mask.from_surface(self.image) def draw(self, win): win.blit(self.image, self.rect) class Cloud(pygame.sprite.Sprite): def __init__(self, x, y): super(Cloud, self).__init__() self.image = pygame.image.load(f'Assets/cloud.png') self.image = pygame.transform.scale(self.image, (60, 18)) self.rect = self.image.get_rect() self.rect.x = x self.rect.y = y def update(self, speed, dino): if dino.alive: self.rect.x -= speed if self.rect.right <= 0: self.kill() def draw(self, win): win.blit(self.image, self.rect) class Star(pygame.sprite.Sprite): def __init__(self, x, y, type): super(Star, self).__init__() image = pygame.image.load(f'Assets/stars.png') self.image_list = [] for i in range(3): img = image.subsurface((0, 20*(i), 18, 18)) self.image_list.append(img) self.image = self.image_list[type-1] self.rect = self.image.get_rect() self.rect.x = x self.rect.y = y def update(self, speed, dino): if dino.alive: self.rect.x -= speed if self.rect.right <= 0: self.kill() def draw(self, win): win.blit(self.image, self.rect)
class Ground(): def __init__(self): self.image = pygame.image.load('Assets/ground.png') self.rect = self.image.get_rect() self.width = self.image.get_width() self.x1 = 0 self.x2 = self.width self.y = 250 def update(self, speed): self.x1 -= speed self.x2 -= speed if self.x1 <= -self.width: self.x1 = self.width if self.x2 <= -self.width: self.x2 = self.width def draw(self, win): win.blit(self.image, (self.x1, self.y)) win.blit(self.image, (self.x2, self.y))
کلاس Ground برای ایجاد زمین به کار می رود. در واقع این کلاس تصویر زمین را وارد بازی می کند و آن را در جای مناسب قرار می د هد.این کلاس مشخص می کند که تصویر زمین یعنی ground.png در چه مختصاتی قرار بگیرد.
این تصویر متحرک است و تمام آن در صفحه قرار نمی گیرد. یعنی طول تصویر از طول صفحه نمایش بیش تر است و تنها بخشی از آن دیده می شود. با حرکت دایناسور تصویر زمین هم تغییر می کند و به عبارت دیگر به روز آوری می شود و این توهم را ایجاد می کند که تصویر حرکت می کند. این کار در متد update در این کلاس اتفاق می افتد. پارامتر این متد سرعت یا speed است. برای رسم تصویر زمین از متد draw استفاده می کنیم.
class Dino(): def __init__(self, x, y): self.x, self.base = x, y self.run_list = [] self.duck_list = [] for i in range(1, 4): img = pygame.image.load(f'Assets/Dino/{i}.png') img = pygame.transform.scale(img, (52, 58)) self.run_list.append(img) for i in range(4, 6): img = pygame.image.load(f'Assets/Dino/{i}.png') img = pygame.transform.scale(img, (70, 38)) self.duck_list.append(img) self.dead_image = pygame.image.load(f'Assets/Dino/8.png') self.dead_image = pygame.transform.scale(self.dead_image, (52,58)) self.reset() self.vel = 0 self.gravity = 1 self.jumpHeight = 15 self.isJumping = False def reset(self): self.index = 0 self.image = self.run_list[self.index] self.rect = self.image.get_rect() self.rect.x = self.x self.rect.bottom = self.base self.alive = True self.counter = 0 def update(self, jump, duck): if self.alive: if not self.isJumping and jump: self.vel = -self.jumpHeight self.isJumping = True self.vel += self.gravity if self.vel >= self.jumpHeight: self.vel = self.jumpHeight self.rect.y += self.vel if self.rect.bottom > self.base: self.rect.bottom = self.base self.isJumping = False if duck: self.counter += 1 if self.counter >= 6: self.index = (self.index + 1) % len(self.duck_list) self.image = self.duck_list[self.index] self.rect = self.image.get_rect() self.rect.x = self.x self.rect.bottom = self.base self.counter = 0 elif self.isJumping: self.index = 0 self.counter = 0 self.image = self.run_list[self.index] else: self.counter += 1 if self.counter >= 4: self.index = (self.index + 1) % len(self.run_list) self.image = self.run_list[self.index] self.rect = self.image.get_rect() self.rect.x = self.x self.rect.bottom = self.base self.counter = 0 self.mask = pygame.mask.from_surface(self.image) else: self.image = self.dead_image def draw(self, win): win.blit(self.image, self.rect)
این کلاس برای نمایش دایناسور به کار می رود. این دایناسور متحرک است و از تصاویر مختلفی برای نمایش آن استفاده می شود. وظیفه این کلاس بارگذاری این عکس ها در برنامه و تعیین موقعیت دایناسور است.
عکس ها از شماره یک تا سه دایناسور در حالت ایستاده و عکس ها با شماره 4 و 5 دایناسور را حالت خمیده نشان می دهند. سرعت، ارتفاع پرش، گرانش زمین و وضعیت پرش دایناسور در این کلاس مشخص می شود.
همچنین اگر دایناسور به مانعی برخورد کند این کلاس تصویر دایناسور مرده که تصویر 8.png است را نمایش می دهد. اگر دایناسور به مانعی برخورد کند بازی باید دوباره به حالت اول برگردد و همه چیز از اول آغاز شود. این کار با متد reset در کلاس Dino انجام می شود.
متد بعدی در این کلاس update است.این متد ابتدا بررسی می کند که دایناسور زنده است یا نه. اگر دایناسور زنده بود حرکت آن چه در حالت ایستاده و چه در حالت خمیده مدیریت می شود. همچنین پرش آن نیز در این جا مدیریت می شود. رسم دایناسور در متد draw انجام می شود.
class Cactus(pygame.sprite.Sprite): def __init__(self, type): super(Cactus, self).__init__() self.image_list = [] for i in range(5): scale = 0.65 img = pygame.image.load(f'Assets/Cactus/{i+1}.png') w, h = img.get_size() img = pygame.transform.scale(img, (int(w*scale), int(h*scale))) self.image_list.append(img) self.image = self.image_list[type-1] self.rect = self.image.get_rect() self.rect.x = WIDTH + 10 self.rect.bottom = 260 def update(self, speed, dino): if dino.alive: self.rect.x -= speed if self.rect.right <= 0: self.kill() self.mask = pygame.mask.from_surface(self.image) def draw(self, win): win.blit(self.image, self.rect)
از این کلاس نیز برای رسم کاکتوس های گوناگون استفاده می شود. حرکت کاکتوس و برخورد آن با دایناسور و نیز رسم آن در این جا صورت می گیرد. اگر کاکتوس از سمت چپ صفحه خارج شود شی مربوط به آن حذف خواهد شد.
class Ptera(pygame.sprite.Sprite): def __init__(self, x, y): super(Ptera, self).__init__() self.image_list = [] for i in range(2): scale = 0.65 img = pygame.image.load(f'Assets/Ptera/{i+1}.png') w, h = img.get_size() img = pygame.transform.scale(img, (int(w*scale), int(h*scale))) self.image_list.append(img) self.index = 0 self.image = self.image_list[self.index] self.rect = self.image.get_rect(center=(x, y)) self.counter = 0 def update(self, speed, dino): if dino.alive: self.rect.x -= speed if self.rect.right <= 0: self.kill() self.counter += 1 if self.counter >= 6: self.index = (self.index + 1) % len(self.image_list) self.image = self.image_list[self.index] self.counter = 0 self.mask = pygame.mask.from_surface(self.image) def draw(self, win): win.blit(self.image, self.rect)
دایناسورهای پرنده در ارتفاع های گوناگون نمایش داده خواهند شد و کاری که دایناسور باید بکند این است که به آن برخورد نکند. این کلاس نیز مانند کلاس های پیشین عکس ها را بارگذاری کرده و در برنامه از آن ها استفاده خواهد کرد. اگر دایناسور پرنده از سمت چپ صفحه خارج شود شی مربوط به آن حذف خواهد شد. با متد draw این دایناسورهای پرنده در صفحه رسم خواهند شد.
class Cloud(pygame.sprite.Sprite): def __init__(self, x, y): super(Cloud, self).__init__() self.image = pygame.image.load(f'Assets/cloud.png') self.image = pygame.transform.scale(self.image, (60, 18)) self.rect = self.image.get_rect() self.rect.x = x self.rect.y = y def update(self, speed, dino): if dino.alive: self.rect.x -= speed if self.rect.right <= 0: self.kill() def draw(self, win): win.blit(self.image, self.rect)
برای رسم ابرها در آسمان به کار می رود و دخالتی در روند بازی ندارد و فقط برای زیبا سازی به کار می رود. اگر ابرها از سمت چپ صفحه خارج شوند شی مربوط به آن ها حذف خواهد شد. با متد draw ابرها در آسمان رسم خواهند شد.
class Star(pygame.sprite.Sprite): def __init__(self, x, y, type): super(Star, self).__init__() image = pygame.image.load(f'Assets/stars.png') self.image_list = [] for i in range(3): img = image.subsurface((0, 20*(i), 18, 18)) self.image_list.append(img) self.image = self.image_list[type-1] self.rect = self.image.get_rect() self.rect.x = x self.rect.y = y def update(self, speed, dino): if dino.alive: self.rect.x -= speed if self.rect.right <= 0: self.kill() def draw(self, win): win.blit(self.image, self.rect)
برای رسم ستاره ها در آسمان به کار می رود و مانند ابرها دخالتی در روند بازی ندارد و فقط برای زیبا سازی به کار می رود. اگر ستاره ها از سمت چپ صفحه خارج شوند شی مربوط به آن ها حذف خواهد شد. با متد draw ابرها در آسمان رسم خواهند شد.
برای ساخت این بازی دایناسور گوگل از pygame استفاده می کنیم. پس باید آن را وارد برنامه کنیم. همچنین از random برای تولید اعداد تصادفی برای اشیای مختلف استفاده می کنیم. این بازی به صورت شی گرا نوشته می شود و برای هر یک از موجودیت های بازی یک کلاس در نظر می گیریم. این کلاس ها را در فایل objects.py ایجاد می کنیم و سپس آن را وارد فایل اصلی خود یعنی main.py می کنیم.
import random import pygame from objects import Ground, Dino, Cactus, Cloud, Ptera, Star
همه متغیرها و ثابت هایی که در طول بازی به آن ها نیاز داریم را تعریف می کنیم.
pygame.init() SCREEN = WIDTH, HEIGHT = (1000, 500) win = pygame.display.set_mode(SCREEN) ICON=pygame.image.load('Assets/start_img.png') pygame.display.set_caption("Dino") pygame.display.set_icon(ICON) clock = pygame.time.Clock() FPS = 60 WHITE = (225,225,225) BLACK = (0, 0, 0) GRAY = (32, 33, 36) start_img = pygame.image.load('Assets/start_img.png') start_img = pygame.transform.scale(start_img, (60, 64)) game_over_img = pygame.image.load('Assets/game_over.png') game_over_img = pygame.transform.scale(game_over_img, (200, 36)) replay_img = pygame.image.load('Assets/replay.png') replay_img = pygame.transform.scale(replay_img, (40, 36)) replay_rect = replay_img.get_rect() replay_rect.x = WIDTH // 2 - 20 replay_rect.y = 150 numbers_img = pygame.image.load('Assets/numbers.png') numbers_img = pygame.transform.scale(numbers_img, (120, 12)) jump_fx = pygame.mixer.Sound('Sounds/jump.wav') die_fx = pygame.mixer.Sound('Sounds/die.wav') checkpoint_fx = pygame.mixer.Sound('Sounds/checkPoint.wav') ground = Ground() dino = Dino(50, 260) cactus_group = pygame.sprite.Group() ptera_group = pygame.sprite.Group() cloud_group = pygame.sprite.Group() stars_group = pygame.sprite.Group() keys = [] GODMODE = False DAYMODE = False LYAGAMI = False counter = 0 enemy_time = 100 cloud_time = 500 stars_time = 175 SPEED = 5 jump = False duck = False score = 0 high_score = 0 start_page = True mouse_pos = (-1, -1) running = True
این متغیرها و ثابت ها شامل رنگ ها، اشیا، بارگذاری تصاویر و صدا و غیره خواهد بود.
def reset(): global counter, SPEED, score, high_score if score and score >= high_score: high_score = score counter = 0 SPEED = 5 score = 0 cactus_group.empty() ptera_group.empty() cloud_group.empty() stars_group.empty() dino.reset()
اگر بازیکن به مانعی برخورد کند بازی باید از اول شروع شود، یعنی یک بازی کاملا جدید داشته باشیم. این کار را با متد reset انجام می دهیم. در این متد امتیازی که به دست آوردیم، اگر از امتیاز قبلی که داشتیم بیش تر بود، امتیاز جدید جایگزین امتیاز قبلی می شود. آرایه ی مربوط به اشیا بازی خالی می شوند و شی dino نیز reset می شود تا یک بازی کاملا جدید داشته باشیم.
while running: jump = False if DAYMODE: win.fill(WHITE) else: win.fill(GRAY) for event in pygame.event.get(): if event.type == pygame.QUIT: running = False if event.type == pygame.KEYDOWN: if event.key == pygame.K_ESCAPE or event.key == pygame.K_q: running = False if event.key == pygame.K_SPACE: if start_page: start_page = False elif dino.alive: jump = True jump_fx.play() else: reset() if event.key == pygame.K_UP: jump = True jump_fx.play() if event.key == pygame.K_DOWN: duck = True key = pygame.key.name(event.key) keys.append(key) keys = keys[-7:] if ''.join(keys).upper() == 'GODMODE': GODMODE = not GODMODE if ''.join(keys).upper() == 'DAYMODE': DAYMODE = not DAYMODE if ''.join(keys).upper() == 'LYAGAMI': LYAGAMI = not LYAGAMI if ''.join(keys).upper() == 'SPEEDUP': SPEED += 2 if ''.join(keys).upper() == 'IAMRICH': score += 10000 if ''.join(keys).upper() == 'HISCORE': high_score = 99999 if event.type == pygame.KEYUP: if event.key == pygame.K_SPACE or event.key == pygame.K_UP: jump = False if event.key == pygame.K_DOWN: duck = False if event.type == pygame.MOUSEBUTTONDOWN: mouse_pos = event.pos if event.type == pygame.MOUSEBUTTONUP: mouse_pos = (-1, -1) if start_page: win.blit(start_img, (50, 200)) else: if dino.alive: counter += 1 if counter % int(enemy_time) == 0: if random.randint(1, 10) == 5: y = random.choice([85, 130]) ptera = Ptera(WIDTH, y) ptera_group.add(ptera) else: type = random.randint(1, 4) cactus = Cactus(type) cactus_group.add(cactus) if counter % cloud_time == 0: y = random.randint(40, 100) cloud = Cloud(WIDTH, y) cloud_group.add(cloud) if counter % stars_time == 0: type = random.randint(1, 3) y = random.randint(40, 100) star = Star(WIDTH, y, type) stars_group.add(star) if counter % 100 == 0: SPEED += 0.1 enemy_time -= 0.5 if counter % 5 == 0: score += 1 if score and score % 100 == 0: checkpoint_fx.play() if not GODMODE: for cactus in cactus_group: if LYAGAMI: dx = cactus.rect.x - dino.rect.x if 0 <= dx <= (70 + (score//100)): jump = True if pygame.sprite.collide_mask(dino, cactus): SPEED = 0 dino.alive = False die_fx.play() for cactus in ptera_group: if LYAGAMI: dx = ptera.rect.x - dino.rect.x if 0 <= dx <= 70: if dino.rect.top <= ptera.rect.top: jump = True else: duck = True else: duck = False if pygame.sprite.collide_mask(dino, ptera): SPEED = 0 dino.alive = False die_fx.play() ground.update(SPEED) ground.draw(win) cloud_group.update(SPEED-3, dino) cloud_group.draw(win) stars_group.update(SPEED-3, dino) stars_group.draw(win) cactus_group.update(SPEED, dino) cactus_group.draw(win) ptera_group.update(SPEED-1, dino) ptera_group.draw(win) dino.update(jump, duck) dino.draw(win) string_score = str(score).zfill(5) for i, num in enumerate(string_score): win.blit(numbers_img, (520+11*i, 10), (10*int(num), 0, 10, 12)) if high_score: win.blit(numbers_img, (425, 10), (100, 0, 20, 12)) string_score = f'{high_score}'.zfill(5) for i, num in enumerate(string_score): win.blit(numbers_img, (455+11*i, 10), (10*int(num), 0, 10, 12)) if not dino.alive: win.blit(game_over_img, (WIDTH//2-100, 80)) win.blit(replay_img, replay_rect) if replay_rect.collidepoint(mouse_pos): reset() pygame.draw.rect(win, WHITE, (0, 0, WIDTH, HEIGHT), 4) clock.tick(FPS) pygame.display.update() pygame.quit()
حلقه بازی (game loop) که حلقه اصلی (main loop) نیز نامیده می شود سه کار را انجام می دهد:
وضعیت بازی راهی ساده برای مراجعه به همه متغیرهای یک بازی است. در بسیاری از بازی ها، وضعیت بازی مقادیر متغیرها را دارد مانند تعداد جان ها، موقعیت بازیکنان و موقعیت دشمنان که در بالا یا پایین صفحه با شکلی ویژه نشان داده می شود. هر گاه رویدادی مانند آسیب دیدن بازیکن (که یکی از جان های او را کم می کند)، حرکت کردن دشمن یا غیره در دنیای بازی اتفاق بیفتد می گوییم که وضعیت بازی تغییر کرده است.
اگر تا به حال بازی ای انجام داده اید که به شما امکان ذخیره کردن وضعیت بازی را می دهد، وضعیت بازی در نقطه ای می ماند که شما آن را ذخیره کرده اید. در بیش تر بازی ها، درنگ در بازی از تغییر وضعیت بازی جلوگیری می کند. از آن جایی که معمولا وضعیت بازی در پاسخ به رویدادها (مانند کلیک موس یا فشار دادن صفحه کلید) یا گذشت زمان به روز می شود، حلقه بازی به طور مداوم در هر ثانیه برای هر رویداد جدیدی که اتفاق افتاده است، بررسی هایی را انجام می دهد. در داخل حلقه اصلی کدی وجود دارد که بررسی می کند کدام رویدادها ایجاد شده اند (با Pygame، این بررسی با فراخوانی تابع pygame.event.get() انجام می شود). حلقه اصلی همچنین کدی دارد که بر اساس رویداد ایجاد شده ، وضعیت بازی را به روز می کند. به این کار معمولا رسیدگی به رویدادها یا مدیریت رویدادها گفته می شود.
اولین کاری که در این حلقه انجام می شود تعیین روز یا شب بودن بازی است. برای بازی در روز DAYMODE باید True باشد در غیر این صورت بازی در شب انجام می شود.
jump = False if DAYMODE: win.fill(WHITE) else: win.fill(GRAY)
در این جا باید رویدادها مدیریت شوند مانند خروج از بازی و فشرده شدن کلیدهای صفحه کلید. برای خروج از بازی رویداد QUIT باید بررسی شود مانند کد زیر:
for event in pygame.event.get(): if event.type == pygame.QUIT: running = False
اگر کلید Escape یا q فشرده شود باید از بازی خارج شویم:
if event.type == pygame.KEYDOWN: if event.key == pygame.K_ESCAPE or event.key == pygame.K_q: running = False
دایناسور با فشردن کلید space یا کلید پیکانی بالا پرش می کند. پس رویداد فشرده شدن کلید هم باید مدیریت شود.
if event.key == pygame.K_SPACE: if start_page: start_page = False elif dino.alive: jump = True jump_fx.play() else: reset()
اگر کلید space یا کلید پیکانی بالا رها شود دایناسور باید پایین بیاید:
if event.key == pygame.K_UP: jump = True jump_fx.play()
اگر کلید پیکانی پایین فشرده شود دایناسور باید خم شود تا به دایناسورهای پرنده برخورد نکند. برای پیاده سازی این قسمت کد زیر را داریم:
if event.key == pygame.K_DOWN: duck = True
در ادامه باید اشیا ایجاد شده از کلاس هایی که در فایل objects.py تعریف کرده ایم را مقداردهی کنیم. جای کاکتوس ها، دایناسورهای پرنده، دایناسور و غیره را این اشیا و مقداری که به آن ها می دهیم مشخص می کند. ابتدا باید بررسی شود دایناسور زنده است یا نه. اگر زنده بود جای تک تک اشیا را تعیین خواهیم کرد.
else: if dino.alive: counter += 1 if counter % int(enemy_time) == 0: if random.randint(1, 10) == 5: y = random.choice([85, 180]) ptera = Ptera(WIDTH, y) ptera_group.add(ptera) else: type = random.randint(1, 4) cactus = Cactus(type) cactus_group.add(cactus) if counter % cloud_time == 0: y = random.randint(40, 100) cloud = Cloud(WIDTH, y) cloud_group.add(cloud) if counter % stars_time == 0: type = random.randint(1, 3) y = random.randint(40, 100) star = Star(WIDTH, y, type) stars_group.add(star) if counter % 100 == 0: SPEED += 0.1 enemy_time -= 0.5 if counter % 5 == 0: score += 1 if score and score % 100 == 0: checkpoint_fx.play() if not GODMODE: for cactus in cactus_group: if LYAGAMI: dx = cactus.rect.x - dino.rect.x if 0 <= dx <= (70 + (score//100)): jump = True if pygame.sprite.collide_mask(dino, cactus): SPEED = 0 dino.alive = False die_fx.play() for cactus in ptera_group: if LYAGAMI: dx = ptera.rect.x - dino.rect.x if 0 <= dx <= 70: if dino.rect.top <= ptera.rect.top: jump = True else: duck = True else: duck = False if pygame.sprite.collide_mask(dino, ptera): SPEED = 0 dino.alive = False die_fx.play()
با استفاده از اشیا ایجاد شده از کلاس هایی که از پیش تعریف کردیم تصاویر را در صفحه نمایش رسم کرده و نشان می دهیم.
ground.update(SPEED) ground.draw(win) cloud_group.update(SPEED-3, dino) cloud_group.draw(win) stars_group.update(SPEED-3, dino) stars_group.draw(win) cactus_group.update(SPEED, dino) cactus_group.draw(win) ptera_group.update(SPEED-1, dino) ptera_group.draw(win) dino.update(jump, duck) dino.draw(win)
با حرکت دایناسور و رد کردن موانع امتیاز باید محاسبه و افزایش یابد. امتیاز باید امتیازهای قبلی که به دست آوردیم مقایسه شود و بزرگترین آن ها در بالای بازی نمایش داده شود.
string_score = str(score).zfill(5) for i, num in enumerate(string_score): win.blit(numbers_img, (520+11*i, 10), (10*int(num), 0, 10, 12)) if high_score: win.blit(numbers_img, (425, 10), (100, 0, 20, 12)) string_score = f'{high_score}'.zfill(5) for i, num in enumerate(string_score): win.blit(numbers_img, (455+11*i, 10), (10*int(num), 0, 10, 12))
اگر دایناسور زنده نبود یعنی با یکی از موانع برخورد کرده بود باید صفحه Game Over نمایش داده شود. این صفحه شامل دکمه reset یا بازنشانی برای راه اندازی دوباره بازی است. اگر این دکمه فشار داده شود بازی باید از اول شروع شود. این دکمه باید با موس کلیک شود. پس رویداد مربوط به کلیک شدن موس را در زیر خواهیم داشت:
if not dino.alive: win.blit(game_over_img, (WIDTH//2-100, 80)) win.blit(replay_img, replay_rect) if replay_rect.collidepoint(mouse_pos): reset()
در آخر نیز باید پنجره بازی را نمایش دهیم و بازی را برای هر گونه تغییر در بازی دایناسور گوگل بررسی و به روز رسانی کنیم.
pygame.draw.rect(win, WHITE, (0, 0, WIDTH, HEIGHT), 4) clock.tick(FPS) pygame.display.update() pygame.quit()
منبع: وب سایت github
در این قسمت، به پرسشهای تخصصی شما دربارهی محتوای مقاله پاسخ داده نمیشود. سوالات خود را اینجا بپرسید.