当前位置:首页>python>Python实战-病毒防卫战

Python实战-病毒防卫战

  • 2026-10-21 13:28:42
Python实战-病毒防卫战

第4课 病毒防卫战

一、作品展示

二、作品分析与制作

2.1 素材简介

3个背景:游戏中,游戏成功,游戏失败

2个角色:卫士,病毒(4个造型)

2.2 游戏背景加载

任务1:创建一个宽480高650的游戏界面,显示游戏中背景,点击关闭窗口按钮,窗口关闭,游戏退出,并将所有背景角色素材载入,并设置合适的图片大小

import pygameimport syspygame.init()screen_size = width, height = (480, 650)screen = pygame.display.set_mode(screen_size)pygame.display.set_caption("病毒防卫战")# 加载背景图片,并适配屏幕bg_game = pygame.image.load('./images/bg1.png')bg_success = pygame.image.load('./images/bg2.png')bg_fail = pygame.image.load('./images/bg3.png')bg_game = pygame.transform.scale(bg_game, screen_size)bg_success = pygame.transform.scale(bg_success, screen_size)bg_fail = pygame.transform.scale(bg_fail, screen_size)# 加载角色图片boy_size = boy_width, boy_height = 80, 100boy_img = pygame.image.load('./images/boy.png')boy_img = pygame.transform.scale(boy_img, boy_size)virus_img = []virus_size = virus_width, virus_height = 30, 30for i in range(4):    img = pygame.image.load("./images/virus{}.png".format(i))    pygame.transform.scale(img, virus_size)    virus_img.append(img)running = Truewhile running:    # 加载背景    screen.blit(bg_game, (0, 0))    # 处理事件    for event in pygame.event.get():        if event.type == pygame.QUIT:            running = False            pygame.quit()            sys.exit()    # 更新屏幕画面    pygame.display.update()

2.2 卫士

任务2:创建一个卫士类,初始化他的位置、大小、造型和生命值,游戏中只有一个卫士角色,能够跟着鼠标移动

1)创建卫士类,设置初始方法进行初始化,显示方法show()将其显示在游戏界面上,移动方法move()使其跟着鼠标的位置移动

class Boy:    def __init__(self):        # 初始化位置(屏幕中间)        self.x = width / 2        self.y = height / 2        # 初始化大小        self.width = boy_width        self.height = boy_height        # 初始化造型        self.img = boy_img        # 初始化生命值        self.life = 1    def show(self):        screen.blit(self.img, (self.x, self.y))    # 设置卫士移动的方法,跟随鼠标移动    def move(self, mouseX, mouseY):        self.x = mouseX - self.width / 2        self.y = mouseY - self.height / 2

2)创建一个卫士对象,调用显示方法和移动方法,使其动起来

2.3 病毒

任务3:创建病毒类,初始化它的位置、大小、造型、移动速度、移动参照物,根据轮数,显示病毒,如第1轮显示1个病毒,第2轮显示2个病毒……

1)创建病毒类,类中有init()方法初始化它的信息,show()方法将其显示在游戏界面上

class Virus:    def __init__(self, x, y, img_index, speed, mouse_x, mouse_y):        # 初始化位置        self.x = x        self.y = y        # 初始化大小        self.width = virus_width        self.height = virus_height        # 初始化造型        self.img = virus_img[img_index]        # 初始化速度        self.speed = speed        # 固定鼠标的位置(当前卫士的位置)        self.mouse_x = mouse_x        self.mouse_y = mouse_y        # 设置移动的方位距离        self.move_x = 0        self.move_y = 0    def show(self):        screen.blit(self.img, (self.x, self.y))

2)创建create_virus(num, mouse_x, mouse_y)函数,用于创建指定个数病毒

num:此次创建的病毒对象个数

mouse_x:病毒移动参照物的x坐标

mouse_y:病毒移动参照物的y坐标

def create_virus(num, mouse_x, mouse_y):    virus_list = []    # 该轮病毒移动的速度    speed = num * 0.4 + 0.4 * random.random()    for i in range(num):        # 病毒的4个随机位置,x坐标范围是0到(屏幕的宽-病毒的宽)        # y坐标的范围是0到(屏幕的高-病毒的高)        rand_pos = random.randint(0, 3)        x = random.random() * (width - virus_width)        y = random.random() * (height - virus_height)        # 病毒的造型下标,随机0到3        virus_index = random.randint(0, 3)        # 创建病毒        if rand_pos == 0:            virus = Virus(x, 0, virus_index, speed, mouse_x, mouse_y)        elif rand_pos == 1:            virus = Virus(0, y, virus_index, speed, mouse_x, mouse_y)        elif rand_pos == 2:            virus = Virus(width - virus_width, y, virus_index, speed, mouse_x, mouse_y)        else:            virus = Virus(x, height - virus_height, virus_index, speed, mouse_x, mouse_y)        # 将新产生的病毒存入列表        virus_list.append(virus)    return virus_list

病毒的可能位置图示:

3)创建show_virus(virus_list)函数,显示所有的病毒

def show_virus(virus_list):    for i in range(len(virus_list)):        virus_list[i].show()

4)调用create_virus()函数和show_virus()函数,将本轮病毒显示在游戏窗口上。只有窗口上没有病毒,才产生新的一轮病毒

任务4:所有病毒可以朝着卫士的方向一直移动

1)在Virus病毒类中创建setMoveXY()方法设置病毒需要移动的方位距离,创建move()方法,使得病毒可以移动

    def setMoveXY(self):        # 获取病毒到卫士的x,y轴的向量        dx = self.mouse_x - self.x        dy = self.mouse_y - self.y        # 两者重合时不移动        if dx == 0 and dy == 0:            return        # 获取两者直线距离(欧几里德距离)        dis = math.hypot(dx, dy)        # 确定移动的方位向量        self.move_x = dx / dis        self.move_y = dy / dis    def move(self):        # 移动        self.x += self.move_x * self.speed        self.y += self.move_y * self.speed

设置x,y方向上的移动距离图示:

2)在创建病毒的方法中,调用setMoveXY()函数,设置病毒移动的初始方向

3)创建move_virus(virus_list)函数,能让所有病毒都移动

def move_virus(virus_list):    for i in range(len(virus_list)):        virus_list[i].move()

4)在while running中调用病毒移动的方法,让该函数生效

2.4 越界监测与碰撞监测

任务5:在游戏窗口指定位置显示游戏轮数与卫士的生命值

1)创建fill_text(text, position)显示文字函数,用于后续显示相关文字

def fill_text(text, position):    textFont = pygame.font.Font("./fonts/WRYH.ttf", 25)    newText = textFont.render(text, True, (255, 0, 0))    screen.blit(newText, position)

2)在while running中调用该方法显示需要显示的文字

任务6:如果所有病毒已经超过游戏界面的范围,则新的一轮病毒开始攻击

1)创建outSide(virus_list)方法,监测病毒是否已经越界,如果已经越界,则移除该病毒

def outSide(virus_list):    for i in range(len(virus_list)):        virus = virus_list[i]        if virus.x <= -virus_width or virus.x >= width or virus.y <= -virus_height or virus.y >= height:            virus_list.remove(virus)            break

2)在while running中调用该方法

任务7:碰撞检测,如果卫士碰到病毒,病毒消失,卫士的生命值减1,如果卫士坚持5轮病毒,则游戏胜利,显示胜利背景,如果卫士的生命值为0,则游戏失败,显示失败背景

1)创建碰撞监测函数collision(virus_list, boy)用于监测病毒和卫士之间是否有碰撞

如上图,以病毒图片的矩形红框为参照物,如果不在这个范围内,则没有碰撞

def collision(virus_list, boy):    for i in range(len(virus_list)):        virus = virus_list[i]        # 矩形范围监测        if boy.x < virus.x - boy.width or boy.x > virus.x + virus.width:            return False        if boy.y < virus.y - boy.height or boy.y > virus.y + virus.height:            return False

但是即使处在矩形范围内,仍有可能没有碰撞,因为卫士图片矩形和病毒图片矩形之间仍然有空白缝隙,则可以做像素级别的碰撞监测

def collision(virus_list, boy):    for i in range(len(virus_list)):        virus = virus_list[i]        # 矩形范围监测        if boy.x < virus.x - boy.width or boy.x > virus.x + virus.width:            return False        if boy.y < virus.y - boy.height or boy.y > virus.y + virus.height:            return False        # 像素级别监测        virus_alpha = virus.img        boy_alpha = boy.img        for x in range(virus_alpha.get_width()):            for y in range(virus_alpha.get_height()):                # 如果这一点不是透明的                if virus_alpha.get_at((x, y)) != (0, 0, 0, 0):                    # 获取这一点在窗口上的位置                    xx, yy = x + virus.x, y + virus.y                    # 获取这一点相对于卫士的位置                    xxx, yyy = int(xx - boy.x), int(yy - boy.y)                    # 如果在卫士的图片范围内,且卫士的这一点也不是透明的,则说明撞上了                    if (0 <= xxx <= boy.width and 0 <= yyy <= boy.height                            and boy_alpha.get_at((xxx, yyy)) != (0, 0, 0, 0)):                        virus_list.remove(virus)  # 如果碰到了,病毒消失                        return True        return False

点击“阅读原文”获取资源

最新文章

随机文章