How to Make Smooth Movement in Pygame

How can I get smooth movement in pygame?

Instead of using pygame.time.delay, you can use clock.tick.

import pygame

pygame.init()

win = pygame.display.set_mode((500, 500))

class player():
def __init__(self, x, y, width, height):
self.x = x
self.y = y
self.width = width
self.height = height
self.vel = 2
self.left = False
self.right = False

def draw(self):
pygame.draw.rect(win, (255, 0, 0), (man.x, man.y, man.height, man.width))
if self.left:
pygame.draw.rect(win, (255, 0, 0), (man.x, man.y, man.height, man.width))
elif self.right:
pygame.draw.rect(win, (255, 0, 0), (man.x, man.y, man.height, man.width))

def re_draw():

man.draw()
pygame.display.update()

man = player(400, 400, 60, 60)

run = True
clock = pygame.time.Clock()

while run:

win.fill((0, 0, 0)) # fill the window with your desired color
# pygame.time.delay(10) use clock.tick instead

for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False

keys = pygame.key.get_pressed()

if keys[pygame.K_LEFT] and man.x > man.vel:
man.x -= man.vel
man.left = True
man.right = False

elif keys[pygame.K_RIGHT] and man.x < 500 - man.width - man.vel:
man.x += man.vel
man.left = False
man.right = True

man.draw() # this might be better

pygame.display.update()

clock.tick(60)

pygame.quit()

Hope this helps and welcome to StackOverflow.

Pygame - Smoother Movement

PROBLEM SOLVED

I have solved the problem by just unindenting this part from the FOR loop
while not exitgame:

    for event in pygame.event.get():
if event.type == pygame.QUIT:
exitgame = True
quitgame()

key_pressed = pygame.key.get_pressed()
if key_pressed[pygame.K_LEFT]:
cellpos_x -= 10
if key_pressed[pygame.K_RIGHT]:
cellpos_x += 10

Pygame smooth movement

How can I get a pygame rect to move smoothly?

If your rectangle has to move 25px per frame, then the it makes no sens to draw the rectangles at the positions in between. The display is updated once per frame and it make no sens at all to draw the rectangle at the positions in between.

Possibly you have to less frames per second. In that case you have to increase the framerate and you can decrease the movement. Note, the human eye can just process a certain number of images per second. The trick is that you generate enough frames, that the movement appears smooth for the human eye.

pygame.Rect can store integral values only. If you want to operate with a very high framerate and floating accuracy, then you have to store the position of the object in separate floating point attributes. Synchronize the rounded position to the rectangle attribute. Note, you cannot draw on a "half" pixel of the window (at least in pygame).

e.g.:

class Dot(pygame.sprite.Sprite):
# This class represents a car. It derives from the "Sprite" class in Pygame.
def __init__(self, color, x, y, width, height):

# Call the parent class (Sprite) constructor
super().__init__()

# Pass in the color of the car, and its x and y position, width and height.
# Set the background color and set it to be transparent
self.x = x
self.y = y
self.image = pygame.Surface([width, height])
self.image.fill(self.color)
self.rect = self.image.get_rect(center = (round(x), round(y)))

def update(self):
# update position of object (change `self.x`, ``self.y``)
# [...]

# synchronize position to `.rect`
self.rect.center = (round(x), round(y))

How do I make smooth movement + rotation in pygame?

The issue is caused by the code which rotates the sprite.

Rotate the image, and get a pygame.Rect of the coated image. Set the center of the rectangle by the position of the object. Use the rectangle to blit the image.

See How do I rotate an image around its center using Pygame?.

img_copy = pygame.transform.rotate(self.player_ship, self.angle)
rotated_rect = img_copy.get_rect(center = (round(self.x), round(self.y)))

To rotate the image it is sufficient to compute the unit direction vector [See Unit vector.)] from the current position to the mouse position. Scale the vector by the speed and add it to the position:

cx, cy = pygame.mouse.get_pos()
dx, dy = cx - self.x, cy - self.y
if abs(dx) > 0 or abs(dy) > 0:
dist = math.hypot(dx, dy)
self.x += min(dist, speed) * dx/dist
self.y += min(dist, speed) * dy/dist

See the example

class player():
def __init__(self, x_position, y_position, length, height):
self.x = x_position
self.y = y_position
self.l = length
self.h = height
self.player_ship = pygame.transform.scale(ships[0], (128, 128))
self.angle = 0

def draw(self, win):

cx, cy = pygame.mouse.get_pos()
dx, dy = cx - self.x, cy - self.y
if abs(dx) > 0 or abs(dy) > 0:
self.angle = math.atan2(-dx, -dy)*57.2957795

img_copy = pygame.transform.rotate(self.player_ship, self.angle)
rotated_rect = img_copy.get_rect(center = (round(self.x), round(self.y)))

win.blit(img_copy, rotated_rect)

def move(self, speed):
cx, cy = pygame.mouse.get_pos()
dx, dy = cx - self.x, cy - self.y
if abs(dx) > 0 or abs(dy) > 0:
dist = math.hypot(dx, dy)
self.x += min(dist, speed) * dx/dist
self.y += min(dist, speed) * dy/dist

Sample Image

Python pygame - smooth movement with float numbers

First of pygame.event.get() get all the messages and remove them from the queue. So either the 1st or the 2nd loop gets an event, but never both loops will get all events. That causes that some events seems to be missed.

implement 1 event loop in your application.

Once UP is released, you've to set a decelerate state. Decrease the variable and move the care forward by the amount in every frame as long decelerate > 0:

def drawbg():
wn.blit(bg, (0, int(bgy)))
wn.blit(bg, (0, int(bgy2)))
drawbg()

def bg_movement(bgy, bgy2, spd):
bgy += float(spd)
bgy2 += float(spd)
if bgy > bg.get_height():
bgy = -bg.get_height()
if bgy2 > bg.get_height():
bgy2 = -bg.get_height()
return bgy, bgy2

decelerate = 0
while run:

clock.tick(60)

# keys binding
keys = pygame.key.get_pressed()
if keys[pygame.K_LEFT]:
if car.x + car.hor_spd > 0:

car.x -= car.hor_spd
if keys[pygame.K_RIGHT]:
if car.x + car.hor_spd < wnw - car.w:
car.x += car.hor_spd
if keys[pygame.K_UP]:
decelerate = 0
if car.y - car.ver_spd > 0:
bgy, bgy2 = bg_movement(bgy, bgy2, car.ver_spd)

if decelerate > 0:
bgy, bgy2 = bg_movement(bgy, bgy2, decelerate)
decelerate -= 0.1

for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
if event.type == pygame.KEYUP:
if event.key == pygame.K_UP:
decelerate = car.ver_spd

drawbg()
wn.blit(car.sprite, (car.x, car.y))

pygame.display.update()

Sample Image



Related Topics



Leave a reply



Submit