我目前正在使用 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() 函数有效),但球仍然只是穿过球员和网