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
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()
Related Topics
Is There a List of Pytz Timezones
How to Convert JSON Data into a Python Object
How to Convert Each Item in the List to String, for the Purpose of Joining Them
Non-Alphanumeric List Order from Os.Listdir()
How to Capitalize the First Letter of Each Word in a String
Python Max Function Using 'Key' and Lambda Expression
How to Have Clusters of Stacked Bars
X, = ... - Is This Trailing Comma the Comma Operator
Is It Pythonic: Naming Lambdas
Pandas Read_Csv: Low_Memory and Dtype Options
Python List VS. Array - When to Use
Scrape Multiple Urls Using Qwebpage
How to Convert a Utc Datetime to a Local Datetime Using Only Standard Library
How to Create a List of Lambdas (In a List Comprehension/For Loop)