繁体   English   中英

pygame 中的奇怪矢量运动

[英]Weird vector movement in pygame

出于某种原因,我的精灵的移动仅在按 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 多行,所以如果需要,请告诉我。

您的 Entiry.update function 中似乎发生了一些奇怪的事情。

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

首先 self.operator 不是 boolean。 其次,如果 x 和 y 值都非零, self.operator.handle返回 true。 这意味着仅在实体不移动时才应用摩擦,这没有任何意义。 但是考虑到整个 if 语句的摩擦总是被应用,因为 self.operator 总是有一个值。 但这一切只会改变规模而不是方向。

真正的问题似乎是错字,再次更新 function。 我不知道这里发生了什么,但我很确定这是问题所在,因为如果这些评估为真,你的 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:

暂无
暂无

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

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