简体   繁体   English

pygame 中的奇怪矢量运动

[英]Weird vector movement in pygame

For some reason the movement of my sprite is only diagonally up and left when pressing A, diagonally down and right when pressing D, and W/S just don't work despite the correct vectors being given to move in any direction.出于某种原因,我的精灵的移动仅在按 A 时沿对角线向上和向左移动,在按 D 时沿对角线向下和向右移动,而 W/S 只是不起作用,尽管给定了正确的向量以向任何方向移动。 Here's where the inputs are handled:这是处理输入的地方:

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)

And here is the relevant sprite code:这是相关的精灵代码:

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

I can provide the whole program, but it's a little over 350 lines so let me know if it's needed.我可以提供整个程序,但它有 350 多行,所以如果需要,请告诉我。

Something weird seems to be going on in your Entiry.update function.您的 Entiry.update function 中似乎发生了一些奇怪的事情。

 if self.operator and not self.operator.handle(self):
      self.internal_velocity *= FRICTION
      self.external_velocity *= FRICTION

Firstly self.operator is not a boolean.首先 self.operator 不是 boolean。 Second, self.operator.handle returns true if both x and y values are non zero.其次,如果 x 和 y 值都非零, self.operator.handle返回 true。 This means friction is only applied when entity is not moving, which does not make any sense.这意味着仅在实体不移动时才应用摩擦,这没有任何意义。 But taking the whole if statement into account friction is always being applied because self.operator will always have a value.但是考虑到整个 if 语句的摩擦总是被应用,因为 self.operator 总是有一个值。 But all of this would only change scale not the direction.但这一切只会改变规模而不是方向。

The real problem seems to be the typo, again in update function.真正的问题似乎是错字,再次更新 function。 I have no idea what is happening here but I am pretty sure this is the problem because if these evaluate to true, your self.internal_velocity vector changes direction.我不知道这里发生了什么,但我很确定这是问题所在,因为如果这些评估为真,你的 self.internal_velocity 向量就会改变方向。 If your vector has has friction applied to it and thus has a value between -1 and 1, it will get floored right down to 0. Assuming your FRICTION constant is less than 1. Which is why I am assuming it does not work.如果你的向量施加了摩擦力,因此它的值在 -1 和 1 之间,它将下降到 0。假设你的 FRICTION 常数小于 1。这就是我假设它不起作用的原因。

if self.internal_velocity.x and 0.2 > self.internal_velocity.x > -0.2:

and

if self.internal_velocity.y and 0.2 > self.internal_velocity.y > -0.2:

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM