Learning Python's Pygame Development Contra (4)
Continue writing Contra
In the last blog Learning Python Pygame Development Contra (3) , we completed the movement and jumping of the character, let's continue to write Contra.
The following is the material of the picture
Link: https://pan.baidu.com/s/1X7tESkes_O6nbPxfpHD6hQ?pwd=hdly
Extraction code: hdly
1. Create the bullet class
To launch a bullet, we must first have a bullet class.
Let's create it
import pygame
from Constants import *
class Bullet(pygame.sprite.Sprite):
def __init__(self, person):
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)
# 销毁开关
self.isDestroy = False
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
2. Set the position of the bullet launch according to the player's direction and state
Since the direction and state of the player are different, the position of the bullet is also different after the player fires.
Let's take a look at the character status and the position where the bullet is fired
(1). Stand and fire bullets to the right
(x,y) is the position of the picture, we calculated that in this state, the position of the bullet launch is (x+24,y+11)
Let's set it up
self.rect.x += 24 * 2.5
self.rect.y += 11 * 2.5
self.ySpeed = 0
self.xSpeed = 7
2.5 is the magnification of the character. When loading the image, the image is magnified by 2.5 times, so when setting the bullet firing position, it must also be multiplied by 2.5
if person.isStanding:
# 判断方向
# 方向向右
if person.direction == Direction.RIGHT:
# 向上
if person.isUp:
pass
# 向右
else:
self.rect.x += 24 * 2.5
self.rect.y += 11 * 2.5
self.ySpeed = 0
self.xSpeed = 7
# 方向向左
else:
if person.isUp:
pass
else:
pass
elif person.isSquating and not person.isWalking:
if person.direction == Direction.RIGHT:
pass
else:
pass
elif person.isWalking:
if person.direction == Direction.RIGHT:
if person.isUp:
pass
elif person.isDown:
pass
else:
pass
else:
if person.isUp:
pass
elif person.isDown:
pass
else:
pass
elif person.isJumping or person.state == State.FALL:
if person.direction == Direction.RIGHT:
pass
else:
pass
(2). Stand and fire bullets to the left
self.rect.y += 11 * 2.5
self.ySpeed = 0
self.xSpeed = -7
# 根据角色的方向和状态设置子弹发射的位置
# 角色站着
if person.isStanding:
# 判断方向
if person.direction == Direction.RIGHT:
# 向上
if person.isUp:
pass
else:
self.rect.x += 24 * 2.5
self.rect.y += 11 * 2.5
self.ySpeed = 0
self.xSpeed = 7
else:
if person.isUp:
pass
else:
self.rect.y += 11 * 2.5
self.ySpeed = 0
self.xSpeed = -7
elif person.isSquating and not person.isWalking:
if person.direction == Direction.RIGHT:
pass
else:
pass
elif person.isWalking:
if person.direction == Direction.RIGHT:
if person.isUp:
pass
elif person.isDown:
pass
else:
pass
else:
if person.isUp:
pass
elif person.isDown:
pass
else:
pass
elif person.isJumping or person.state == State.FALL:
if person.direction == Direction.RIGHT:
pass
else:
pass
(3). Stand up and fire bullets
Stand right and shoot bullets upwards
self.rect.x += 10 * 2.5
self.rect.y += -1 * 2.5
self.ySpeed = -7
self.xSpeed = 0
Here I slightly adjusted the value of y, the direction is upward, so the y of the bullet is gradually reduced, so the y speed is negative
# 根据角色的方向和状态设置子弹发射的位置
# 角色站着
if person.isStanding:
# 判断方向
if person.direction == Direction.RIGHT:
# 向上
if person.isUp:
self.rect.x += 10 * 2.5
self.rect.y += -1 * 2.5
self.ySpeed = -7
self.xSpeed = 0
else:
self.rect.x += 24 * 2.5
self.rect.y += 11 * 2.5
self.ySpeed = 0
self.xSpeed = 7
else:
if person.isUp:
pass
else:
self.rect.y += 11 * 2.5
self.ySpeed = 0
self.xSpeed = -7
elif person.isSquating and not person.isWalking:
if person.direction == Direction.RIGHT:
pass
else:
pass
elif person.isWalking:
if person.direction == Direction.RIGHT:
if person.isUp:
pass
elif person.isDown:
pass
else:
pass
else:
if person.isUp:
pass
elif person.isDown:
pass
else:
pass
elif person.isJumping or person.state == State.FALL:
if person.direction == Direction.RIGHT:
pass
else:
pass
Standing up and shooting bullets to the left is the same calculation method
self.rect.x += 10 * 2.5
self.rect.y += -1 * 2.5
self.ySpeed = -7
self.xSpeed = 0
# 根据角色的方向和状态设置子弹发射的位置
# 角色站着
if person.isStanding:
# 判断方向
if person.direction == Direction.RIGHT:
# 向上
if person.isUp:
self.rect.x += 10 * 2.5
self.rect.y += -1 * 2.5
self.ySpeed = -7
self.xSpeed = 0
else:
self.rect.x += 24 * 2.5
self.rect.y += 11 * 2.5
self.ySpeed = 0
self.xSpeed = 7
else:
if person.isUp:
self.rect.x += 10 * 2.5
self.rect.y += -1 * 2.5
self.ySpeed = -7
self.xSpeed = 0
else:
self.rect.y += 11 * 2.5
self.ySpeed = 0
self.xSpeed = -7
elif person.isSquating and not person.isWalking:
if person.direction == Direction.RIGHT:
pass
else:
pass
elif person.isWalking:
if person.direction == Direction.RIGHT:
if person.isUp:
pass
elif person.isDown:
pass
else:
pass
else:
if person.isUp:
pass
elif person.isDown:
pass
else:
pass
elif person.isJumping or person.state == State.FALL:
if person.direction == Direction.RIGHT:
pass
else:
pass
(4). Crouch down and fire bullets
Schematic diagram to the right
self.rect.x += 34 * 2.5
self.rect.y += 25 * 2.5
self.ySpeed = 0
self.xSpeed = 7
# 根据角色的方向和状态设置子弹发射的位置
# 角色站着
if person.isStanding:
# 判断方向
if person.direction == Direction.RIGHT:
# 向上
if person.isUp:
self.rect.x += 10 * 2.5
self.rect.y += -1 * 2.5
self.ySpeed = -7
self.xSpeed = 0
else:
self.rect.x += 24 * 2.5
self.rect.y += 11 * 2.5
self.ySpeed = 0
self.xSpeed = 7
else:
if person.isUp:
self.rect.x += 10 * 2.5
self.rect.y += -1 * 2.5
self.ySpeed = -7
self.xSpeed = 0
else:
self.rect.y += 11 * 2.5
self.ySpeed = 0
self.xSpeed = -7
elif person.isSquating and not person.isWalking:
if person.direction == Direction.RIGHT:
self.rect.x += 34 * 2.5
self.rect.y += 25 * 2.5
self.ySpeed = 0
self.xSpeed = 7
else:
pass
elif person.isWalking:
if person.direction == Direction.RIGHT:
if person.isUp:
pass
elif person.isDown:
pass
else:
pass
else:
if person.isUp:
pass
elif person.isDown:
pass
else:
pass
elif person.isJumping or person.state == State.FALL:
if person.direction == Direction.RIGHT:
pass
else:
pass
Similarly, set the launch position to the left
self.rect.y += 25 * 2.5
self.ySpeed = 0
self.xSpeed = -7
# 根据角色的方向和状态设置子弹发射的位置
# 角色站着
if person.isStanding:
# 判断方向
if person.direction == Direction.RIGHT:
# 向上
if person.isUp:
self.rect.x += 10 * 2.5
self.rect.y += -1 * 2.5
self.ySpeed = -7
self.xSpeed = 0
else:
self.rect.x += 24 * 2.5
self.rect.y += 11 * 2.5
self.ySpeed = 0
self.xSpeed = 7
else:
if person.isUp:
self.rect.x += 10 * 2.5
self.rect.y += -1 * 2.5
self.ySpeed = -7
self.xSpeed = 0
else:
self.rect.y += 11 * 2.5
self.ySpeed = 0
self.xSpeed = -7
elif person.isSquating and not person.isWalking:
if person.direction == Direction.RIGHT:
self.rect.x += 34 * 2.5
self.rect.y += 25 * 2.5
self.ySpeed = 0
self.xSpeed = 7
else:
self.rect.y += 25 * 2.5
self.ySpeed = 0
self.xSpeed = -7
elif person.isWalking:
if person.direction == Direction.RIGHT:
if person.isUp:
pass
elif person.isDown:
pass
else:
pass
else:
if person.isUp:
pass
elif person.isDown:
pass
else:
pass
elif person.isJumping or person.state == State.FALL:
if person.direction == Direction.RIGHT:
pass
else:
pass
(5). Shoot bullets diagonally
Schematic diagram of firing bullets to the upper right
self.rect.x += 20 * 2.5
self.rect.y += -1 * 2.5
self.ySpeed = -7
self.xSpeed = 7
Bullet position when firing a bullet to the upper left
self.rect.x += -3 * 2.5
self.rect.y += -1 * 2.5
self.ySpeed = -7
self.xSpeed = -7
Schematic diagram of firing bullets to the lower right
self.rect.x += 21 * 2.5
self.rect.y += 20 * 2.5
self.ySpeed = 7
self.xSpeed = 7
The position of the bullet when firing the bullet to the lower left
self.rect.x += -3 * 2.5
self.rect.y += 20 * 2.5
self.ySpeed = 7
self.xSpeed = -7
(6). Fire bullets while running
Shooting bullets while running is the same as firing bullets while standing
To the right
self.rect.x += 24 * 2.5
self.rect.y += 11 * 2.5
self.ySpeed = 0
self.xSpeed = 7
left
self.rect.y += 11 * 2.5
self.ySpeed = 0
self.xSpeed = -7
complete code
if person.isStanding:
if person.direction == Direction.RIGHT:
if person.isUp:
self.rect.x += 10 * 2.5
self.rect.y += -1 * 2.5
self.ySpeed = -7
self.xSpeed = 0
else:
self.rect.x += 24 * 2.5
self.rect.y += 11 * 2.5
self.ySpeed = 0
self.xSpeed = 7
else:
if person.isUp:
self.rect.x += 10 * 2.5
self.rect.y += -1 * 2.5
self.ySpeed = -7
self.xSpeed = 0
else:
self.rect.y += 11 * 2.5
self.ySpeed = 0
self.xSpeed = -7
elif person.isSquating and not person.isWalking:
if person.direction == Direction.RIGHT:
self.rect.x += 34 * 2.5
self.rect.y += 25 * 2.5
self.ySpeed = 0
self.xSpeed = 7
else:
self.rect.y += 25 * 2.5
self.ySpeed = 0
self.xSpeed = -7
elif person.isWalking:
if person.direction == Direction.RIGHT:
if person.isUp:
self.rect.x += 20 * 2.5
self.rect.y += -1 * 2.5
self.ySpeed = -7
self.xSpeed = 7
elif person.isDown:
self.rect.x += 21 * 2.5
self.rect.y += 20 * 2.5
self.ySpeed = 7
self.xSpeed = 7
else:
self.rect.x += 24 * 2.5
self.rect.y += 11 * 2.5
self.ySpeed = 0
self.xSpeed = 7
else:
if person.isUp:
self.rect.x += -3 * 2.5
self.rect.y += -1 * 2.5
self.ySpeed = -7
self.xSpeed = -7
elif person.isDown:
self.rect.x += -3 * 2.5
self.rect.y += 20 * 2.5
self.ySpeed = 7
self.xSpeed = -7
else:
self.rect.y += 11 * 2.5
self.ySpeed = 0
self.xSpeed = -7
elif person.isJumping or person.state == State.FALL:
if person.direction == Direction.RIGHT:
pass
else:
pass
(7). Fire bullets when jumping
elif person.isJumping or person.state == State.FALL:
if person.direction == Direction.RIGHT:
self.rect.x += 16 * 2.5
self.rect.y += 8 * 2.5
self.ySpeed = 0
self.xSpeed = 7
else:
self.rect.x += -2 * 2.5
self.rect.y += 8 * 2.5
self.ySpeed = 0
self.xSpeed = -7
Complete bullet class code
import pygame
from Constants import *
class Bullet(pygame.sprite.Sprite):
def __init__(self, person):
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 person.isStanding:
if person.direction == Direction.RIGHT:
if person.isUp:
self.rect.x += 10 * 2.5
self.rect.y += -1 * 2.5
self.ySpeed = -7
self.xSpeed = 0
else:
self.rect.x += 24 * 2.5
self.rect.y += 11 * 2.5
self.ySpeed = 0
self.xSpeed = 7
else:
if person.isUp:
self.rect.x += 10 * 2.5
self.rect.y += -1 * 2.5
self.ySpeed = -7
self.xSpeed = 0
else:
self.rect.y += 11 * 2.5
self.ySpeed = 0
self.xSpeed = -7
elif person.isSquating and not person.isWalking:
if person.direction == Direction.RIGHT:
self.rect.x += 34 * 2.5
self.rect.y += 25 * 2.5
self.ySpeed = 0
self.xSpeed = 7
else:
self.rect.y += 25 * 2.5
self.ySpeed = 0
self.xSpeed = -7
elif person.isWalking:
if person.direction == Direction.RIGHT:
if person.isUp:
self.rect.x += 20 * 2.5
self.rect.y += -1 * 2.5
self.ySpeed = -7
self.xSpeed = 7
elif person.isDown:
self.rect.x += 21 * 2.5
self.rect.y += 20 * 2.5
self.ySpeed = 7
self.xSpeed = 7
else:
self.rect.x += 24 * 2.5
self.rect.y += 11 * 2.5
self.ySpeed = 0
self.xSpeed = 7
else:
if person.isUp:
self.rect.x += -3 * 2.5
self.rect.y += -1 * 2.5
self.ySpeed = -7
self.xSpeed = -7
elif person.isDown:
self.rect.x += -3 * 2.5
self.rect.y += 20 * 2.5
self.ySpeed = 7
self.xSpeed = -7
else:
self.rect.y += 11 * 2.5
self.ySpeed = 0
self.xSpeed = -7
elif person.isJumping or person.state == State.FALL:
if person.direction == Direction.RIGHT:
self.rect.x += 16 * 2.5
self.rect.y += 8 * 2.5
self.ySpeed = 0
self.xSpeed = 7
else:
self.rect.x += -2 * 2.5
self.rect.y += 8 * 2.5
self.ySpeed = 0
self.xSpeed = -7
# 销毁开关
self.isDestroy = False
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
3. Add fire to the player class
Set the bullet cap in the constants file
# 设置玩家子弹上限
PLAYER_BULLET_NUMBER = 15
Add the launch code to the four state functions of the player class
if keys[pygame.K_j]:
self.isFiring = True
if len(playerBulletList) < PLAYER_BULLET_NUMBER:
# 设置子弹发射的间隔为150
if currentTime - self.fireLastTimer > 150:
playerBulletList.append(Bullet(self))
self.fireLastTimer = currentTime
complete player class
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.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.STAND
# 角色的方向
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.gravity = 0.7
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)
# 更新位置
# 记录前一次的位置坐标
pre = self.rect.x
self.rect.x += self.xSpeed
self.rect.y += self.ySpeed
# 如果x位置小于0了,就不能移动,防止人物跑到屏幕左边
if self.rect.x <= 0:
self.rect.x = pre
# 更新动画
# 跳跃状态
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 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.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.isFiring = True
if len(playerBulletList) < PLAYER_BULLET_NUMBER:
if currentTime - self.fireLastTimer > 150:
playerBulletList.append(Bullet(self))
self.fireLastTimer = currentTime
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.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
# 按下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
if keys[pygame.K_j]:
self.isFiring = True
if len(playerBulletList) < PLAYER_BULLET_NUMBER:
if currentTime - self.fireLastTimer > 150:
playerBulletList.append(Bullet(self))
self.fireLastTimer = currentTime
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.isFiring = True
if len(playerBulletList) < PLAYER_BULLET_NUMBER:
if currentTime - self.fireLastTimer > 150:
playerBulletList.append(Bullet(self))
self.fireLastTimer = currentTime
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 self.rect.bottom > SCREEN_HEIGHT - GROUND_HEIGHT:
self.state = State.WALK
self.ySpeed = 0
self.rect.bottom = SCREEN_HEIGHT - GROUND_HEIGHT
self.isJumping = False
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.isFiring = True
if len(playerBulletList) < PLAYER_BULLET_NUMBER:
if currentTime - self.fireLastTimer > 150:
playerBulletList.append(Bullet(self))
self.fireLastTimer = currentTime
4. Modify the main class to enable the player to fire
Since the update() method in the player class has an additional parameter of the bullet list, now we need to modify the main class
Add bullet list to main class
# 子弹
player1BulletList = []
Modify the run() function and pass the bullet list into the update() function
def run(self):
while not self.isEnd:
# 获取窗口中的事件
self.getPlayingModeEvent()
# 游戏场景和景物更新函数
self.update(MainGame.window, MainGame.player1BulletList)
# 更新窗口
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()
Modify the update() function
def update(self, window, player1BulletList):
# 更新物体
currentTime = pygame.time.get_ticks()
MainGame.allSprites.update(self.keys, currentTime, player1BulletList)
drawPlayerOneBullet(player1BulletList)
# 显示物体
MainGame.allSprites.draw(window)
Create a display bullet function, created outside the class
def drawPlayerOneBullet(player1BulletList):
for bullet in player1BulletList:
if bullet.isDestroy:
player1BulletList.remove(bullet)
else:
bullet.draw(MainGame.window)
bullet.move()
complete main class code
import sys
import pygame
from Constants import *
from PlayerOne import PlayerOne
def drawPlayerOneBullet(player1BulletList):
for bullet in player1BulletList:
if bullet.isDestroy:
player1BulletList.remove(bullet)
else:
bullet.draw(MainGame.window)
bullet.move()
class MainGame:
player1 = None
allSprites = None
window = None
# 子弹
player1BulletList = []
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())
# 设置角色的初始位置
# 这里设置为(0,80),可以实现一开始玩家掉下来的动画
MainGame.player1.rect.x = 80
MainGame.player1.rect.bottom = 300
# 把角色放入组中,方便统一管理
MainGame.allSprites = pygame.sprite.Group(MainGame.player1)
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):
# 更新物体
currentTime = pygame.time.get_ticks()
MainGame.allSprites.update(self.keys, currentTime, player1BulletList)
drawPlayerOneBullet(player1BulletList)
# 显示物体
MainGame.allSprites.draw(window)
if __name__ == '__main__':
MainGame().run()
Run it and see the effect
Haha, it’s done