为什么球不与球员或球网相撞?

问题描述 投票:0回答:0

我目前正在使用 python、pygame 和 pymunk 进行物理排球比赛。 它还不是很先进,但我正在努力。 目前我面临的问题是我的 pymunk 对象的碰撞似乎不起作用。

这是我的代码:

import pygame,sys,pymunk
import pymunk.pygame_util

pygame.init()
pygame.display.set_caption('Cubic Volley')
clock = pygame.time.Clock()
space = pymunk.Space()
space.gravity = (0,500)

# Fenstergröße
window_X = 1280
window_Y = 720

FPS = 120

# Variablen
game_active = True
black = (0, 0, 0)
white = (255, 255, 255)
blue = (2, 119, 189)
green = (43, 175, 43)
red = (255, 0, 0)

# Gravitation
gravity = 1

# Player 1
player1_X = 0
player1_Y = window_Y
player1_H = 100
player1_W = 100

# Player 2
player2_X = window_X
player2_Y = window_Y
player2_H = 100
player2_W = 100

# Punkte
points_player1 = 0
points_player2 = 0

# Ball
ball_X = window_X / 4
ball_Y = window_Y / 2
ball_R = 25


class Ball():
    def __init__(self, category, mask):
        self.body = pymunk.Body(1,100,body_type = pymunk.Body.DYNAMIC)
        self.body.position = (ball_X,ball_Y)
        self.shape = pymunk.Circle(self.body,ball_R)
        self.shape.density = 1
        self.shape.elasticity = 1.0
        self.shape.friction = 1.0
        self.shape.body.velocity = (0, 0)
        self.shape.collision_type = 0
        self.shape.filter = pymunk.ShapeFilter(categories = category, mask = mask)
        self.x_speed = 5
        self.y_speed = 5
        space.add(self.body,self.shape)

    def draw(self):
        x, y = self.body.position
        pygame.draw.circle(screen, red, (int(x),int(y)), ball_R)

    def move(self):
        # Wir nutzen die Physik-Engine, um den Ball zu bewegen
        self.shape.body.velocity = (self.x_speed, self.y_speed)
        space.step(1/FPS)

        # Wenn der Ball den oberen oder unteren Bildschirmrand berührt, ändern wir seine Y-Geschwindigkeit
        if self.body.position[1] < 0 + ball_R or self.body.position[1] > window_Y - ball_R:
            self.y_speed *= -1

        # Wenn der Ball den linken oder rechten Bildschirmrand berührt, ändern wir seine X-Geschwindigkeit
        if self.body.position[0] < 0 + ball_R or self.body.position[0] > window_X - ball_R:
            self.x_speed *= -1

        self.body.position = (self.body.position[0] + self.x_speed, self.body.position[1] + self.y_speed)

class Player1():
    def __init__(self, category, mask):
        self.body = pymunk.Body(body_type = pymunk.Body.KINEMATIC)
        self.body.position = (player1_X, player1_Y)
        self.shape = pymunk.Poly.create_box(self.body, size = (player1_W, player1_H))
        self.shape.collision_type = 1
        self.shape.filter = pymunk.ShapeFilter(categories = category, mask = mask)
        self.shape.body.velocity = (0, 0)
        self.width = player1_W
        self.height = player1_H
        self.x_movement = 0
        self.y_movement = 0
        self.jumping = False
        self.jumpheight = 20
        self.velocity = self.jumpheight
        space.add(self.body, self.shape)
    
    def draw(self):
        x, y = self.body.position
        pygame.draw.rect(screen, green, [x - self.width/2 + 50, y - self.height/2 - 50, self.width, self.height])

    def move(self):
        x, y = self.body.position

        # Bewegung X-Achse
        if self.x_movement != 0:
            x += self.x_movement
            # Begrenzung auf das Spielfeld
            if x < 0:
                x = 0
            if x > window_X/2 - self.width:
                x = window_X/2 - self.width
        # Bewegung Y-Achse
        if self.y_movement != 0:
            y += self.y_movement
            # Begrenzung auf das Spielfeld
            if y < 0:
                y = 0
            if y > window_Y - self.width:
                y = window_Y - self.width
        # Springen
        if self.jumping:
            y -= self.velocity
            self.velocity -= gravity
        if self.velocity < -self.jumpheight:
            self.jumping = False
            self.velocity = self.jumpheight

        self.body.position = (x, y)


class Player2():
    def __init__(self, category, mask):
        self.body = pymunk.Body(body_type = pymunk.Body.KINEMATIC)
        self.body.position = (player2_X, player2_Y)
        self.shape = pymunk.Poly.create_box(self.body, size = (player2_W, player2_H))
        self.shape.collision_type = 2
        self.shape.filter = pymunk.ShapeFilter(categories = category, mask = mask)
        self.shape.body.velocity = (0, 0)
        self.width = player1_W
        self.height = player1_H
        self.x_movement = 0
        self.y_movement = 0
        self.jumping = False
        self.jumpheight = 20
        self.velocity = self.jumpheight
        space.add(self.body, self.shape)
    
    def draw(self):
        x, y = self.body.position
        pygame.draw.rect(screen, blue, [x - self.width/2 - 50, y - self.height/2 - 50, self.width, self.height])

    def move(self):
            x, y = self.body.position

            # Bewegung X-Achse
            if self.x_movement != 0:
                x += self.x_movement
                # Begrenzung auf das Spielfeld
                if x < window_X/2 + self.width:
                    x = window_X/2 + self.width
                if x > window_X:
                    x = window_X
            # Bewegung Y-Achse
            if self.y_movement != 0:
                y += self.y_movement
                # Begrenzung auf das Spielfeld
                if y < 0:
                    y = 0
                if y > window_Y - self.width:
                    y = window_Y - self.width
            # Springen
            if self.jumping:
                y -= self.velocity
                self.velocity -= gravity
            if self.velocity < -self.jumpheight:
                self.jumping = False
                self.velocity = self.jumpheight

            self.body.position = (x, y)

class Netz():
    def __init__(self, category, mask):
        self.segment_body = pymunk.Body(body_type = pymunk.Body.STATIC)
        self.segment_shape = pymunk.Segment(self.segment_body, (window_X/2, window_Y), (window_X/2, window_Y/2), 5)
        self.segment_shape.elasticity = 1.0
        self.segment_shape.collision_type = 3
        self.segment_shape.filter = pymunk.ShapeFilter(categories = category, mask = mask)
        space.add(self.segment_body, self.segment_shape)

    def draw(self):
        pygame.draw.line(screen, white, self.segment_shape.a, self.segment_shape.b, 5)


# Fenster öffnen
screen = pygame.display.set_mode((window_X,window_Y))

# Ball
ball = Ball(1, 15)

# Netz
netz = Netz(8, 9)

# Spieler 1
player1 = Player1(2, 13)

# Spieler 2
player2 = Player2(4, 11)


c1 = space.add_collision_handler(0, 1)
c2 = space.add_collision_handler(0, 2)
c3 = space.add_collision_handler(0, 3)

def ball_hit_player1(arbiter, space, data):
    # Wir holen die Kollisionsformen des Balls und des Players
    ball.shape.body.velocity = (-abs(ball.shape.body.velocity[0]), -ball.shape.body.velocity[1])
    ball.shape, player1.shape = arbiter.shapes
    print("KOLLISION")
    return True

def ball_hit_player2(arbiter, space, data):
    # Wir holen die Kollisionsformen des Balls und des Players
    ball.shape, player2.shape = arbiter.shapes
    ball.shape.body.velocity = (-abs(ball.shape.body.velocity[0]), -ball.shape.body.velocity[1])
    print("KOLLISION")
    return True

def ball_hit_net(arbiter, space, data):
    ball.shape, netz.segment_shape = arbiter.shapes
    ball.shape.body.velocity = (-abs(ball.shape.body.velocity[0]), -ball.shape.body.velocity[1])
    print("KOLLISION")
    return True

c1.pre_solve = ball_hit_player1
c2.pre_solve = ball_hit_player2
c3.pre_solve = ball_hit_net


while game_active:
    for event in pygame.event.get():
        if event.type == pygame.QUIT or event.type == pygame.KEYDOWN and event.key == pygame.K_ESCAPE:
            game_active = False
            print("Das Spiel wurde beendet!")
        
        if event.type == pygame.KEYDOWN:
            print("Tastendruck")

            # Tasten für Spieler 1
            if event.key == pygame.K_a:
                print("Spieler 1 hat A gedrückt")
                player1.x_movement = -6
            if event.key == pygame.K_d:
                print("Spieler 1 hat S gedrückt")
                player1.x_movement = 6
            if event.key == pygame.K_SPACE:
                print("Spieler 1 springt!")
                player1.jumping = True

            # Tasten für Spieler 2
            if event.key == pygame.K_KP4:
                print("Spieler 1 hat LINKS gedrückt")
                player2.x_movement = -6
            if event.key == pygame.K_KP6:
                print("Spieler 1 hat RECHTS gedrückt")
                player2.x_movement = 6
            if event.key == pygame.K_KP0:
                print("Spieler 2 springt!")
                player2.jumping = True

        # Stoppen der Bewegung (KEYUP = Taste wird losgelassen)
        if event.type == pygame.KEYUP:
            print("Taste losgelassen")
            
            if event.key == pygame.K_w or event.key == pygame.K_s or event.key == pygame.K_a or event.key == pygame.K_d:
                print("Spieler 1 stoppt")
                player1.x_movement = 0
                player1.y_movement = 0
            elif event.key == pygame.K_KP8 or event.key == pygame.K_KP5 or event.key == pygame.K_KP4 or event.key == pygame.K_KP6:
                print("Spieler 2 stoppt")
                player2.x_movement = 0
                player2.y_movement = 0


    # Bildschirm löschen
    screen.fill(black)
    # Pymunk-Space aktualisieren
    space.step(1/FPS)

    # Player 1 zeichnen und bewegen
    player1.draw()
    player1.move()
    
    # Player 2 zeichnen und bewegen
    player2.draw()
    player2.move()

    # Netz zeichnen
    netz.draw()

    # Ball zeichnen
    ball.draw()
    ball.move()

    
    pygame.display.update()
    clock.tick(FPS)
    
pygame.quit()

评论是德语的,我希望这不是问题。

我尝试过使用碰撞处理程序和 ShapeFilter,当碰撞似乎被注册时我感到非常困惑(碰撞方法中的 print() 函数有效),但球仍然只是穿过球员和网

python pygame pymunk
© www.soinside.com 2019 - 2024. All rights reserved.