当前位置: 首页 > 知识库问答 >
问题:

Pygame碰撞问题

沙富
2023-03-14

所以我在为我的平台游戏编写攻击方法时,我注意到我的游戏中的碰撞行为很奇怪,当我向敌人发起攻击(我的游戏中的火球)时没有损坏的记录,我添加了一个打印声明来检查他们是否失去任何生命值和没有记录,但是当我按住攻击方法(这是空格键)时,敌人上记录了多个攻击。

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

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

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

敌手

字符周围形成的矩形有问题,但我不确定是什么问题。

任何建议都会有帮助。

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

共有1个答案

逄烨
2023-03-14

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

除此之外,你可能想把你的游戏循环封装在一个函数中(比如把它命名为< code>main),然后分成几个更小的函数,以符合单一责任原则。将代码放在全局范围内(函数和类之外)几乎总是不好的做法,应该避免。同样,注释每一行明显的代码是不必要的(除非只是为了学习)。

 类似资料:
  • 所以我试图用Python和Pyplay创建一个益智平台游戏,但是我遇到了一点麻烦。当我为主要角色使用单点图像,而不是矩形图像时,如何制作碰撞检测器?我知道直角图像有左、右、顶部和底部像素功能(这对冲突检测非常有用),但是对于单片图像有这样的功能吗?或者我只需要为x和y坐标创建一个变量图像的宽度/高度?我试过用那个 但是catImg一直在通过窗户的尽头。我做错了什么?提前谢谢。

  • 我正在用Python创建一个乒乓游戏(很明显),我是Pyplay的新手,所以我想要一些帮助,当球碰到桨时,它会反转速度,朝相反的方向移动。到目前为止,一切都正常,但是当球到达桨时,它会穿过桨,不会改变方向。我已经解决了,所以桨不会离开屏幕,当球遇到墙时,球会改变方向,但当球遇到桨时,不会。任何帮助或提示将不胜感激。 我的划桨课: 我的球课 我的目标是当球触到球拍或反弹(重叠点)时,使球的速度反向(

  • 我是蟒蛇/蟒蛇游戏的新手。我已经能够在小型测试程序中拼凑出一些东西,但试图掌握碰撞并没有发生。我尝试过学习多个教程,但我觉得我需要它完全分解,然后才能很好地理解它。 有人能解释一下像CollidRect(Rect)这样的东西是如何工作的吗?我需要一个碰撞函数的类,还是只需要两个矩形就可以得到结果? 我尝试使用的代码如下。我能够制作两个图像,每个图像都由一个矩形包围,我假设碰撞仅适用于精灵而不是图像

  • 我已经有一段时间了。我正在尝试用PyGame制作一个游戏,我到达了碰撞段,已经被卡住了一段时间,并且检查了一些线程。 这是我的代码(删除了中间的其他方法和条件语句,但保留了相关部分)。我对这个错误有点困惑,因为我在两个类init中都self.imageRect=self.image.get_rect(),但是我有这个错误。当程序试图在dog类中执行冲突检测部分时,该错误具体为: "属性错误:'Pe

  • 我一直在学习一些pygame教程,并且基于这些教程开发了自己的代码。具体如下: 所以我想出了如何让我的家伙跳跃,但是我已经在天空中放置了一个块并试图这样做: 试图让角色停止跳跃。有没有一个内置的函数来测试这一点,或者有没有一个适合我的方法。顺便说一下,这是行不通的,我似乎也不知道该怎么做。非常感谢任何帮助:)

  • 问题内容: 在pygame中,有没有一种方法来寻找某一方之间的碰撞 一个精灵和另一个精灵的特殊一面?例如,如果 精灵A的顶部与精灵B的底部碰撞,返回True。 我肯定有办法做到这一点,但我找不到任何特别的方法 在文档中。 谢谢! 问题答案: 在PyGame中没有函数来获取侧面碰撞。 但你可以试着用 pygame.Rect.CollipePoint公司 测试是否,,, ,,,, 在里面 (pygam