python - 碰撞检测问题 - PyGame

标签 python pygame collision-detection collision

我对 Python 和 PyGame 还很陌生。我做了一个球和两个桨(两个桨由 2 个玩家控制)。我的问题是当球击中玩家 2 的桨时,它不会反弹。问题出在代码的底部,其中有一条注释:#WITH PLAYER 2

# IMPORTS
import pygame, time;

# INIT PYGAME
pygame.init();

# GLOBALS
global screen, display_w, display_h;
global clock, FPS;
global gameOver;
global ball, player_1, player_2;

# ASSIGN GLOBALS
def assign_globals():
    global screen, display_w, display_h;
    global clock, FPS;
    global gameOver;
    global ball, player_1, player_2;

    display_w = 800;
    display_h = 600;
    screen = pygame.display.set_mode((display_w, display_h));

    clock = pygame.time.Clock();
    FPS = 60;

    gameOver = False;

    ball = Ball();
    player_1 = Player();
    player_1.x = 0;
    player_1.color = (255, 0, 0);
    player_2 = Player();
    player_2.x = display_w - 15;
    player_2.color = (0, 255, 0);

# MAIN
def main():
    assign_globals();
    setup();
    game_loop();
    set_fps();

# GAME LOOP
def game_loop():
    global gameOver;

    while(not gameOver):
        for event in pygame.event.get():
            if(event.type == pygame.QUIT):
                gameOver = True;

            if(event.type == pygame.KEYDOWN):
                # PLAYER 1
                if(event.key == pygame.K_w):
                    player_1.velY -= 1;
                if(event.key == pygame.K_s):
                    player_1.velY += 1;
                # PLAYER 2
                if(event.key == pygame.K_UP):
                    player_2.velY -= 1;
                if(event.key == pygame.K_DOWN):
                    player_2.velY += 1;

            if(event.type == pygame.KEYUP):
                # PLAYER 1
                if(event.key == pygame.K_w or event.key == pygame.K_s):
                    player_1.velY = 0;
                # PLAYER 2
                if(event.key == pygame.K_UP or event.key == pygame.K_DOWN):
                    player_2.velY = 0;

        draw();
        animate();
        collision();

# DRAW
def draw():
    global screen;

    screen.fill((0, 0, 0));
    ball.draw();
    player_1.draw();
    player_2.draw();

    pygame.display.update();

# ANIMATE
def animate():
    ball.animate();
    player_1.animate();
    player_2.animate();

# COLLISION
def collision():
    ball.collision();
    player_1.collision();
    player_2.collision();

# SETUP
def setup():
    pygame.display.set_caption("Pong");

# CLASSES
class Ball():
    def __init__(self, x=0, y=0, w=0, h=0, velX=0, velY=0, color=()):
        global display_w, display_h;

        self.x = display_w / 2;
        self.y = display_w / 2;
        self.w = 20;
        self.h = 20;
        self.color = (0, 0, 255);
        self.velX = 0.4;
        self.velY = 0.4;

    def reset(self):
        self.x = display_w / 2;
        self.y = display_w / 2;
        self.velX = 0.4;
        self.velY = 0.4;

    def draw(self):
        global screen;

        pygame.draw.ellipse(screen, self.color, (self.x, self.y, self.w, self.h));

    def animate(self):
        self.x += self.velX;
        self.y += self.velY;

    def collision(self):
        global display_w, display_h;

        # WITH WALL
        if(self.x >= display_w - self.w):
            self.reset();
        if(self.x <= 0):
            self.reset();
        if(self.y >= display_h - self.h):
            self.velY *= -1;
        if(self.y <= 0):
            self.velY *= -1;

        # WITH PLAYER 1
        if(self.x <= player_1.x + player_1.w and
            self.x >= player_1.x and
            self.y >= player_1.y and
            self.y <= player_1.y + player_1.h):
                ball.velX *= -1;

        # WITH PLAYER 2
        if(self.x <= player_2.x + player_2.w and
            self.x >= player_2.x and
            self.y >= player_2.y and
            self.y <= player_2.y + player_2.h):
                ball.velX *= -1;

class Player():
    def __init__(self, x=0, y=0, w=0, h=0, velY=0, color=()):
        global display_w, display_h;

        self.w = 15;
        self.h = 100;
        self.x = color;
        self.y = display_h / 2 - self.h / 2;
        self.velY = 0;
        self.color = color;

    def draw(self):
        global screen;

        pygame.draw.rect(screen, self.color, (self.x, self.y, self.w, self.h));

    def animate(self):
        self.y += self.velY;

    def collision(self):
        global display_h;

        # WITH WALL
        if(self.y + self.h > display_h):
            self.velY = 0;
        elif(self.y < 0):
            self.velY = 0;


# SET FPS
def set_fps():
    global clock, FPS;

    clock.tick(FPS);

# CALL MAIN
if(__name__ == "__main__"):
    main();

# QUIT
pygame.quit();
quit();

最佳答案

问题似乎是您将碰撞检测基于球矩形的左上角。左 Racket 对着左侧,所以(不准确但通常)还不错,但是右 Racket 对着右边,所以球矩形的左角只会在玩家 2 的 Racket 内球已经穿透 Racket ,此时,墙壁检测例程(在 Racket 检测之前出现)将触发重置,因为它得分了。

所以玩家 2 的 Racket 变得无关紧要,因为它检测到远角,并且只要检测到碰撞,它就会检测得分,并在测试碰撞之前重置球的位置。

所以,你需要考虑球的整体形状,或者至少让检测点对称。如果你使用中心点,它会很公平,但它也会错过球的边缘。理想情况下,您可以测试 Racket 是否与球的椭圆相交。

关于python - 碰撞检测问题 - PyGame,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41971403/

相关文章:

python - 在 python 中打印来自父类(super class)的元素

python - map() 的参数 2 必须支持迭代

python - pygame.draw 和 pygame.gfxdraw 之间的区别

python - 在 pygame 的类/子类中设置和显示 Sprite 时遇到问题

ios - 防止与 b2ContactListener 发生一次碰撞而产生多个回调?

swift - didBegin 联系人未在 Swift 中被调用

python - 与 'in' 关键字的连接给出错误的结果

python - 为什么我不能使用切片表示法通过 pyPDF 迭代页面

python - Python 中的常用日志记录模块

c++ - 如何获得圆形和三角形的碰撞检测