学习 Python 之 Pygame 开发魂斗罗(七)

news2024/11/23 18:57:07

学习 Python 之 Pygame 开发魂斗罗(七)

    • 继续编写魂斗罗
      • 1. 载入水中图片并添加在水中的标志
      • 2. 修改玩家类函数
      • 3. 增加河的碰撞体
      • 4. 实现玩家在河中的样子

继续编写魂斗罗

在上次的博客学习 Python 之 Pygame 开发魂斗罗(六)中,我们实现玩家跳上和跳下,这次我们完成让玩家可以跳到水里

在水中,玩家的姿势会变得不一样,下面我们来实现一下

下面是图片的素材

链接:https://pan.baidu.com/s/1X7tESkes_O6nbPxfpHD6hQ?pwd=hdly
提取码:hdly

1. 载入水中图片并添加在水中的标志

在玩家类的__init__()函数加载图片

# 加载玩家在水中的图片
self.upRightImageInWater = loadImage('../Image/Player/Player1/Water/up.png')
self.upLeftImageInWater = loadImage('../Image/Player/Player1/Water/up.png', True)
self.diveRightImageInWater = loadImage('../Image/Player/Player1/Water/dive.png')
self.diveLeftImageInWater = loadImage('../Image/Player/Player1/Water/dive.png', True)
self.standRightImageInWater = loadImage('../Image/Player/Player1/Water/stand.png')
self.standLeftImageInWater = loadImage('../Image/Player/Player1/Water/stand.png', True)
self.fireRightInWater = loadImage('../Image/Player/Player1/Water/standFire.png')
self.fireLeftInWater = loadImage('../Image/Player/Player1/Water/standFire.png', True)
self.obliqueRightInWater = loadImage('../Image/Player/Player1/Water/obliqueRight.png')
self.obliqueLeftInWater = loadImage('../Image/Player/Player1/Water/obliqueRight.png', True)
self.rightInWaterImage = loadImage('../Image/Player/Player1/Water/inWater.png')
self.leftInWaterImage = loadImage('../Image/Player/Player1/Water/inWater.png', True)

在这里插入图片描述

并且设置在水中的标志

self.isInWater = False

在这里插入图片描述

2. 修改玩家类函数

接下来我们把玩家类的函数进行调整

把原来update()函数中圈出的代码,写成一个函数landUpdate()

在这里插入图片描述

def landUpdate(self):
    # 跳跃状态
    if self.isJumping:
        # 根据方向
        if self.direction == Direction.RIGHT:
            # 方向向右,角色加载向右跳起的图片
            self.image = self.upRightImages[self.upImageIndex]
        else:
            # 否则,方向向左,角色加载向左跳起的图片
            self.image = self.upLeftImages[self.upImageIndex]

    # 角色蹲下
    if self.isSquating:
        if self.direction == Direction.RIGHT:
            # 加载向右蹲下的图片
            self.image = self.downRightImage
        else:
            # 加载向左蹲下的图片
            self.image = self.downLeftImage

    # 角色站着
    if self.isStanding:
        if self.direction == Direction.RIGHT:
            if self.isUp:
                # 加载向右朝上的图片
                self.image = self.upRightImage
            elif self.isDown:
                # 加载向右蹲下的图片
                self.image = self.downRightImage
            else:
                # 加载向右站着的图片
                self.image = self.standRightImage
        else:
            # 向左也是同样的效果
            if self.isUp:
                self.image = self.upLeftImage
            elif self.isDown:
                self.image = self.downLeftImage
            else:
                self.image = self.standLeftImage

    # 角色移动
    if self.isWalking:
        if self.direction == Direction.RIGHT:
            if self.isUp:
                # 加载斜右上的图片
                self.image = self.obliqueUpRightImages[self.obliqueImageIndex]
            elif self.isDown:
                # 加载斜右下的图片
                self.image = self.obliqueDownRightImages[self.obliqueImageIndex]
            else:
                # 加载向右移动的图片,根据开火状态是否加载向右开火移动的图片
                if self.isFiring:
                    self.image = self.rightFireImages[self.imageIndex]
                else:
                    self.image = self.rightImages[self.imageIndex]
        else:
            if self.isUp:
                self.image = self.obliqueUpLeftImages[self.obliqueImageIndex]
            elif self.isDown:
                self.image = self.obliqueDownLeftImages[self.obliqueImageIndex]
            else:
                if self.isFiring:
                    self.image = self.leftFireImages[self.imageIndex]
                else:
                    self.image = self.leftImages[self.imageIndex]

这个函数的作用是,如果玩家在陆地上,就按照这个函数来显示玩家的图片

我们再加一个waterUpdate()函数,作用是,如果玩家在水中,就按照这个函数来显示玩家的图片

def waterUpdate(self):
    pass

里面的代码稍后写

之后把这两个函数在update()函数中调用一下

def update(self, keys, currentTime, playerBulletList):
    # 更新站或者走的状态
    # 根据状态响应按键
    if self.state == State.STAND:
        self.standing(keys, currentTime, playerBulletList)
    elif self.state == State.WALK:
        self.walking(keys, currentTime, playerBulletList)
    elif self.state == State.JUMP:
        self.jumping(keys, currentTime, playerBulletList)
    elif self.state == State.FALL:
        self.falling(keys, currentTime, playerBulletList)

    # 更新动画
    if self.isInWater:
        self.waterUpdate()
    else:
        self.landUpdate()

在这里插入图片描述
然后呢,我们把玩家开火的代码也单独提出来形成函数

def fire(self, currentTime, playerBulletList):
    self.isFiring = True
    if len(playerBulletList) < PLAYER_BULLET_NUMBER:
        if currentTime - self.fireLastTimer > 150:
            playerBulletList.append(Bullet(self))
            self.fireLastTimer = currentTime

之后在下面的这四个函数中调用一下

在这里插入图片描述
把原来的代码替换成函数

在这里插入图片描述
在这里插入图片描述
其他的函数也是一样

好,这样的话,这一步就完成了

下面我们把walking()函数修改一下
在这里插入图片描述

把圈出的代码提出来写成一个函数

def walkingInLand(self, currentTime):
    # 如果当前是站立的图片
    if self.isStanding:
        # 方向向右,方向向上
        if self.direction == Direction.RIGHT and self.isUp:
            # 设置为向右朝上的图片
            self.image = self.upRightImage
        # 方向向右
        elif self.direction == Direction.RIGHT and not self.isUp:
            # 设置为向右站立的图片
            self.image = self.standRightImage
        elif self.direction == Direction.LEFT and self.isUp:
            self.image = self.upLeftImage
        elif self.direction == Direction.LEFT and not self.isUp:
            self.image = self.standLeftImage
        # 记下当前时间
        self.runLastTimer = currentTime
    else:
        # 如果是走动的图片,先判断方向
        if self.direction == Direction.RIGHT:
            # 设置速度
            self.xSpeed = PLAYER_X_SPEED
            # 根据上下方向觉得是否角色要加载斜射的图片
            if self.isUp or self.isDown:
                # isUp == True表示向上斜射
                # isDown == True表示向下斜射
                # 计算上一次加载图片到这次的时间,如果大于115,即11.5帧,即上次加载图片到这次加载图片之间,已经加载了11张图片
                if currentTime - self.runLastTimer > 115:
                    # 那么就可以加载斜着奔跑的图片
                    # 如果角色加载的图片不是第三张,则加载下一张就行
                    if self.obliqueImageIndex < 2:
                        self.obliqueImageIndex += 1
                    # 否则就加载第一张图片
                    else:
                        self.obliqueImageIndex = 0
                    # 记录变换图片的时间,为下次变换图片做准备
                    self.runLastTimer = currentTime
            # 不是斜射
            else:
                # 加载正常向右奔跑的图片
                if currentTime - self.runLastTimer > 115:
                    if self.imageIndex < 2:
                        self.imageIndex += 1
                    else:
                        self.imageIndex = 0
                    self.runLastTimer = currentTime
        else:
            self.xSpeed = -PLAYER_X_SPEED
            if self.isUp or self.isDown:
                if currentTime - self.runLastTimer > 115:
                    if self.obliqueImageIndex < 2:
                        self.obliqueImageIndex += 1
                    else:
                        self.obliqueImageIndex = 0
                    self.runLastTimer = currentTime
            else:
                if currentTime - self.runLastTimer > 115:
                    if self.imageIndex < 2:
                        self.imageIndex += 1
                    else:
                        self.imageIndex = 0
                    self.runLastTimer = currentTime

把刚才圈出来的部分进行修改

在这里插入图片描述
再创建一个walkingInWater函数

def walkingInWater(self, currentTime):
    pass

完整的代码

import pygame
from Constants import *
from Bullet import Bullet


class PlayerOne(pygame.sprite.Sprite):

    def __init__(self, currentTime):
        pygame.sprite.Sprite.__init__(self)
        # 加载角色图片
        self.standRightImage = loadImage('../Image/Player/Player1/Right/stand.png')
        self.standLeftImage = loadImage('../Image/Player/Player1/Left/stand.png')
        self.upRightImage = loadImage('../Image/Player/Player1/Up/upRight(small).png')
        self.upLeftImage = loadImage('../Image/Player/Player1/Up/upLeft(small).png')
        self.downRightImage = loadImage('../Image/Player/Player1/Down/down.png')
        self.downLeftImage = loadImage('../Image/Player/Player1/Down/down.png', True)
        self.obliqueUpRightImages = [
            loadImage('../Image/Player/Player1/Up/rightUp1.png'),
            loadImage('../Image/Player/Player1/Up/rightUp2.png'),
            loadImage('../Image/Player/Player1/Up/rightUp3.png'),
        ]
        self.obliqueUpLeftImages = [
            loadImage('../Image/Player/Player1/Up/rightUp1.png', True),
            loadImage('../Image/Player/Player1/Up/rightUp2.png', True),
            loadImage('../Image/Player/Player1/Up/rightUp3.png', True),
        ]
        self.obliqueDownRightImages = [
            loadImage('../Image/Player/Player1/ObliqueDown/1.png'),
            loadImage('../Image/Player/Player1/ObliqueDown/2.png'),
            loadImage('../Image/Player/Player1/ObliqueDown/3.png'),
        ]
        self.obliqueDownLeftImages = [
            loadImage('../Image/Player/Player1/ObliqueDown/1.png', True),
            loadImage('../Image/Player/Player1/ObliqueDown/2.png', True),
            loadImage('../Image/Player/Player1/ObliqueDown/3.png', True),
        ]
        # 角色向右的全部图片
        self.rightImages = [
            loadImage('../Image/Player/Player1/Right/run1.png'),
            loadImage('../Image/Player/Player1/Right/run2.png'),
            loadImage('../Image/Player/Player1/Right/run3.png')
        ]
        # 角色向左的全部图片
        self.leftImages = [
            loadImage('../Image/Player/Player1/Left/run1.png'),
            loadImage('../Image/Player/Player1/Left/run2.png'),
            loadImage('../Image/Player/Player1/Left/run3.png')
        ]
        # 角色跳跃的全部图片
        self.upRightImages = [
            loadImage('../Image/Player/Player1/Jump/jump1.png'),
            loadImage('../Image/Player/Player1/Jump/jump2.png'),
            loadImage('../Image/Player/Player1/Jump/jump3.png'),
            loadImage('../Image/Player/Player1/Jump/jump4.png'),
        ]
        self.upLeftImages = [
            loadImage('../Image/Player/Player1/Jump/jump1.png', True),
            loadImage('../Image/Player/Player1/Jump/jump2.png', True),
            loadImage('../Image/Player/Player1/Jump/jump3.png', True),
            loadImage('../Image/Player/Player1/Jump/jump4.png', True),
        ]
        self.rightFireImages = [
            loadImage('../Image/Player/Player1/Right/fire1.png'),
            loadImage('../Image/Player/Player1/Right/fire2.png'),
            loadImage('../Image/Player/Player1/Right/fire3.png'),
        ]
        self.leftFireImages = [
            loadImage('../Image/Player/Player1/Right/fire1.png', True),
            loadImage('../Image/Player/Player1/Right/fire2.png', True),
            loadImage('../Image/Player/Player1/Right/fire3.png', True),
        ]
        # 加载玩家在水中的图片
        self.upRightImageInWater = loadImage('../Image/Player/Player1/Water/up.png')
        self.upLeftImageInWater = loadImage('../Image/Player/Player1/Water/up.png', True)
        self.diveRightImageInWater = loadImage('../Image/Player/Player1/Water/dive.png')
        self.diveLeftImageInWater = loadImage('../Image/Player/Player1/Water/dive.png', True)
        self.standRightImageInWater = loadImage('../Image/Player/Player1/Water/stand.png')
        self.standLeftImageInWater = loadImage('../Image/Player/Player1/Water/stand.png', True)
        self.fireRightInWater = loadImage('../Image/Player/Player1/Water/standFire.png')
        self.fireLeftInWater = loadImage('../Image/Player/Player1/Water/standFire.png', True)
        self.obliqueRightInWater = loadImage('../Image/Player/Player1/Water/obliqueRight.png')
        self.obliqueLeftInWater = loadImage('../Image/Player/Player1/Water/obliqueRight.png', True)
        self.rightInWaterImage = loadImage('../Image/Player/Player1/Water/inWater.png')
        self.leftInWaterImage = loadImage('../Image/Player/Player1/Water/inWater.png', True)
        # 角色左右移动下标
        self.imageIndex = 0
        # 角色跳跃下标
        self.upImageIndex = 0
        # 角色斜射下标
        self.obliqueImageIndex = 0
        # 上一次显示图片的时间
        self.runLastTimer = currentTime
        self.fireLastTimer = currentTime

        # 选择当前要显示的图片
        self.image = self.standRightImage
        # 获取图片的rect
        self.rect = self.image.get_rect()
        # 设置角色的状态
        self.state = State.FALL
        # 角色的方向
        self.direction = Direction.RIGHT
        # 速度
        self.xSpeed = PLAYER_X_SPEED
        self.ySpeed = 0
        self.jumpSpeed = -11
        # 人物当前的状态标志
        self.isStanding = False
        self.isWalking = False
        self.isJumping = True
        self.isSquating = False
        self.isFiring = False
        self.isInWater = False
        # 重力加速度
        self.gravity = 0.8

        # 玩家上下方向
        self.isUp = False
        self.isDown = False

    def update(self, keys, currentTime, playerBulletList):
        # 更新站或者走的状态
        # 根据状态响应按键
        if self.state == State.STAND:
            self.standing(keys, currentTime, playerBulletList)
        elif self.state == State.WALK:
            self.walking(keys, currentTime, playerBulletList)
        elif self.state == State.JUMP:
            self.jumping(keys, currentTime, playerBulletList)
        elif self.state == State.FALL:
            self.falling(keys, currentTime, playerBulletList)

        # 更新动画
        if self.isInWater:
            self.waterUpdate()
        else:
            self.landUpdate()

    def landUpdate(self):
        # 跳跃状态
        if self.isJumping:
            # 根据方向
            if self.direction == Direction.RIGHT:
                # 方向向右,角色加载向右跳起的图片
                self.image = self.upRightImages[self.upImageIndex]
            else:
                # 否则,方向向左,角色加载向左跳起的图片
                self.image = self.upLeftImages[self.upImageIndex]

        # 角色蹲下
        if self.isSquating:
            if self.direction == Direction.RIGHT:
                # 加载向右蹲下的图片
                self.image = self.downRightImage
            else:
                # 加载向左蹲下的图片
                self.image = self.downLeftImage

        # 角色站着
        if self.isStanding:
            if self.direction == Direction.RIGHT:
                if self.isUp:
                    # 加载向右朝上的图片
                    self.image = self.upRightImage
                elif self.isDown:
                    # 加载向右蹲下的图片
                    self.image = self.downRightImage
                else:
                    # 加载向右站着的图片
                    self.image = self.standRightImage
            else:
                # 向左也是同样的效果
                if self.isUp:
                    self.image = self.upLeftImage
                elif self.isDown:
                    self.image = self.downLeftImage
                else:
                    self.image = self.standLeftImage

        # 角色移动
        if self.isWalking:
            if self.direction == Direction.RIGHT:
                if self.isUp:
                    # 加载斜右上的图片
                    self.image = self.obliqueUpRightImages[self.obliqueImageIndex]
                elif self.isDown:
                    # 加载斜右下的图片
                    self.image = self.obliqueDownRightImages[self.obliqueImageIndex]
                else:
                    # 加载向右移动的图片,根据开火状态是否加载向右开火移动的图片
                    if self.isFiring:
                        self.image = self.rightFireImages[self.imageIndex]
                    else:
                        self.image = self.rightImages[self.imageIndex]
            else:
                if self.isUp:
                    self.image = self.obliqueUpLeftImages[self.obliqueImageIndex]
                elif self.isDown:
                    self.image = self.obliqueDownLeftImages[self.obliqueImageIndex]
                else:
                    if self.isFiring:
                        self.image = self.leftFireImages[self.imageIndex]
                    else:
                        self.image = self.leftImages[self.imageIndex]

    def waterUpdate(self):
        pass

    def standing(self, keys, currentTime, playerBulletList):
        """角色站立"""

        # 设置角色状态
        self.isStanding = True
        self.isWalking = False
        self.isJumping = False
        self.isSquating = False
        self.isUp = False
        self.isDown = False
        self.isFiring = False

        # 设置速度
        self.ySpeed = 0
        self.xSpeed = 0

        # 按下A键
        if keys[pygame.K_a]:
            # A按下,角色方向向左
            self.direction = Direction.LEFT
            # 改变角色的状态,角色进入移动状态
            self.state = State.WALK
            # 设置站立状态为False,移动状态为True
            self.isStanding = False
            self.isWalking = True
            # 向左移动,速度为负数,这样玩家的x坐标是减小的
            self.xSpeed = -PLAYER_X_SPEED
        # 按下D键
        elif keys[pygame.K_d]:
            # D按下,角色方向向右
            self.direction = Direction.RIGHT
            # 改变角色的状态,角色进入移动状态
            self.state = State.WALK
            # 设置站立状态为False,移动状态为True
            self.isStanding = False
            self.isWalking = True
            # 向右移动,速度为正数
            self.xSpeed = PLAYER_X_SPEED
        # 按下k键
        elif keys[pygame.K_k]:
            # K按下,角色进入跳跃状态,但是不会改变方向
            self.state = State.JUMP
            # 设置站立状态为False,跳跃状态为True
            # 不改变移动状态,因为移动的时候也可以跳跃
            self.isStanding = False
            self.isJumping = True
            # 设置速度,速度为负数,因为角色跳起后,要下落
            self.isUp = True
            self.ySpeed = self.jumpSpeed
        # 没有按下按键
        else:
            # 没有按下按键,角色依然是站立状态
            self.state = State.STAND
            self.isStanding = True

        # 按下w键
        if keys[pygame.K_w]:
            # W按下,角色向上,改变方向状态
            self.isUp = True
            self.isStanding = True
            self.isDown = False
            self.isSquating = False
        # 按下s键
        elif keys[pygame.K_s]:
            # S按下,角色蹲下,改变方向状态,并且蹲下状态设置为True
            self.isUp = False
            self.isStanding = False
            self.isDown = True
            self.isSquating = True

        if keys[pygame.K_j]:
            self.fire(currentTime, playerBulletList)

    def walking(self, keys, currentTime, playerBulletList):
        """角色行走,每10帧变换一次图片"""
        self.isStanding = False
        self.isWalking = True
        self.isJumping = False
        self.isSquating = False
        self.isFiring = False
        self.ySpeed = 0
        self.xSpeed = PLAYER_X_SPEED

        if self.isInWater:
            self.walkingInWater(currentTime)
        else:
            self.walkingInLand(currentTime)

        # 按下D键
        if keys[pygame.K_d]:
            self.direction = Direction.RIGHT
            self.xSpeed = PLAYER_X_SPEED
        # 按下A键
        elif keys[pygame.K_a]:
            self.direction = Direction.LEFT
            self.xSpeed = -PLAYER_X_SPEED
         # 按下S键
        elif keys[pygame.K_s]:
            self.isStanding = False
            self.isDown = True

        # 按下W键
        if keys[pygame.K_w]:
            self.isUp = True
            self.isDown = False
        # 没有按键按下
        else:
            self.state = State.STAND

        # 移动时按下K键
        if keys[pygame.K_k]:
            # 角色状态变为跳跃
            self.state = State.JUMP
            self.ySpeed = self.jumpSpeed
            self.isJumping = True
            self.isStanding = False
            self.isUp = True

        if keys[pygame.K_j]:
            self.fire(currentTime, playerBulletList)

    def walkingInLand(self, currentTime):
        # 如果当前是站立的图片
        if self.isStanding:
            # 方向向右,方向向上
            if self.direction == Direction.RIGHT and self.isUp:
                # 设置为向右朝上的图片
                self.image = self.upRightImage
            # 方向向右
            elif self.direction == Direction.RIGHT and not self.isUp:
                # 设置为向右站立的图片
                self.image = self.standRightImage
            elif self.direction == Direction.LEFT and self.isUp:
                self.image = self.upLeftImage
            elif self.direction == Direction.LEFT and not self.isUp:
                self.image = self.standLeftImage
            # 记下当前时间
            self.runLastTimer = currentTime
        else:
            # 如果是走动的图片,先判断方向
            if self.direction == Direction.RIGHT:
                # 设置速度
                self.xSpeed = PLAYER_X_SPEED
                # 根据上下方向觉得是否角色要加载斜射的图片
                if self.isUp or self.isDown:
                    # isUp == True表示向上斜射
                    # isDown == True表示向下斜射
                    # 计算上一次加载图片到这次的时间,如果大于115,即11.5帧,即上次加载图片到这次加载图片之间,已经加载了11张图片
                    if currentTime - self.runLastTimer > 115:
                        # 那么就可以加载斜着奔跑的图片
                        # 如果角色加载的图片不是第三张,则加载下一张就行
                        if self.obliqueImageIndex < 2:
                            self.obliqueImageIndex += 1
                        # 否则就加载第一张图片
                        else:
                            self.obliqueImageIndex = 0
                        # 记录变换图片的时间,为下次变换图片做准备
                        self.runLastTimer = currentTime
                # 不是斜射
                else:
                    # 加载正常向右奔跑的图片
                    if currentTime - self.runLastTimer > 115:
                        if self.imageIndex < 2:
                            self.imageIndex += 1
                        else:
                            self.imageIndex = 0
                        self.runLastTimer = currentTime
            else:
                self.xSpeed = -PLAYER_X_SPEED
                if self.isUp or self.isDown:
                    if currentTime - self.runLastTimer > 115:
                        if self.obliqueImageIndex < 2:
                            self.obliqueImageIndex += 1
                        else:
                            self.obliqueImageIndex = 0
                        self.runLastTimer = currentTime
                else:
                    if currentTime - self.runLastTimer > 115:
                        if self.imageIndex < 2:
                            self.imageIndex += 1
                        else:
                            self.imageIndex = 0
                        self.runLastTimer = currentTime

    def walkingInWater(self, currentTime):
        pass

    def jumping(self, keys, currentTime, playerBulletList):
        """跳跃"""
        # 设置标志
        self.isJumping = True
        self.isStanding = False
        self.isDown = False
        self.isSquating = False
        self.isFiring = False
        # 更新速度
        self.ySpeed += self.gravity
        if currentTime - self.runLastTimer > 115:
            if self.upImageIndex < 3:
                self.upImageIndex += 1
            else:
                self.upImageIndex = 0
            # 记录变换图片的时间,为下次变换图片做准备
            self.runLastTimer = currentTime

        if keys[pygame.K_d]:
            self.direction = Direction.RIGHT

        elif keys[pygame.K_a]:
            self.direction = Direction.LEFT

        # 按下W键
        if keys[pygame.K_w]:
            self.isUp = True
            self.isDown = False
        elif keys[pygame.K_s]:
            self.isUp = False
            self.isDown = True

        if self.ySpeed >= 0:
            self.state = State.FALL

        if not keys[pygame.K_k]:
            self.state = State.FALL

        if keys[pygame.K_j]:
            self.fire(currentTime, playerBulletList)

    def falling(self, keys, currentTime, playerBulletList):
        # 下落时速度越来越快,所以速度需要一直增加
        self.ySpeed += self.gravity
        if currentTime - self.runLastTimer > 115:
            if self.upImageIndex < 3:
                self.upImageIndex += 1
            else:
                self.upImageIndex = 0
            self.runLastTimer = currentTime

        if keys[pygame.K_d]:
            self.direction = Direction.RIGHT
            self.isWalking = False

        elif keys[pygame.K_a]:
            self.direction = Direction.LEFT
            self.isWalking = False

        if keys[pygame.K_j]:
            self.fire(currentTime, playerBulletList)

    def fire(self, currentTime, playerBulletList):
        self.isFiring = True
        if len(playerBulletList) < PLAYER_BULLET_NUMBER:
            if currentTime - self.fireLastTimer > 150:
                playerBulletList.append(Bullet(self))
                self.fireLastTimer = currentTime

3. 增加河的碰撞体

我们修改主类代码,增加河的碰撞体

首先增加一个列表,用来存放河的碰撞体

在这里插入图片描述
其次,创建初始化河碰撞体函数,并把河碰撞体列表放入总的碰撞体列表

def initRiver(self):
    river1 = Collider(0, 215 * MAP_SCALE, 289 * MAP_SCALE, LAND_THICKNESS * MAP_SCALE, (0, 0, 255))
    river2 = Collider(880, 215 * MAP_SCALE, 255 * MAP_SCALE, LAND_THICKNESS * MAP_SCALE, (0, 0, 255))
    river3 = Collider(1680, 215 * MAP_SCALE, 737 * MAP_SCALE, LAND_THICKNESS * MAP_SCALE, (0, 0, 255))
    MainGame.riverGroup.add(river1)
    MainGame.riverGroup.add(river2)
    MainGame.riverGroup.add(river3)
    MainGame.colliderGroup.add(MainGame.riverGroup)

这里Collider()构造函数中要多一个参数,表示颜色,我们等下修改一下

之后,在update()函数中调用

def update(self, window, player1BulletList):
    # 加载背景
    window.blit(self.background, self.backRect)
    # 更新物体
    currentTime = pygame.time.get_ticks()
    MainGame.allSprites.update(self.keys, currentTime, player1BulletList)
    self.updatePlayerPosition()
    drawPlayerOneBullet(player1BulletList)
    # 摄像机移动
    self.camera()
    # 显示物体
    MainGame.allSprites.draw(window)
    for collider in MainGame.landGroup:
        r = collider.draw(window, self.player1.rect.y)
        # 如果没有画出来,表示玩家高度低于直线,所有把直线从组中删除
        if not r:
            # 删除前先检查一下是不是在组中
            if collider in MainGame.colliderGroup:
                # 删除并加入栈
                MainGame.colliderStack.insert(0, collider)
                MainGame.colliderGroup.remove(collider)
        else:
            # 如果画出来了,判断一下玩家距离是否高于线的距离
            if collider.rect.y > self.player1.rect.bottom:
                # 如果是的话,且冲突栈不为空,那么从栈中取出一个元素放入冲突组,最前面的元素一定是先如队列的
                if len(MainGame.colliderStack) > 0:
                    f = MainGame.colliderStack.pop()
                    MainGame.colliderGroup.add(f)
    MainGame.riverGroup.draw(window)

然后再修改一下Collider类的__init__()函数

def __init__(self, x, y, width, height, color = (255, 0, 0)):
    pygame.sprite.Sprite.__init__(self)

    self.image = pygame.Surface((width, height)).convert()
    self.image.fill(color)
    self.rect = self.image.get_rect()
    self.rect.x = x
    self.rect.y = y

使创建的冲突默认为红色显示

最后在主类的__init__()函数中,把initRiver()函数调用一下

在这里插入图片描述
现在我们运行一下,看看效果

在这里插入图片描述
河的碰撞体出现了,我们人物可以站在上面

4. 实现玩家在河中的样子

当我掉落到河里时,应该是游泳的状态,我们要设置一下,在碰撞体那里设置

修改updatePlayerPosition()函数

增加代码

# 检测碰撞
# 这里是玩家和所有碰撞组中的碰撞体检测碰撞,如果发生了碰撞,就会返回碰撞到的碰撞体对象
collider = pygame.sprite.spritecollideany(self.player1, MainGame.colliderGroup)
# 如果发生碰撞,判断是不是在河里
if collider in MainGame.riverGroup:
    # 在河里设置isInWater
    self.player1.isInWater = True
    # 设置玩家在河里不能跳跃
    self.player1.isJumping = False
    # 默认落下去是站在河里的
    self.player1.isStanding = True
    # 玩家方向不能向下
    self.player1.isDown = False
    # 根据玩家方向,加载落入河中的一瞬间的图片
    if self.player1.direction == Direction.RIGHT:
        self.player1.image = self.player1.rightInWaterImage
    else:
        self.player1.image = self.player1.leftInWaterImage
# 判断是不是在陆地上
elif collider in MainGame.landGroup:
        self.player1.isInWater = False

在这里插入图片描述
在这里插入图片描述
这里主要是判断碰撞体是陆地还是河,如果是河就要把 isInWater 设置为True,这样在显示人物图片的时候,就能够显示人在河里的图片

这个代码

# 根据玩家方向,加载落入河中的一瞬间的图片
if self.player1.direction == Direction.RIGHT:
    self.player1.image = self.player1.rightInWaterImage
else:
    self.player1.image = self.player1.leftInWaterImage

用来设置落入河中的一瞬间的图片,即下面的图片

在这里插入图片描述

这幅图是玩家落水溅出水花的图片

下面是完整的updatePlayerPosition()函数

def updatePlayerPosition(self):
    # 在index的循环次数中,不进行碰撞检测,用来让玩家向下跳跃
    if self.index > 0:
        self.index -= 1
        self.player1.rect.x += self.player1.xSpeed
        self.player1.rect.y += self.player1.ySpeed
        self.player1.isDown = False
    else:
        # 首先更新y的位置
        self.player1.rect.y += self.player1.ySpeed
        # 玩家向下跳跃,35次循环内不进行碰撞检测
        if self.player1.state == State.JUMP and self.player1.isDown:
            self.index = 35
        # 玩家向上跳跃,15次循环内不进行碰撞检测
        elif self.player1.state == State.JUMP and self.player1.isUp:
            self.index = 15
        else:
            # 检测碰撞
            # 这里是玩家和所有碰撞组中的碰撞体检测碰撞,如果发生了碰撞,就会返回碰撞到的碰撞体对象
            collider = pygame.sprite.spritecollideany(self.player1, MainGame.colliderGroup)
            # 如果发生碰撞,判断是不是在河里
            if collider in MainGame.riverGroup:
                # 在河里设置isInWater
                self.player1.isInWater = True
                # 设置玩家在河里不能跳跃
                self.player1.isJumping = False
                # 默认落下去是站在河里的
                self.player1.isStanding = True
                # 玩家方向不能向下
                self.player1.isDown = False
                # 根据玩家方向,加载落入河中的一瞬间的图片
                if self.player1.direction == Direction.RIGHT:
                    self.player1.image = self.player1.rightInWaterImage
                else:
                    self.player1.image = self.player1.leftInWaterImage
            # 判断是不是在陆地上
            elif collider in MainGame.landGroup:
                    self.player1.isInWater = False
            # 如果发生碰撞
            if collider:
                # 判断一下人物的y速度,如果大于0,则说明玩家已经接触到了碰撞体表面,需要让玩家站在表面,不掉下去
                if self.player1.ySpeed > 0:
                    self.player1.ySpeed = 0
                    self.player1.state = State.WALK
                    self.player1.rect.bottom = collider.rect.top
            else:
                # 否则的话,我们创建一个玩家的复制
                tempPlayer = copy.copy(self.player1)
                # 让玩家的纵坐标—+1,看看有没有发生碰撞
                tempPlayer.rect.y += 1
                # 如果没有发生碰撞,就说明玩家下面不是碰撞体,是空的
                if not pygame.sprite.spritecollideany(tempPlayer, MainGame.colliderGroup):
                    # 如果此时不是跳跃状态,那么就让玩家变成下落状态,因为玩家在跳跃时,是向上跳跃,不需要对下面的物体进行碰撞检测
                    if tempPlayer.state != State.JUMP:
                        self.player1.state = State.FALL
                tempPlayer.rect.y -= 1

        # 更新x的位置
        self.player1.rect.x += self.player1.xSpeed
        # 同样的检查碰撞
        collider = pygame.sprite.spritecollideany(self.player1, MainGame.colliderGroup)
        # 如果发生了碰撞
        if collider:
            # 判断玩家的x方向速度,如果大于0,表示右边有碰撞体
            if self.player1.xSpeed > 0:
                # 设置玩家的右边等于碰撞体的左边
                self.player1.rect.right = collider.rect.left
            else:
                # 左边有碰撞体
                self.player1.rect.left = collider.rect.right
            self.player1.xSpeed = 0

此时我们运行,会是如下情况

在这里插入图片描述
因为此时是isInWater状态,玩家类的update()函数执行的显示图片的函数是空语句,所以,图片会保持之前的样子,之前我们设置了图片是落水溅出水花的,所以现在我们就看到了上面这幅图片

下面我们对玩家类的waterUpdate()函数进行修改

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/378217.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

csgo搬砖项目详细拆解,附选品+详细操作教程

项目实操 一&#xff1a;项目原理 csgo这款游戏不知道大家玩过没有&#xff0c;如果不了解的话&#xff0c;那你肯定知道穿越火线这款游戏吧&#xff0c;都是一个类型的射击游戏。 说到csgo&#xff0c;就得所以一下今天项目的平台steam&#xff0c;它是一个游戏平台&#x…

Redis面试问题总结

1. 什么是Redis&#xff1f;Redis 是一个使用 C 语言写成的&#xff0c;开源的高性能key-value非关系缓存数据库。它支持存储的value类型相对更多&#xff0c;包括string(字符串)、list(链表)、set(集合)、zset(sorted set --有序集合)和hash&#xff08;哈希类型&#xff09;。…

【Redis】Redis主从同步中数据同步原理

【Redis】Redis主从同步中数据同步原理 文章目录【Redis】Redis主从同步中数据同步原理1. 全量同步1.1 判断是否第一次数据同步2. 增量同步3. 优化Redis主从集群4. 总结1. 全量同步 主从第一次同步是全量同步。 数据同步包括以下三个阶段&#xff1a; 在从节点执行slaveof命令…

技术分担产品之忧(上):挑选有业务专家潜力的人

你好&#xff0c;我是王植萌&#xff0c;去哪儿网的高级技术总监、TC主席。从2014年起&#xff0c;担任一个部门的技术负责人&#xff0c;有8年技术总监经验、5年TC主席的经验。这节课我会从去哪儿网产研融合的经验出发&#xff0c;和你聊一聊怎么让技术分担产品之忧。 技术分…

SSL证书与我们普通人之间有什么关系

对于很多普通人来说&#xff0c;SSL证书似乎会感到很陌生&#xff0c;总觉得离自己很遥远&#xff0c;从而并没有引起察觉。要是这么想的话那么就真的大错特错了&#xff0c;其实SSL证书与我们普通人之间还是很密密相关的&#xff0c;是我们应该都需要关注的&#xff0c;下面就…

cesium学习记录02-vue项目中cesium的配置与使用

1&#xff0c;下载cesium包 &#xff08;当然&#xff0c;使用npm install cesium安装也是可以的&#xff0c;不过在这里选择下载包放到本地&#xff09; 官方下载地址 笔者的cesium版本为1.101 2&#xff0c;将下载的Cesium文件夹放到项目里某个位置 这里&#xff0c;笔者将…

又一个国内类ChatGPT模型?【秘塔科技上线自研LLM大模型「对话写作猫」】

又一个国内类ChatGPT模型&#xff1f;【秘塔科技上线自研LLM大模型「对话写作猫」】 &#xff08;马上被打脸 ~ ~&#xff09; 一直期待中国有没有类ChatGPT产品可以出现。 昨天&#xff0c;2023年2月27日&#xff0c;秘塔科技上线了自研LLM大模型「对话写作猫」&#xff0c;…

全屋Wi-Fi领域「兵戎相见」,鸿雁这一局赢面大不大?

作者 | 牧之 编辑 | 小沐 出品 | 智哪儿 zhinaer.cn相比全屋智能&#xff0c;另一个刚需属性更强&#xff0c;消费规模更大的细分市场&#xff0c;便是全屋Wi-Fi。在这个板块&#xff0c;当鸿雁入局的时候&#xff0c;笔者还是有些许的「诧异」。毕竟&#xff0c;鸿雁给大众的印…

【Vue3】vue3 + ts 封装城市选择组件

城市选择-基本功能 能够封装城市选择组件&#xff0c;并且完成基础的显示隐藏的交互功能 &#xff08;1&#xff09;封装通用组件src/components/city/index.vue <script lang"ts" setup name"City"></script> <template><div class…

【PyTorch】教程:torch.nn.Conv2d

Conv2d CLASS torch.nn.Conv2d(in_channels, out_channels, kernel_size, stride1, padding0, dilation1, groups1, biasTrue, padding_modezeros, deviceNone, dtypeNone) 2D 卷积 out(Ni,Coutj)bias(Coutj)∑k0Cin−1Weight(Coutj,k)∗input(Ni,k)out(N_i, C_{out_j})bias(C_…

k8s环境jenkins发布vue项目指定nodejs版本

k8s环境jenkins发布vue项目指定nodejs版本1、背景2、分析3、解决方法3.1、 找到配置镜像位置3.2、 制作新镜像3.3、 推送镜像到私有仓库3.4、 修改配置文件1、背景 发布一个前端项目&#xff0c;它需要nodejs 16.9.0版本支持&#xff0c;而kubesphere 3.2.0集成的jenkins 的镜…

Hbase2.4.11简单了解_搭建Hbase集群_配置Hbase高可用---大数据之Hbase工作笔记0034

然后我们看一下hbase的集群架构,可以看到跟其他Hadoop系列的架构一样 都是有个master对吧,然后 还有3个region server,然后所有的机器,都连接到zookeeper 然后这里还要注意有个:backup-master103 ,这个是个备用的master 看看master 和 regionserver的作用. master部署到namen…

深度学习之神经网络的优化器篇

神经网络的优化器 文章目录神经网络的优化器GD 梯度下降算法重球法SGD随机梯度下降Momentum动量梯度NAG(Nesterov accelerated gradient)AdaGrad(Adaptive gradient)RMSProp(Root mean square prop)Adam(Adaptive Moment Estimation)AdamWAdan(Adaptive Nesterov Momentum)本片…

cesium学习记录03-QGis数据生产=>Postgis存储=>Geoserver发布=>Cesium调用

说明&#xff1a; 参照文章 1&#xff0c;安装 QGIS 下载安装 &#xff08;前四步就可以了&#xff09; 2&#xff0c;下载安装postgresql 3&#xff0c;下载安装PostGis 4&#xff0c;QGIS连接PostGis 5&#xff0c;QGIS 上传到Postgis 1&#xff0c;QGIS图的图 &…

坚鹏:学习贯彻二十大精神 解码共同富裕之道(面向银行)

学习贯彻二十大精神 解码共同富裕之道课程背景&#xff1a; 很多银行从业人员存在以下问题&#xff1a; 不知道如何准确解读二十大精神&#xff1f; 不清楚共同富裕相关政策要求&#xff1f; 不知道如何有效推动共同富裕&#xff1f; 课程特色&#xff1a; 有实战案例 有…

【C++】STL 模拟实现之 list

文章目录一、list 的常用接口及其使用1、list 一般接口2、list 特殊接口3、list 排序的性能分析二、list 迭代器的实现1、迭代器的分类2、list 迭代器失效问题3、list 迭代器源码分析4、list 迭代器模拟实现4.1 普通迭代器4.2 const 迭代器4.3 完整版迭代器三、list 的模拟实现…

05 封装

在对 context 的封装中&#xff0c;我们只是将 request、response 结构直接放入 context 结构体中&#xff0c;对应的方法并没有很好的封装。 函数封装并不是一件很简单、很随意的事情。相反&#xff0c;如何封装出易用、可读性高的函数是非常需要精心考量的&#xff0c;框架中…

Pwn 二进制漏洞审计

PWN的另一个名字是二进制漏洞审计 Pwn和逆向工程一样&#xff0c;是操作底层二进制的&#xff0c;web则是在php层面进行渗透测试 我是从re开始接触CTF的&#xff0c;有一点二进制基础&#xff0c;本文可能会忽略一些基础知识的补充 ”Pwn”是一个黑客语法的俚语词 &#xff0c;…

JS#1 引入方式和基础语法

JavaScript(JS)是一门跨平台, 面向对象的脚本语言, 来控制网页行为的, 它能够是网页可交互一. 引入方式内部脚本与外部脚本内部脚本: 将JS代码定义在HTML页面中外部脚本: 将JS代码定义在外部JS文件中, 然后引入到HTML页面中注意: 在HTML中,JS代码必须位于<script></sc…

纯手动搭建大数据集群架构_记录008_搭建Hbase集群_配置集群高可用---大数据之Hadoop3.x工作笔记0169

首先准备安装包 然后将安装包分发到集群的其他机器上去 然后因为运行hbase需要zookeeper支持,所以这里首先要去,启动zk 走到/opt/module/hadoop-3.1.3/bin/zk.sh 然后 zk.sh start 启动一下,可以看到启动了已经 然后zk.sh status 可以看zookeeper的状态 然后我们再去启动一下…