简体   繁体   English

在pygame中使用标准化向量不一致?

[英]moving with a normalized vector in pygame inconsistent?

I have 2 points in pygame and I want to move a sprite from point 1 to point 2. The approach I went with was that I get the vectors for both points (target - start), normalized that vector and then applied it to the sprite and multiplied the vector with a speed.我在 pygame 中有 2 个点,我想将精灵从点 1 移动到点 2。我采用的方法是获取两个点的向量(目标 - 开始),对该向量进行归一化,然后将其应用于精灵并将向量与速度相乘。 This does move the sprite but the angle it is moving changes depending on the speed.这确实会移动精灵,但它移动的角度会根据速度而变化。

Here is the code:这是代码:

import pygame, sys
from pygame.math import Vector2

class Icon(pygame.sprite.Sprite):
    def __init__(self,start,end):
        super().__init__()
        # setup
        self.image = pygame.Surface((40,40))
        self.image.fill('red')
        self.rect = self.image.get_rect(center = start)
        
        # positions
        self.direction = Vector2(end) - Vector2(start) 
        self.speed = 10 # changing this changes the direction the sprite moves
        self.moving = False

    def move(self):
        self.moving = True

    def update(self):
        if self.moving:
            self.rect.center += self.direction.normalize() * self.speed 

# drawing the points to show where things are supposed to be
def draw_path_points(p1,p2):
    pygame.draw.lines(screen,'grey',False,(p1,p2),4)
    pygame.draw.circle(screen,'white',p1,20)
    pygame.draw.circle(screen,'white',p2,20)


pygame.init()
screen = pygame.display.set_mode((600,600))
clock = pygame.time.Clock()
font = pygame.font.Font(None,40)

point_1 = (100,100)
point_2 = (400,520)
icon = pygame.sprite.GroupSingle(Icon(point_1,point_2))

while True:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            pygame.quit()
            sys.exit()
        if event.type == pygame.KEYDOWN:
            if event.key == pygame.K_SPACE:
                icon.sprite.move()

    screen.fill((30,30,30))
    draw_path_points(point_1,point_2)
    icon.update()
    icon.draw(screen)


    pygame.display.update()
    clock.tick(60)

I am really confused by this, did I make a mistake somewhere or misunderstood vectors somewhere?我真的对此感到困惑,我是否在某处犯了错误或在某处误解了向量? Worst of all is that regardless of the speed the sprite never actually hits the second point and always misses it by a tiny bit...最糟糕的是,无论速度如何,精灵从未真正击中第二个点,并且总是稍微错过它......

Since pygame.Rect is supposed to represent an area on the screen, a pygame.Rect object can only store integral data.由于pygame.Rect应该代表屏幕上的一个区域,因此pygame.Rect对象只能存储整数数据。

The coordinates for Rect objects are all integers. Rect 对象的坐标都是整数。 [...] [...]

The fraction part of the coordinates gets lost when the new position of the object is assigned to the Rect object.当对象的新位置分配给Rect对象时,坐标的小数部分会丢失。 If this is done every frame, the position error will accumulate over time.如果每帧都这样做,位置误差将随着时间累积。

If you want to store object positions with floating point accuracy, you have to store the location of the object in a separate variable respectively attribute and to synchronize the pygame.Rect object.如果要以浮点精度存储对象位置,则必须将对象的位置分别存储在单独的变量中,并同步pygame.Rect对象。round the coordinates and assign it to the location of the rectangle:将坐标round并将其分配给矩形的位置:

class Icon(pygame.sprite.Sprite):
    def __init__(self,start,end):
        # [...]

        self.pos = Vector2(start)
        self.rect = self.image.get_rect(center = start)
        
        # [...]

    def update(self):
        if self.moving:
            self.pos += self.direction.normalize() * self.speed 
            self.rect.center = (round(self.pos.x), round(self.pos.y))

Complete example:完整示例:

import pygame, sys
from pygame.math import Vector2

class Icon(pygame.sprite.Sprite):
    def __init__(self,start,end):
        super().__init__()
        # setup
        self.image = pygame.Surface((40,40))
        self.image.fill('red')
        self.pos = Vector2(start)
        self.rect = self.image.get_rect(center = start)
        
        # positions
        self.direction = Vector2(end) - Vector2(start) 
        self.speed = 10 # changing this changes the direction the sprite moves
        self.moving = False

    def move(self):
        self.moving = True

    def update(self):
        if self.moving:
            self.pos += self.direction.normalize() * self.speed 
            self.rect.center = (round(self.pos.x), round(self.pos.y))

# drawing the points to show where things are supposed to be
def draw_path_points(p1,p2):
    pygame.draw.lines(screen,'grey',False,(p1,p2),4)
    pygame.draw.circle(screen,'white',p1,20)
    pygame.draw.circle(screen,'white',p2,20)


pygame.init()
screen = pygame.display.set_mode((600,600))
clock = pygame.time.Clock()
font = pygame.font.Font(None,40)

point_1 = (100,100)
point_2 = (400,520)
icon = pygame.sprite.GroupSingle(Icon(point_1,point_2))

while True:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            pygame.quit()
            sys.exit()
        if event.type == pygame.KEYDOWN:
            if event.key == pygame.K_SPACE:
                icon.sprite.move()

    screen.fill((30,30,30))
    draw_path_points(point_1,point_2)
    icon.update()
    icon.draw(screen)


    pygame.display.update()
    clock.tick(60)

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

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