当前位置:   article > 正文

【Python游戏开发】使用pygame实现谷歌小恐龙_谷歌小恐龙代码pygame

谷歌小恐龙代码pygame

在上一期中我使用了PixiJS开发了网页版的谷歌小恐龙,这一期我使用python也实现一下

介绍

Pygame是一个开放源代码的跨平台Python库,它使得多媒体应用程序(尤其是视频游戏)的开发变得简单易行。Pygame基于Simple DirectMedia Layer(SDL)库和多个流行的库来抽象最常见的功能,使编写程序变得更直观。

Pygame的主要特点和功能包括:

  1. 跨平台:Pygame支持在大部分操作系统上运行,包括Windows、Mac OS和Linux等,并且可以在经过编译后在Android手机和网页上运行。
  2. 适合新手:与一些类似框架相比,Pygame更加适合新手入门游戏开发。
  3. 功能全面:Pygame支持的功能包括图片、文字、绘图、OpenGL 3D、音频、摄像头、游戏手柄等。
  4. 易于使用:Pygame提供了直观的API,使得开发者可以简单地创建游戏窗口、绘制图像、形状和文字,以及添加音效和背景音乐到游戏中。
  5. 游戏开发框架:Pygame游戏开发框架共包含四个部分:引入pygame和sys、初始化pygame游戏引擎并完成游戏窗体设置、在一个无限循环中获取pygame事件并逐类响应、在该无限循环中不断刷新游戏屏幕。

Pygame的原作者是Pete Shinners,其协议为GNU Lesser General Public License。它原本是为了代替突然停止的pySDL和其他一些游戏制作竞赛中的工具而开发的。

要使用Pygame,你需要先将它安装到你的机器上。最简单的安装方法是使用pip:pip install pygamepip install pygame-ce(推荐使用pygame官方的社区编辑版)。

封装动画精灵类

  1. #创建动画精灵父类,继承pygame的Sprite
  2. class AnimatedSprite(pygame.sprite.Sprite):
  3. def __init__(self, animation_frames):
  4. super().__init__()
  5. #传入动画每一帧的列表
  6. self.frames = animation_frames
  7. #当前帧索引
  8. self.frame_index = 0
  9. self.image, self.rect = self.frames[self.frame_index]
  10. self.animation_speed = 0.1 # 动画速度,单位是秒
  11. self.last_update = pygame.time.get_ticks()
  12. def update(self, current_time):
  13. # 检查是否需要更新帧
  14. if current_time - self.last_update > int(self.animation_speed * 1000):
  15. self.frame_index = (self.frame_index + 1) % len(self.frames)
  16. self.image, self.rect = self.frames[self.frame_index]
  17. self.last_update = current_time

该部分编写了动画精灵类,用于实现精灵的动画效果

编写恐龙精灵类

  1. #编写恐龙类,继承我们刚刚编写的动画精灵类
  2. class PinoSprite(AnimatedSprite):
  3. def __init__(self):
  4. self.load_animation_frames()
  5. #调用父类构造方法,将帧列表传入
  6. super().__init__(self.run_animation_frames)
  7. self.is_jump = False
  8. self.speed = 7
  9. #获取动画帧列表
  10. def load_animation_frames(self):
  11. #加载总素材图片
  12. base_frame = pygame.image.load("./googlepino.png").convert_alpha()
  13. self.run_animation_frames = []
  14. for i in range(2):
  15. #切割出每一帧的奔跑动作
  16. frame = base_frame.subsurface(pygame.Rect(935 + (i * 45), 0, 45, 50))
  17. frame_rect = frame.get_rect()
  18. #设置位置
  19. frame_rect.bottom = SCREEN_HEIGHT
  20. frame_rect.x = 50
  21. self.run_animation_frames.append((frame, frame_rect))
  22. self.squat_animation_frames = []
  23. for i in range(2):
  24. #切割出每一帧的蹲下动作
  25. frame = base_frame.subsurface(pygame.Rect(1110 + (i * 60), 20, 60, 30))
  26. frame_rect = frame.get_rect()
  27. #设置位置
  28. frame_rect.bottom = SCREEN_HEIGHT
  29. frame_rect.x = 50
  30. self.squat_animation_frames.append((frame, frame_rect))
  31. #切换蹲下动作
  32. def squat(self):
  33. self.frames = self.squat_animation_frames
  34. #切换奔跑动作
  35. def run(self):
  36. self.frames = self.run_animation_frames
  37. #切换跳跃动作
  38. def jump(self):
  39. self.is_jump = True
  40. self.is_up = True
  41. def update(self, current_time):
  42. super().update(current_time)
  43. if self.is_jump:
  44. #如果跳跃的话,设置每一个动作的位置
  45. for frame in self.frames:
  46. rect = frame[1]
  47. if self.is_up:
  48. #向上的话y坐标减小
  49. rect.bottom -= self.speed
  50. #如果y坐标已经达到跳跃最高处,则向下
  51. if rect.bottom <= SCREEN_HEIGHT - rect.height * 2:
  52. self.is_up = False
  53. else:
  54. #向下的话y坐标增加
  55. rect.bottom += self.speed
  56. #如果y坐标已经到地面了,则跳跃结束
  57. if rect.bottom >= SCREEN_HEIGHT:
  58. self.is_jump = False
  59. #如果已经完成跳跃动作了,则设置每一个动作的位置都到地面
  60. if not self.is_jump:
  61. for frame in self.frames:
  62. rect = frame[1]
  63. rect.bottom = SCREEN_HEIGHT

该部分我们实现了恐龙精灵的编写,完成了恐龙的跳跃,奔跑,蹲下动作

编写飞鸟精灵类

  1. #编写飞鸟类,继承动画精灵类
  2. class FlyBirdSprite(AnimatedSprite):
  3. def __init__(self):
  4. self.load_animation_frames()
  5. super().__init__(self.animation_frames)
  6. #获取飞鸟动画帧列表
  7. def load_animation_frames(self):
  8. self.animation_frames = []
  9. base_frame = pygame.image.load("./googlepino.png").convert_alpha()
  10. #设置x坐标随机位置
  11. x = random.randint(1400, 1500)
  12. #切割出每一个动画动作帧
  13. for i in range(2):
  14. frame = base_frame.subsurface(pygame.Rect(135 + (i * 45), 0, 45, 30))
  15. frame_rect = frame.get_rect()
  16. #设置位置
  17. frame_rect.bottom = SCREEN_HEIGHT - 35
  18. frame_rect.x = x
  19. self.animation_frames.append((frame, frame_rect))
  20. def update(self, current_time):
  21. super().update(current_time)
  22. for frame in self.frames:
  23. rect = frame[1]
  24. #设置每次向左移动10
  25. rect.x -= 10
  26. #如果已经超出了屏幕,则重新设置飞鸟的位置
  27. if rect.x <= 0:
  28. x = random.randint(1400, 1500)
  29. for frame in self.frames:
  30. frame[1].x = x

该部分我们完成了飞鸟类的编写,实现了飞鸟的移动,刷新

封装自己的精灵类

  1. #封装自己的精灵类
  2. class GameSprite(pygame.sprite.Sprite):
  3. def __init__(self, rect):
  4. super().__init__()
  5. base_frame = pygame.image.load("./googlepino.png").convert_alpha()
  6. #设置图片切割的位置
  7. self.image = base_frame.subsurface(rect)
  8. self.rect = self.image.get_rect()
  9. def update(self):
  10. #每次向左移动10
  11. self.rect.x -= 10

该部分我们封装了自己的精灵类,用于继承

编写地面精灵类

  1. #编写仙人掌精灵类,继承我们编写的精灵父类
  2. class GroundSprite(GameSprite):
  3. def __init__(self, is_alt=False):
  4. #调用父类构造方法,切割出仙人掌的图片
  5. super().__init__(pygame.Rect(10, 52, 1200, 15))
  6. #设置位置
  7. self.rect.bottom = SCREEN_HEIGHT
  8. #如果是第二张图片,则放到后面
  9. if is_alt:
  10. self.rect.x = SCREEN_WIDTH
  11. def update(self):
  12. super().update()
  13. #判断是否滚动完一张,滚动完设置到后面,循环滚动
  14. if self.rect.right <= 0:
  15. self.rect.x = SCREEN_WIDTH

该部分完成了地面精灵类的编写,实现地面循环滚动

编写仙人掌精灵类

  1. #编写仙人掌精灵类,继承父类精灵
  2. class CactusSprite(GameSprite):
  3. def __init__(self):
  4. #切割仙人掌图片
  5. super().__init__(pygame.Rect(356, 0, 25, 55))
  6. #位置设置到中间
  7. self.rect.x = SCREEN_WIDTH / 2
  8. self.rect.bottom = SCREEN_HEIGHT
  9. def update(self):
  10. super().update()
  11. #超出屏幕左侧时设置到右侧
  12. if self.rect.x <= 0:
  13. self.rect.x = SCREEN_WIDTH

该部分完成了仙人掌精灵类的编写,实现仙人掌的移动,刷新

编写游戏类

  1. class Game:
  2. #初始化
  3. def __init__(self):
  4. pygame.init()
  5. #设置游戏窗口
  6. self.screen = pygame.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT))
  7. self.clock = pygame.time.Clock()
  8. #设置分数
  9. self.score = 0
  10. #设置游戏状态
  11. self.game_play = False
  12. #设置字体
  13. self.game_font = pygame.font.Font("./中文像素字体.ttf", 25)

该部分我们完成了游戏类的构造方法

  1. #设置字体
  2. def set_text(self, text):
  3. if text != "开始游戏":
  4. #清除掉原来的文字区域内容
  5. pygame.draw.rect(self.screen, (255, 255, 255), self.text_rect)
  6. self.text_info = text
  7. self.text = self.game_font.render(text, True, (0, 0, 0))
  8. self.text_rect = self.text.get_rect()
  9. #设置位置
  10. self.text_rect.center = self.screen.get_rect().center
  11. #显示到屏幕
  12. self.screen.blit(self.text, self.text_rect)

编写了游戏字体的设置

  1. #创建精灵
  2. def create_sprites(self):
  3. self.pino = PinoSprite()
  4. self.pino_group = pygame.sprite.Group(self.pino)
  5. ground1 = GroundSprite()
  6. ground2 = GroundSprite(True)
  7. self.ground_group = pygame.sprite.Group(ground1, ground2)
  8. self.cactus = CactusSprite()
  9. self.cactus_group = pygame.sprite.Group(self.cactus)
  10. self.fly_brid_group = pygame.sprite.Group()

该部分我们编写了精灵的创建方法,创建了恐龙精灵,地面精灵,仙人掌精灵和组,添加到组中

  1. #精灵状态的更新
  2. def update_sprites(self):
  3. #填充为白色
  4. self.screen.fill((255, 255, 255))
  5. current_time = pygame.time.get_ticks()
  6. self.pino_group.update(current_time)
  7. self.pino_group.draw(self.screen)
  8. self.fly_brid_group.update(current_time)
  9. self.fly_brid_group.draw(self.screen)
  10. self.ground_group.update()
  11. self.ground_group.draw(self.screen)
  12. self.cactus_group.update()
  13. self.cactus_group.draw(self.screen)

该部分编写了所有精灵的更新方法

  1. #检测碰撞
  2. def check_bump(self):
  3. #如果恐龙和仙人掌碰撞,则游戏结束
  4. group = pygame.sprite.spritecollide(self.pino, self.cactus_group, False)
  5. if len(group) > 0:
  6. self.game_over()
  7. #如果恐龙和飞鸟碰撞,则游戏结束
  8. group = pygame.sprite.spritecollide(self.pino, self.fly_brid_group, False)
  9. if len(group) > 0:
  10. self.game_over()
  11. def game_over(self):
  12. self.game_play = False
  13. self.set_text("游戏结束,分数为: {},点击重新开始游戏".format(self.score))

该部分我们编写了恐龙的碰撞检测方法,检测恐龙是否与障碍物碰撞了,如果发生碰撞,游戏结束,spritecollide方法是pygame提供的一个检测碰撞的方法,如果发生碰撞了会返回碰撞到的精灵组

  1. #计算分数
  2. def calculate_scroe(self):
  3. #如果仙人掌已经到屏幕左侧,则分数加1
  4. if self.cactus.rect.x <= 10:
  5. self.score += 1
  6. #分数到5时出现飞鸟
  7. if self.score == 5:
  8. self.fly_brid = FlyBirdSprite()
  9. self.fly_brid_group.add(self.fly_brid)
  10. if len(self.fly_brid_group) > 0:
  11. #如果飞鸟已经到屏幕左侧,则分数加1
  12. for frame in self.fly_brid.frames:
  13. rect = frame[1]
  14. if rect.x <= 10:
  15. self.score += 1
  16. break
  17. #设置当前分数信息
  18. self.set_text("当前分数为: {}".format(self.score))

该部分完成了分数的计算

  1. #编写事件判断
  2. def event_handle(self):
  3. #遍历所有事件
  4. for event in pygame.event.get():
  5. #如果是关闭窗口,则直接停止程序
  6. if event.type == pygame.QUIT:
  7. pygame.quit()
  8. exit()
  9. #鼠标点击文字开始游戏
  10. elif event.type == pygame.MOUSEBUTTONDOWN:
  11. if self.text_rect.collidepoint(event.pos):
  12. if self.text_info == "开始游戏":
  13. self.game_play = True
  14. self.set_text("当前分数为: {}".format(self.score))
  15. else:
  16. #游戏重新开始,初始化游戏状态
  17. self.score = 0
  18. self.cactus.rect.x = SCREEN_WIDTH / 2
  19. self.fly_brid_group.empty()
  20. self.game_play = True
  21. self.set_text("当前分数为: {}".format(self.score))
  22. #如果按下了空格,则恐龙跳跃
  23. key_pressed = pygame.key.get_pressed()
  24. if key_pressed[pygame.K_SPACE]:
  25. self.pino.jump()
  26. #如果按下下箭头,则恐龙蹲下
  27. elif key_pressed[pygame.K_DOWN]:
  28. #判断当前状态是否跳跃,跳跃时不能蹲下
  29. if not self.pino.is_jump:
  30. self.pino.squat()
  31. else:
  32. #其他状态恐龙恢复奔跑状态
  33. self.pino.run()

该部分完成了游戏的操作,键盘控制恐龙的状态以及开始游戏和重新开始

  1. if __name__ == "__main__":
  2. #游戏运行
  3. game = Game()
  4. game.start_game()

最后我们可以运行游戏了!

最终效果

游戏完整代码

项目文件

game_sprite.py文件

  1. import random
  2. import pygame
  3. SCREEN_WIDTH = 1200
  4. SCREEN_HEIGHT = 300
  5. class AnimatedSprite(pygame.sprite.Sprite):
  6. def __init__(self, animation_frames):
  7. super().__init__()
  8. self.frames = animation_frames
  9. self.frame_index = 0
  10. self.image, self.rect = self.frames[self.frame_index]
  11. self.animation_speed = 0.1 # 动画速度,单位是秒
  12. self.last_update = pygame.time.get_ticks()
  13. def update(self, current_time):
  14. # 检查是否需要更新帧
  15. if current_time - self.last_update > int(self.animation_speed * 1000):
  16. self.frame_index = (self.frame_index + 1) % len(self.frames)
  17. self.image, self.rect = self.frames[self.frame_index]
  18. self.last_update = current_time
  19. class PinoSprite(AnimatedSprite):
  20. def __init__(self):
  21. self.load_animation_frames()
  22. super().__init__(self.run_animation_frames)
  23. self.is_jump = False
  24. self.speed = 7
  25. def load_animation_frames(self):
  26. base_frame = pygame.image.load("./googlepino.png").convert_alpha()
  27. self.run_animation_frames = []
  28. for i in range(2):
  29. frame = base_frame.subsurface(pygame.Rect(935 + (i * 45), 0, 45, 50))
  30. frame_rect = frame.get_rect()
  31. frame_rect.bottom = SCREEN_HEIGHT
  32. frame_rect.x = 50
  33. self.run_animation_frames.append((frame, frame_rect))
  34. self.squat_animation_frames = []
  35. for i in range(2):
  36. frame = base_frame.subsurface(pygame.Rect(1110 + (i * 60), 20, 60, 30))
  37. frame_rect = frame.get_rect()
  38. frame_rect.bottom = SCREEN_HEIGHT
  39. frame_rect.x = 50
  40. self.squat_animation_frames.append((frame, frame_rect))
  41. def squat(self):
  42. self.frames = self.squat_animation_frames
  43. def run(self):
  44. self.frames = self.run_animation_frames
  45. def jump(self):
  46. self.is_jump = True
  47. self.is_up = True
  48. def update(self, current_time):
  49. super().update(current_time)
  50. if self.is_jump:
  51. for frame in self.frames:
  52. rect = frame[1]
  53. if self.is_up:
  54. rect.bottom -= self.speed
  55. if rect.bottom <= SCREEN_HEIGHT - rect.height * 2:
  56. self.is_up = False
  57. else:
  58. rect.bottom += self.speed
  59. if rect.bottom >= SCREEN_HEIGHT:
  60. self.is_jump = False
  61. if not self.is_jump:
  62. for frame in self.frames:
  63. rect = frame[1]
  64. rect.bottom = SCREEN_HEIGHT
  65. class FlyBirdSprite(AnimatedSprite):
  66. def __init__(self):
  67. self.load_animation_frames()
  68. super().__init__(self.animation_frames)
  69. def load_animation_frames(self):
  70. self.animation_frames = []
  71. base_frame = pygame.image.load("./googlepino.png").convert_alpha()
  72. x = random.randint(1400, 1500)
  73. for i in range(2):
  74. frame = base_frame.subsurface(pygame.Rect(135 + (i * 45), 0, 45, 30))
  75. frame_rect = frame.get_rect()
  76. frame_rect.bottom = SCREEN_HEIGHT - 35
  77. frame_rect.x = x
  78. self.animation_frames.append((frame, frame_rect))
  79. def update(self, current_time):
  80. super().update(current_time)
  81. for frame in self.frames:
  82. rect = frame[1]
  83. rect.x -= 10
  84. if rect.x <= 0:
  85. x = random.randint(1400, 1500)
  86. for frame in self.frames:
  87. frame[1].x = x
  88. class GameSprite(pygame.sprite.Sprite):
  89. def __init__(self, rect):
  90. super().__init__()
  91. base_frame = pygame.image.load("./googlepino.png").convert_alpha()
  92. self.image = base_frame.subsurface(rect)
  93. self.rect = self.image.get_rect()
  94. def update(self):
  95. self.rect.x -= 10
  96. class GroundSprite(GameSprite):
  97. def __init__(self, is_alt=False):
  98. super().__init__(pygame.Rect(10, 52, 1200, 15))
  99. self.rect.bottom = SCREEN_HEIGHT
  100. if is_alt:
  101. self.rect.x = SCREEN_WIDTH
  102. def update(self):
  103. super().update()
  104. if self.rect.right <= 0:
  105. self.rect.x = SCREEN_WIDTH
  106. class CactusSprite(GameSprite):
  107. def __init__(self):
  108. super().__init__(pygame.Rect(356, 0, 25, 55))
  109. self.rect.x = SCREEN_WIDTH / 2
  110. self.rect.bottom = SCREEN_HEIGHT
  111. def update(self):
  112. super().update()
  113. if self.rect.x <= 0:
  114. self.rect.x = SCREEN_WIDTH

game.py文件

  1. import pygame
  2. from game_sprite import *
  3. class Game:
  4. def __init__(self):
  5. pygame.init()
  6. self.screen = pygame.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT))
  7. self.clock = pygame.time.Clock()
  8. self.score = 0
  9. self.game_play = False
  10. self.game_font = pygame.font.Font("./中文像素字体.ttf", 25)
  11. def start_game(self):
  12. self.create_sprites()
  13. self.update_sprites()
  14. self.set_text("开始游戏")
  15. while True:
  16. self.event_handle()
  17. if self.game_play:
  18. self.clock.tick(60)
  19. self.update_sprites()
  20. self.calculate_scroe()
  21. self.check_bump()
  22. pygame.display.update()
  23. def set_text(self, text):
  24. if text != "开始游戏":
  25. pygame.draw.rect(self.screen, (255, 255, 255), self.text_rect)
  26. self.text_info = text
  27. self.text = self.game_font.render(text, True, (0, 0, 0))
  28. self.text_rect = self.text.get_rect()
  29. self.text_rect.center = self.screen.get_rect().center
  30. self.screen.blit(self.text, self.text_rect)
  31. def create_sprites(self):
  32. self.pino = PinoSprite()
  33. self.pino_group = pygame.sprite.Group(self.pino)
  34. ground1 = GroundSprite()
  35. ground2 = GroundSprite(True)
  36. self.ground_group = pygame.sprite.Group(ground1, ground2)
  37. self.cactus = CactusSprite()
  38. self.cactus_group = pygame.sprite.Group(self.cactus)
  39. self.fly_brid_group = pygame.sprite.Group()
  40. def update_sprites(self):
  41. self.screen.fill((255, 255, 255))
  42. current_time = pygame.time.get_ticks()
  43. self.pino_group.update(current_time)
  44. self.pino_group.draw(self.screen)
  45. self.fly_brid_group.update(current_time)
  46. self.fly_brid_group.draw(self.screen)
  47. self.ground_group.update()
  48. self.ground_group.draw(self.screen)
  49. self.cactus_group.update()
  50. self.cactus_group.draw(self.screen)
  51. def check_bump(self):
  52. group = pygame.sprite.spritecollide(self.pino, self.cactus_group, False)
  53. if len(group) > 0:
  54. self.game_over()
  55. group = pygame.sprite.spritecollide(self.pino, self.fly_brid_group, False)
  56. if len(group) > 0:
  57. self.game_over()
  58. def calculate_scroe(self):
  59. if self.cactus.rect.x <= 10:
  60. self.score += 1
  61. if self.score == 5:
  62. self.fly_brid = FlyBirdSprite()
  63. self.fly_brid_group.add(self.fly_brid)
  64. if len(self.fly_brid_group) > 0:
  65. for frame in self.fly_brid.frames:
  66. rect = frame[1]
  67. if rect.x <= 10:
  68. self.score += 1
  69. break
  70. self.set_text("当前分数为: {}".format(self.score))
  71. def game_over(self):
  72. self.game_play = False
  73. self.set_text("游戏结束,分数为: {},点击重新开始游戏".format(self.score))
  74. def event_handle(self):
  75. for event in pygame.event.get():
  76. if event.type == pygame.QUIT:
  77. pygame.quit()
  78. exit()
  79. elif event.type == pygame.MOUSEBUTTONDOWN:
  80. if self.text_rect.collidepoint(event.pos):
  81. if self.text_info == "开始游戏":
  82. self.game_play = True
  83. self.set_text("当前分数为: {}".format(self.score))
  84. else:
  85. self.score = 0
  86. self.cactus.rect.x = SCREEN_WIDTH / 2
  87. self.fly_brid_group.empty()
  88. self.game_play = True
  89. self.set_text("当前分数为: {}".format(self.score))
  90. key_pressed = pygame.key.get_pressed()
  91. if key_pressed[pygame.K_SPACE]:
  92. self.pino.jump()
  93. elif key_pressed[pygame.K_DOWN]:
  94. if not self.pino.is_jump:
  95. self.pino.squat()
  96. else:
  97. self.pino.run()
  98. if __name__ == "__main__":
  99. game = Game()
  100. game.start_game()

游戏素材

声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:【wpsshop博客】
推荐阅读
相关标签
  

闽ICP备14008679号