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

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

    • 继续编写魂斗罗
      • 1. 在子弹类中修改敌人发射子弹的位置
      • 2. 创建显示敌人子弹的函数
      • 3. 解决敌人不会向下掉落的问题
      • 4. 给敌人碰撞体组增加碰撞体
      • 5. 解决敌人叠加在一起的问题

继续编写魂斗罗

在上次的博客学习 Python 之 Pygame 开发魂斗罗(八)中,我们加入了敌人,但是敌人不能发射子弹,而且也没有碰撞体,接下来我们来实现一下

下面是图片的素材

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

1. 在子弹类中修改敌人发射子弹的位置

敌人和玩家的图片不一样,所以发射子弹的位置就不一样

下面是敌人发射子弹的图片

学习 Python 之 Pygame 开发魂斗罗(九)_第1张图片
通过这个图片,我们就可以计算出发射子弹的位置了

我们修改子弹类代码

在__init__()函数中增加一个参数,isEnemy,用来指定这个子弹是不是敌人发射的

class Bullet(pygame.sprite.Sprite):

    def __init__(self, person, isEnemy = False):
        pygame.sprite.Sprite.__init__(self)
        self.images = [
            loadImage('../Image/Bullet/bullet1.png')
        ]

然后把下面红框框出的代码进行修改

学习 Python 之 Pygame 开发魂斗罗(九)_第2张图片

def __init__(self, person, isEnemy = False):
    pygame.sprite.Sprite.__init__(self)
    self.images = [
        loadImage('../Image/Bullet/bullet1.png')
    ]
    self.index = 0
    self.image = self.images[self.index]
    # 速度
    self.xSpeed = 1
    self.ySpeed = 1
    self.rect = pygame.Rect(person.rect)

    if not isEnemy:
        if person.isInWater:
            self.waterPosition(person)
        else:
            self.landPosition(person)
    else:
        if person.direction == Direction.RIGHT:
            self.rect.x += 27 * PLAYER_SCALE
            self.rect.y += 7 * PLAYER_SCALE
            self.ySpeed = 0
            self.xSpeed = 7

        else:
            self.rect.x += -1 * PLAYER_SCALE
            self.rect.y += 7 * PLAYER_SCALE
            self.ySpeed = 0
            self.xSpeed = -7

    # 销毁开关
    self.isDestroy = False

接下来来到敌人1类
打开下面框出的代码的注释

学习 Python 之 Pygame 开发魂斗罗(九)_第3张图片

好,我们现在运行一下游戏,看看效果

学习 Python 之 Pygame 开发魂斗罗(九)_第4张图片

没有报错信息,但是没看到敌人的子弹,这是为什么呢?

原来是我们没有写显示敌人子弹的函数

2. 创建显示敌人子弹的函数

下面我们来写一下,进入主类

在主类外面创建全局函数

def drawEnemyBullet(enemyBulletList):
    for bullet in enemyBulletList:
        if bullet.isDestroy:
            enemyBulletList.remove(bullet)
        else:
            bullet.draw(MainGame.window)
            bullet.move()

该函数用来显示子弹,并让子弹移动

之后在update()函数中调用

学习 Python 之 Pygame 开发魂斗罗(九)_第5张图片
现在运行一下游戏

学习 Python 之 Pygame 开发魂斗罗(九)_第6张图片
敌人确实发射子弹了

3. 解决敌人不会向下掉落的问题

学习 Python 之 Pygame 开发魂斗罗(九)_第7张图片
我们走到桥边,发现敌人没办法掉下去,这不对,我们需要解决这个问题

在主类外面写一个全局函数,用来让检测敌人碰撞问题,敌人下落是垂直方向的碰撞问题

def updateEnemyPosition():
    # 遍历全部敌人列表
    for enemy in MainGame.enemyList:
        # 创建一个复制
        t = copy.copy(enemy)
        t.rect.y += 1
        # 让复制的y加1,看看有没有发生碰撞,这里看的碰撞是enemyColliderGroup中的碰撞
        collide = pygame.sprite.spritecollideany(t, MainGame.enemyColliderGroup)
        # 没有发生碰撞,让敌人下落
        if not collide:
            enemy.rect.y += 4
            enemy.isFalling = True
            # 改变下落时的图片
            enemy.image = enemy.rightFallImage if enemy.direction == Direction.RIGHT else enemy.leftFallImage
        else:
            # 如果与河发生碰撞,表示敌人落到了水中,那么敌人直接死亡
            if collide in MainGame.enemyRiverGroup:
                enemy.isDestroy = True
        t.rect.y -= 1

之后调用一下这个函数,在主类的update()函数中加入该函数

学习 Python 之 Pygame 开发魂斗罗(九)_第8张图片
然后我们给敌人加入下降时的图片

来到敌人1类,在__init__()函数中加入下面的代码

self.rightFireImage = loadImage('../Image/Enemy/Enemy1/fire.png')
self.leftFireImage = loadImage('../Image/Enemy/Enemy1/fire.png', True)
self.rightFallImage = loadImage('../Image/Enemy/Enemy1/fall.png')
self.leftFallImage = loadImage('../Image/Enemy/Enemy1/fall.png', True)

学习 Python 之 Pygame 开发魂斗罗(九)_第9张图片

接下来运行一下游戏
学习 Python 之 Pygame 开发魂斗罗(九)_第10张图片
我们看到敌人直接掉下去了,这是为什么?

4. 给敌人碰撞体组增加碰撞体

这是因为现在敌人碰撞体组中什么都没有,敌人脚下是空的,当地人出现后,就直接会掉下去啦

接下来我们给敌人增加碰撞体

学习 Python 之 Pygame 开发魂斗罗(九)_第11张图片
注意看这个图,position one表示这是产生敌人的第一个地区,之前我们在Constants.py中设置了,这个变量记录着敌人产生的高度

我们给敌人增加碰撞体,需要清楚哪些地方需要增加

2的位置需要吗?不需要,因为敌人不会向下跳
1的位置需要吗?需要,因为敌人一出来就会在这个地方

根据分析我们得到

1需要增加陆地碰撞体,r1和r3需要增加河碰撞体

下面我们来添加一下

修改initLand()函数河initRiver()函数

先把这两个函数拿出来,作为全局函数

学习 Python 之 Pygame 开发魂斗罗(九)_第12张图片
修改代码

def initLand():
    land1 = Collider(81, 119 * MAP_SCALE, 737 * MAP_SCALE, LAND_THICKNESS * MAP_SCALE)
    land2 = Collider(400, 151 * MAP_SCALE, 96 * MAP_SCALE, LAND_THICKNESS * MAP_SCALE)
    land3 = Collider(640, 183 * MAP_SCALE, 33 * MAP_SCALE, LAND_THICKNESS * MAP_SCALE)
    land4 = Collider(880, 183 * MAP_SCALE, 33 * MAP_SCALE, LAND_THICKNESS * MAP_SCALE)
    land5 = Collider(720, 215 * MAP_SCALE, 2 * LAND_LENGTH * MAP_SCALE, LAND_THICKNESS * MAP_SCALE)
    land6 = Collider(1040, 154 * MAP_SCALE, 2 * LAND_LENGTH * MAP_SCALE, LAND_THICKNESS * MAP_SCALE)
    land7 = Collider(1600, 166 * MAP_SCALE, 3 * LAND_LENGTH * MAP_SCALE, LAND_THICKNESS * MAP_SCALE)
    land8 = Collider(1120 * RATIO, 215 * MAP_SCALE, 2 * LAND_LENGTH * MAP_SCALE, LAND_THICKNESS * MAP_SCALE)
    land9 = Collider(1650 * RATIO, 119 * MAP_SCALE, 5 * LAND_LENGTH * MAP_SCALE, LAND_THICKNESS * MAP_SCALE)
    land10 = Collider(2185 * RATIO, 119 * MAP_SCALE, 8 * LAND_LENGTH * MAP_SCALE, LAND_THICKNESS * MAP_SCALE)
    land11 = Collider(2595 * RATIO, 215 * MAP_SCALE, 3 * LAND_LENGTH * MAP_SCALE, LAND_THICKNESS * MAP_SCALE)
    land12 = Collider(2770 * RATIO, 167 * MAP_SCALE, 2 * LAND_LENGTH * MAP_SCALE, LAND_THICKNESS * MAP_SCALE)
    land13 = Collider(2535 * RATIO, 87 * MAP_SCALE, 16 * LAND_LENGTH * MAP_SCALE, LAND_THICKNESS * MAP_SCALE)
    land14 = Collider(2950 * RATIO, 151 * MAP_SCALE, 7 * LAND_LENGTH * MAP_SCALE, LAND_THICKNESS * MAP_SCALE)
    land15 = Collider(3185 * RATIO, 215 * MAP_SCALE, 6 * LAND_LENGTH * MAP_SCALE, LAND_THICKNESS * MAP_SCALE)
    MainGame.playerLandGroup = pygame.sprite.Group(
        land1, land2, land3, land4, land5, land6, land7, land8, land9, land10,
        land11, land12, land13, land14, land15
    )
    eland1 = Collider(81, 119 * MAP_SCALE, 737 * MAP_SCALE, LAND_THICKNESS * MAP_SCALE)
    eland9 = Collider(1650 * RATIO, 119 * MAP_SCALE, 5 * LAND_LENGTH * MAP_SCALE, LAND_THICKNESS * MAP_SCALE)
    MainGame.enemyLandGroup = pygame.sprite.Group(eland1, eland9)
    MainGame.playerColliderGroup.add(MainGame.playerLandGroup)
    MainGame.enemyColliderGroup.add(MainGame.enemyLandGroup)



def initRiver():
    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))
    eRiver1 = Collider(0, 215 * MAP_SCALE, 289 * MAP_SCALE, LAND_THICKNESS * MAP_SCALE, (0, 0, 255))
    eRiver3 = Collider(1680, 215 * MAP_SCALE, 737 * MAP_SCALE, LAND_THICKNESS * MAP_SCALE, (0, 0, 255))
    MainGame.playerRiverGroup = pygame.sprite.Group(river1, river2, river3)
    MainGame.enemyRiverGroup = pygame.sprite.Group(eRiver1, eRiver3)
    MainGame.playerColliderGroup.add(MainGame.playerRiverGroup)
    MainGame.enemyColliderGroup.add(MainGame.enemyRiverGroup)

学习 Python 之 Pygame 开发魂斗罗(九)_第13张图片
e开头的是敌人碰撞体,这里我多加入了一些碰撞体,为地图后面的陆地也增加了

我们在Constants.py中加入

RATIO = 1.3571428571428572

我其实不太确定地图中冲突的尺寸,在图片中1000的位置应该是一个陆地,但是在窗口中,这个地方不是陆地,里面有一个对应的系数,我试了放大倍数2.5,发现对不上,所以我就想找一个系数1.3571428571428572,但是这个系数也有问题,窗口上面的图片的系数和下面的系数不一样

我觉得这个地方不需要明白,能在地图中的对应位置设置碰撞体就行,至于位置大家可以自己探索

学习 Python 之 Pygame 开发魂斗罗(九)_第14张图片
把碰撞体加入不同的组

接下来修改camera()函数,让敌人碰撞体也随地图移动而移动

学习 Python 之 Pygame 开发魂斗罗(九)_第15张图片

之后运行一下游戏,看看效果

学习 Python 之 Pygame 开发魂斗罗(九)_第16张图片
我们可以看到敌人掉不下去了,我们来到河边看看
学习 Python 之 Pygame 开发魂斗罗(九)_第17张图片

哈哈,敌人掉下去了

但是又遇到了新的问题,敌人会出现多个叠加在一起,看上去重合了

下面来修复一下

5. 解决敌人叠加在一起的问题

敌人出现重叠的问题,是产生敌人时,两个敌人产生的地方很近导致的

我们修改产生敌人的代码即可

学习 Python 之 Pygame 开发魂斗罗(九)_第18张图片

也可以增加玩家速度

我们让这两个if语句只执行一次就行,执行多次就会出现敌人重叠

学习 Python 之 Pygame 开发魂斗罗(九)_第19张图片

把代码改成3,试试
学习 Python 之 Pygame 开发魂斗罗(九)_第20张图片
运行后发现问题解决了

现在,敌人有了,子弹有了,下一步就是实现玩家死亡和子弹消灭敌人了

完整的主类代码

import copy
import sys
import pygame
from Constants import *
from PlayerOne import PlayerOne
from Collider import Collider
from Enemy1 import Enemy1


def drawPlayerOneBullet(player1BulletList):
    for bullet in player1BulletList:
        if bullet.isDestroy:
            player1BulletList.remove(bullet)
        else:
            bullet.draw(MainGame.window)
            bullet.move()

def enemyUpdate(enemyList, enemyBulletList):
    # 遍历整个敌人列表
    for enemy in enemyList:
        # 如果敌人已经被摧毁了
        if enemy.isDestroy:
            # 删除它的相关信息
            enemyList.remove(enemy)
            MainGame.allSprites.remove(enemy)
            MainGame.enemyGroup.remove(enemy)
        # 否则
        else:
            # 检查位置
            enemy.checkPosition(MainGame.player1.rect.x, MainGame.player1.rect.y)
            # 显示敌人
            enemy.draw(pygame.time.get_ticks())
            # 敌人移动
            enemy.move(pygame.time.get_ticks())
            # 敌人开火
            enemy.fire(enemyBulletList)

def updateEnemyPosition():
    # 遍历全部敌人列表
    for enemy in MainGame.enemyList:
        # 创建一个复制
        t = copy.copy(enemy)
        t.rect.y += 1
        # 让复制的y加1,看看有没有发生碰撞,这里看的碰撞是enemyColliderGroup中的碰撞
        collide = pygame.sprite.spritecollideany(t, MainGame.enemyColliderGroup)
        # 没有发生碰撞,让敌人下落
        if not collide:
            enemy.rect.y += 4
            enemy.isFalling = True
            # 改变下落时的图片
            enemy.image = enemy.rightFallImage if enemy.direction == Direction.RIGHT else enemy.leftFallImage
        else:
            # 如果与河发生碰撞,表示敌人落到了水中,那么敌人直接死亡
            if collide in MainGame.enemyRiverGroup:
                enemy.isDestroy = True
                # MainGame.explodeList.append(Explode(enemy))
        t.rect.y -= 1

def drawEnemyBullet(enemyBulletList):
    for bullet in enemyBulletList:
        if bullet.isDestroy:
            enemyBulletList.remove(bullet)
        else:
            bullet.draw(MainGame.window)
            bullet.move()


def initLand():
    land1 = Collider(81, 119 * MAP_SCALE, 737 * MAP_SCALE, LAND_THICKNESS * MAP_SCALE)
    land2 = Collider(400, 151 * MAP_SCALE, 96 * MAP_SCALE, LAND_THICKNESS * MAP_SCALE)
    land3 = Collider(640, 183 * MAP_SCALE, 33 * MAP_SCALE, LAND_THICKNESS * MAP_SCALE)
    land4 = Collider(880, 183 * MAP_SCALE, 33 * MAP_SCALE, LAND_THICKNESS * MAP_SCALE)
    land5 = Collider(720, 215 * MAP_SCALE, 2 * LAND_LENGTH * MAP_SCALE, LAND_THICKNESS * MAP_SCALE)
    land6 = Collider(1040, 154 * MAP_SCALE, 2 * LAND_LENGTH * MAP_SCALE, LAND_THICKNESS * MAP_SCALE)
    land7 = Collider(1600, 166 * MAP_SCALE, 3 * LAND_LENGTH * MAP_SCALE, LAND_THICKNESS * MAP_SCALE)
    land8 = Collider(1120 * RATIO, 215 * MAP_SCALE, 2 * LAND_LENGTH * MAP_SCALE, LAND_THICKNESS * MAP_SCALE)
    land9 = Collider(1650 * RATIO, 119 * MAP_SCALE, 5 * LAND_LENGTH * MAP_SCALE, LAND_THICKNESS * MAP_SCALE)
    land10 = Collider(2185 * RATIO, 119 * MAP_SCALE, 8 * LAND_LENGTH * MAP_SCALE, LAND_THICKNESS * MAP_SCALE)
    land11 = Collider(2595 * RATIO, 215 * MAP_SCALE, 3 * LAND_LENGTH * MAP_SCALE, LAND_THICKNESS * MAP_SCALE)
    land12 = Collider(2770 * RATIO, 167 * MAP_SCALE, 2 * LAND_LENGTH * MAP_SCALE, LAND_THICKNESS * MAP_SCALE)
    land13 = Collider(2535 * RATIO, 87 * MAP_SCALE, 16 * LAND_LENGTH * MAP_SCALE, LAND_THICKNESS * MAP_SCALE)
    land14 = Collider(2950 * RATIO, 151 * MAP_SCALE, 7 * LAND_LENGTH * MAP_SCALE, LAND_THICKNESS * MAP_SCALE)
    land15 = Collider(3185 * RATIO, 215 * MAP_SCALE, 6 * LAND_LENGTH * MAP_SCALE, LAND_THICKNESS * MAP_SCALE)
    MainGame.playerLandGroup = pygame.sprite.Group(
        land1, land2, land3, land4, land5, land6, land7, land8, land9, land10,
        land11, land12, land13, land14, land15
    )
    eland1 = Collider(81, 119 * MAP_SCALE, 737 * MAP_SCALE, LAND_THICKNESS * MAP_SCALE)
    eland9 = Collider(1650 * RATIO, 119 * MAP_SCALE, 5 * LAND_LENGTH * MAP_SCALE, LAND_THICKNESS * MAP_SCALE)
    MainGame.enemyLandGroup = pygame.sprite.Group(eland1, eland9)
    MainGame.playerColliderGroup.add(MainGame.playerLandGroup)
    MainGame.enemyColliderGroup.add(MainGame.enemyLandGroup)



def initRiver():
    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))
    eRiver1 = Collider(0, 215 * MAP_SCALE, 289 * MAP_SCALE, LAND_THICKNESS * MAP_SCALE, (0, 0, 255))
    eRiver3 = Collider(1680, 215 * MAP_SCALE, 737 * MAP_SCALE, LAND_THICKNESS * MAP_SCALE, (0, 0, 255))
    MainGame.playerRiverGroup = pygame.sprite.Group(river1, river2, river3)
    MainGame.enemyRiverGroup = pygame.sprite.Group(eRiver1, eRiver3)
    MainGame.playerColliderGroup.add(MainGame.playerRiverGroup)
    MainGame.enemyColliderGroup.add(MainGame.enemyRiverGroup)



class MainGame:

    player1 = None
    allSprites = None

    # 敌人
    enemyList = []

    window = None
    # 子弹
    player1BulletList = []
    enemyBulletList = []

    # 冲突
    playerLandGroup = pygame.sprite.Group()
    playerRiverGroup = pygame.sprite.Group()
    enemyLandGroup = pygame.sprite.Group()
    enemyRiverGroup = pygame.sprite.Group()
    playerColliderGroup = pygame.sprite.Group()
    enemyColliderGroup = pygame.sprite.Group()
    enemyGroup = pygame.sprite.Group()
    bridgeGroup = pygame.sprite.Group()

    # 冲突栈
    colliderStack = []

    def __init__(self):
        # 初始化展示模块
        pygame.display.init()

        SCREEN_SIZE = (SCREEN_WIDTH, SCREEN_HEIGHT)
        # 初始化窗口
        MainGame.window = pygame.display.set_mode(SCREEN_SIZE)
        # 设置窗口标题
        pygame.display.set_caption('魂斗罗角色')
        # 是否结束游戏
        self.isEnd = False
        # 获取按键
        self.keys = pygame.key.get_pressed()
        # 帧率
        self.fps = 60
        self.clock = pygame.time.Clock()

        # 初始化角色
        MainGame.player1 = PlayerOne(pygame.time.get_ticks())
        # 设置角色的初始位置
        MainGame.player1.rect.x = 80
        MainGame.player1.rect.bottom = 0

        # 把角色放入组中,方便统一管理
        MainGame.allSprites = pygame.sprite.Group(MainGame.player1)

        # 读取背景图片
        self.background = pygame.image.load('../Image/Map/1/Background/First(Bridge).png')
        self.backRect = self.background.get_rect()
        self.background = pygame.transform.scale(
            self.background,
            (int(self.backRect.width * MAP_SCALE),
             int(self.backRect.height * MAP_SCALE))
        )
        self.backRect.x = -1280

        # 摄像头调整
        self.cameraAdaption = 0

        # 加载场景景物
        initLand()
        initRiver()

        # 碰撞失效间隔
        self.index = 0

    def run(self):
        while not self.isEnd:

            # 设置背景颜色
            pygame.display.get_surface().fill((0, 0, 0))

            # 游戏场景和景物更新函数
            self.update(MainGame.window, MainGame.player1BulletList)

            # 获取窗口中的事件
            self.getPlayingModeEvent()

            # 更新窗口
            pygame.display.update()

            # 设置帧率
            self.clock.tick(self.fps)
            fps = self.clock.get_fps()
            caption = '魂斗罗 - {:.2f}'.format(fps)
            pygame.display.set_caption(caption)
        else:
            sys.exit()

    def getPlayingModeEvent(self):
        # 获取事件列表
        for event in pygame.event.get():
            # 点击窗口关闭按钮
            if event.type == pygame.QUIT:
                self.isEnd = True
            # 键盘按键按下
            elif event.type == pygame.KEYDOWN:
                self.keys = pygame.key.get_pressed()
            # 键盘按键抬起
            elif event.type == pygame.KEYUP:
                self.keys = pygame.key.get_pressed()

    def update(self, window, player1BulletList):
        # 加载背景
        window.blit(self.background, self.backRect)
        enemyUpdate(MainGame.enemyList, MainGame.enemyBulletList)
        # 更新物体
        currentTime = pygame.time.get_ticks()
        MainGame.allSprites.update(self.keys, currentTime, player1BulletList)
        self.updatePlayerPosition()
        drawPlayerOneBullet(player1BulletList)
        drawEnemyBullet(MainGame.enemyBulletList)
        updateEnemyPosition()
        # 摄像机移动
        self.camera()
        # 显示物体
        MainGame.allSprites.draw(window)
        # 加载敌人
        if -1503 < self.backRect.x < -1500:
            self.generateEnemy(MainGame.player1.rect.x + 600, POSITION_1, Direction.LEFT, pygame.time.get_ticks())
            self.generateEnemy(MainGame.player1.rect.x - 360, POSITION_1, Direction.RIGHT, pygame.time.get_ticks())

        if -1703 < self.backRect.x < -1700:
            self.generateEnemy(MainGame.player1.rect.x - 360, POSITION_1, Direction.RIGHT, pygame.time.get_ticks())
            self.generateEnemy(MainGame.player1.rect.x - 400, POSITION_1, Direction.RIGHT,
                               pygame.time.get_ticks())

        for collider in MainGame.playerLandGroup:
            r = collider.draw(window, self.player1.rect.y)
            # 如果没有画出来,表示玩家高度低于直线,所有把直线从组中删除
            if not r:
                # 删除前先检查一下是不是在组中
                if collider in MainGame.playerColliderGroup:
                    # 删除并加入栈
                    MainGame.colliderStack.insert(0, collider)
                    MainGame.playerColliderGroup.remove(collider)
            else:
                # 如果画出来了,判断一下玩家距离是否高于线的距离
                if collider.rect.y > self.player1.rect.bottom:
                    # 如果是的话,且冲突栈不为空,那么从栈中取出一个元素放入冲突组,最前面的元素一定是先如队列的
                    if len(MainGame.colliderStack) > 0:
                        f = MainGame.colliderStack.pop()
                        MainGame.playerColliderGroup.add(f)
        MainGame.playerRiverGroup.draw(window)

    def camera(self):
        # 如果玩家的右边到达了屏幕的一半
        if self.player1.rect.right > SCREEN_WIDTH / 2:
            if not (self.backRect.x <= -3500 * MAP_SCALE):
                # 计算出超过的距离
                self.cameraAdaption = self.player1.rect.right - SCREEN_WIDTH / 2
                # 让背景向右走这么多距离
                self.backRect.x -= self.cameraAdaption
                # 场景中的物体都走这么多距离
                for sprite in MainGame.allSprites:
                    sprite.rect.x -= self.cameraAdaption
                for collider in MainGame.playerColliderGroup:
                    collider.rect.x -= self.cameraAdaption
                for collider in MainGame.colliderStack:
                    collider.rect.x -= self.cameraAdaption
                for collider in MainGame.enemyColliderGroup:
                    collider.rect.x -= self.cameraAdaption

    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.playerColliderGroup)
                # 如果发生碰撞,判断是不是在河里
                if collider in MainGame.playerRiverGroup:
                    # 在河里设置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.playerLandGroup:
                        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.playerColliderGroup):
                        # 如果此时不是跳跃状态,那么就让玩家变成下落状态,因为玩家在跳跃时,是向上跳跃,不需要对下面的物体进行碰撞检测
                        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.playerColliderGroup)
            # 如果发生了碰撞
            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

            tempPlayer = copy.copy(self.player1)
            tempPlayer.rect.y += 1
            if c := pygame.sprite.spritecollideany(tempPlayer, MainGame.playerColliderGroup):
                if c in MainGame.playerLandGroup:
                    self.player1.isInWater = False
                elif c in MainGame.playerRiverGroup:
                    self.player1.isInWater = True
            tempPlayer.rect.y -= 1

    def generateEnemy(self, x, y, direction, currentTime):
        # 根据玩家的当前位置和方向产生一个敌人
        enemy = Enemy1(x, y, direction, currentTime)
        # 分别加入敌人列表,所有角色组,敌人碰撞组
        MainGame.enemyList.append(enemy)
        MainGame.allSprites.add(enemy)
        MainGame.enemyGroup.add(enemy)

if __name__ == '__main__':
    MainGame().run()

完整的敌人1类代码

import random

import pygame
from Constants import *
from Bullet import Bullet

class Enemy1(pygame.sprite.Sprite):

    def __init__(self, x, y, direction, currentTime):
        pygame.sprite.Sprite.__init__(self)

        self.lastTime = currentTime
        self.fireTime = currentTime
        self.rightImages = [
            loadImage('../Image/Enemy/Enemy1/1.png'),
            loadImage('../Image/Enemy/Enemy1/2.png'),
            loadImage('../Image/Enemy/Enemy1/3.png')
        ]
        self.leftImages = [
            loadImage('../Image/Enemy/Enemy1/1.png', True),
            loadImage('../Image/Enemy/Enemy1/2.png', True),
            loadImage('../Image/Enemy/Enemy1/3.png', True)
        ]
        self.rightFireImage = loadImage('../Image/Enemy/Enemy1/fire.png')
        self.leftFireImage = loadImage('../Image/Enemy/Enemy1/fire.png', True)
        self.fallImage = loadImage('../Image/Enemy/Enemy1/fall.png', True)

        self.rightFireImage = loadImage('../Image/Enemy/Enemy1/fire.png')
        self.leftFireImage = loadImage('../Image/Enemy/Enemy1/fire.png', True)
        self.rightFallImage = loadImage('../Image/Enemy/Enemy1/fall.png')
        self.leftFallImage = loadImage('../Image/Enemy/Enemy1/fall.png', True)

        self.index = 0
        self.direction = direction
        if self.direction == Direction.RIGHT:
            self.image = self.rightImages[self.index]
        else:
            self.image = self.leftImages[self.index]
        self.rect = self.image.get_rect()
        self.isFalling = False
        self.rect.x = x
        self.rect.y = y
        self.speed = 3
        self.isDestroy = False
        self.isFiring = False
        self.life = 1

    def move(self, currentTime):
        # 首先判断敌人是否开火,如果是开火状态,就不能移动
        if not self.isFiring:
            # 没有开火,就根据方向移动,这里我设置敌人只能向一个方向移动,不能转身
            if self.direction == Direction.RIGHT:
                self.rect.left += self.speed
            else:
                self.rect.left -= self.speed
        else:
            # 如果此时是开火状态,判断一下上次开火的时间和这次的时间是否相差1000
            # 这个的作用在于让敌人开火的时候站在那里不动,因为敌人移动时是不能开火的
            if currentTime - self.fireTime > 1000:
                # 如果两次开火间隔相差很大,那么就可以让敌人再次开火
                self.isFiring = False
                self.fireTime = currentTime

    def draw(self, currentTime):
        if self.isFiring:
            if self.direction == Direction.RIGHT:
                self.image = self.rightFireImage
            else:
                self.image = self.leftFireImage
        else:
            if currentTime - self.lastTime > 115:
                if self.index < 2:
                    self.index += 1
                else:
                    self.index = 0
                self.lastTime = currentTime
            if self.direction == Direction.RIGHT:
                self.image = self.rightImages[self.index]
            else:
                self.image = self.leftImages[self.index]

    def fire(self, enemyBulletList):
        if not self.isFalling:
            i = random.randint(0, 50)
            if i == 5:
                if not self.isFiring:
                    self.isFiring = True
                    enemyBulletList.append(Bullet(self, True))

    def checkPosition(self, x, y):
        if abs(self.rect.x - x) > 1000:
            self.isDestroy = True
        elif abs(self.rect.y - y) > 600:
            self.isDestroy = True

完整的子弹类代码

import pygame
from Constants import *

class Bullet(pygame.sprite.Sprite):

    def __init__(self, person, isEnemy = False):
        pygame.sprite.Sprite.__init__(self)
        self.images = [
            loadImage('../Image/Bullet/bullet1.png')
        ]
        self.index = 0
        self.image = self.images[self.index]
        # 速度
        self.xSpeed = 1
        self.ySpeed = 1
        self.rect = pygame.Rect(person.rect)

        if not isEnemy:
            if person.isInWater:
                self.waterPosition(person)
            else:
                self.landPosition(person)
        else:
            if person.direction == Direction.RIGHT:
                self.rect.x += 27 * PLAYER_SCALE
                self.rect.y += 7 * PLAYER_SCALE
                self.ySpeed = 0
                self.xSpeed = 7

            else:
                self.rect.x += -1 * PLAYER_SCALE
                self.rect.y += 7 * PLAYER_SCALE
                self.ySpeed = 0
                self.xSpeed = -7

        # 销毁开关
        self.isDestroy = False

    def landPosition(self, person):
        if person.isStanding:
            if person.direction == Direction.RIGHT:
                if person.isUp:
                    self.rect.x += 10 * PLAYER_SCALE
                    self.rect.y += -1 * PLAYER_SCALE
                    self.ySpeed = -7
                    self.xSpeed = 0
                else:
                    self.rect.x += 24 * PLAYER_SCALE
                    self.rect.y += 11 * PLAYER_SCALE
                    self.ySpeed = 0
                    self.xSpeed = 7
            else:
                if person.isUp:
                    self.rect.x += 10 * PLAYER_SCALE
                    self.rect.y += -1 * PLAYER_SCALE
                    self.ySpeed = -7
                    self.xSpeed = 0
                else:
                    self.rect.y += 11 * PLAYER_SCALE
                    self.ySpeed = 0
                    self.xSpeed = -7

        elif person.isSquating and not person.isWalking:
            if person.direction == Direction.RIGHT:
                self.rect.x += 34 * PLAYER_SCALE
                self.rect.y += 25 * PLAYER_SCALE
                self.ySpeed = 0
                self.xSpeed = 7
            else:
                self.rect.y += 25 * PLAYER_SCALE
                self.ySpeed = 0
                self.xSpeed = -7

        elif person.isWalking:
            if person.direction == Direction.RIGHT:
                if person.isUp:
                    self.rect.x += 20 * PLAYER_SCALE
                    self.rect.y += -1 * PLAYER_SCALE
                    self.ySpeed = -7
                    self.xSpeed = 7
                elif person.isDown:
                    self.rect.x += 21 * PLAYER_SCALE
                    self.rect.y += 20 * PLAYER_SCALE
                    self.ySpeed = 7
                    self.xSpeed = 7
                else:
                    self.rect.x += 24 * PLAYER_SCALE
                    self.rect.y += 11 * PLAYER_SCALE
                    self.ySpeed = 0
                    self.xSpeed = 7
            else:
                if person.isUp:
                    self.rect.x += -3 * PLAYER_SCALE
                    self.rect.y += -1 * PLAYER_SCALE
                    self.ySpeed = -7
                    self.xSpeed = -7
                elif person.isDown:
                    self.rect.x += -3 * PLAYER_SCALE
                    self.rect.y += 20 * PLAYER_SCALE
                    self.ySpeed = 7
                    self.xSpeed = -7
                else:
                    self.rect.y += 11 * PLAYER_SCALE
                    self.ySpeed = 0
                    self.xSpeed = -7

        elif person.isJumping or person.state == State.FALL:
            if person.direction == Direction.RIGHT:
                self.rect.x += 16 * PLAYER_SCALE
                self.rect.y += 8 * PLAYER_SCALE
                self.ySpeed = 0
                self.xSpeed = 7
            else:
                self.rect.x += -2 * PLAYER_SCALE
                self.rect.y += 8 * PLAYER_SCALE
                self.ySpeed = 0
                self.xSpeed = -7

    def waterPosition(self, person):
        if person.isStanding:
            if person.direction == Direction.RIGHT:
                if person.isUp:
                    self.rect.x += 14 * PLAYER_SCALE
                    self.rect.y += 7 * PLAYER_SCALE
                    self.ySpeed = -7
                    self.xSpeed = 0
                else:
                    self.rect.x += 27 * PLAYER_SCALE
                    self.rect.y += 29 * PLAYER_SCALE
                    self.ySpeed = 0
                    self.xSpeed = 7
            else:
                if person.isUp:
                    self.rect.x += 7 * PLAYER_SCALE
                    self.rect.y += 3 * PLAYER_SCALE
                    self.ySpeed = -7
                    self.xSpeed = 0
                else:
                    self.rect.x += -1 * PLAYER_SCALE
                    self.rect.y += 29 * PLAYER_SCALE
                    self.ySpeed = 0
                    self.xSpeed = -7

        elif person.isWalking:
            if person.direction == Direction.RIGHT:
                if person.isUp:
                    self.rect.x += 23 * PLAYER_SCALE
                    self.rect.y += 17 * PLAYER_SCALE
                    self.ySpeed = -7
                    self.xSpeed = 7
                else:
                    self.rect.x += 27 * PLAYER_SCALE
                    self.rect.y += 29 * PLAYER_SCALE
                    self.ySpeed = 0
                    self.xSpeed = 7
            else:
                if person.isUp:
                    self.rect.x += -3 * PLAYER_SCALE
                    self.rect.y += -1 * PLAYER_SCALE
                    self.ySpeed = -7
                    self.xSpeed = -7
                else:
                    self.rect.x += -1 * PLAYER_SCALE
                    self.rect.y += 29 * PLAYER_SCALE
                    self.ySpeed = 0
                    self.xSpeed = -7

    def move(self):
        self.rect.x += self.xSpeed
        self.rect.y += self.ySpeed
        self.checkBullet()

    def draw(self, window):
        window.blit(self.image, self.rect)

    def checkBullet(self):
        toDestroy = False
        if self.rect.top < 0 or self.rect.top > 600:
            toDestroy = True
        if self.rect.left < 0 or self.rect.right > 900:
            toDestroy = True
        if toDestroy:
            self.isDestroy = True

你可能感兴趣的:(Python,python,pygame,学习)