之前始终在手机上玩flappy bird游戏,空闲工夫就编写了一个
是采纳python3+pygame模块制作而成的,运行成果十分晦涩,会让你大吃一惊哦????哈哈
一、运行成果展现
下载游戏之后,留神在本人的python环境中装置pygame模块,如果没有装置能够应用pip install pygame 进行装置
而后应用应用命令运行起这个.py文件,运行之后的第一个界面成果如下,是不是很酷炫
当点击上图中的“Play”按钮之后的成果如下:
运行之后是有音乐的,大家能够下载代码的时候一起将素材下载,这样就在运行时就能听到音乐
二、残缺代码
上面代码用到了素材(背景图片,音乐等,下载地址 https://www.itprojects.cn/detail.html?example_id=8af93ac601523a955f8280c95c2a9e0b)
import mathimport osimport timefrom random import randintfrom random import uniformimport pygamefrom pygame.locals import * #导入一些罕用的变量from collections import deque#退出了队列FPS = 60BK_WIDTH = 900 #背景宽度BK_HEIGHT = 650 #背景高度PIPE_WIDTH = 80 #水管的宽度PIPE_HEIGHT = 10 #水管素材的高度PIPE_HEAD_HEIGHT = 32#管子头的高度#初始化全局变量BK_MOVE_SPEED = 0.22#主柱子每毫秒挪动的速度ADD_TIME = 2500##每隔多少毫秒就减少一个柱子 这种办法不会有破绽吗 就是当毫秒数和帧数不匹配啥的 #还须要认真的思考TOTAL_PIPE_BODY = int(3/5 * BK_HEIGHT) # 像素值必须为整数 占窗口的3/5PIPE_RATE =0.96a_i="bird-wingup"b_i="bird-wingmid"c_i="bird-wingdown"INITAL_SPEED = -0.37#鸟的Y轴初速度BIRD_WIDTH = 50BIRD_HEIGHT = 40BIRD_INIT_SCORE = 7#鸟的初始通关分数STONE_ADD_TIME = 1000 #每隔多少毫秒就减少一个石头STONE_WIDTH = 40STONE_HEIGHT = 30STONE_LEVEL = 4#石头呈现的等级BUTTON_WIDTH = 140BUTT0N_HEIGHT = 60BULLET_SPEED = 0.32#子弹的速度BULLET_WIETH = 50BULLET_HEIGHT = 30#设置全局变量 不便批改参数pygame.init()screen = pygame.display.set_mode((BK_WIDTH,BK_HEIGHT))pygame.mixer.init()music_lose = pygame.mixer.Sound("lose.wav")music1 = pygame.mixer.Sound("touch.wav")pygame.mixer.music.load("bkm.mp3")font = pygame.font.SysFont('comicsansms', 25)#用于设置鸟的品种def little_bird(list): global a_i global b_i global c_i a_i=list[0] b_i=list[1] c_i=list[2]#用于设置关卡难度def seteasy(list): global BK_MOVE_SPEED # 背景每毫秒挪动的速度 就是柱子挪动的速度 global ADD_TIME # 每隔多少毫秒就减少一个柱子 global TOTAL_PIPE_BODY # 像素值必须为整数 占窗口的3/5 global PIPE_RATE global STONE_LEVEL # 鸟呈现的等 global BIRD_INIT_SCORE BK_MOVE_SPEED = list[0] # 背景每毫秒挪动的速度 ADD_TIME = list[1] # 每隔多少毫秒就减少一个柱子 TOTAL_PIPE_BODY =list[2] # 像素值必须为整数 占窗口的3/5 PIPE_RATE = list[3] Pipe.add_time = list[1] BIRD_INIT_SCORE = list[4] STONE_LEVEL = list[5]#子弹类class Bullet(pygame.sprite.Sprite): speed = BULLET_SPEED width = BULLET_WIETH height = BULLET_HEIGHT def __init__(self,bird,images): super(Bullet,self).__init__() #d调用父类的初始函数 应用此办法 能够缩小代码的更改量 并且解决了多重继承的问题 self.x,self.y = bird.x,bird.y self.bullet = images #给鸟的图片进行赋值 self.mask_bullet = pygame.mask.from_surface(self.bullet) def update(self):#计算鸟在下一点的新坐标并更新 self.x=self.x+self.speed*frames_to_msec(1) @property def image(self): return self.bullet @property def mask(self): return self.mask_bullet @property def rect(self): return Rect(self.x,self.y,Bullet.width,Bullet.height) def visible(self): return 0<self.x<BK_WIDTH+Bullet.width#小鸟做竖直上抛静止 当小鸟减速到肯定状态时 就不再减速了class Bird(pygame.sprite.Sprite): width =BIRD_WIDTH #鸟宽 height = BIRD_HEIGHT #鸟长 sink_gravity = 0.001#鸟的降落重力 def __init__(self,x,y,level,images): super(Bird,self).__init__() #d调用父类的初始函数 应用此办法 能够缩小代码的更改量 并且解决了多重继承的问题 self.x,self.y = x,y self.wing_up,self.wing_mid,self.wing_down = images #给鸟的图片进行赋值 self.mask_wing_up = pygame.mask.from_surface(self.wing_up) self.mask_wing_mid = pygame.mask.from_surface(self.wing_mid) self.mask_wing_down = pygame.mask.from_surface(self.wing_down) self.inital_speed = 0 #鸟向上的初速度 self.level = level #鸟的初始等级 self.score = 0 #鸟的初始分数为 0 def update(self,t):#计算鸟在下一点的新坐标并更新 y_ = self.inital_speed*t+0.5*self.sink_gravity*t*t if self.inital_speed<=0.3: self.inital_speed = self.inital_speed +self.sink_gravity*t self.y+=y_ #在主函数里计算工夫 @property def image(self): if pygame.time.get_ticks()%400>=120: return self.wing_up elif pygame.time.get_ticks()%400>=280: return self.wing_mid else: return self.wing_down @property def mask(self): if pygame.time.get_ticks()%400>=120: return self.mask_wing_up elif pygame.time.get_ticks()%400>=280: return self.mask_wing_mid else: return self.mask_wing_down @property def rect(self): return Rect(self.x,self.y,Bird.width,Bird.height)class Pipe(pygame.sprite.Sprite): width = PIPE_WIDTH pipe_head_height = PIPE_HEAD_HEIGHT add_time = ADD_TIME def __init__(self,pipe_head_image,pipe_body_image): super(Pipe, self).__init__() self.x = float(BK_WIDTH-1) self.score_count = False self.image = pygame.Surface((Pipe.width,BK_HEIGHT),SRCALPHA)#创立一个surface 我了解为能画到窗口上的对象 # #意为创立一个有ALPHA 通道的surface 如果须要通明就须要这个选项 self.image.convert() self.image.fill((0,0,0,0))#前三位是色彩 最初一位是透明度 total_pipe_length = TOTAL_PIPE_BODY self.bottom_length = randint(int(0.1*total_pipe_length),int(0.8*total_pipe_length))#用于生成指定范畴内的整数 self.top_length = total_pipe_length-self.bottom_length for i in range(1,self.bottom_length+1): pos = (0,BK_HEIGHT - i) self.image.blit (pipe_body_image,pos)#用重叠的技术画进去管子 bottom_head_y = BK_HEIGHT - self.bottom_length-self.pipe_head_height #求出管子头的长度 bottom_head_pos = (0,bottom_head_y) self.image.blit(pipe_head_image,bottom_head_pos)#画管子 for i in range(-PIPE_HEIGHT,self.top_length-PIPE_HEIGHT): pos = (0,i) self.image.blit(pipe_body_image,pos) top_head_y = self.top_length self.image.blit(pipe_head_image,(0,top_head_y)) self.mask = pygame.mask.from_surface(self.image) @property def rect(self): return Rect(self.x,0,Pipe.width,PIPE_HEIGHT) @property def visible(self): return -Pipe.width<self.x<BK_WIDTH def update(self,delta_frames=1): self.x-=BK_MOVE_SPEED*frames_to_msec(delta_frames) def collides(self,bird): return pygame.sprite.collide_mask(self,bird)def change_add_time(): Pipe.add_time= int( (Pipe.add_time*PIPE_RATE) /100)*100#扭转管子的减少工夫#石头具备速度 地位等不同属性#起始的x属性为固定值 y随机 速度在肯定范畴内随机class Stone(pygame.sprite.Sprite): add_time = STONE_ADD_TIME width = STONE_WIDTH height = STONE_HEIGHT def __init__(self,image): super(Stone, self).__init__() self.x =BK_WIDTH-5 self.y = randint(1,int(0.95*BK_HEIGHT)) self.speed = uniform(0.1 ,0.5) self.stone_image = image self.mask_image = pygame.mask.from_surface(self.image) @property def rect(self): return Rect(self.x,self.y,self.width,self.height) @property def image(self): return self.stone_image @property def mask(self): return self.mask_image def update(self,frame = 1): self.x -= int(self.speed*frames_to_msec(frame)) def collides(self, b): return pygame.sprite.collide_mask(self, b) def visible(self): return -self.width<self.x<BK_WIDTH#返回每关须要达到的通关分数def level_goal(bird): return bird.level*BIRD_INIT_SCORE#载入图片def load_image(img_file_name): file_name = os.path.join(".","images",img_file_name)#进行门路字符串的合并 img = pygame.image.load(file_name) img.convert() return img#依据所在的等级返回须要的背景名def search_bk(bird): return "bk"+str(bird.level)img_x = load_image('backgroundx.png')#加载背景图像def load_images(): #加载所有游戏须要用到的图像 #下面写了这个函数上面就用了起来 join用于分隔符和元组的拼接 os.path.join 用于门路的程序拼接 return {'bk1': load_image('background.png'), 'bk2':load_image("background2.png"), "bk3":load_image("background3.png"), "bk4":load_image("background4.png"), "bk5":load_image("background5.png"), "bk6":load_image("background6.png"), 'stone':load_image('stone.png'), 'bullet': load_image('bullet.png'), 'pipe-end': load_image('pipe_end.png'), 'pipe-body': load_image('pipe_body.png'), 'f_u': load_image('fenghuang_up.png'), 'f_m': load_image('fenghuang_mid.png'), 'f_w': load_image('fenghuang_down.png'), 'bird-wingup': load_image('bird_wing_up.png'), 'bird-wingmid': load_image('bird_wing_mid.png'), 'bird-wingdown': load_image('bird_wing_down.png')}def frames_to_msec(frames,fps=FPS): return 1000.0*frames/fps #难道限度的意思就是我能够限度图片进去的工夫def msec_to_frames(milliseconds, fps=FPS): return fps * milliseconds / 1000.0#转化成对应的帧数 #转化成每秒的相应的帧数def game_loop(): pygame.mixer.music.play(-1) pygame.display.set_caption("Flappy Bird") clock = pygame.time.Clock()#创立一个时钟对象 images = load_images()#建设所有须要的图像字典 bird = Bird(20,BK_HEIGHT//2,1,(images[a_i],images[b_i] ,images[c_i])) score_font = pygame.font.SysFont(None,50,bold=True)#名字 大小 粗体 建设画笔 用于记录 分数 score_font2 = pygame.font.SysFont(None, 40, bold=True) # 名字 大小 粗体 建设画笔 用于记录 分数 score_font3 = pygame.font.SysFont(None, 70, bold=True) # 名字 大小 粗体 建设画笔 用于记录 分数 pipes = deque() stones =pygame.sprite.Group()#将石头新建为一个精灵组 bullets =pygame.sprite.Group()#将子弹新建为一个精灵组 pause = done = False frames=0 while not done :#当没有按下停止键 clock.tick(FPS) if not (pause or frames%msec_to_frames(Pipe.add_time)):#如果没有按下暂停 或者满足新生成柱子的条件 pp=Pipe(images['pipe-end'], images['pipe-body']) pipes.append(pp)#生成新管子 并退出队列 if not (pause or frames%msec_to_frames(Stone.add_time)or bird.level<STONE_LEVEL): ss = Stone(images["stone"]) stones.add(ss) #退出新生成的石头 #判断产生了什么事件进行相应的解决 for e in pygame.event.get(): if e.type == QUIT: done = True break elif e.type == KEYUP : if e.key == K_p: pause = not pause elif e.key ==K_d:#发射子弹 bb=Bullet(bird,images["bullet"]) bullets.add(bb) elif e.key ==K_s or e.key == K_SPACE: bird.inital_speed = INITAL_SPEED elif e.type == MOUSEBUTTONUP: bird.inital_speed =INITAL_SPEED # 从新更新工夫 # 使小鸟又进入相应的静止的开始 if pause: continue # 这个时段什么都不做 pygame.sprite.groupcollide(stones,bullets,True,True,pygame.sprite.collide_mask) pipe_collision = any(p.collides(bird) for p in pipes) stone_collision = any(s.collides(bird) for s in stones) if pipe_collision: pygame.mixer.music.stop() done = True pygame.mixer.Sound.play(music_lose, -1) time.sleep(3.5) pygame.mixer.Sound.stop(music_lose) time.sleep(0.1) if stone_collision: pygame.mixer.music.stop() pygame.mixer.Sound.play(music_lose, -1) time.sleep(3.5) pygame.mixer.Sound.stop(music_lose) time.sleep(0.1) done = True if 0>=bird.y or bird.y>BK_HEIGHT-Bird.height: done = True pygame.mixer.music.stop() pygame.mixer.Sound.play(music_lose, -1) time.sleep(3.5) pygame.mixer.Sound.stop(music_lose) time.sleep(0.1) screen.blit(images[search_bk(bird)], (0, 0))#画背景墙 这种是离开两张的 while pipes and not pipes[0].visible: pipes.popleft()#当队列不为空 且管子 0 曾经不可见的时候 for s in stones:#删除看不见的石头 if not s.visible(): del s for b in bullets:#删除看不见的子弹 if not b.visible(): del b for p in pipes: p.update() screen.blit(p.image,p.rect)#在指定的地位 画柱子 for s in stones: s.update() screen.blit(s.image,s.rect) for b in bullets: b.update() screen.blit(b.bullet,b.rect) for p in pipes: if bird.x>p.x+Pipe.width and not p.score_count: #当柱子超过了鸟的地位并且柱子还没有被计分 bird.score+=1 p.score_count = True sl = score_font.render("level:",True,(255,255,255)) sc = score_font.render("score:",True,(255,255,255)) sl2 = score_font2.render(str(bird.level),True,(255,255,255)) sc2 = score_font2.render(str(bird.score),True,(255,255,255)) screen.blit (sc,(BK_WIDTH-170,20)) screen.blit(sl, (BK_WIDTH - 320, 20)) screen.blit(sc2, (BK_WIDTH - 50, 27)) screen.blit(sl2, (BK_WIDTH - 210, 27)) bird.update(frames_to_msec(1))#计算一帧所须要的工夫 screen.blit(bird.image,bird.rect) pygame.display.flip()#绘制图像到屏幕 if bird.score >= level_goal(bird):#如果曾经达到了通关分数 #升入下一级 首先要初始化所有变量#清空柱子#扭转等级 change_add_time() pipes.clear() stones.empty() bullets.empty() bird.level += 1 # 分数先暂不做清空后续再退出吧 if bird.level<=6: s3 = score_font3.render("Next Level", True, (255, 255, 255)) screen.blit(s3, (BK_WIDTH//2-150, BK_HEIGHT//2-50)) pygame.display.flip() time.sleep(2) if bird.level >6: s3 = score_font3.render("You Win!", True, (255, 255, 255)) screen.blit(s3, (BK_WIDTH // 2 - 150, BK_HEIGHT // 2 - 50)) pygame.display.flip() time.sleep(2) exit() frames+= 1 pygame.mixer.music.stop() Pipe.add_time = ADD_TIME#再次初始化柱子的速度 main()def quit_but(): pygame.quit() exit()def buttons(x, y, w, h, color, color2, text,action,list=[]): mouse_position = pygame.mouse.get_pos() click = pygame.mouse.get_pressed() if x+w > mouse_position[0] > x and y+h > mouse_position[1] > y: color = color2 #get_pressed 只返回鼠标三个键是否被按过的状态 不会分辨它是在哪里被按的 if click[0]== 1 and action != None: pygame.mixer.Sound.play(music1, -1) time.sleep(0.215) pygame.mixer.Sound.stop(music1) if list: action(list) else: action() pygame.draw.rect(screen, color, (x, y, w, h)) # font = pygame.font.SysFont('comicsansms', 25) TextSurf = font.render(text, True, (0,0,0)) TextRect = TextSurf.get_rect() TextRect.center = ((x + (w / 2)), (y + (h / 2))) screen.blit(TextSurf, TextRect) pygame.display.update()def setting(): # img = load_image('backgroundx.png') screen.blit(img_x, (0, 0)) # 画背景墙 这种是离开两张的 pygame.display.flip() while True: for event in pygame.event.get(): if event.type==pygame.QUIT: exit() buttons(100, 200, BUTTON_WIDTH, BUTT0N_HEIGHT,(255, 0, 0), (170, 0, 0), 'easy',seteasy,[0.19,2500,int(5 / 11 * BK_HEIGHT),0.97,5,6]) # 绘制图标 进行事件 buttons(400, 200, BUTTON_WIDTH, BUTT0N_HEIGHT,(0, 255, 0), (0, 170, 0), 'normal', seteasy,[0.19,2500,int(3 / 5 * BK_HEIGHT),0.96,7,4]) # 绘制图标 进行事件 buttons(700 ,200, BUTTON_WIDTH, BUTT0N_HEIGHT,(0, 0, 255), (0, 0, 160),'hard',seteasy,[0.21,1300,int(9 / 14 * BK_HEIGHT),0.96,2,1]) # 绘制图标 进行事件 buttons(700, 550, BUTTON_WIDTH, BUTT0N_HEIGHT, (0, 0, 255), (0, 0, 160), 'back', main) # 绘制图标 进行事件 buttons(100, 400, BUTTON_WIDTH, BUTT0N_HEIGHT, (255, 0, 0), (170, 0, 0), 'huo lie niao',little_bird,["f_u","f_m","f_w"]) # 绘制图标 进行事件 buttons(400, 400, BUTTON_WIDTH, BUTT0N_HEIGHT, (0, 255, 0), (0, 170, 0), 'xiao niao',little_bird,["bird-wingup","bird-wingmid","bird-wingdown"]) # 绘制图标 进行事件 # buttons(700, 400, BUTTON_WIDTH, BUTT0N_HEIGHT, (0, 0, 255), (0, 0, 160), 'back', main) # 绘制图标 进行事件def main(): screen.blit(img_x, (0, 0)) # 画背景墙 这种是离开两张的 pygame.display.flip() while True: for event in pygame.event.get(): if event.type==pygame.QUIT: exit() buttons((BK_WIDTH-BUTTON_WIDTH)//2,(BK_HEIGHT-BUTT0N_HEIGHT-100)//2,BUTTON_WIDTH,BUTT0N_HEIGHT,(0,255,0),(0,170,0),'Play!',game_loop)#绘制图标 进行事件 buttons((BK_WIDTH - BUTTON_WIDTH) // 2, (BK_HEIGHT - BUTT0N_HEIGHT + 100) // 2, BUTTON_WIDTH, BUTT0N_HEIGHT,(0, 0, 255), (0, 0, 160), 'setting', setting) # 绘制图标 进行事件 buttons((BK_WIDTH - BUTTON_WIDTH) // 2, (BK_HEIGHT - BUTT0N_HEIGHT + 300) // 2, BUTTON_WIDTH, BUTT0N_HEIGHT,(255, 0, 0), (170, 0, 0), 'Quit', quit_but)if __name__ =="__main__": main()
上述代码是第1版本,简略起见 没有齐全封装为面向对象,等前面有工夫再进行欠缺
指标是:全副用类进行分装,而后拆分到多个模块中