【问题标题】:Pygame Collidepoint Function Not Working As DesiredPygame Collidepoint 函数未按预期工作
【发布时间】:2019-12-29 20:05:49
【问题描述】:

我正在用 Python 的 PyGame 编写一个决斗玩家坦克游戏,并且已经完成了大部分。为了给我的工作提供一些背景知识,游戏涉及两辆可以互相射击弹丸的坦克,一旦被击中,另一名玩家就会获得一分。该过程一直持续到一名玩家达到 10 分,此时他们被宣布为获胜者,游戏和计时器重置。

现在我的问题出现了,因为我在屏幕上画了一个迷宫来补充游戏并增加一些创造性。我遇到了一个基本问题。 Pygame .collidepoint 没有按预期运行。我打算这样做,每次来自任一坦克的子弹击中迷宫墙时,它都应该消失,因为墙壁是不可穿透的。然而,该功能可以任意选择子弹是否在接触时消失 - 正如我希望的那样 - 或者继续通过 - 正如我不希望的那样。有谁知道为什么会发生这种情况?我开始假设它与.collidepoint 对坐标的解释有关,我已经对此进行了测试,但没有成功。有没有更好的方法或功能来解决这个问题?如果有人能告诉我问题是否出在我认为的位置,并告诉我如何/给我调整后的代码的小sn-p来解决它,那将不胜感激。我的整个代码很长,所以我只包含了我认为必要的代码,以提供有关我正在做什么的足够信息。

但是,我仍然会清楚地强调我遇到的问题,这些部分是由围绕代码部分的 cmets 构成的大型显式块。如果上下文需要更多代码,请告诉我,我可以提供。

import pygame
import random
import time 

pygame.init()

screenWidth = 700
screenHeight = 700

screen = pygame.display.set_mode((screenWidth,screenHeight))            
#---------------------------------------------------------#

#Very important function, moves tanks/bullets appropriately, keeps time and score.
def redraw():
    screen.blit(background, (0,0))
    #DRAW SPRITES TO SCREEN
    tank.draw(screen)
    tank2.draw(screen)
    global barrier 
    barrier = pygame.draw.rect(screen,WHITE, pygame.Rect((100,0),(5,150)))
    global barrier2 
    barrier2 = pygame.draw.rect(screen,WHITE, pygame.Rect((0,40), (50, 5))) 
    global barrier3 
    barrier3 = pygame.draw.rect(screen,WHITE, pygame.Rect((50, 120), (50, 5)))
    global barrier4
    barrier4 = pygame.draw.rect(screen, WHITE, pygame.Rect((100, 150), (100,5)))

    global barrier5
    barrier5 = pygame.draw.rect(screen,WHITE, pygame.Rect((0,175),(50,5)))
    global barrier6
    barrier6 = pygame.draw.rect(screen,WHITE, pygame.Rect((150, 100),(5, 50)))
    global barrier7
    barrier7 = pygame.draw.rect(screen,WHITE, pygame.Rect((150, 50), (550,5)))
    global barrier8
    barrier8 = pygame.draw.rect(screen, WHITE, pygame.Rect((50,175),(5,50)))
    global barrier9
    barrier9 = pygame.draw.rect(screen, WHITE, pygame.Rect((50,225),(100,5)))
    global barrier10
    barrier10 = pygame.draw.rect(screen,WHITE, pygame.Rect((200,50),(5,50)))    
    global barrier11
    barrier11 = pygame.draw.rect(screen,WHITE, pygame.Rect((375,100),(50,5)))
    global barrier12
    barrier12 = pygame.draw.rect(screen,WHITE, pygame.Rect((375,150),(50,5)))    
    global barrier13
    barrier13 = pygame.draw.rect(screen,WHITE, pygame.Rect((375,100),(5,50)))   
    global barrier14
    barrier14 = pygame.draw.rect(screen,WHITE, pygame.Rect((75, 500),(350,5)))
    global barrier15
    barrier15 = pygame.draw.rect(screen,WHITE,pygame.Rect((250, 225),(5,200)))
    global barrier16
    barrier16 = pygame.draw.rect(screen,WHITE,pygame.Rect((150,225),(5,200)))
    global barrier17
    barrier17 = pygame.draw.rect(screen,WHITE,pygame.Rect((350,225),(5,200))) 
    global barrier18
    barrier18 = pygame.draw.rect(screen,WHITE,pygame.Rect((350,425),(200,5)))
    global barrier19
    barrier19 = pygame.draw.rect(screen,WHITE,pygame.Rect((550,425),(5,75)))
    global barrier20
    barrier20 = pygame.draw.rect(screen,WHITE,pygame.Rect((625,225),(5,325)))
    global barrier21
    barrier21 = pygame.draw.rect(screen,WHITE,pygame.Rect((380,550),(250,5)))
    global barrier22
    barrier22 = pygame.draw.rect(screen,WHITE,pygame.Rect((305,625),(325,5)))
    global barrier23
    barrier23 = pygame.draw.rect(screen,WHITE,pygame.Rect((305,550),(5,75)))
    global barrier24
    barrier24 = pygame.draw.rect(screen,WHITE,pygame.Rect((230, 550),(75,5)))
    global barrier25
    barrier25 = pygame.draw.rect(screen,WHITE,pygame.Rect((230,550),(5,75)))
    global barrier26
    barrier26 = pygame.draw.rect(screen,WHITE,pygame.Rect((160,625),(75,5)))
    global barrier27
    barrier27 = pygame.draw.rect(screen,WHITE,pygame.Rect((160,625),(5,75)))
    global barrier28
    barrier28 = pygame.draw.rect(screen,WHITE,pygame.Rect((50,575),(5,50)))
    global barrier29
    barrier29 = pygame.draw.rect(screen,WHITE,pygame.Rect((50,575),(65,5)))
    global barrier30
    barrier30 = pygame.draw.rect(screen,WHITE,pygame.Rect((70,420),(5,155)))
    global barrier31
    barrier31 = pygame.draw.rect(screen,WHITE,pygame.Rect((0,500),(30,5)))
    global barrier32
    barrier32 = pygame.draw.rect(screen,WHITE,pygame.Rect((45,420),(30,5)))
    global barrier33
    barrier33 = pygame.draw.rect(screen,WHITE,pygame.Rect((430,225), (200,5)))
    global barrier34
    barrier34 = pygame.draw.rect(screen,WHITE,pygame.Rect((530,125),(5,100)))
    global barrier35
    barrier35 = pygame.draw.rect(screen,WHITE,pygame.Rect((625,175),(75,5)))
    global barrier36
    barrier36 = pygame.draw.rect(screen,WHITE, pygame.Rect((650,200),(50,5)))
    #Draw bullets to screen
    for bullet in bullets:
        bullet.draw(screen)
    for bullet in bullets2:
        bullet.draw(screen)
    pygame.display.update()



while run:

    if hCounter1 < 10 and hCounter2 < 10:
        clock.tick(30)

        previous = passedTime
        passedTime = round(time.time() - begin,2)
        timer = timer + passedTime - previous  

        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                run = False
                quit()
            if event.type == pygame.KEYDOWN:            
                if event.key == pygame.K_m: #to shoot projectiles
                    px, py = round(tank.x + tank.width // 2), round(tank.y + tank.height // 2)
                    if len(bullets) < 1:
                        bullets.append(projectile(px, py, 4, (255,255,255), direction))
                if event.key == pygame.K_q:
                    px2, py2 = round(tank2.x + tank2.width // 1.7), round(tank2.y + tank2.height // 2)
                    if len(bullets2) < 1:
                        bullets2.append(projectile2(px2, py2, 4, (255,255,255), direction2))




        for bullet in bullets[:]:
            bullet.move()
            window_rect = pygame.Rect(0, 0, screenWidth, screenHeight)
            if not window_rect.collidepoint((bullet.x, bullet.y)):
                bullets.pop(bullets.index(bullet)) #if off the screen, delete bullet 

            #------------------------FOR THE FIRST TANK -- THE CONDITIONS OF THIS IF STATEMENTS IS WHERE I BELIEVE THE BUG IS OCCURRING AND WHERE IT MUST BE RESOLVED----------#
            #######################################################################################################################################
            #######################################################################################################################################
            ##################################################################################################################################################

            if barrier.collidepoint((bullet.x + 3, bullet.y + 3)) or barrier2.collidepoint((bullet.x, bullet.y)) or barrier3.collidepoint((bullet.x, bullet.y)) or barrier4.collidepoint((bullet.x, bullet.y)) or barrier5.collidepoint((bullet.x, bullet.y)) or barrier6.collidepoint((bullet.x, bullet.y)) or barrier7.collidepoint((bullet.x, bullet.y)) or barrier8.collidepoint((bullet.x, bullet.y)) or barrier9.collidepoint((bullet.x, bullet.y)) or barrier10.collidepoint((bullet.x, bullet.y)) or barrier11.collidepoint((bullet.x, bullet.y)) or barrier12.collidepoint((bullet.x, bullet.y)) or barrier13.collidepoint((bullet.x, bullet.y)) or barrier14.collidepoint((bullet.x, bullet.y)) or barrier15.collidepoint((bullet.x, bullet.y)) or barrier16.collidepoint((bullet.x, bullet.y)) or barrier17.collidepoint((bullet.x, bullet.y)) or barrier18.collidepoint((bullet.x, bullet.y)) or barrier19.collidepoint((bullet.x, bullet.y)) or barrier20.collidepoint((bullet.x, bullet.y)) or barrier21.collidepoint((bullet.x, bullet.y)) or barrier22.collidepoint((bullet.x, bullet.y)) or barrier23.collidepoint((bullet.x, bullet.y)) or barrier24.collidepoint((bullet.x, bullet.y)) or barrier25.collidepoint((bullet.x, bullet.y)) or barrier26.collidepoint((bullet.x, bullet.y)) or barrier27.collidepoint((bullet.x, bullet.y)) or barrier28.collidepoint((bullet.x, bullet.y)) or barrier28.collidepoint((bullet.x, bullet.y)) or barrier29.collidepoint((bullet.x, bullet.y)) or barrier30.collidepoint((bullet.x, bullet.y)) or barrier31.collidepoint((bullet.x, bullet.y)) or barrier32.collidepoint((bullet.x, bullet.y)) or barrier33.collidepoint((bullet.x, bullet.y)) or barrier34.collidepoint((bullet.x, bullet.y)) or barrier35.collidepoint((bullet.x, bullet.y)) or barrier35.collidepoint((bullet.x,bullet.y)):
                bullets.pop(bullets.index(bullet)) #if it touches a wall, delete bullet 

            #######################################################################################################################################
            #######################################################################################################################################
            ##################################################################################################################################################

            if bullet.y - bullet.radius < tank2.hitbox[1] + tank2.hitbox[3] and bullet.y + bullet.radius > tank2.hitbox[1]:
                if bullet.x + bullet.radius > tank2.hitbox[0] and bullet.x - bullet.radius < tank2.hitbox[0] + tank2.hitbox[2]:
                    hCounter1 += 1
                    tank2.x, tank2.y = random.randint(1,475), random.randint(20,475)
                    tank.x, tank.y = random.randint(1,475), random.randint(20,475)
                    tank2.hit(screen)
                    bullets.pop(bullets.index(bullet))

        for bullet in bullets2[:]:
            bullet.move()
            window_rect2 = pygame.Rect(0,0, screenWidth, screenHeight)
            if not window_rect2.collidepoint((bullet.x, bullet.y)):
                bullets2.pop(bullets2.index(bullet))
            if bullet.y - bullet.radius < tank.hitbox[1] + tank.hitbox[3] and bullet.y + bullet.radius > tank.hitbox[1]:
                if bullet.x + bullet.radius > tank.hitbox[0] and bullet.x - bullet.radius < tank.hitbox[0] + tank.hitbox[2]:
                    hCounter2 += 1
                    tank2.x, tank2.y = random.randint(1,475), random.randint(20,475)
                    tank.x, tank.y = random.randint(1,475), random.randint(20,475)                
                    tank.hit() 
                    bullets2.pop(bullets2.index(bullet))
           #------------------------FOR THE SECOND TANK -- THE CONDITIONS OF THIS IF STATEMENTS IS WHERE I BELIEVE THE BUG IS OCCURRING AND WHERE IT MUST BE RESOLVED----------#
            #######################################################################################################################################
            #######################################################################################################################################
            ##################################################################################################################################################

            if barrier.collidepoint((bullet.x + 3, bullet.y + 3)) or barrier2.collidepoint((bullet.x, bullet.y)) or barrier3.collidepoint((bullet.x, bullet.y)) or barrier4.collidepoint((bullet.x, bullet.y)) or barrier5.collidepoint((bullet.x, bullet.y)) or barrier6.collidepoint((bullet.x, bullet.y)) or barrier7.collidepoint((bullet.x, bullet.y)) or barrier8.collidepoint((bullet.x, bullet.y)) or barrier9.collidepoint((bullet.x, bullet.y)) or barrier10.collidepoint((bullet.x, bullet.y)) or barrier11.collidepoint((bullet.x, bullet.y)) or barrier12.collidepoint((bullet.x, bullet.y)) or barrier13.collidepoint((bullet.x, bullet.y)) or barrier14.collidepoint((bullet.x, bullet.y)) or barrier15.collidepoint((bullet.x, bullet.y)) or barrier16.collidepoint((bullet.x, bullet.y)) or barrier17.collidepoint((bullet.x, bullet.y)) or barrier18.collidepoint((bullet.x, bullet.y)) or barrier19.collidepoint((bullet.x, bullet.y)) or barrier20.collidepoint((bullet.x, bullet.y)) or barrier21.collidepoint((bullet.x, bullet.y)) or barrier22.collidepoint((bullet.x, bullet.y)) or barrier23.collidepoint((bullet.x, bullet.y)) or barrier24.collidepoint((bullet.x, bullet.y)) or barrier25.collidepoint((bullet.x, bullet.y)) or barrier26.collidepoint((bullet.x, bullet.y)) or barrier27.collidepoint((bullet.x, bullet.y)) or barrier28.collidepoint((bullet.x, bullet.y)) or barrier28.collidepoint((bullet.x, bullet.y)) or barrier29.collidepoint((bullet.x, bullet.y)) or barrier30.collidepoint((bullet.x, bullet.y)) or barrier31.collidepoint((bullet.x, bullet.y)) or barrier32.collidepoint((bullet.x, bullet.y)) or barrier33.collidepoint((bullet.x, bullet.y)) or barrier34.collidepoint((bullet.x, bullet.y)) or barrier35.collidepoint((bullet.x, bullet.y)) or barrier36.collidepoint((bullet.x, bullet.y)):
                bullets.pop(bullets.index(bullet))

【问题讨论】:

  • 你发布的代码太多了。请仅发布您遇到问题的代码的相关部分
  • @Iain Shelvington 这更好吗?我这样做是因为我认为大多数信息对于建立有关坐标的所有信息都是必要的。
  • 会不会是子弹在第一个刻度时位于屏障的一侧,然后在第二个刻度时位于屏障的另一侧?如果是这种情况,那么子弹与障碍物碰撞时就不会出现滴答声
  • 也许,但我不希望子弹的速度比现在慢。否则将如何修改?
  • 这个问题有一个答案可能会有所帮助,尽管stackoverflow.com/questions/40431402/line-collision-in-pygame 相当复杂

标签: python python-3.x animation pygame collision-detection


【解决方案1】:

答案是子弹的速度,因为它太快了,程序无法捕捉到它的滴答声,这基本上让子弹穿过迷宫墙。

可以将时钟调整为每秒 60 帧,如下所示:

clock.tick(60)

然后在射弹类中,或者在确定子弹速度的任何地方——必须根据时钟频率进行调整。

如果您的速度为 8 且显示的时钟频率为 30,则将时钟频率调整为 60,将速度调整为该速度的一半左右,以达到您想要的速度比率。就我而言:

def __init__(self,x, y, radius, color, direction): 
    #ESTABLISH ALL DIMENSIONS
    self.x = x
    self.y = y
    self.radius = radius
    self.color = color
    self.direction = direction
    self.vel = 5 #if it was previously 8 with a clock tick of 30.

程序应该能够抓住子弹的滴答声并在它穿过墙壁之前阻止它。并且子弹在屏幕上移动的相对速度应该保持不变——记住也要相应地调整其他移动对象的速度,例如精灵。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-02-01
    • 1970-01-01
    • 2019-10-30
    • 2015-04-11
    • 2022-01-25
    • 2019-12-22
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多