> 文章列表 > 学习 Python 之 Pygame 开发魂斗罗(九)

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

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

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

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

继续编写魂斗罗

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

下面是图片的素材

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

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')]

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

在这里插入图片描述

def __init__(self, person, isEnemy = False):pygame.sprite.Sprite.__init__(self)self.images = [loadImage('../Image/Bullet/bullet1.png')]self.index = 0self.image = self.images[self.index]# 速度self.xSpeed = 1self.ySpeed = 1self.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_SCALEself.rect.y += 7 * PLAYER_SCALEself.ySpeed = 0self.xSpeed = 7else:self.rect.x += -1 * PLAYER_SCALEself.rect.y += 7 * PLAYER_SCALEself.ySpeed = 0self.xSpeed = -7# 销毁开关self.isDestroy = False

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

在这里插入图片描述

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

在这里插入图片描述

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

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

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

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

在主类外面创建全局函数

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

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

之后在update()函数中调用

在这里插入图片描述
现在运行一下游戏

在这里插入图片描述
敌人确实发射子弹了

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

在这里插入图片描述
我们走到桥边,发现敌人没办法掉下去,这不对,我们需要解决这个问题

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

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 += 4enemy.isFalling = True# 改变下落时的图片enemy.image = enemy.rightFallImage if enemy.direction == Direction.RIGHT else enemy.leftFallImageelse:# 如果与河发生碰撞,表示敌人落到了水中,那么敌人直接死亡if collide in MainGame.enemyRiverGroup:enemy.isDestroy = Truet.rect.y -= 1

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

在这里插入图片描述
然后我们给敌人加入下降时的图片

来到敌人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)

在这里插入图片描述

接下来运行一下游戏
在这里插入图片描述
我们看到敌人直接掉下去了,这是为什么?

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

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

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

在这里插入图片描述
注意看这个图,position one表示这是产生敌人的第一个地区,之前我们在Constants.py中设置了,这个变量记录着敌人产生的高度

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

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

根据分析我们得到

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

下面我们来添加一下

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

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

在这里插入图片描述
修改代码

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)

在这里插入图片描述
e开头的是敌人碰撞体,这里我多加入了一些碰撞体,为地图后面的陆地也增加了

我们在Constants.py中加入

RATIO = 1.3571428571428572

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

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

在这里插入图片描述
把碰撞体加入不同的组

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

在这里插入图片描述

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

在这里插入图片描述
我们可以看到敌人掉不下去了,我们来到河边看看
在这里插入图片描述

哈哈,敌人掉下去了

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

下面来修复一下

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

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

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

在这里插入图片描述

也可以增加玩家速度

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

在这里插入图片描述

把代码改成3,试试
在这里插入图片描述
运行后发现问题解决了

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

完整的主类代码

import copy
import sys
import pygame
from Constants import *
from PlayerOne import PlayerOne
from Collider import Collider
from Enemy1 import Enemy1def 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 += 4enemy.isFalling = True# 改变下落时的图片enemy.image = enemy.rightFallImage if enemy.direction == Direction.RIGHT else enemy.leftFallImageelse:# 如果与河发生碰撞,表示敌人落到了水中,那么敌人直接死亡if collide in MainGame.enemyRiverGroup:enemy.isDestroy = True# MainGame.explodeList.append(Explode(enemy))t.rect.y -= 1def 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 = NoneallSprites = 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 = 60self.clock = pygame.time.Clock()# 初始化角色MainGame.player1 = PlayerOne(pygame.time.get_ticks())# 设置角色的初始位置MainGame.player1.rect.x = 80MainGame.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 = 0def 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.cameraAdaptionfor collider in MainGame.playerColliderGroup:collider.rect.x -= self.cameraAdaptionfor collider in MainGame.colliderStack:collider.rect.x -= self.cameraAdaptionfor collider in MainGame.enemyColliderGroup:collider.rect.x -= self.cameraAdaptiondef updatePlayerPosition(self):# 在index的循环次数中,不进行碰撞检测,用来让玩家向下跳跃if self.index > 0:self.index -= 1self.player1.rect.x += self.player1.xSpeedself.player1.rect.y += self.player1.ySpeedself.player1.isDown = Falseelse:# 首先更新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 = 15else:# 检测碰撞# 这里是玩家和所有碰撞组中的碰撞体检测碰撞,如果发生了碰撞,就会返回碰撞到的碰撞体对象collider = pygame.sprite.spritecollideany(self.player1, MainGame.playerColliderGroup)# 如果发生碰撞,判断是不是在河里if collider in MainGame.playerRiverGroup:# 在河里设置isInWaterself.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.rightInWaterImageelse: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 = 0self.player1.state = State.WALKself.player1.rect.bottom = collider.rect.topelse:# 否则的话,我们创建一个玩家的复制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.FALLtempPlayer.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.leftelse:# 左边有碰撞体self.player1.rect.left = collider.rect.rightself.player1.xSpeed = 0tempPlayer = copy.copy(self.player1)tempPlayer.rect.y += 1if c := pygame.sprite.spritecollideany(tempPlayer, MainGame.playerColliderGroup):if c in MainGame.playerLandGroup:self.player1.isInWater = Falseelif c in MainGame.playerRiverGroup:self.player1.isInWater = TruetempPlayer.rect.y -= 1def 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 randomimport pygame
from Constants import *
from Bullet import Bulletclass Enemy1(pygame.sprite.Sprite):def __init__(self, x, y, direction, currentTime):pygame.sprite.Sprite.__init__(self)self.lastTime = currentTimeself.fireTime = currentTimeself.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 = 0self.direction = directionif 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 = Falseself.rect.x = xself.rect.y = yself.speed = 3self.isDestroy = Falseself.isFiring = Falseself.life = 1def move(self, currentTime):# 首先判断敌人是否开火,如果是开火状态,就不能移动if not self.isFiring:# 没有开火,就根据方向移动,这里我设置敌人只能向一个方向移动,不能转身if self.direction == Direction.RIGHT:self.rect.left += self.speedelse:self.rect.left -= self.speedelse:# 如果此时是开火状态,判断一下上次开火的时间和这次的时间是否相差1000# 这个的作用在于让敌人开火的时候站在那里不动,因为敌人移动时是不能开火的if currentTime - self.fireTime > 1000:# 如果两次开火间隔相差很大,那么就可以让敌人再次开火self.isFiring = Falseself.fireTime = currentTimedef draw(self, currentTime):if self.isFiring:if self.direction == Direction.RIGHT:self.image = self.rightFireImageelse:self.image = self.leftFireImageelse:if currentTime - self.lastTime > 115:if self.index < 2:self.index += 1else:self.index = 0self.lastTime = currentTimeif 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 = TrueenemyBulletList.append(Bullet(self, True))def checkPosition(self, x, y):if abs(self.rect.x - x) > 1000:self.isDestroy = Trueelif 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 = 0self.image = self.images[self.index]# 速度self.xSpeed = 1self.ySpeed = 1self.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_SCALEself.rect.y += 7 * PLAYER_SCALEself.ySpeed = 0self.xSpeed = 7else:self.rect.x += -1 * PLAYER_SCALEself.rect.y += 7 * PLAYER_SCALEself.ySpeed = 0self.xSpeed = -7# 销毁开关self.isDestroy = Falsedef landPosition(self, person):if person.isStanding:if person.direction == Direction.RIGHT:if person.isUp:self.rect.x += 10 * PLAYER_SCALEself.rect.y += -1 * PLAYER_SCALEself.ySpeed = -7self.xSpeed = 0else:self.rect.x += 24 * PLAYER_SCALEself.rect.y += 11 * PLAYER_SCALEself.ySpeed = 0self.xSpeed = 7else:if person.isUp:self.rect.x += 10 * PLAYER_SCALEself.rect.y += -1 * PLAYER_SCALEself.ySpeed = -7self.xSpeed = 0else:self.rect.y += 11 * PLAYER_SCALEself.ySpeed = 0self.xSpeed = -7elif person.isSquating and not person.isWalking:if person.direction == Direction.RIGHT:self.rect.x += 34 * PLAYER_SCALEself.rect.y += 25 * PLAYER_SCALEself.ySpeed = 0self.xSpeed = 7else:self.rect.y += 25 * PLAYER_SCALEself.ySpeed = 0self.xSpeed = -7elif person.isWalking:if person.direction == Direction.RIGHT:if person.isUp:self.rect.x += 20 * PLAYER_SCALEself.rect.y += -1 * PLAYER_SCALEself.ySpeed = -7self.xSpeed = 7elif person.isDown:self.rect.x += 21 * PLAYER_SCALEself.rect.y += 20 * PLAYER_SCALEself.ySpeed = 7self.xSpeed = 7else:self.rect.x += 24 * PLAYER_SCALEself.rect.y += 11 * PLAYER_SCALEself.ySpeed = 0self.xSpeed = 7else:if person.isUp:self.rect.x += -3 * PLAYER_SCALEself.rect.y += -1 * PLAYER_SCALEself.ySpeed = -7self.xSpeed = -7elif person.isDown:self.rect.x += -3 * PLAYER_SCALEself.rect.y += 20 * PLAYER_SCALEself.ySpeed = 7self.xSpeed = -7else:self.rect.y += 11 * PLAYER_SCALEself.ySpeed = 0self.xSpeed = -7elif person.isJumping or person.state == State.FALL:if person.direction == Direction.RIGHT:self.rect.x += 16 * PLAYER_SCALEself.rect.y += 8 * PLAYER_SCALEself.ySpeed = 0self.xSpeed = 7else:self.rect.x += -2 * PLAYER_SCALEself.rect.y += 8 * PLAYER_SCALEself.ySpeed = 0self.xSpeed = -7def waterPosition(self, person):if person.isStanding:if person.direction == Direction.RIGHT:if person.isUp:self.rect.x += 14 * PLAYER_SCALEself.rect.y += 7 * PLAYER_SCALEself.ySpeed = -7self.xSpeed = 0else:self.rect.x += 27 * PLAYER_SCALEself.rect.y += 29 * PLAYER_SCALEself.ySpeed = 0self.xSpeed = 7else:if person.isUp:self.rect.x += 7 * PLAYER_SCALEself.rect.y += 3 * PLAYER_SCALEself.ySpeed = -7self.xSpeed = 0else:self.rect.x += -1 * PLAYER_SCALEself.rect.y += 29 * PLAYER_SCALEself.ySpeed = 0self.xSpeed = -7elif person.isWalking:if person.direction == Direction.RIGHT:if person.isUp:self.rect.x += 23 * PLAYER_SCALEself.rect.y += 17 * PLAYER_SCALEself.ySpeed = -7self.xSpeed = 7else:self.rect.x += 27 * PLAYER_SCALEself.rect.y += 29 * PLAYER_SCALEself.ySpeed = 0self.xSpeed = 7else:if person.isUp:self.rect.x += -3 * PLAYER_SCALEself.rect.y += -1 * PLAYER_SCALEself.ySpeed = -7self.xSpeed = -7else:self.rect.x += -1 * PLAYER_SCALEself.rect.y += 29 * PLAYER_SCALEself.ySpeed = 0self.xSpeed = -7def move(self):self.rect.x += self.xSpeedself.rect.y += self.ySpeedself.checkBullet()def draw(self, window):window.blit(self.image, self.rect)def checkBullet(self):toDestroy = Falseif self.rect.top < 0 or self.rect.top > 600:toDestroy = Trueif self.rect.left < 0 or self.rect.right > 900:toDestroy = Trueif toDestroy:self.isDestroy = True