当前位置:   article > 正文

【Pygame小游戏】超好玩的——Python版“愤怒的小鸟”,我能玩上一整天(附源码)_用python做一个愤怒的小鸟

用python做一个愤怒的小鸟

导语

哈喽!大家好!今天给大家更新一款经典小游戏吖!

十几年过去了,这款游戏渐渐被人遗忘。这是多少人的童年呢?

过气游戏?小鸟不angry,你还真以为我是“hello bird”?

图片

现在的冷天气,除了穿多点儿衣服,可能就要靠这只火爆的小鸟给大家升温了!

图片
正文

首先环境安装部分:

准备—Python3.6、Pycharm2021、最主要的游戏模块Pygame、以及一些自带的模块直接可用的。

游戏源码可版本不一致也能运行,相应的模块安装好就可,自行安排!

pip install -i https://pypi.douban.com/simple/  pygame

准备—相应的素材图片、音乐背景等:

定义精灵类这里定义的是对手的猪猪。

  1. class Pig(pygame.sprite.Sprite):
  2. def __init__(self, screen, imagepaths, loc_info, velocity=None, **kwargs):
  3. pygame.sprite.Sprite.__init__(self)
  4. assert len(loc_info) == 3
  5. assert len(imagepaths) == 3
  6. # 设置必要的属性常量
  7. self.screen = screen
  8. self.loc_info = list(loc_info)
  9. self.imagepaths = imagepaths
  10. self.velocity = VelocityVector() if velocity is None else velocity
  11. self.type = 'pig'
  12. self.is_dead = False
  13. self.elasticity = 0.8
  14. self.switch_freq = 20
  15. self.animate_count = 0
  16. self.inverse_friction = 0.99
  17. self.gravity = VelocityVector(0.2, math.pi)
  18. # 屏幕大小
  19. self.screen_size = screen.get_rect().size
  20. self.screen_size = (self.screen_size[0], self.screen_size[1] - 50)
  21. # 导入图像
  22. self.pig_images = []
  23. for imagepath in imagepaths: self.pig_images.append(pygame.image.load(imagepath))
  24. # 设置当前图像
  25. self.image = random.choice(self.pig_images[:2])
  26. '''画到屏幕上'''
  27. def draw(self):
  28. self.animate_count += 1
  29. if (self.animate_count % self.switch_freq == 0) and (not self.is_dead):
  30. self.animate_count = 0
  31. self.image = random.choice(self.pig_images[:2])
  32. position = self.loc_info[0] - self.loc_info[2], self.loc_info[1] - self.loc_info[2]
  33. self.screen.blit(self.image, position)
  34. '''移动猪'''
  35. def move(self):
  36. # 根据重力改变猪的速度向量
  37. self.velocity = VectorAddition(self.velocity, self.gravity)
  38. self.loc_info[0] += self.velocity.magnitude * math.sin(self.velocity.angle)
  39. self.loc_info[1] -= self.velocity.magnitude * math.cos(self.velocity.angle)
  40. self.velocity.magnitude *= self.inverse_friction
  41. # 宽度超出屏幕
  42. if self.loc_info[0] > self.screen_size[0] - self.loc_info[2]:
  43. self.loc_info[0] = 2 * (self.screen_size[0] - self.loc_info[2]) - self.loc_info[0]
  44. self.velocity.angle *= -1
  45. self.velocity.magnitude *= self.elasticity
  46. elif self.loc_info[0] < self.loc_info[2]:
  47. self.loc_info[0] = 2 * self.loc_info[2] - self.loc_info[0]
  48. self.velocity.angle *= -1
  49. self.velocity.magnitude *= self.elasticity
  50. # 高度超出屏幕
  51. if self.loc_info[1] > self.screen_size[1] - self.loc_info[2]:
  52. self.loc_info[1] = 2 * (self.screen_size[1] - self.loc_info[2]) - self.loc_info[1]
  53. self.velocity.angle = math.pi - self.velocity.angle
  54. self.velocity.magnitude *= self.elasticity
  55. elif self.loc_info[1] < self.loc_info[2]:
  56. self.loc_info[1] = 2 * self.loc_info[2] - self.loc_info[1]
  57. self.velocity.angle = math.pi - self.velocity.angle
  58. self.velocity.magnitude *= self.elasticity
  59. '''猪死掉了'''
  60. def setdead(self):
  61. self.is_dead = True
  62. self.image = self.pig_images[-1]

​然后这里定义的精灵类是小鸟即玩家:

  1. class Bird(pygame.sprite.Sprite):
  2. def __init__(self, screen, imagepaths, loc_info, velocity=None, color=(255, 255, 255), **kwargs):
  3. pygame.sprite.Sprite.__init__(self)
  4. assert len(loc_info) == 3
  5. assert len(imagepaths) == 1
  6. # 设置必要的属性常量
  7. self.color = color
  8. self.screen = screen
  9. self.loc_info = list(loc_info)
  10. self.imagepaths = imagepaths
  11. self.velocity = VelocityVector() if velocity is None else velocity
  12. self.type = 'bird'
  13. self.fly_path = []
  14. self.is_dead = False
  15. self.elasticity = 0.8
  16. self.is_loaded = False
  17. self.is_selected = False
  18. self.inverse_friction = 0.99
  19. self.gravity = VelocityVector(0.2, math.pi)
  20. # 屏幕大小
  21. self.screen_size = screen.get_rect().size
  22. self.screen_size = (self.screen_size[0], self.screen_size[1] - 50)
  23. # 导入图像
  24. self.image = pygame.image.load(imagepaths[0])
  25. '''画到屏幕上'''
  26. def draw(self):
  27. if not self.is_loaded:
  28. for point in self.fly_path:
  29. pygame.draw.ellipse(self.screen, self.color, (point[0], point[1], 3, 3), 1)
  30. position = self.loc_info[0] - self.loc_info[2], self.loc_info[1] - self.loc_info[2]
  31. self.screen.blit(self.image, position)
  32. '''判断有没有被鼠标选中'''
  33. def selected(self):
  34. pos = pygame.mouse.get_pos()
  35. dx, dy = pos[0] - self.loc_info[0], pos[1] - self.loc_info[1]
  36. dist = math.hypot(dy, dx)
  37. if dist < self.loc_info[2]:
  38. return True
  39. return False
  40. '''加载到弹弓上'''
  41. def load(self, slingshot):
  42. self.loc_info[0], self.loc_info[1] = slingshot.x, slingshot.y
  43. self.is_loaded = True
  44. '''重新设置位置'''
  45. def reposition(self, slingshot):
  46. pos = pygame.mouse.get_pos()
  47. if self.selected:
  48. self.loc_info[0], self.loc_info[1] = pos[0], pos[1]
  49. dx, dy = slingshot.x - self.loc_info[0], slingshot.y - self.loc_info[1]
  50. self.velocity.magnitude = min(int(math.hypot(dx, dy) / 2), 80)
  51. self.velocity.angle = math.pi / 2 + math.atan2(dy, dx)
  52. '''显示发射小鸟的路径'''
  53. def projectpath(self):
  54. if self.is_loaded:
  55. path = []
  56. bird = Bird(self.screen, self.imagepaths, self.loc_info, velocity=self.velocity)
  57. for i in range(30):
  58. bird.move()
  59. if i % 5 == 0: path.append((bird.loc_info[0], bird.loc_info[1]))
  60. for point in path:
  61. pygame.draw.ellipse(self.screen, self.color, (point[0], point[1], 2, 2))
  62. '''移动小鸟'''
  63. def move(self):
  64. # 根据重力改变小鸟的速度向量
  65. self.velocity = VectorAddition(self.velocity, self.gravity)
  66. self.loc_info[0] += self.velocity.magnitude * math.sin(self.velocity.angle)
  67. self.loc_info[1] -= self.velocity.magnitude * math.cos(self.velocity.angle)
  68. self.velocity.magnitude *= self.inverse_friction
  69. # 宽度超出屏幕
  70. if self.loc_info[0] > self.screen_size[0] - self.loc_info[2]:
  71. self.loc_info[0] = 2 * (self.screen_size[0] - self.loc_info[2]) - self.loc_info[0]
  72. self.velocity.angle *= -1
  73. self.velocity.magnitude *= self.elasticity
  74. elif self.loc_info[0] < self.loc_info[2]:
  75. self.loc_info[0] = 2 * self.loc_info[2] - self.loc_info[0]
  76. self.velocity.angle *= -1
  77. self.velocity.magnitude *= self.elasticity
  78. # 高度超出屏幕
  79. if self.loc_info[1] > self.screen_size[1] - self.loc_info[2]:
  80. self.loc_info[1] = 2 * (self.screen_size[1] - self.loc_info[2]) - self.loc_info[1]
  81. self.velocity.angle = math.pi - self.velocity.angle
  82. self.velocity.magnitude *= self.elasticity
  83. elif self.loc_info[1] < self.loc_info[2]:
  84. self.loc_info[1] = 2 * self.loc_info[2] - self.loc_info[1]
  85. self.velocity.angle = math.pi - self.velocity.angle
  86. self.velocity.magnitude *= self.elasticity

定义地图里面的木桩:

  1. class Block(pygame.sprite.Sprite):
  2. def __init__(self, screen, imagepaths, loc_info, velocity=None, **kwargs):
  3. pygame.sprite.Sprite.__init__(self)
  4. assert len(loc_info) == 3
  5. assert len(imagepaths) == 2
  6. # 设置必要的属性常量
  7. self.type = 'block'
  8. self.screen = screen
  9. self.loc_info = list(loc_info)
  10. self.imagepaths = imagepaths
  11. self.velocity = VelocityVector() if velocity is None else velocity
  12. self.elasticity = 0.7
  13. self.is_destroyed = False
  14. self.inverse_friction = 0.99
  15. self.gravity = VelocityVector(0.2, math.pi)
  16. # 导入图像
  17. self.block_images = []
  18. for imagepath in imagepaths: self.block_images.append(pygame.transform.scale(pygame.image.load(imagepath), (100, 100)))
  19. # 屏幕大小
  20. self.screen_size = screen.get_rect().size
  21. self.screen_size = (self.screen_size[0], self.screen_size[1] - 50)
  22. # 设置当前图像
  23. self.image = self.block_images[0]
  24. self.rect = self.image.get_rect()
  25. self.rotate_angle = math.radians(0)
  26. '''画到屏幕上'''
  27. def draw(self):
  28. pygame.transform.rotate(self.image, self.rotate_angle)
  29. self.screen.blit(self.image, (self.loc_info[0] - self.rect.width // 2, self.loc_info[1]))
  30. '''设置为损坏状态'''
  31. def setdestroy(self):
  32. self.is_destroyed = True
  33. self.image = self.block_images[1]
  34. '''移动木块'''
  35. def move(self):
  36. # 根据重力改变木块的速度向量
  37. self.velocity = VectorAddition(self.velocity, self.gravity)
  38. self.loc_info[0] += self.velocity.magnitude * math.sin(self.velocity.angle)
  39. self.loc_info[1] -= self.velocity.magnitude * math.cos(self.velocity.angle)
  40. self.velocity.magnitude *= self.inverse_friction
  41. # 宽度超出屏幕
  42. if self.loc_info[0] > self.screen_size[0] - self.rect.width:
  43. self.loc_info[0] = 2 * (self.screen_size[0] - self.rect.width) - self.loc_info[0]
  44. self.velocity.angle *= -1
  45. self.rotate_angle = -self.velocity.angle
  46. self.velocity.magnitude *= self.elasticity
  47. elif self.loc_info[0] < self.rect.width:
  48. self.loc_info[0] = 2 * self.rect.width - self.loc_info[0]
  49. self.velocity.angle *= -1
  50. self.rotate_angle = -self.velocity.angle
  51. self.velocity.magnitude *= self.elasticity
  52. # 高度超出屏幕
  53. if self.loc_info[1] > self.screen_size[1] - self.rect.height:
  54. self.loc_info[1] = 2 * (self.screen_size[1] - self.rect.height) - self.loc_info[1]
  55. self.velocity.angle = math.pi - self.velocity.angle
  56. self.rotate_angle = math.pi - self.velocity.angle
  57. self.velocity.magnitude *= self.elasticity
  58. elif self.loc_info[1] < self.rect.height:
  59. self.loc_info[1] = 2 * self.rect.height - self.loc_info[1]
  60. self.velocity.angle = math.pi - self.velocity.angle
  61. self.rotate_angle = math.pi - self.velocity.angle
  62. self.velocity.magnitude *= self.elasticity

游戏主程序:

  1. import sys
  2. import cfg
  3. import pygame
  4. from modules import *
  5. '''游戏主程序'''
  6. def main(cfg):
  7. # 初始化
  8. pygame.init()
  9. pygame.mixer.init()
  10. pygame.mixer.music.load(cfg.BGMPATH)
  11. pygame.mixer.music.play(-1, 0.0)
  12. screen = pygame.display.set_mode(cfg.SCREENSIZE)
  13. pygame.display.set_caption(' 愤怒的小鸟')
  14. # 开始游戏
  15. def startgame():
  16. game_levels = GameLevels(cfg, screen)
  17. game_levels.start()
  18. # 退出游戏
  19. def quitgame():
  20. pygame.quit()
  21. sys.exit()
  22. # 开始界面
  23. components = pygame.sprite.Group()
  24. title_label = Label(screen, 700, 100, 400, 200)
  25. title_label.addtext('ANGRY BIRDS', 80, cfg.FONTPATH['arfmoochikncheez'], (236, 240, 241))
  26. components.add(title_label)
  27. start_btn = Button(screen, 500, 400, 300, 100, startgame, (244, 208, 63), (247, 220, 111))
  28. start_btn.addtext('START GAME', 60, cfg.FONTPATH['arfmoochikncheez'], cfg.BACKGROUND_COLOR)
  29. components.add(start_btn)
  30. quit_btn = Button(screen, 1000, 400, 300, 100, quitgame, (241, 148, 138), (245, 183, 177))
  31. quit_btn.addtext('QUIT', 60, cfg.FONTPATH['arfmoochikncheez'], cfg.BACKGROUND_COLOR)
  32. components.add(quit_btn)
  33. charles_label = Label(screen, cfg.SCREENSIZE[0] - 300, cfg.SCREENSIZE[1] - 80, 300, 100)
  34. charles_label.addtext('CHARLES', 60, cfg.FONTPATH['arfmoochikncheez'], (41, 41, 41))
  35. components.add(charles_label)
  36. clock = pygame.time.Clock()
  37. while True:
  38. for event in pygame.event.get():
  39. if event.type == pygame.QUIT:
  40. quitgame()
  41. elif event.type == pygame.KEYDOWN:
  42. if event.key == pygame.K_q:
  43. quitgame()
  44. elif event.type == pygame.MOUSEBUTTONDOWN:
  45. if start_btn.selected():
  46. start_btn.action()
  47. elif quit_btn.selected():
  48. quit_btn.action()
  49. screen.fill(cfg.BACKGROUND_COLOR)
  50. for component in components: component.draw()
  51. pygame.display.update()
  52. clock.tick(cfg.FPS)
  53. '''run'''
  54. if __name__ == '__main__':
  55. main(cfg)

由于这款愤怒的小鸟代码量太对,所以全部代码没放进来!文末有代码!

效果图:

总结

赶紧先跟着小编涨姿势啊!这款游戏你也想拥嘛?

完整的项目源码免费领:关注小编公众号:Python顾木子吖

好啦!本次文章就到这里了~如有想跟着小编一起学习交流的,欢迎大家!

学无止境哦!你们的支持是我最大的动力!

图片

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

闽ICP备14008679号