“十年之前,我不认识你,你不属于我”,十年之后,我已经忘记你是谁。
这首表达爱意的歌曲,用来形容现在过气的心声可能再合适不过了!!
十年前,你肯定也玩儿过这款经典游戏。
一只红色的小鸟让年轻人找到了情绪的宣泄口。他们意气风发、踌躇满志,在让人欲罢不能的游戏世界寻找欢乐和寄托
十几年过去了,这款游戏渐渐被人遗忘。过气游戏?小鸟不angry,你还真以为我是“hello bird”?
现在的高温天气,除了防晒衣外,可能就要靠这只火爆的小鸟给大家降温消暑了!
首先环境安装部分:
准备—Python3.6、Pycharm2021、最主要的游戏模块Pygame、以及一些自带的模块直接可用的。
游戏源码可版本不一致也能运行,相应的模块安装好就可,自行安排!
pip install -i https://pypi.douban.com/simple/ pygame 复制代码
准备—相应的素材图片、音乐背景等:
定义精灵类这里定义的是对手抛掷的猪猪。
class Pig(pygame.sprite.Sprite): def __init__(self, screen, imagepaths, loc_info, velocity=None, **kwargs): pygame.sprite.Sprite.__init__(self) assert len(loc_info) == 3 assert len(imagepaths) == 3 # 设置必要的属性常量 self.screen = screen self.loc_info = list(loc_info) self.imagepaths = imagepaths self.velocity = VelocityVector() if velocity is None else velocity self.type = 'pig' self.is_dead = False self.elasticity = 0.8 self.switch_freq = 20 self.animate_count = 0 self.inverse_friction = 0.99 self.gravity = VelocityVector(0.2, math.pi) # 屏幕大小 self.screen_size = screen.get_rect().size self.screen_size = (self.screen_size[0], self.screen_size[1] - 50) # 导入图像 self.pig_images = [] for imagepath in imagepaths: self.pig_images.append(pygame.image.load(imagepath)) # 设置当前图像 self.image = random.choice(self.pig_images[:2]) '''画到屏幕上''' def draw(self): self.animate_count += 1 if (self.animate_count % self.switch_freq == 0) and (not self.is_dead): self.animate_count = 0 self.image = random.choice(self.pig_images[:2]) position = self.loc_info[0] - self.loc_info[2], self.loc_info[1] - self.loc_info[2] self.screen.blit(self.image, position) '''移动猪''' def move(self): # 根据重力改变猪的速度向量 self.velocity = VectorAddition(self.velocity, self.gravity) self.loc_info[0] += self.velocity.magnitude * math.sin(self.velocity.angle) self.loc_info[1] -= self.velocity.magnitude * math.cos(self.velocity.angle) self.velocity.magnitude *= self.inverse_friction # 宽度超出屏幕 if self.loc_info[0] > self.screen_size[0] - self.loc_info[2]: self.loc_info[0] = 2 * (self.screen_size[0] - self.loc_info[2]) - self.loc_info[0] self.velocity.angle *= -1 self.velocity.magnitude *= self.elasticity elif self.loc_info[0] < self.loc_info[2]: self.loc_info[0] = 2 * self.loc_info[2] - self.loc_info[0] self.velocity.angle *= -1 self.velocity.magnitude *= self.elasticity # 高度超出屏幕 if self.loc_info[1] > self.screen_size[1] - self.loc_info[2]: self.loc_info[1] = 2 * (self.screen_size[1] - self.loc_info[2]) - self.loc_info[1] self.velocity.angle = math.pi - self.velocity.angle self.velocity.magnitude *= self.elasticity elif self.loc_info[1] < self.loc_info[2]: self.loc_info[1] = 2 * self.loc_info[2] - self.loc_info[1] self.velocity.angle = math.pi - self.velocity.angle self.velocity.magnitude *= self.elasticity '''猪死掉了''' def setdead(self): self.is_dead = True self.image = self.pig_images[-1] 复制代码
然后这里定义的精灵类是小鸟即玩家:
class Bird(pygame.sprite.Sprite): def __init__(self, screen, imagepaths, loc_info, velocity=None, color=(255, 255, 255), **kwargs): pygame.sprite.Sprite.__init__(self) assert len(loc_info) == 3 assert len(imagepaths) == 1 # 设置必要的属性常量 self.color = color self.screen = screen self.loc_info = list(loc_info) self.imagepaths = imagepaths self.velocity = VelocityVector() if velocity is None else velocity self.type = 'bird' self.fly_path = [] self.is_dead = False self.elasticity = 0.8 self.is_loaded = False self.is_selected = False self.inverse_friction = 0.99 self.gravity = VelocityVector(0.2, math.pi) # 屏幕大小 self.screen_size = screen.get_rect().size self.screen_size = (self.screen_size[0], self.screen_size[1] - 50) # 导入图像 self.image = pygame.image.load(imagepaths[0]) '''画到屏幕上''' def draw(self): if not self.is_loaded: for point in self.fly_path: pygame.draw.ellipse(self.screen, self.color, (point[0], point[1], 3, 3), 1) position = self.loc_info[0] - self.loc_info[2], self.loc_info[1] - self.loc_info[2] self.screen.blit(self.image, position) '''判断有没有被鼠标选中''' def selected(self): pos = pygame.mouse.get_pos() dx, dy = pos[0] - self.loc_info[0], pos[1] - self.loc_info[1] dist = math.hypot(dy, dx) if dist < self.loc_info[2]: return True return False '''加载到弹弓上''' def load(self, slingshot): self.loc_info[0], self.loc_info[1] = slingshot.x, slingshot.y self.is_loaded = True '''重新设置位置''' def reposition(self, slingshot): pos = pygame.mouse.get_pos() if self.selected: self.loc_info[0], self.loc_info[1] = pos[0], pos[1] dx, dy = slingshot.x - self.loc_info[0], slingshot.y - self.loc_info[1] self.velocity.magnitude = min(int(math.hypot(dx, dy) / 2), 80) self.velocity.angle = math.pi / 2 + math.atan2(dy, dx) '''显示发射小鸟的路径''' def projectpath(self): if self.is_loaded: path = [] bird = Bird(self.screen, self.imagepaths, self.loc_info, velocity=self.velocity) for i in range(30): bird.move() if i % 5 == 0: path.append((bird.loc_info[0], bird.loc_info[1])) for point in path: pygame.draw.ellipse(self.screen, self.color, (point[0], point[1], 2, 2)) '''移动小鸟''' def move(self): # 根据重力改变小鸟的速度向量 self.velocity = VectorAddition(self.velocity, self.gravity) self.loc_info[0] += self.velocity.magnitude * math.sin(self.velocity.angle) self.loc_info[1] -= self.velocity.magnitude * math.cos(self.velocity.angle) self.velocity.magnitude *= self.inverse_friction # 宽度超出屏幕 if self.loc_info[0] > self.screen_size[0] - self.loc_info[2]: self.loc_info[0] = 2 * (self.screen_size[0] - self.loc_info[2]) - self.loc_info[0] self.velocity.angle *= -1 self.velocity.magnitude *= self.elasticity elif self.loc_info[0] < self.loc_info[2]: self.loc_info[0] = 2 * self.loc_info[2] - self.loc_info[0] self.velocity.angle *= -1 self.velocity.magnitude *= self.elasticity # 高度超出屏幕 if self.loc_info[1] > self.screen_size[1] - self.loc_info[2]: self.loc_info[1] = 2 * (self.screen_size[1] - self.loc_info[2]) - self.loc_info[1] self.velocity.angle = math.pi - self.velocity.angle self.velocity.magnitude *= self.elasticity elif self.loc_info[1] < self.loc_info[2]: self.loc_info[1] = 2 * self.loc_info[2] - self.loc_info[1] self.velocity.angle = math.pi - self.velocity.angle self.velocity.magnitude *= self.elasticity 复制代码
定义地图里面的木桩:
class Block(pygame.sprite.Sprite): def __init__(self, screen, imagepaths, loc_info, velocity=None, **kwargs): pygame.sprite.Sprite.__init__(self) assert len(loc_info) == 3 assert len(imagepaths) == 2 # 设置必要的属性常量 self.type = 'block' self.screen = screen self.loc_info = list(loc_info) self.imagepaths = imagepaths self.velocity = VelocityVector() if velocity is None else velocity self.elasticity = 0.7 self.is_destroyed = False self.inverse_friction = 0.99 self.gravity = VelocityVector(0.2, math.pi) # 导入图像 self.block_images = [] for imagepath in imagepaths: self.block_images.append(pygame.transform.scale(pygame.image.load(imagepath), (100, 100))) # 屏幕大小 self.screen_size = screen.get_rect().size self.screen_size = (self.screen_size[0], self.screen_size[1] - 50) # 设置当前图像 self.image = self.block_images[0] self.rect = self.image.get_rect() self.rotate_angle = math.radians(0) '''画到屏幕上''' def draw(self): pygame.transform.rotate(self.image, self.rotate_angle) self.screen.blit(self.image, (self.loc_info[0] - self.rect.width // 2, self.loc_info[1])) '''设置为损坏状态''' def setdestroy(self): self.is_destroyed = True self.image = self.block_images[1] '''移动木块''' def move(self): # 根据重力改变木块的速度向量 self.velocity = VectorAddition(self.velocity, self.gravity) self.loc_info[0] += self.velocity.magnitude * math.sin(self.velocity.angle) self.loc_info[1] -= self.velocity.magnitude * math.cos(self.velocity.angle) self.velocity.magnitude *= self.inverse_friction # 宽度超出屏幕 if self.loc_info[0] > self.screen_size[0] - self.rect.width: self.loc_info[0] = 2 * (self.screen_size[0] - self.rect.width) - self.loc_info[0] self.velocity.angle *= -1 self.rotate_angle = -self.velocity.angle self.velocity.magnitude *= self.elasticity elif self.loc_info[0] < self.rect.width: self.loc_info[0] = 2 * self.rect.width - self.loc_info[0] self.velocity.angle *= -1 self.rotate_angle = -self.velocity.angle self.velocity.magnitude *= self.elasticity # 高度超出屏幕 if self.loc_info[1] > self.screen_size[1] - self.rect.height: self.loc_info[1] = 2 * (self.screen_size[1] - self.rect.height) - self.loc_info[1] self.velocity.angle = math.pi - self.velocity.angle self.rotate_angle = math.pi - self.velocity.angle self.velocity.magnitude *= self.elasticity elif self.loc_info[1] < self.rect.height: self.loc_info[1] = 2 * self.rect.height - self.loc_info[1] self.velocity.angle = math.pi - self.velocity.angle self.rotate_angle = math.pi - self.velocity.angle self.velocity.magnitude *= self.elasticity 复制代码
游戏主程序:
import sys import cfg import pygame from modules import * '''游戏主程序''' def main(cfg): # 初始化 pygame.init() pygame.mixer.init() pygame.mixer.music.load(cfg.BGMPATH) pygame.mixer.music.play(-1, 0.0) screen = pygame.display.set_mode(cfg.SCREENSIZE) pygame.display.set_caption(' 愤怒的小鸟 —— csdn账号:顾木子吖') # 开始游戏 def startgame(): game_levels = GameLevels(cfg, screen) game_levels.start() # 退出游戏 def quitgame(): pygame.quit() sys.exit() # 开始界面 components = pygame.sprite.Group() title_label = Label(screen, 700, 100, 400, 200) title_label.addtext('ANGRY BIRDS', 80, cfg.FONTPATH['arfmoochikncheez'], (236, 240, 241)) components.add(title_label) start_btn = Button(screen, 500, 400, 300, 100, startgame, (244, 208, 63), (247, 220, 111)) start_btn.addtext('START GAME', 60, cfg.FONTPATH['arfmoochikncheez'], cfg.BACKGROUND_COLOR) components.add(start_btn) quit_btn = Button(screen, 1000, 400, 300, 100, quitgame, (241, 148, 138), (245, 183, 177)) quit_btn.addtext('QUIT', 60, cfg.FONTPATH['arfmoochikncheez'], cfg.BACKGROUND_COLOR) components.add(quit_btn) charles_label = Label(screen, cfg.SCREENSIZE[0] - 300, cfg.SCREENSIZE[1] - 80, 300, 100) charles_label.addtext('CHARLES', 60, cfg.FONTPATH['arfmoochikncheez'], (41, 41, 41)) components.add(charles_label) clock = pygame.time.Clock() while True: for event in pygame.event.get(): if event.type == pygame.QUIT: quitgame() elif event.type == pygame.KEYDOWN: if event.key == pygame.K_q: quitgame() elif event.type == pygame.MOUSEBUTTONDOWN: if start_btn.selected(): start_btn.action() elif quit_btn.selected(): quit_btn.action() screen.fill(cfg.BACKGROUND_COLOR) for component in components: component.draw() pygame.display.update() clock.tick(cfg.FPS) '''run''' if __name__ == '__main__': main(cfg) 复制代码
由于这款愤怒的小鸟代码量太对,所以全部代码没放进来!文末有代码!
效果图:
赶紧先跟着小编涨姿势啊!这款游戏你也想拥有嘛?源码分享后台暗号666点击链接找我