"""pygame生死存亡,两只老鼠掉进熊熊燃烧的大火炉,只有用键盘操作它们碰到正确的算术式子才能挽救它们性命。 这是一个双人小游戏,按上下左右,或wasd操作两只老鼠去碰撞正确的算术式子即可。 结束逻辑一:设定游戏时间 game_time 为 100秒,超过则游戏结束,通过判断得分高低判定输赢。 结束逻辑二:不小心被烧死了,则没烧死的为赢,和得分无关。 通过一个事件,每隔一秒进行一次判断。 """ __author__ = "李兴球" __date__ = "2018年12月左右" import os import time import pygame from pygame.locals import * from random import randint,choice class Flame(pygame.sprite.Sprite): """火焰类""" def __init__(self,images,rat,screen): pygame.sprite.Sprite.__init__(self) self.images = images # 这是已经用pygame.image.load转换成surface后的列表 self.index = 0 # 造型的初始索引号 pass class DynamicBackground(pygame.sprite.Sprite): """动态背景类,它是一个角色,画在最下面的,本质就是不断地切换帧图""" def __init__(self,images,screen): pygame.sprite.Sprite.__init__(self) # 帧图列表 self.images = [pygame.image.load(image).convert_alpha() for image in images] self.index = 0 self.amounts = len(images) self.screen = screen pass class Arithmetic(pygame.sprite.Sprite): """算术题类,每隔一定的时候,会生成一个算术题""" def __init__(self,font,group,screen,rat_group): pygame.sprite.Sprite.__init__(self) self.font = font self.group = group self.group.add(self) self.screen = screen self.srceen_width = screen.get_width() self.screen_height = screen.get_height() self.survival_time = 10 # 生存时间,秒 self.expression_type = ["+","-","*","//"] pass def render_question(self): self.font_image = self.font.render(self.expression,True,(120,10,15)) self.rect = self.font_image.get_rect() self.width = self.rect.w self.height = self.rect.h "把字渲染到self.image上,只是为了有个背景,也可以不用这一步" self.image = pygame.Surface((self.width + 20,self.height+20)) self.image.set_colorkey((0,0,0)) rect = self.image.get_rect() pygame.draw.ellipse(self.image,(0,128,128),rect) # 在image上画个椭圆 self.image.blit(self.font_image,(10,10)) # 在image上再把算术题画上去 "移到随机位置" x = randint(self.width,self.srceen_width - self.width) y = randint(self.height,self.screen_height - self.height) self.rect.center = (x,y) def update(self): """超过生存时间,则从组中移动,这样就不会被渲染了""" if time.time() - self.begin_time > self.survival_time: self.die() self.bump_rats_check() def bump_rats_check(self): """碰鼠检测,遍历所有老鼠""" for rat in self.rat_group: if rat.dead : continue if self.rect.colliderect(rat.rect) and self in self.group: if self.good : rat.score += 10 if not self.good : rat.score -= 10 self.die() def die(self): self.group.remove(self) class Rat(pygame.sprite.Sprite): def __init__(self,images,keys,screen,initheading,name,background,flame_images): pygame.sprite.Sprite.__init__(self) "原始图,是向右的" self.flame_images = flame_images # 鼠死后要生成火焰对象,这个是传递给此对象的 self.background = background # 能访问背景 self.name = name # 给他们取个名字 self.keys = keys # 右,上,左,下 self.screen = screen self.screen_width = self.screen.get_width() self.screen_height = self.screen.get_height() self.raw_images = [pygame.image.load(image).convert_alpha() for image in images] self.right_images = self.raw_images self.up_images = [pygame.transform.rotate(image,90) for image in self.raw_images] self.left_images = [pygame.transform.rotate(image,180) for image in self.raw_images] self.down_images = [pygame.transform.rotate(image,-90) for image in self.raw_images] "images列表,右,上,左,下,每个images包括两个造型" self.images_list = [self.right_images,self.up_images,self.left_images,self.down_images] self.right_rects = [image.get_rect() for image in self.right_images] # 向右方向的2个矩形对象 self.up_rects = [image.get_rect() for image in self.up_images] # 向上方向的2个矩形对象 self.left_rects = [image.get_rect() for image in self.left_images] # 向左方向的2个矩形对象 self.down_rects = [image.get_rect() for image in self.down_images] # 向下方向的2个矩形对象 self.rects_list = [self.right_rects,self.up_rects,self.left_rects,self.down_rects] self.heading_index = initheading # 朝向索引号,初始朝向, self.costume_index = 0 # 造型索引,0为第一个造型,1为第二个造型 self.costume = self.images_list[self.heading_index][self.costume_index] # 初始image对象,向右的第一个造型 self.rect = self.rects_list[self.heading_index][self.costume_index] # 初始矩形对象 self.rect.center = self.screen_width//2,50 self.xspeed = 0 self.yspeed = 0 self.begin_time = time.time() # 起始时间,用于造型切换 self.score = 0 # 接到一个正确的题目就加分,否则减分 self.dead = False # 增加 dead属性 self.aspeed = 0 # 往下掉的加速度 self.flame = None # 火焰对象 def keys_check(self,allkeys): if self.dead : return # 碰到火苗后死亡,按键失效 if allkeys[self.keys[0]] : # 右 self.xspeed = 5 self.yspeed = 0 self.heading_index = 0 if allkeys[self.keys[1]] : # 上 self.xspeed = 0 self.yspeed = -5 self.heading_index = 1 if allkeys[self.keys[2]] : # 左 self.xspeed = -5 self.yspeed = 0 self.heading_index = 2 if allkeys[self.keys[3]] : # 下 self.xspeed = 0 self.yspeed = 5 self.heading_index = 3 def update(self): self.rect.move_ip(self.xspeed,self.yspeed) self.yspeed = self.yspeed + self.aspeed self.bump_edge_check() # 碰到边缘检测 self.bump_background_check() # 碰到火苗检测 if self.flame : self.flame.update() def bump_background_check(self): if self.rect.y - self.background.y >=0 and not self.dead: self.die() def die(self): self.dead = True self.xspeed = 0 self.aspeed = 0.5 "死后要有一个火焰在它上面燃烧" self.flame = Flame(flame_images,self,self.screen) def bump_edge_check(self): if self.rect.right >= self.screen_width : # 到了最右边,要反过来向左移动 self.xspeed = -5 self.yspeed = 0 self.heading_index = 2 if self.rect.left <= 0 : # 到了最左边,要反过来向右移动 self.xspeed = 5 self.yspeed = 0 self.heading_index = 0 if self.rect.top <= 0 : # 到了最顶上,要向下移动 self.xspeed = 0 self.yspeed = 5 self.heading_index = 3 if self.rect.bottom >= self.screen_height : self.xspeed = 0 self.yspeed = -5 self.heading_index = 1 # 到了最下,要向上移动 def draw(self): if time.time() - self.begin_time > 0.1: # 超过0.1秒,换造型 oldrect = self.rect self.costume_index = 1 - self.costume_index self.costume = self.images_list[self.heading_index][self.costume_index] self.rect = self.rects_list[self.heading_index][self.costume_index] self.rect.center = oldrect.center self.begin_time = time.time() self.screen.blit(self.costume,self.rect) if self.flame : self.flame.draw() def check_end_condition(past_time): global game_end string = None if past_time<=0 : if not game_end: game_end = True if rat1.score > rat2.score : string ="舒克赢了!" elif rat1.score < rat2.score: string = "贝塔赢了!" else: string = "平局!" else: if rat1.dead == True: string = "贝塔赢了!" game_end == True elif rat2.dead == True: string = "舒克赢了!" game_end == True #print(string) return string if __name__ == "__main__": msyh_font = "msyh.ttf" width,height = 960,720 # 加载素材图像 flames_list = [os.getcwd() + os.sep + "flames" + os.sep + "0"*(4-len(str(i))) + str(i) + ".png" for i in range(1,13)] bg_list = [os.getcwd() + os.sep + "bgframes" + os.sep + str(i) + ".png" for i in range(13,38)] rat_images = ['mouse_right_a.png','mouse_right_b.png'] rat_images = [os.getcwd() + os.sep + "images" + os.sep + image for image in rat_images] rat1_keys = [K_RIGHT,K_UP,K_LEFT,K_DOWN] # 玩家一按键表 rat2_keys = [K_d,K_w,K_a,K_s] # 玩家二按键表 pygame.init() screen = pygame.display.set_mode((width,height)) pygame.display.set_caption("生死存亡_双人算术小游戏_作者李兴球,风火轮少儿编程 www.scratch8.net") msyh_font = pygame.font.Font(msyh_font,32) flame_images = [ pygame.image.load(image).convert_alpha() for image in flames_list] # 小老鼠死后身上的火焰 expressionEVENT = USEREVENT + 1 pygame.time.set_timer(expressionEVENT,5000) # 设定时任务(生成算术表达式) endEVENT = USEREVENT + 2 pygame.time.set_timer(endEVENT,1000) expression_group = pygame.sprite.Group() clock = pygame.time.Clock() running = True background = DynamicBackground(bg_list,screen) # 创建动态背景实例 rat_group = pygame.sprite.Group() rat1 = Rat(rat_images,rat1_keys,screen,0,"舒克",background,flame_images) # 生成老鼠1,参数为图形列表,按键列表,屏幕,初始方向右 rat2 = Rat(rat_images,rat2_keys,screen,2,"贝塔",background,flame_images) # 初始方向左 rat_group.add(rat1) rat_group.add(rat2) ret_string = None end_image = msyh_font.render(ret_string,True,(255,0,0)) end_image_rect = end_image.get_rect() end_image_rect.center = width//2 , height//2 game_end = False # 游戏结束的逻辑变量 game_time = 100 # 游戏时间为100秒 begin_time = time.time() # 游戏起始时间 while running: past_time = game_time - time.time() + begin_time for event in pygame.event.get(): if event.type == QUIT: running = False break if event.type == endEVENT: # 每隔一定的时间检测 ret_string = check_end_condition(past_time) if ret_string : end_image = msyh_font.render(ret_string,True,(255,0,0)) end_image_rect = end_image.get_rect() end_image_rect.center = width//2 , height//2 pygame.time.set_timer(endEVENT,100000000) # 删除此事件,先用这个方法 if event.type == expressionEVENT: # 产生一道算术题 Arithmetic(msyh_font,expression_group,screen,rat_group) # 把老鼠组加进去,碰撞检测封装到这个类 background.update() # 背景y坐标不断更新 if ret_string == None: all_keys = pygame.key.get_pressed() # 所有的按键检测 rat1.keys_check(all_keys) # 对老鼠1进行按键检测 rat1.update() # 更新老鼠1坐标 rat2.keys_check(all_keys) # 对老鼠2进行按键检测 rat2.update() # 更新老鼠2坐标 expression_group.update() # 算术表达式更新,碰撞检测在每个update后 screen.fill((20,20,0)) # 背景颜色 background.draw() # 动态背景渲染 if ret_string == None: expression_group.draw(screen) # 算术题组渲染 for rat in rat_group: rat.draw() # 老鼠渲染,不使用rat_group.draw if ret_string != None: screen.blit(end_image,end_image_rect) info = str(rat2.name) + "得分:" + str(rat2.score) + "," + str(rat1.name) + "得分:" + str(rat1.score) info = info + " ,游戏剩余时间:" + str(round(past_time)) pygame.display.set_caption(info) pygame.display.update() clock.tick(60) pygame.quit()
下载完整源代码与素材,请
需要浏览更多吗?
成为会员后,登陆才能继续浏览!联系微信scratch8即可办理会员。
(会员专属:能浏览所有文章,下载所有带链接的Python资源。)
发表评论