Pygame对角运动不正确的角度

发布于 2025-02-08 22:00:13 字数 1492 浏览 0 评论 0 原文

我希望我的玩家以与水平或垂直移动时相同的速度以对角线移动。但是,当沿着正梯度移动时,在与负梯度的一条线上移动时确实可以工作,玩家并没有以完美的45度角移动。

这是我移动玩家的代码:

def move(self, speed):
    if self.direction.magnitude() != 0:
        self.direction = self.direction.normalize()
            
    self.rect.x += self.direction.x * speed
    self.rect.y += self.direction.y * speed

正如我之前说的,我想要的只是让玩家以与X或Y方向相同的速度对角移动。

这是完整的玩家课程,以防需要:

class Player:
    def __init__(self, x, y):
        self.image = pygame.Surface((30, 30))
        self.image.fill((255, 255, 255))
        self.rect = self.image.get_rect(center = (x, y))
        self.direction = pygame.math.Vector2()
        self.speed = 5 

    def input(self):
        keys = pygame.key.get_pressed()

        if keys[K_w]:
            self.direction.y = -1
        elif keys[K_s]:
            self.direction.y = 1
        else:
            self.direction.y = 0
            
        if keys[K_a]:
            self.direction.x = -1
        elif keys[K_d]:
            self.direction.x = 1
        else:
            self.direction.x = 0

    def move(self, speed):
        if self.direction.magnitude() != 0:
            self.direction = self.direction.normalize()
            
        self.rect.x += self.direction.x * speed
        self.rect.y += self.direction.y * speed

    def update(self):
        self.input()
        self.move(self.speed)
            
    def draw(self, screen):
        screen.blit(self.image, self.rect.center)

I would like my player to move diagonally at the same speed as it does when only moving horizontally or vertically. This does work when moving in a line with a negative gradient however, when moving along a positive gradient, the player doesn't move at a perfect 45 degree angle.

This is my code for moving the player:

def move(self, speed):
    if self.direction.magnitude() != 0:
        self.direction = self.direction.normalize()
            
    self.rect.x += self.direction.x * speed
    self.rect.y += self.direction.y * speed

As I said earlier, all I want is for the player to move diagonally at the same speed as it does in only the x or y direction.

Here is the full player class in case it is needed:

class Player:
    def __init__(self, x, y):
        self.image = pygame.Surface((30, 30))
        self.image.fill((255, 255, 255))
        self.rect = self.image.get_rect(center = (x, y))
        self.direction = pygame.math.Vector2()
        self.speed = 5 

    def input(self):
        keys = pygame.key.get_pressed()

        if keys[K_w]:
            self.direction.y = -1
        elif keys[K_s]:
            self.direction.y = 1
        else:
            self.direction.y = 0
            
        if keys[K_a]:
            self.direction.x = -1
        elif keys[K_d]:
            self.direction.x = 1
        else:
            self.direction.x = 0

    def move(self, speed):
        if self.direction.magnitude() != 0:
            self.direction = self.direction.normalize()
            
        self.rect.x += self.direction.x * speed
        self.rect.y += self.direction.y * speed

    def update(self):
        self.input()
        self.move(self.speed)
            
    def draw(self, screen):
        screen.blit(self.image, self.rect.center)

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

橪书 2025-02-15 22:00:13

因为 pygame.Rect 应该代表一个屏幕上的区域, pygame.Rect 对象只能存储积分数据。

rect对象的坐标都是整数。 [...]

当对象的新位置分配给 rect 对象时,坐标部分会丢失。如果要使用浮点精度移动对象,则必须将对象的位置分别存储在单独的变量属性中,并同步 pygame.Rect.Rect 对象。 round> rounh 坐标并将其分配给矩形的位置:

class Player:
   def __init__(self, x, y):
       self.image = pygame.Surface((30, 30))
       self.image.fill((255, 255, 255))
       self.rect = self.image.get_rect(center = (x, y))
       self.direction = pygame.math.Vector2()
       self.speed = 5 

       self.position = pygame.math.Vector2(x, y)

   def input(self):
       keys = pygame.key.get_pressed()
       dx = keys[K_d] - keys[K_a]
       dy = keys[K_s] - keys[K_w]
       self.direction = pygame.math.Vector2(dx, dy)
       if dx != 0 and dy != 0:
           self.direction /= 1.41421

   def move(self, speed):    
       self.position += self.direction * speed
       self.rect.x = round(self.position.x)
       self.rect.y = round(self.position.y)
       
   def update(self):
       self.input()
       self.move(self.speed)
           
   def draw(self, screen):
       screen.blit(self.image, self.rect.center)

另请参见Pygame doesn't let me use float for rect.move, but I need it and


请注意, pygame.math.math.vector2。幅度 > MATH.VECTOR2.Normalize 性能很昂贵。尝试避免此操作。仅在沿两个轴移动时才需要归一化。由于在这种情况下,向量的绝对值为√2,因此可以通过除以√2代替归一化。

dx = keys[K_d] - keys[K_a]                   # dx is -1, 0 or 1
dy = keys[K_s] - keys[K_w]                   # dy is -1, 0 or 1
self.direction = pygame.math.Vector2(dx, dy)
if dx != 0 and dy != 0:  
    self.direction /= 1.41421                # sqrt(2) is ~1.41421

Since pygame.Rect is supposed to represent an area on the screen, a pygame.Rect object can only store integral data.

The coordinates for Rect objects are all integers. [...]

The fraction part of the coordinates gets lost when the new position of the object is assigned to the Rect object. If you want to move the object with floating point accuracy, you have to store the location of the object in separate variables respectively attributes and to synchronize the pygame.Rect object. round the coordinates and assign it to the location of the rectangle:

class Player:
   def __init__(self, x, y):
       self.image = pygame.Surface((30, 30))
       self.image.fill((255, 255, 255))
       self.rect = self.image.get_rect(center = (x, y))
       self.direction = pygame.math.Vector2()
       self.speed = 5 

       self.position = pygame.math.Vector2(x, y)

   def input(self):
       keys = pygame.key.get_pressed()
       dx = keys[K_d] - keys[K_a]
       dy = keys[K_s] - keys[K_w]
       self.direction = pygame.math.Vector2(dx, dy)
       if dx != 0 and dy != 0:
           self.direction /= 1.41421

   def move(self, speed):    
       self.position += self.direction * speed
       self.rect.x = round(self.position.x)
       self.rect.y = round(self.position.y)
       
   def update(self):
       self.input()
       self.move(self.speed)
           
   def draw(self, screen):
       screen.blit(self.image, self.rect.center)

See also Pygame doesn't let me use float for rect.move, but I need it and moving with a normalized vector in pygame inconsistent?.


Note, that pygame.math.Vector2.magnitude and math.Vector2.normalize are expensive for performance. Try to avoid this operations. Normalization of the vector is only required when moving along both axes. Since the absolute value of the vector is √2 in this case, the normalization can be replaced by dividing by √2.

dx = keys[K_d] - keys[K_a]                   # dx is -1, 0 or 1
dy = keys[K_s] - keys[K_w]                   # dy is -1, 0 or 1
self.direction = pygame.math.Vector2(dx, dy)
if dx != 0 and dy != 0:  
    self.direction /= 1.41421                # sqrt(2) is ~1.41421
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文