我正在用Pygame编写一个Pong游戏,这是到目前为止我的Ball类的代码:
class Ball(pygame.sprite.Sprite):
def __init__(self, game, vector=Vec2D.Vec2D()):
super(Ball, self).__init__()
self.image = pygame.Surface((BALL_RADIUS*2, BALL_RADIUS*2))
self.rect = self.image.get_rect()
self.__draw_ball()
screen = pygame.display.get_surface()
self.area = screen.get_rect().inflate(-GAP*2, 0)
self.vector = vector
self.game = game
self.reinit()
def __draw_ball(self):
self.image.fill(BLACK)
self.image.set_colorkey(BLACK, RLEACCEL)
pygame.draw.circle(self.image, WHITE, (self.rect.centerx, self.rect.centery), BALL_RADIUS)
def reinit(self):
self.rect.centerx = self.area.centerx
self.rect.centery = self.area.centery
self.vector = Vec2D.Vec2D.from_magn_and_angle(BALL_SPEED, 0)
def update(self):
self.rect = self.calcnewpos()
self.handle_collision()
def calcnewpos(self):
(dx, dy) = self.vector.get_xy()
return self.rect.move(dx, dy)
def handle_collision(self):
(dx, dy) = self.vector.get_xy()
if not self.area.contains(self.rect):
if self.__hit_topbottom():
dy = -dy
elif self.__hit_leftright():
self.game.increase_score()
self.reinit()
else:
for paddle in self.hit_paddle(dx):
if dx < 0: self.rect.left = GAP + PADDLE_WIDTH
elif dx > 0: self.rect.right = SCREEN_WIDTH - (GAP + PADDLE_WIDTH)
dx = -dx
dy = paddle.hitpos / 4
paddle.collided = True
self.vector = Vec2D.Vec2D(dx, dy)
def _hit_topbottom(self):
return self.rect.top < 0 or self.rect.bottom > SCREEN_HEIGHT
def _hit_leftright(self):
return self.rect.left < self.area.left or self.rect.right > self.area.right
def hit_paddle(self, dx):
if dx < 0: paddle = self.game.paddles['left']
elif dx > 0: paddle = self.game.paddles['right']
if self.rect.colliderect(paddle.rect): return [paddle]
else: return []
好吧,在玩家(或AI)得分后,球调用其reinit方法,将球放在屏幕中间并重置矢量:
def reinit(self):
self.rect.centerx = self.area.centerx
self.rect.centery = self.area.centery
self.vector = Vec2D.Vec2D.from_magn_and_angle(BALL_SPEED, 0)
但是,不知何故,球仍然保持着在reinit被调用之前拥有的矢量。因此,当球以 (-5.0 -2.0) 这样的向量穿过左侧时,它会在 reinit 调用中快速变化,然后变回 (-5.0, -2.0)。有人可以告诉我为什么会这样吗?
问题出在您的handle_collision
方法中。
短篇小说:
该函数做的第一件事是将 dx 和 dy 设置为当前向量。然后它调用reinit()
.然后,它会将它们设置回函数末尾的第一个。
要修复:
改变
def handle_collision(self):
(dx, dy) = self.vector.get_xy() # <-- It first sets (dx, dy) to the old vector
if not self.area.contains(self.rect):
if self.__hit_topbottom():
...
elif self.__hit_leftright():
... # <-- here is where the reinit gets called, which changes the vector to new values.
else:
for paddle in self.hit_paddle(dx):
...
self.vector = Vec2D.Vec2D(dx, dy) # <-- Then the vector gets changed again, to the OLD vector saved above in (dx, dy)
自
def handle_collision(self):
(dx, dy) = self.vector.get_xy()
if not self.area.contains(self.rect):
if self.__hit_topbottom():
...
elif self.__hit_leftright():
...
return # <-- With the return here, the parsing never gets to change it back
else:
for paddle in self.hit_paddle(dx):
...
self.vector = Vec2D.Vec2D(dx, dy)
这将防止矢量被设置回原来的状态,同时在需要时仍然设置它。