"""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资源。)

