Pygame Doesn't Let Me Use Float For Rect.Move, But I Need It

Pygame doesn't let me use float for rect.move, but I need it

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. [...]

If you want to store object positions 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 (e.g. .topleft) of the rectangle:

x, y = # floating point coordinates
rect.topleft = round(x), round(y)

Sprite doesn't move right when rect.x change is <1

pygame.Rect only accepts integer values. floating points will get rounded, and for very small values will equal 0 which is why it won't move unless it's bigger than -1 in your case.

From the documentation

The coordinates for Rect objects are all integers.

Pygame diagonal movement not at correct angle

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

My pygame sprites get missaligned overtime

This is a very common problem and is related to pygame.Rect. 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 offset is added to the position of the Rect object. If this is done every frame, the position error will accumulate over time.

self.rect.x += x_shift
self.rect.y -= y_shift

If you want to store object positions 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 (e.g. .topleft) of the rectangle:

class Tile(pygame.sprite.Sprite):
def __init__(self,pos):
super().__init__()
self.image = pygame.Surface((tile_size,tile_size))
self.image.fill('grey')
self.rect = self.image.get_rect(topleft = pos)
self.x = self.rect.x
self.y = self.rect.y

def update(self,x_shift,y_shift):
self.x += x_shift
self.y -= y_shift
self.rect.topleft = round(self.x), round(self.y)

pygame delta time causes inconsistent movement

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 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 separate variables and you have to synchronize the pygame.Rect object. round the coordinate and assign it to the position of the rectangle:

rect1 = pygame.Rect(0,150,100,100)
rect2 = pygame.Rect(1180,500,100,100)
pos1_x = rect1.x
pos2_x = rect2.x
while True:
# [...]

pos1_x += speed * dt
pos2_x -= speed * dt
rect1.x = round(pos1_x)
rect2.x = round(pos2_x)

# [...]

See also Pygame doesn't let me use float for rect.move, but I need it

pygame move rectangle stays at top but move_ip moves

While move_ip() changes the position of the object itself, move returns a new object with a different position, but does not change the object itself.

Hence self.rect.move(50,400) does nothing at all, because the return value goes nowhere.

The statement

self.rect.move_ip(50,400)

can be replaced by

self.rect = self.rect.move(50,400)

Why is my sprite moving faster to left while colliding with floor? pygame

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. This causes the object to move faster to the left than to the right.

If you want to store object positions 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 (e.g. .topleft) of the rectangle:

class Character(pygame.sprite.Sprite):
def __init__(self, color, width, height):
super().__init__()
self.image = pygame.Surface([width, height])
pygame.draw.rect(self.image, color, [0, 0, width, height])
self.image = pygame.image.load("Fuses.png").convert_alpha()
self.rect = self.image.get_rect()
self.x, self.y = self.rect.center

def update(self):
self.rect.center = round(self.x), round(self.y)
def update():
# updates player position
player.x += velx
player.y += vely
player.update()

def collide():
# [...]

if player.x < 37 / 2:
player.x = 37 / 2
velx = velx * 0.85
if player.x > screen_width - 37 / 2:
player.x = screen_width - 37 / 2
velx = velx * 0.85
if player.y < 63 / 2:
player.y = 63 / 2
vely = vely * 0.90
if player.y > screen_height - 63 / 2 + 1:
player.y = screen_height - 63 / 2 + 1
vely = vely * 0.90
velx = velx * 0.85


Related Topics



Leave a reply



Submit