Pygame冲突问题



所以我在为我的平台游戏编写攻击方法时,注意到碰撞在我的游戏中表现得很奇怪,当我对没有注册损坏的敌人发起攻击(游戏中的火球(时,我添加了一个打印声明来检查他们是否失去了任何健康,也没有注册,然而,当我按下攻击方法(空格键(时,会对敌人进行多次攻击。

玩家角色是蓝色的,敌人是绿色的。

控制台显示敌人生命值降低,但仅当空格键按下时。

此外,当我走进敌人的精灵,点击空格键一次时,我也可以用这种方式造成伤害,但不能在远处造成伤害。

玩家在敌方内

围绕字符形成的矩形有问题,但我不确定出了什么问题。

任何建议都会很有帮助。

import pygame  #imports the pygame library
#variables for player
moveright = False  #declared a variable to store boolean value for if player is moving right
moveleft = False  #declared a variable to store boolean value for if player is moving left
fire = False
#constant variables
width = 700
height = 700
size_of_screen = (width, height)  #declared a variable to store the height and width of the screen
bg_colour = (222, 203, 104)  #declared a variable to store the bg colour of screen
pf_colour = (0, 0, 0)
FPS = 60  #declared variable to store the speed at which game runs
gravity = 0.5
#init
pygame.init()  #all imported python modules are initialised
screen = pygame.display.set_mode(size_of_screen)  #a game window is initialised
pygame.display.set_caption("Platform Game")  #game windows caption is set
system_clock = pygame.time.Clock()  #declared variable to control speed of game
fireball_img = pygame.image.load("FB500-5.png").convert_alpha()
class Characters(pygame.sprite.Sprite):  #base class is created and inherits from sprite class
def __init__(self, char, x, y, scale, speed, health):  #values are put in the constructor method
pygame.sprite.Sprite.__init__(self)  #constructor from sprite class is called
self.health = health
self.max_health = self.health
self.attack_cooldown = 0
self.direction = 1  
self.air = True
self.char = char
self.life = True  #attribute initialised to store state of characters life
self.jump = False
self.vv = 0
self.speed = speed  #attribute for character is initialised to store speed of character
self.spin = False  #attribute initialised to store direction character is moving
self.animation_list = []  #attribute initialised to store all sequence of animations for sprites within 2D list
self.index = 0  #attribute initialised to locate index of sequences within specific animation
self.activity = 0  #attribute initialised to locate index of animation sequences within animation list
self.time = pygame.time.get_ticks()  #attribute declared to store current time game has been running
types_of_animation = ['idle', 'moving', 'jump']
for ani in types_of_animation:
templist = []  #declared a variable which will be used to store a temporary list
for x in range(10):  #loops through numbers 0-10
try:
img = pygame.image.load(f'{self.char}/{self.char}.{ani}.sprite_{x}.png').convert_alpha() #loads an image from your file
img = pygame.transform.scale(img, (int(scale), int(scale)))  #resizes your image
templist.append(img)  #resized image is added to temporary list
except:
break
self.animation_list.append(templist)  #adds all images passed into temporary list to main one
self.img = self.animation_list[self.activity][self.index]  #attribute initialised to store intial image of sprite
self.rect = self.img.get_rect()  #a rectangle is formed around sprite
self.rect.center = (x+100, y-50)  #centre of rectangle varies with the position of sprite

def movecharacter(self, moveleft, moveright):  #new method defined to move character
#change in movement variables
dy = 0  #declared a variable to store the change in distance travelled in the vertical direction
dx = 0  #declared a variable to store the change in distance travelled in the horizontal direction
#movement variables are updated if there are movements left or right
if moveleft:  #checks to see if user has inputted "a" key
dx -= self.speed  #character has moved backwards
self.direction = -1
self.spin = True  #character changed direction(faces left)
if moveright:  #checks to see if the user has inputted "d" key
dx += self.speed  #character has moved forward
self.spin = False  #character changed direction(faces right)
self.direction = 1
#these variables are for jumping
if self.jump and not self.air:  #checks to see if user has inputted "w" key and is in mid-air
self.vv = -10  #determines how high the character can jump
self.jump = False  #this variable is set to false so character doesn't fly of the screen
self.air = True  #this variable is set to true so character can't infinitely jump while in mid-dair
#gravity is applied here
self.vv += gravity  #vertical velocity is incremented until character starts to move in opposite direction
if self.vv > 9:  #checks to see if character's vertical velocity has passed 9
self.vv = 9  #vertical velocity is capped to 9
dy += self.vv  #change in distance travelled in vertical direction is increased
if self.rect.bottom + dy > 400:  #checks if distance the player travelled
dy = 400 - self.rect.bottom
self.air = False
#rectangle position is updated
self.rect.x += dx  #position of rectangle has changed in horizontal direction
self.rect.y += dy  #position of rectangle has changed in vertical direction
def attack(self):  
if not self.attack_cooldown:
self.attack_cooldown = 50
ball = Fireball(self.rect.centerx, self.rect.centery, self.direction, self.spin)
fireball_group.add(ball)
if pygame.sprite.spritecollide(player, fireball_group, False):
if player.life:
player.health -=5
self.kill()
if pygame.sprite.spritecollide(enemy, fireball_group, False):
if player.life:
enemy.health -=25
print(enemy.health)
self.kill()
def cooldown(self):
if self.attack_cooldown > 0:
self.attack_cooldown -=1
def animation(self):  #new method defined to change characters animation
animation_timer = 100  #declared variable to store time for how long character is in each animation
self.img = self.animation_list[self.activity][self.index]  #characters animation is updated
if pygame.time.get_ticks() - self.time > animation_timer:  #checks to see if it is time to update sprites
self.time = pygame.time.get_ticks()  #time game has been running for is redefined
self.index += 1  #index for current animation sequence is increased so next animation can be outputted
if self.index >= len(self.animation_list[self.activity]):  #checks to see if index value has passed the highest index of animation sequence list
self.index = 0  #index is reset back to initial value
def update_activity(self, updated_activity):  #new method defined to update which animation sequence character is in
if updated_activity != self.activity:  #checks if current activity is equal to new activity
self.activity = updated_activity  #value for activity is updated
self.index = 0  #index is reset to initial value
self.time = pygame.time.get_ticks()  #time game has been running is updated
def draw(self):  #new method defined to draw images to screen
screen.blit(pygame.transform.flip(self.img, self.spin, False), self.rect)  #draws image to screen
class Fireball(pygame.sprite.Sprite):
def __init__(self, x, y, direction, spin):
pygame.sprite.Sprite.__init__(self)
self.spin = spin    
self.direction = direction
self.speed = 10
self.image = fireball_img
self.image = pygame.transform.scale(self.image, (50,50))
self.image = pygame.transform.flip(self.image, self.spin, False)
self.rect = self.image.get_rect()
self.rect.center = (x,y) 
def update(self):
self.rect.x +=(self.direction * self.speed)
if self.rect.right < 100 or self.rect.left > width - 100:
self.kill()
fireball_group = pygame.sprite.Group()    

player = Characters("player", 100, 200, 100, 5, 100)
enemy = Characters("enemy", 10, 400, 100, 5, 100)

run = True  #declared a variable to store a boolean value to determine state of game
while run:  #game loop-infinite loop which runs game until game is finished
#draw
screen.fill(bg_colour)  #displays the specified bg colour
pygame.draw.line(screen, pf_colour, (0, 400), (width, 400))
player.draw()  #calls the draw method from base class so character can move
enemy.draw()
fireball_group.update()
fireball_group.draw(screen)
pygame.display.flip()  #the contents of entire display are updated
system_clock.tick(FPS)  #function declared to limit the speed game runs at
player.animation()  #calls animation method from base class so characters animation is updated
player.cooldown()
if player.life:  #checks to see if player is alive
if fire:
player.attack() 
if player.air:  #checks to see if player is in air
player.update_activity(2)  #updates the value of activity attribute within base class
elif moveleft or moveright:  #checks if player is moving
player.update_activity(1)  #updates the value of activity attribute within base class
else:
player.update_activity(0)  #current value of acitivity remains 0
player.movecharacter(moveleft, moveright)  #calls movecharacter method from base class so character can move
#input
for event in pygame.event.get():  #loops through all the events registered by user
#quit game
if event.type == pygame.QUIT:  #checks to see if user has selected the exit button
run = False  #state of game is set to false to signal game window has been closed
#keyboard inputs
if event.type == pygame.KEYDOWN:  #checks to see if user has inputted a key
if event.key == pygame.K_a:  #checks to see if user has inputted "a" key
moveleft = True  #variable is set to true so character moves left
if event.key == pygame.K_d:  #checks to see if user has inputted "d" key
moveright = True  #variable is set to true so character moves right
if event.key == pygame.K_w and player.life:  #checks to see if the user has inputted "w" key
player.jump = True  #variable is set to true so character jumps
if event.key == pygame.K_SPACE:
fire = True
#keyboard input released
if event.type == pygame.KEYUP:  #checks to see if user released a key
if event.key == pygame.K_a:  #checks to see if user has inputted "a" key
moveleft = False  #variable is set to false so character stops moving left
if event.key == pygame.K_d:  #checks to see if user has inputted the "d" key
moveright = False  #variable is set to false so character stops moving right
if event.key == pygame.K_SPACE:
fire = False
#quit
pygame.quit()  #all pygame modules are uninitialised

我在变量fire中看到了问题。仅当检测到K_SPACE时才将其设置为True,并且仅当fire == True时才检测到与火球的碰撞(在player.attack()内部(。因此,只有按下空格键时才会检查碰撞。我建议将方法Character.attack()(注意,按照惯例,类名应该是单数(拆分为两个方法:一个用于仅攻击,另一个用于检查冲突。所以你们可以在主循环中检查是否有任何火球和玩家物体碰撞,并独立地投掷另一个火球。

此外,您可能希望将游戏循环封装在一个函数中(命名为类似main的函数(,并拆分为几个较小的函数,以符合单一责任原则。将代码放在全局范围(函数和类之外(几乎总是一种糟糕的做法,应该避免。此外,注释每一行明显的代码是不必要的(除非只是为了学习目的(。

最新更新