当前位置:首页>python>Python实战-植物大战僵尸

Python实战-植物大战僵尸

  • 2026-10-25 20:56:32
Python实战-植物大战僵尸

一、作品展示

二、作品分析与制作

2.1 创建窗口与加载背景

任务1:创建一个合适大小(长1100,宽600)的游戏窗口,设置游戏窗口的标题,加载植物大战僵尸的背景图片,显示在游戏窗口上,点击关闭窗口按钮,窗口关闭

import pygame# 初始化pygame环境pygame.init()# 设置一个长为1100,宽为600的窗口screen = pygame.display.set_mode((1100, 600))# 设置窗口标题pygame.display.set_caption("植物大战僵尸")# 背景图片加载bg_img = pygame.image.load("./img/bg_play.jpg")running = Truewhile running:    # 将背景显示在窗口上    screen.blit(bg_img, (0, 0))    # 监测游戏窗口事件    for event in pygame.event.get():        # 如果是退出事件,游戏退出        if event.type == pygame.QUIT:            running = False            pygame.quit()    # 刷新游戏画面    pygame.display.flip()

2.2 坚果

2.2.1 坚果静态显示

任务2:定义一个坚果类,包含init初始化函数和paint显示函数。

初始化函数中初始化坚果的大小(宽高)、位置和造型。

显示函数实现将坚果显示在窗口上。实现坚果静态显示在窗口上的效果。

1)加载坚果的相关造型图片

# 坚果图片加载nut1 = pygame.image.load('./img/plants/TallNut.gif')nut2 = pygame.image.load('./img/plants/TallnutCracked1.gif')nut3 = pygame.image.load('./img/plants/TallnutCracked2.gif')

2)定义坚果类

# 坚果类class Tallnut():    # 初始化    def __init__(self):        # 初始化位置        self.x = 500        self.y = 250        # 初始化大小        self.width = 83        self.height = 119        # 初始化造型        self.image = nut1    # 显示    def paint(self):        screen.blit(self.image, (self.x, self.y))

3)创建坚果对象,显示在游戏窗口上

2.2.2 坚果动态显示

任务3:将坚果的静态显示优化成动态显示

1)安装PIL模块

pip install pillow

2)导入PIL模块中的Image和ImageSequence

from PIL import Image, ImageSequence

3)加载坚果gif图的所有帧

# 坚果加载动图,获取所有帧nuts1 = []with open('./img/plants/TallNut.gif', 'rb') as f:    for frame in ImageSequence.Iterator(Image.open(f)):        image = frame.convert()        image = pygame.image.frombuffer(image.tobytes(), image.size, image.mode)        nuts1.append(image)nuts2 = []with open('./img/plants/TallnutCracked1.gif', 'rb') as f:    for frame in ImageSequence.Iterator(Image.open(f)):        image = frame.convert()        image = pygame.image.frombuffer(image.tobytes(), image.size, image.mode)        nuts2.append(image)nuts3 = []with open('./img/plants/TallnutCracked2.gif', 'rb') as f:    for frame in ImageSequence.Iterator(Image.open(f)):        image = frame.convert()        image = pygame.image.frombuffer(image.tobytes(), image.size, image.mode)        nuts3.append(image)

4)优化上诉代码,创建加载gif图片返回图片列表的函数load_gif()

def load_gif(path):    nuts = []    with open(path, 'rb') as f:        for frame in ImageSequence.Iterator(Image.open(f)):            image = frame.convert()            image = pygame.image.frombuffer(image.tobytes(), image.size, image.mode)            nuts.append(image)    return nuts# 加载坚果gif图片,获取所有帧nuts1 = load_gif('./img/plants/TallNut.gif')nuts2 = load_gif('./img/plants/TallnutCracked1.gif')nuts3 = load_gif('./img/plants/TallnutCracked2.gif')

5)修改坚果类的初始化函数和显示函数

6)此时坚果仍然是静态的,如何让坚果动起来呢?定义播放动画animation函数修改显示的造型编号

7)调用这个函数

8)解决造型变化太快的问题

2.3 僵尸

任务4:定义一个僵尸类,僵尸有三种状态(移动、站立和攻击),包含初始化函数、显示函数和播放动画函数,将僵尸动态显示在游戏界面上

1)创建一个方法load_images加载僵尸三种状态的所有图片

# 加载多个图片,返回一个造型列表def load_images(path, suffix, start, end):    images = []    for i in range(start, end + 1):        image_name = "%02d%s" % (i, suffix)        img = pygame.image.load(path + image_name)        images.append(img)    return images# 僵尸的三种状态设置,移动,站立,攻击MOVE, STAND, ATTACK = 0, 1, 2# 将僵尸三种状态的图片加载zombieM = load_images('./img/move/', '.png', 1, 13)zombieS = load_images('./img/stand/', '.png', 21, 26)zombieA = load_images('./img/attack/', '.png', 31, 41)

2)定义一个僵尸类,同样的有三个函数,初始化函数,显示函数,移动函数和播放动画函数

初始化函数:初始化僵尸的位置大小状态和造型

显示函数:将僵尸显示在游戏窗口的指定位置

移动函数:僵尸从右往左移动,即x坐标减小

播放动画函数:根据3种不同的状态播放指定的动画

①移动状态,僵尸播放移动的造型,并从右到左移动

②站立状态,僵尸播放站立的造型,位置不变

③攻击状态,僵尸播放攻击的造型,位置不变

class Zombie():    def __init__(self):        # 初始化位置        self.x = 1000        self.y = 210        # 初始化大小        self.width = 180        self.height = 180        # 初始化状态        self.state = MOVE        # 初始化造型        self.images = zombieM        self.images_index = 0  # 起始造型的下标    def paint(self):        screen.blit(self.images[self.images_index], (self.x, self.y))    def move(self):        self.x -= 10    def animation(self):        if self.state == MOVE:  # 移动            self.images = zombieM            self.move()  # 移动        elif self.state == STAND:  # 站立            self.images = zombieS        else:  # 攻击            self.images = zombieA        self.images_index = (self.images_index + 1) % len(self.images)

3)创建一个僵尸对象,显示在游戏界面并播放相关动画

2.4 碰撞检测

任务5:

如果僵尸碰到了坚果,僵尸变成攻击状态

坚果被攻击后,随着生命值的减少,会展示不同的造型,直到生命值为0,坚果消失

僵尸继续移动的窗口的左方后,站立在原地不动,显示提示信息,直到玩家关闭游戏窗口

1)在坚果的初始化方法中,将坚果的生命值初始化为66

2)在全局中创建一个检测碰到的函数check()

思考1:如何进行碰撞检测?碰撞检测实际上检测的是什么?

回答1:碰撞检测实际上检测的是僵尸和坚果的图片坐标是否有重合的地方,如果有重合的地方则,说明碰撞上了,如下方左图

思考2:为什么真实写代码是小于等于nut.x+nut.width / 2而不是nut.x+nut.width?

回答2:width和height是整个图片的宽高,而不是图片中角色的宽高,如上诉右图。在本作品中如果使用图片的宽高,显示的效果是,两者还有很宽的距离,僵尸就已经在攻击了,不符合常理,所以需要除以2,更符合实际情况

def check(zom, nut):    # 僵尸碰到了坚果    if zom.x <= nut.x + nut.width / 2:        # 僵尸的状态设置为攻击状态        zom.state = ATTACK        # 坚果被攻击后,随着生命值的减少,造型也跟着变化        if nut.life > 44:            nut.images = nuts1        elif nut.life > 22:            nut.images = nuts2        elif nut.life > 0:            nut.images = nuts3        elif zom.x > 200:  # 僵尸还没走到门口,继续移动            zom.state = MOVE            return        nut.life -= 1  # 生命值减少

3)调用check()函数,坚果生命值小于0时,不显示,僵尸到达门口,僵尸变成站立状态,显示结束提示语

点击“阅读原文”获取素材

最新文章

随机文章