making a simple game in pygame. have imported an image for my charactater and can move him around freely. I was wondering how to make the character slowly stop when the;
event.type == KEYUP:
as in, When I release the key the character will take say, 50 pixels from when the key has been released to the character slowly stopping.
I have tried a few different things but nothing seems to work. below is my code. any help would be great =]
bg="bg.jpg"
staticCharacter="toon.png"
import pygame, sys, time
from pygame.locals import *
pygame.init()
screen = pygame.display.set_mode((640,360),0,32)
background=pygame.image.load(bg).convert()
staticToon = pygame.image.load(characterMid).convert_alpha()
x = 0
y = 0
movex = 0
movey = 0
while True:
for event in pygame.event.get():
if event.type == QUIT:
pygame.quit()
sys.exit()
if event.type == KEYDOWN:
if event.key == K_LEFT:
movex = -0.20
elif event.key == K_RIGHT:
movex = +0.20
elif event.key == K_UP:
movey = -0.20
elif event.key == K_DOWN:
movey = +0.20
if event.type == KEYUP:
if event.key == K_LEFT:
movex = 0
elif event.key == K_RIGHT:
movex = 0
elif event.key == K_UP:
movey = 0
elif event.key == K_DOWN:
movey = 0
x += movex
y += movey
if x > 560:
x = 560
if y > 280:
y = 280
if x < 0:
x = 0
if y < 0:
y = 0
screen.blit(background,(0,0))
screen.blit(staticToon,(x,y))
pygame.display.update()
distance = speed*time
Instead of augmenting the position (through movex or movey), you want to augment the speed:
delta = {
pygame.K_LEFT: (-20, 0),
pygame.K_RIGHT: (+20, 0),
pygame.K_UP: (0, -20),
pygame.K_DOWN: (0, +20),
}
...
elif event.type == pygame.KEYDOWN:
deltax, deltay = delta.get(event.key, (0, 0))
ball.speed[0] += deltax
ball.speed[1] += deltay
Now, to slow down the object (a ball in my example below), add some friction:
ball.speed[0] *= 0.95
ball.speed[1] *= 0.95
This diminishes the speed by a little bit each time through the event loop.
Move the object a distance equal to speed * time. To make things simple, let's just take change in time to be 1.
self.rect = self.rect.move(self.speed)
Here is a runnable example: (just add a correct path for staticCharacter.)
import sys
import pygame
import os
'''
Based on http://www.pygame.org/docs/tut/intro/intro.html
Draws a red ball bouncing around in the window.
Pressing the arrow keys moves the ball
'''
staticCharacter = "toon.png"
delta = {
pygame.K_LEFT: (-20, 0),
pygame.K_RIGHT: (+20, 0),
pygame.K_UP: (0, -20),
pygame.K_DOWN: (0, +20),
}
class Ball(pygame.sprite.Sprite):
def __init__(self):
pygame.sprite.Sprite.__init__(self)
self.image = pygame.image.load(staticCharacter)
self.rect = self.image.get_rect()
self.speed = [2, 2]
self.area = pygame.display.get_surface().get_rect()
def update(self):
self.rect = self.rect.move(self.speed)
if self.rect.left < 0 or self.rect.right > self.area.width:
self.speed[0] = -self.speed[0]
if self.rect.top < 0 or self.rect.bottom > self.area.height:
self.speed[1] = -self.speed[1]
class Main(object):
def __init__(self):
self.setup()
def setup(self):
pygame.init()
size = (self.width, self.height) = (640,360)
self.black = (0, 0, 0)
self.screen = pygame.display.set_mode(size, 0, 32)
self.ball = Ball()
self.setup_background()
def setup_background(self):
self.background = pygame.Surface(self.screen.get_size())
self.background = self.background.convert()
self.background.fill(self.black)
self.screen.blit(self.background, (0, 0))
pygame.display.flip()
def draw(self):
self.screen.blit(self.background, (0, 0))
self.screen.blit(self.ball.image, self.ball.rect)
pygame.display.flip()
def event_loop(self):
ball = self.ball
while True:
for event in pygame.event.get():
if ((event.type == pygame.QUIT) or
(event.type == pygame.KEYDOWN and
event.key == pygame.K_ESCAPE)):
sys.exit()
elif event.type == pygame.KEYDOWN:
deltax, deltay = delta.get(event.key, (0, 0))
ball.speed[0] += deltax
ball.speed[1] += deltay
ball.speed = [0.99*s for s in ball.speed]
ball.update()
self.draw()
pygame.time.delay(10)
if __name__ == '__main__':
app = Main()
app.event_loop()
Normally, character movement is made to be independent from the machine speed. In your example, you do not know how many times per second the While loop goes, it is dependent on the computer speed. So firstly, you should use the pygame Clock to calculate the time difference between each call to move().
myclock = pygame.Clock()
delta = myclock.tick()
when you have the time difference, you can use a distance equation such as this:
position += speed * direction * delta
delta is in ms, so you need to set your speed accordingly. The direction would be -1 or +1 depending on the current key pressed. A keyup would set direction to 0.
Now back to the question. You would have to change the above a bit differently.
A keyup would subtract a small value from direction.
Then check if direction isn't 1 or -1 and then subtract a value from your direction. You would do this every loop. This way it will get smaller and smaller, and it will appear that your character is slowing down. It is good to also multiply the value that you subtract by delta so it will be deacceleration will constant on every computer.
My advice:
Go to the following website: http://karpathy.ca/phyces/tutorial1.php
Download pygamehelper and startercode (I promise it will make your life easier).
FPS is built-in so you don't need to make the adjustments within your movement logic.
Review some of the other tutorials if you want further clarification and use the vector library if you want some extra snaz.
Related
I'm quite new with python and coding. Trying to code a simple game using pygame I have found an issue that I can't solve in my movement function.
I have a function that uses the pygame method get_pressed() in order to set the direction of the player velocity vector (see below). With this code if in the game I hold down a and then press d the player surface changes direction even if i'm still holding down the a key, while if I do the opposite the player continues moving to the right as if I don't press the a key.
I understand that this is due to the order of the if statements in the function and my question is: is there a way to make the player change direction in both cases?
I really hope that the question is clear and thanks in advance if someone will help me.
The function that sets the direction of the velocity:
def get_keys(self):
self.vel = vec(0, 0)
keys = pg.key.get_pressed()
if keys[pg.K_a]:
self.vel.x = -PLAYER_SPEED
if keys[pg.K_d]:
self.vel.x = PLAYER_SPEED
if keys[pg.K_w]:
self.vel.y = -PLAYER_SPEED
if keys[pg.K_s]:
self.vel.y = PLAYER_SPEED
if self.vel.x != 0 and self.vel.y != 0:
self.vel *= 0.7071
The update function:
def update(self)
self.get_keys()
self.pos += self.vel * self.game.dt
self.rect.centerx = self.pos.x
self.rect.centery = self.pos.y
For what you want to do you have to use the keyboard events. Note that you want to change direction as soon as a key is pressed. This is and event. e.g.:
import pygame
pygame.init()
window = pygame.display.set_mode((400, 400))
clock = pygame.time.Clock()
pos = pygame.Vector2(window.get_rect().center)
dx, dy = 0, 0
speed = 5
run = True
while run:
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_a:
dx = -1
if event.key == pygame.K_d:
dx = 1
if event.key == pygame.K_w:
dy = -1
if event.key == pygame.K_s:
dy = 1
if event.type == pygame.KEYUP:
if (event.key == pygame.K_a and dx < 0) or (event.key == pygame.K_d and dx > 0):
dx = 0
if (event.key == pygame.K_w and dy < 0) or (event.key == pygame.K_s and dy > 0):
dy = 0
vel = pygame.Vector2(dx, dy)
if vel.x != 0 or vel.y != 0:
vel.scale_to_length(speed)
pos += vel
pos.x %= window.get_width()
pos.y %= window.get_height()
window.fill(0)
pygame.draw.circle(window, (255, 0, 0), pos, 20)
pygame.display.flip()
clock.tick(60)
pygame.quit()
exit()
I am having problems with making a homing algorithm to move an enemy towards a player in a game. For some reason, the algorithm works sometimes, but as you move the player around, the enemy gets to points where it just stops even though there is still a difference between the player x and y variables and the enemy x and y variables (which the code should be applying to the enemy at all times). If you run the code you'll see what I mean.
Here is my code:
import pygame
import sys, os, random
from pygame.locals import *
from pygame import mixer
import math
clock = pygame.time.Clock()
screen_width = 700
screen_height = 700
screen = pygame.display.set_mode((screen_width, screen_height))
player_rect = pygame.Rect(200, 200, 10, 10)
moving_left = False
moving_right = False
moving_down = False
moving_up = False
hunter_rect = pygame.Rect(500, 500, 48, 60)
player_rect.x = 300
player_rect.y = 200
while True:
screen.fill((50, 50, 50))
#screen.blit(player, (player_rect.x, player_rect.y))
#screen.blit(hunter, (hunter_rect.x, hunter_rect.y))
pygame.draw.rect(screen, (255, 255, 255), player_rect)
pygame.draw.rect(screen, (255, 0, 0), hunter_rect)
#### getting the change in y and the change in x from enemy to player ###
ychange = (hunter_rect.y - player_rect.y)/100
xchange = (hunter_rect.x - player_rect.x)/100
hunter_rect.x -= xchange
hunter_rect.y -= ychange
if moving_left:
player_rect.x -= 4
if moving_right:
player_rect.x += 4
if moving_up:
player_rect.y -= 4
if moving_down:
player_rect.y += 4
for event in pygame.event.get():
if event.type == QUIT:
sys.exit()
pygame.quit()
if event.type == KEYDOWN:
if event.key == K_ESCAPE:
pygame.quit()
sys.exit()
if event.key == K_a:
moving_left = True
if event.key == K_d:
moving_right = True
if event.key == K_s:
moving_down = True
if event.key == K_w:
moving_up = True
if event.type == KEYUP:
if event.key == K_a:
moving_left = False
if event.key == K_d:
moving_right = False
if event.key == K_w:
moving_up = False
if event.key == K_s:
moving_down = False
pygame.display.update()
clock.tick(60)
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 movement gets lost when the movement is add to the position of the rectangle.
If you want to store object positions with floating point accuracy, you have to store the location of the object in separate variables and to synchronize the pygame.Rect object. round the coordinates and assign it to the location (e.g. .topleft) of the rectangle:
hunter_rect = pygame.Rect(500, 500, 48, 60)
hunter_x, hunter_y = hunter_rect.topleft
# [...]
while True:
# [...]
hunter_x -= xchange
hunter_y -= ychange
hunter_rect.topleft = round(hunter_x), round(hunter_y)
# [...]
I am making a mini-game that involves movement. I created an object that moves according to the controls, but how do i make it not move if it collides with a wall?
#Imports
import pygame, sys
#Functions
#General Set Up
pygame.init()
clock = pygame.time.Clock()
#Main Window
swid = 1280
shgt = 700
screen = pygame.display.set_mode((swid, shgt))
pygame.display.set_caption("Raid: The Game || Movement Test")
#Game Rectangles
player = pygame.Rect(30, 30, 30, 30)
wall = pygame.Rect(140, 80, 1000, 20)
window = pygame.Rect(300, 400, 220, 20)
door = pygame.Rect(500, 500, 120, 18)
bgcol = (0,0,0)
playercol = (200,0,0)
wallcol = pygame.Color("grey12")
doorcol = pygame.Color("blue")
windowcol = (100,100,100)
xwalkspeed = 0
ywalkspeed = 0
while True:
#Handling Input
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_DOWN:
ywalkspeed += 10
if event.key == pygame.K_UP:
ywalkspeed -= 10
if event.key == pygame.K_LEFT:
xwalkspeed -= 10
if event.key == pygame.K_RIGHT:
xwalkspeed += 10
if event.type == pygame.KEYUP:
if event.key == pygame.K_DOWN:
ywalkspeed -= 10
if event.key == pygame.K_UP:
ywalkspeed += 10
if event.key == pygame.K_LEFT:
xwalkspeed += 10
if event.key == pygame.K_RIGHT:
xwalkspeed -= 10
player.x += xwalkspeed
player.y += ywalkspeed
distancebetween = 0
if player.colliderect(wall):
ywalkspeed = 0
xwalkspeed= 0
if player.top <= 0:
player.top = 0
if player.bottom >= shgt:
player.bottom = shgt
if player.left <= 0:
player.left = 0
if player.right >= swid:
player.right = swid
#Visuals
screen.fill(bgcol)
pygame.draw.ellipse(screen, playercol, player)
pygame.draw.rect(screen, wallcol, wall)
pygame.draw.rect(screen, doorcol, door)
pygame.draw.rect(screen, windowcol, window)
#Updating the Window
pygame.display.flip()
clock.tick(60)
Whenever my Object collides upon a wall, it starts moving the opposite way until it is no longer seen in the screen.
I Found the Reason why it kept moving the opposite way when it collides the wall. It is because if I move towards the wall, my ywalkspeed = 10 and when I collided with the wall, it becomes 0, then if I started to let go of the movement key, the ywalkspeed becomes ywalkspeed = -10. I currently don't know a way how to fix this as I am just a noob.
Make a copy of the original player rectangle with copy(). Move the player. If a collision is detected, restore the player rectangle:
copy_of_player_rect = player.copy()
# move player
# [...]
if player.colliderect(wall):
player = copy_of_player_rect
You can watch for the distance between the wall and the player and when the distance according to axis positions reaches zero, just do
xwalkspeed = 0
ywalkspeed = 0
To measure the distance and smooth realistic movement, you can also use equations of motion from Physics.
I'm trying to use time.Time() to control the fire rate of my projectiles, but after putting in the time logic, my player can no longer shoot any projectiles at all. How can I make it so that my player only fires once every half a second or so?
The following is a workable example;
main game module
import pygame
from constants import *
from player import Player
from Projectile import Projectiles
import time
pygame.init()
screen = pygame.display.set_mode([500, 500])
pygame.display.set_caption('Labyrinth')
# Spawn player
player = Player(50, 50)
all_sprites_list = pygame.sprite.Group()
all_sprites_list.add(player)
projectile_list = pygame.sprite.Group()
clock = pygame.time.Clock()
done = False
# ----- Event Loop
while not done:
for event in pygame.event.get():
if event.type == pygame.QUIT:
done = True
elif event.type == pygame.KEYDOWN:
if event.key == ord('a'):
player.changespeed(-3, 0)
elif event.key == ord('d'):
player.changespeed(3, 0)
elif event.key == ord('w'):
player.changespeed(0, -3)
elif event.key == ord('s'):
player.changespeed(0, 3)
elif event.key == pygame.K_LEFT:
projectile = Projectiles(player.rect.x, player.rect.y, -5, 0)
elif event.key == pygame.K_RIGHT:
projectile = Projectiles(player.rect.x, player.rect.y, 5, 0)
elif event.key == pygame.K_UP:
projectile = Projectiles(player.rect.x, player.rect.y, 0, -5)
elif event.key == pygame.K_DOWN:
projectile = Projectiles(player.rect.x, player.rect.y, 0, 5)
try:
if projectile:
if time.Time() - last_shot > player.fire_rate:
projectile_list.add(projectile)
last_shot = time.Time()
except:
pass
elif event.type == pygame.KEYUP:
if event.key == ord('a'):
player.changespeed(3, 0)
elif event.key == ord('d'):
player.changespeed(-3, 0)
elif event.key == ord('w'):
player.changespeed(0, 3)
elif event.key == ord('s'):
player.changespeed(0, -3)
# ----- Game Logic
all_sprites_list.update()
projectile_list.update()
screen.fill(GREEN)
all_sprites_list.draw(screen)
projectile_list.draw(screen)
pygame.display.flip()
clock.tick(60)
pygame.quit()
player module
from constants import *
import pygame
import time
from datetime import datetime, timedelta
class Player(pygame.sprite.Sprite):
def __init__(self, x, y):
super().__init__()
self.image = pygame.Surface([15, 15])
self.image.fill(BLACK)
self.rect = self.image.get_rect()
self.rect.x = x
self.rect.y = y
self.fire_rate = 1
self.change_x = 0
self.change_y = 0
def changespeed(self, x, y):
self.change_x += x
self.change_y += y
def update(self):
self.rect.x += self.change_x
self.rect.y += self.change_y
projectile module
import pygame
from constants import *
class Projectiles(pygame.sprite.Sprite):
def __init__(self, x, y, x_speed, y_speed):
super().__init__()
self.image = pygame.Surface([4, 4])
self.image.fill(RED)
self.rect = self.image.get_rect()
self.rect.x = x
self.rect.y = y
self.x_speed = x_speed
self.y_speed = y_speed
def update(self):
self.rect.x += self.x_speed
self.rect.y += self.y_speed
constants module defines a few colours. Any help is much appreciated!
Well, strictly speaking, the answer is that you have time.Time() in a try block, and it should be time.time() (all lowercase). This throws an exception, so any time time.Time() - last_shot > player.fire_rate is evaluated, the try block isn't run. This would have been more apparent if you had caught the exception and thrown an error message rather than just passing.
There likely are further issues, but a more in-depth analysis of your code is difficult, as I don't see you initializing last_shot anywhere, nor player.fire_rate. The "minimal complete example" standard isn't just for the answerers, but for the asker as well. Basic debugging in isolating the issue as much as possible.
As another note, your while loop appears to contain nothing but a for loop, making it redundant. If you're doing that to just have the program run through the loop over and over again until the appropriate time, then time.sleep() would be probably be a better way to do that.
A try with a bare except is an anti-pattern and should almost never be used, because it hides all errors in the try clause and makes the code hard to debug. I'd remove it and rearrange the event handling code.
When an arrow key gets pressed, only change the velocity vector depending on the key instead of creating new projectile instances. Then check again if any of the arrow keys were pressed and if the timer is finished, create a projectile instance and pass the current velocity vector.
import pygame as pg
from pygame.math import Vector2
BULLET_IMG = pg.Surface((9, 9))
BULLET_IMG.fill(pg.Color('aquamarine2'))
class Projectile(pg.sprite.Sprite):
def __init__(self, pos, vel):
super().__init__()
self.image = BULLET_IMG
self.rect = self.image.get_rect(center=pos)
self.vel = Vector2(vel)
def update(self):
self.rect.move_ip(self.vel)
def main():
pg.init()
screen = pg.display.set_mode((640, 480))
clock = pg.time.Clock()
projectiles = pg.sprite.Group()
previous_time = pg.time.get_ticks()
speed = 12
vel = Vector2(speed, 0)
done = False
while not done:
for event in pg.event.get():
if event.type == pg.QUIT:
done = True
elif event.type == pg.KEYDOWN:
# Only change the velocity vector.
if event.key == pg.K_LEFT:
vel = Vector2(-speed, 0)
elif event.key == pg.K_RIGHT:
vel = Vector2(speed, 0)
elif event.key == pg.K_UP:
vel = Vector2(0, -speed)
elif event.key == pg.K_DOWN:
vel = Vector2(0, speed)
# If an arrow keys was pressed, create a new projectile.
if event.key in (pg.K_LEFT, pg.K_RIGHT, pg.K_UP, pg.K_DOWN):
current_time = pg.time.get_ticks()
# We're ready to fire when 500 ms have passed.
if current_time - previous_time > 500:
previous_time = current_time
# Now create the projectile instance and pass
# the position and the velocity.
projectiles.add(Projectile(pg.mouse.get_pos(), vel))
projectiles.update()
screen.fill((30, 30, 30))
projectiles.draw(screen)
pg.display.update()
clock.tick(60)
if __name__ == '__main__':
main()
pg.quit()
I'm working on a racing game. I have been using this code but my player keeps moving once only. How do I solve this problem?
change = 7
dist = 7
change_r = 0
change_l = 0
dist_u = 0
dist_d = 0
pygame.display.update()
for event in pygame.event.get():
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_RIGHT:
change_r = True
elif event.key == pygame.K_LEFT:
change_l = True
elif event.key == pygame.K_UP:
dist_u = True
elif event.key == pygame.K_DOWN:
dist_d = True
if event.type == pygame.KEYUP:
if event.key == pygame.K_RIGHT or event.key == pygame.K_LEFT or event.key == pygame.K_UP or event.key == pygame.K_DOWN:
change_r = False
change_l = False
dist_u = False
dist_d = False
clock.tick(60)
if change_r == True:
x += change
if change_l == True:
x -= change
if dist_u == True:
y -= dist
if dist_d == True:
y += dist
There are different ways you could go about making move-able shapes/sprites using Pygame. The code you posted in your question seems overly complex. I'll give you two different ways that are simpler, and easier to use. Using a sprite class, and using a function.
It may not seem like I'm answering your question, but if I just told you what to fix in your code you posted, I'd just be knowingly steering you down a road that will lead to many problems, and much complexity in the future.
Method 1: Using a sprite class
To make a your race car sprite, you could use a sprite class like the one below.
class Player(pygame.sprite.Sprite):
def __init__(self):
pygame.sprite.Sprite.__init__(self)
self.image = pygame.Surface((50, 50))
self.image.fill((255, 0, 0))
self.rect = self.image.get_rect()
self.rect.x = WIDTH / 2
self.rect.y = HEIGHT / 2
self.vx = 0
self.vy = 0
def update(self):
self.vx = 0
self.vy = 0
key = pygame.key.get_pressed()
if key[pygame.K_LEFT]:
self.vx = -5
elif key[pygame.K_RIGHT]:
self.vx = 5
if key[pygame.K_UP]:
self.vy = -5
elif key[pygame.K_DOWN]:
self.vy = 5
self.rect.x += self.vx
self.rect.y += self.vy
Since your class is inheriting from Pygame's sprite class, You must name your image self.image and you must name your rectangle for the image self.rect. As you can also see, the class has two main methods. One for creating the sprite(__init__) and one for updating the sprite(update)
To use your class, make a Pygame sprite group to hold all your sprites, and then add your player object to the group:
sprites = pygame.sprite.Group()
player = Player()
sprtites.add(player)
And to actual render your sprites to the screen call sprites.update() and sprites.draw() in your game loop, where you update the screen:
sprites.update()
window_name.fill((200, 200, 200))
sprites.draw(window_name)
pygame.display.flip()
The reason i highly recommended using sprite classes, is that it will make your code look much cleaner, and be much easier to maintain. You could even move each sprite class to their own separate file.
Before diving fully into the method above however, you should read up on pygame.Rect objects and pygame.sprite objects, as you'll be using them.
Method 2: Using A function
If you prefer not to get into sprite classes, you can create your game entities using a function similar to the one below.
def create_car(surface, x, y, w, h, color):
rect = pygame.Rect(x, y, w, h)
pygame.draw.rect(surface, color, rect)
return rect
If you would still like to use a sprites, but don't want to make a class just modify the function above slightly:
def create_car(surface, x, y, color, path_to_img):
img = pygame.image.load(path_to_img)
rect = img.get_rect()
surface.blit(img, (x, y))
Here is an example of how i would use the functions above to make a movable rectangle/sprite:
import pygame
WIDTH = 640
HEIGHT = 480
display = pygame.display.set_mode((WIDTH, HEIGHT))
pygame.display.set_caption("Moving Player Test")
clock = pygame.time.Clock()
FPS = 60
def create_car(surface, x, y, w, h, color):
rect = pygame.Rect(x, y, w, h)
pygame.draw.rect(surface, color, rect)
return rect
running = True
vx = 0
vy = 0
player_x = WIDTH / 2 # middle of screen width
player_y = HEIGHT / 2 # middle of screen height
player_speed = 5
while running:
clock.tick(FPS)
for e in pygame.event.get():
if e.type == pygame.QUIT:
running = False
pygame.quit()
quit()
if e.type == pygame.KEYDOWN:
if e.key == pygame.K_LEFT:
vx = -player_speed
elif e.key == pygame.K_RIGHT:
vx = player_speed
if e.key == pygame.K_UP:
vy = -player_speed
elif e.key == pygame.K_DOWN:
vy = player_speed
if e.type == pygame.KEYUP:
if e.key == pygame.K_LEFT or e.key == pygame.K_RIGHT or\
e.key == pygame.K_UP or e.key == pygame.K_DOWN:
vx = 0
vy = 0
player_x += vx
player_y += vy
display.fill((200, 200, 200))
####make the player#####
player = create_car(display, player_x, player_y, 10, 10, (255, 0, 0))
pygame.display.flip()
As you may see above, your code for moving your race car can be simplified.
I should note, I'm assuming a few things with each method outlined above.
That your either using a circle, square, or some type of pygame shape object.
Or that your using a sprite.
If your not currently using any of the methods outlined above, I suggest that you do. Doing so will make your code much eaiser to maintain once you begin to build larger and more complex games.
You should have a global loop irrespective of your event handling. You should place your clock.tick() and your movement there. Namely:
#some constants here
while True:
pygame.display.update()
clock.tick(60)
#update you game state
if change_r == True:
x += change
if change_l == True:
x -= change
if dist_u == True:
y -= dist
if dist_d == True:
y += dist
for event in pygame.event.get():
# react to player input by changing the game state