pygame中奇怪的矢量运动
Posted
技术标签:
【中文标题】pygame中奇怪的矢量运动【英文标题】:Weird vector movement in pygame 【发布时间】:2022-01-24 01:56:31 【问题描述】:由于某种原因,我的精灵的移动仅在按 A 时沿对角线向上和向左移动,在按 D 时沿对角线向下和向右移动,并且 W/S 只是不起作用,尽管给定了正确的向量以向任何方向移动。这是处理输入的地方:
class Operator:
PLAYER = 'player'
COMPUTER = 'computer'
def __init__(self, type, AI=None):
self.type = type
self.AI = AI
def handle(self, entity):
keys = pygame.key.get_pressed()
direction = Vector(0, 0)
if self.type == Operator.PLAYER:
if keys[pygame.K_w]:
direction += Vector(0, -1)
if keys[pygame.K_s]:
direction += Vector(0, 1)
if keys[pygame.K_a]:
direction += Vector(-1, 0)
if keys[pygame.K_d]:
direction += Vector(1, 0)
if direction:
entity.move(direction)
return bool(direction)
这里是相关的精灵代码:
class Sprite(pygame.sprite.Sprite):
@property
def x(self):
return self._x_coordinate
@x.setter
def x(self, value):
self._x_coordinate = self.rect.centerx = wrap(value,
WIDTH,
-self.width)
@property
def y(self):
return self._y_coordinate
@x.setter
def y(self, value):
self._y_coordinate = self.rect.centery = wrap(value,
HEIGHT,
-self.height)
@property
def position(self):
return Vector(self.x, self.y)
@position.setter
def position(self, value: Vector):
self.x, self.y = value
@property
def width(self):
return self.rect.width
@property
def height(self):
return self.rect.height
def set_surface(self, surface):
self.image = surface
class Entity(Sprite):
@property
def colliding(self):
return pygame.sprite.spritecollide(self,
sprites(self),
False)
@property
def velocity(self):
return self.internal_velocity + self.external_velocity
@property
def angle(self):
return self.velocity.as_polar()[1]
def __init__(self, size, position, operator=None, image=None, color='#FF4C4C'):
super().__init__()
if image:
image = pygame.image.load(image)
self.image = pygame.Surface(image.get_size() if image else size)
self.rect = self.image.get_rect()
self.position = position
self.operator = operator
self.internal_velocity = Vector(0, 0)
self.external_velocity = Vector(0, 0)
if not image:
self.image.fill(color)
else:
self.image.blit(image, ORIGIN)
def draw(self, surface):
if camera.on_screen(self):
surface.blit(self.image,
(self.x - self.width / 2, self.y - self.height / 2))
if debugging:
offset = Vector()
offset.from_polar((20, self.angle))
pygame.draw.line(surface,
'#54CE0E',
self.position,
self.position + offset,
1)
def update(self):
if self.operator and not self.operator.handle(self):
self.internal_velocity *= FRICTION
self.external_velocity *= FRICTION
self.position += self.velocity
if self.internal_velocity.x and 0.2 > self.internal_velocity.x > -0.2:
self.internal_velocity.x = floor(self.internal_velocity.x)
if self.internal_velocity.y and 0.2 > self.internal_velocity.y > -0.2:
self.internal_velocity.y = floor(self.internal_velocity.y)
def move(self, vector: Vector):
self.internal_velocity += vector
if self.internal_velocity.length() > MOVE_SPEED:
self.internal_velocity.scale_to_length(MOVE_SPEED)
def set_operator(self, operator):
self.operator = operator
def wrap(number, maximum, minimum=0):
return (number - minimum) % (maximum - minimum + 1) + minimum
def floor(number):
if number > 0:
return math.floor(number)
elif not number:
return 0
else:
return math.floor(abs(number)) * -1
我可以提供整个程序,但它有 350 多行,如果需要,请告诉我。
【问题讨论】:
Yeaaaaaaaah hmmmmm 可能不提供整个代码。你提供的已经很长了。我怀疑你不会发现很多人有兴趣浏览你的代码并为你调试它。你能尝试用更小的代码重现这个问题吗?请参阅minimal reproducible example 获取建议。 请修剪您的代码,以便更容易找到您的问题。请按照以下指南创建minimal reproducible example。 【参考方案1】:Entiry.update 函数中似乎发生了一些奇怪的事情。
if self.operator and not self.operator.handle(self):
self.internal_velocity *= FRICTION
self.external_velocity *= FRICTION
首先 self.operator 不是布尔值。其次,如果 x 和 y 值都非零,self.operator.handle
返回 true。这意味着仅在实体不移动时才应用摩擦,这没有任何意义。但是考虑到整个 if 语句的摩擦总是被应用,因为 self.operator 总是有一个值。但这一切只会改变规模而不是方向。
真正的问题似乎是错字,同样在更新功能中。我不知道这里发生了什么,但我很确定这是问题所在,因为如果这些评估为真,你的 self.internal_velocity 向量就会改变方向。如果你的向量施加了摩擦力,因此它的值在 -1 和 1 之间,它将下降到 0。假设你的 FRICTION 常数小于 1。这就是我假设它不起作用的原因。
if self.internal_velocity.x and 0.2 > self.internal_velocity.x > -0.2:
和
if self.internal_velocity.y and 0.2 > self.internal_velocity.y > -0.2:
【讨论】:
以上是关于pygame中奇怪的矢量运动的主要内容,如果未能解决你的问题,请参考以下文章