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
Why Should Exec() and Eval() Be Avoided
"Ask Forgiveness Not Permission" - Explain
Can't Send Input to Running Program in Sublime Text
Should I Put #! (Shebang) in Python Scripts, and What Form Should It Take
How to Properly Determine the Current Script Directory
Converting Unix Timestamp String to Readable Date
"Inconsistent Use of Tabs and Spaces in Indentation"
String Count With Overlapping Occurrences
Select Dataframe Rows Between Two Dates
What's the Difference Between Eval, Exec, and Compile
How to Capture Sigint in Python
How to Find the Cumulative Sum of Numbers in a List
Pandas Groupby With Delimiter Join
Urllib and "Ssl: Certificate_Verify_Failed" Error
Import a Module from a Relative Path
Refering to a Directory in a Flask App Doesn't Work Unless the Path Is Absolute