How can I make the movement smoother? - python

I'm developing a very basic engine, basing myself on tutorials from Pygame, and I'm having a little problem with "smoothness". How do I make my player walk "smoother"?
My event handler is pretty basic, pretty standard, nothing new, and I even figured out how to make a "boost" (run) for test. But the thing is, at the pygame.KEYUP, those lots of zeros destroy the "smoothness" of my little player, and I don't want that, but I don't want it to walk ad infinitum.
import pygame
import gfx
# Main Class
class Setup:
background = gfx.Images.background
player = gfx.Images.player
pygame.init()
# Configuration Variables:
black = (0,0,0)
white = (255,255,255)
green = (0,255,0)
red = (255,0,0)
title = "Ericson's Game"
# Setup:
size = [700,700]
screen = pygame.display.set_mode(size)
pygame.display.set_caption(title)
done = False
clock = pygame.time.Clock()
# Logic Variables
x_speed = 0
y_speed = 0
x_speed_boost = 0
y_speed_boost = 0
x_coord = 350
y_coord = 350
screen.fill(white)
# Main Loop:
while done == False:
screen.blit(background,[0,0])
screen.blit(player,[x_coord,y_coord])
for event in pygame.event.get():
if event.type == pygame.QUIT:
done = True
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_ESCAPE:
done = True
if event.key == pygame.K_a:
x_speed = -6
x_speed_boost = 1
if event.key == pygame.K_d:
x_speed = 6
x_speed_boost = 2
if event.key == pygame.K_w:
y_speed = -6
y_speed_boost = 1
if event.key == pygame.K_s:
y_speed = 6
y_speed_boost = 2
if event.key == pygame.K_LSHIFT:
if x_speed_boost == 1:
x_speed = -10
if x_speed_boost == 2:
x_speed = 10
if y_speed_boost == 1:
y_speed = -10
if y_speed_boost == 2:
y_speed = 10
if event.type == pygame.KEYUP:
if event.key == pygame.K_a:
x_speed = 0
x_speed_boost = 0
if event.key == pygame.K_d:
x_speed = 0
x_speed_boost = 0
if event.key == pygame.K_w:
y_speed = 0
y_speed_boost = 0
if event.key == pygame.K_s:
y_speed = 0
y_speed_boost = 0
x_coord = x_coord + x_speed
y_coord = y_coord + y_speed
pygame.display.flip()
pygame.display.update()
clock.tick(20)
pygame.quit()

Code will be simpler/clearer using keystate polling for your use. If other parts of the game use 'on press' logic, you can use event handling. So your movement would be:
If you are calling pygame.display.flip() then you don't use pygame.display.update(). Infact it will probably slow it down to use both.
I used your x_coord variable. But it would simplify things to use a tuple or vector for player location. You can use a float, for smoother precision for movement. Then it blits as an int to screen.
while not done:
for event in pygame.event.get():
# any other key event input
if event.type == QUIT:
done = True
elif event.type == KEYDOWN:
if event.key == K_ESC:
done = True
vel_x = 0
vel_y = 0
speed = 1
if pygame.key.get_mods() & KMOD_SHIFT
speed = 2
# get key current state
keys = pygame.key.get_pressed()
if keys[K_A]:
vel_x = -1
if keys[K_D]:
vel_x = 1
if keys[K_W]:
vel_y = -1
if keys[K_S]:
vel_y = 1
x_coord += vel_x * speed
y_coord += vel_y * speed

You are ticking the clock at a rate of 20 frames per second. This is probably causing the choppiness. Change it to something bigger like 70:
clock.tick(70)

Related

How to collide two images in Pygame module [duplicate]

This question already has an answer here:
How to detect collisions between two rectangular objects or images in pygame
(1 answer)
Closed 2 years ago.
I’m new to programming and know the basics of Python and wanted to ask how I can perform an action if two images overlap a little bit and then a specific button is pressed in pygame.
The game looks like following:
import pygame
import random
pygame.init()
window = pygame.display.set_mode((1000, 600))
caption = pygame.display.set_caption(
'Test your reaction speed. Shoot the target game!') # sets a caption for the window
game_running = True # this is the gameloop so the window stays open
PlayerImg = pygame.image.load('F:\PythonPortable\oscn.png')
PlayerX = 370
PlayerY = 420
PlayerX_change = 0
PlayerY_change = 0
def player():
window.blit(PlayerImg, (PlayerX, PlayerY))
aim_sight = pygame.image.load('F:\PythonPortable\ktarget.png')
aim_sightX = 460
aim_sightY = 300
aim_sight_changeX = 0
aim_sight_changeY = 0
def aim_sight_function(x, y):
window.blit(aim_sight, (x, y))
targetedImg = pygame.image.load('F:\PythonPortable\ktargetedperson.png')
targetedX = random.randint(0, 872)
targetedY = random.randint(0, 200)
def random_target():
window.blit(targetedImg, (targetedX, targetedY))
while game_running:
window.fill((255, 255, 255))
random_target()
for event in pygame.event.get():
if event.type == pygame.QUIT:
game_running = False
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_LEFT:
aim_sight_changeX = -2
PlayerX_change = -2
elif event.key == pygame.K_RIGHT:
aim_sight_changeX = 2
PlayerX_change = 2
elif event.key == pygame.K_UP:
aim_sight_changeY = -2
PlayerY_change = -2
elif event.key == pygame.K_DOWN:
aim_sight_changeY = 2
PlayerY_change = 2
elif event.type == pygame.KEYUP:
if event.key == pygame.K_LEFT or event.key == pygame.K_RIGHT:
aim_sight_changeX = 0
PlayerX_change = 0
elif event.key == pygame.K_UP or event.key == pygame.K_DOWN:
aim_sight_changeY = 0
PlayerY_change = 0
aim_sightX += aim_sight_changeX
if aim_sightX <= 46.5:
aim_sight_changeX = 0
elif aim_sightX >= 936:
aim_sight_changeX = 0
aim_sightY += aim_sight_changeY
if aim_sightY <= 0:
aim_sight_changeY = 0
elif aim_sightY >= 400:
aim_sight_changeY = 0
PlayerX += PlayerX_change
if PlayerX <= -50:
PlayerX_change = 0
elif PlayerX >= 850:
PlayerX_change = 0
player()
aim_sight_function(aim_sightX, aim_sightY)
pygame.display.update()
I would like to know how a do what I want. I thought maybe:
if event.type == pygame.K_SPACE and targetedX == targetedX in range(aim_sightX - 100, aim_sightY + 100) or targetedY == targetedY in range (aim_sightY - 100, aim_sightY + 100):
...
It seems as though none of the tutorials I watched cover this topic and would like to recieve recommendations for tutorials that cover this problem or a direct answer.
I recommend to use a pygame.Rect objects and colliderect() to find a collision between two Surface objects. pygame.Surface.get_rect.get_rect() returns a rectangle with the size of the Surface object, that always starts at (0, 0) since a Surface object has no position. The position of the rectangle can be specified by a keyword argument:
PlayerImg_rect = PlayerImg.get_rect(topleft = (PlayerX, PlayerY))
targetedImg_rect = targetedImg .get_rect(topleft = (targetedX, targetedX))
if PlayerImg_rect.colliderect(targetedImg_rect):
print("hit")

Pygame Game Development shoot functionality

My question is how can I better my shooting functionality in my game. I am trying to make it to where the player can shoot in the direction it is moving (ex.shoot up,down,left,right) as well as shoot while moving and shoot while idle.
The player and missile are both rectangular using pygame shapes to make it easier for me to understand the logic behind game development.
def player(px,py):
pygame.draw.rect(gameWindow,black,[px,py,30,30])
def missile(mx,my):
pygame.draw.rect(gameWindow,black,[mx,my,10,10])
Here is the code of the game to help better understand what I'm talking about. The small section I have commented out is what I have tried. I only have it currently set to move in the x direction going left from its initial starting point.
import pygame #####IMPORTING PYGAME MODULE###########################
pygame.init() #####INITIALIZING PYGAME##################################
gameWindow = pygame.display.set_mode((800,600)) ###Screen Width and Height###
clock = pygame.time.Clock() ## FRAMES PER SECOND ##
white = (255,255,255)
black = (0,0,0)
red = (255,0,0)
def player(px,py):
pygame.draw.rect(gameWindow,black,[px,py,30,30])
def missile(mx,my):
pygame.draw.rect(gameWindow,black,[mx,my,10,10])
def enemies():
return
def gameloop():
px = 700
py = 300
mx = 700
my = 300
px_change = 0
py_change = 0
mx_change = 0
my_change = 0
gameExit = False
while not gameExit:
for event in pygame.event.get():
if event.type == pygame.QUIT:
gameExit = True
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_LEFT:
mx_change = -10
if event.key == pygame.K_RIGHT:
mx_change = 10
if event.key == pygame.K_UP:
my_change = -10
if event.key == pygame.K_DOWN:
my_change = 10
if event.key == pygame.K_SPACE:
mx_change = -6
#if event.key == pygame.K_SPACE and pygame.K_RIGHT:
#mx_change = 6
if event.key == pygame.K_LEFT:
px_change = -10
if event.key == pygame.K_RIGHT:
px_change = 10
if event.key == pygame.K_UP:
py_change = -10
if event.key == pygame.K_DOWN:
py_change = 10
if event.type == pygame.KEYUP:
if event.key == pygame.K_LEFT or event.key == pygame.K_RIGHT:
px_change = 0
if event.key == pygame.K_UP or event.key == pygame.K_DOWN:
py_change = 0
if event.type == pygame.KEYUP:
if event.key == pygame.K_LEFT or event.key == pygame.K_RIGHT:
mx_change = 0
mx = px
if event.key == pygame.K_UP or event.key == pygame.K_DOWN:
my_change = 0
my = py
if event.key == pygame.K_SPACE:
mx_change = 0
my_change = 0
mx = px
my = py
px += px_change
py += py_change
mx += mx_change
my += my_change
gameWindow.fill(white)
player(px,py)
missile(mx,my)
pygame.display.update()
clock.tick(100)
pygame.quit()
quit()
gameloop()
I would suggest using different objects for your player and missile. The way you have things set up right now, there can only be 1 player and 1 missile. Only having 1 player might be fine but 1 missile makes for a dull game. I suggest using a class, such as this simple example:
class Projectile():
def init(self,x,y,vx,vy):
self.x = x
self.y = y
self.vx = vx
self.vy = vy
def update(self):
self.x += self.vx
self.y += self.vy
Now that you have a class you can start doing great things! Want to have spacebar fire a new missile instead of moving the one missile on screen? ezpz! All you need is a list of your missile objects to keep track of, say my_missile_list:
if event.key == pygame.K_SPACE:
my_missile_list.append(Projectile(px,py,missile_x_velocity,missile_y_velocity))
This creates an entirely new instance of the class Projectile based on the input position and speeds.
Finally, we need to have all these missiles move! This is where the class definition makes our life easier! Once per frame we just have to update the bullets:
for b in my_missile_list:
b.update()
There are more advantages to using classes here but this is a start. If you read through this and make a few changes your game will work much more like what you are looking for.
You should set missille only when you KEYDOWN space, and not use other keys to change it. Player may have variable direction so you will know in which direction it is looking when it stay and you will know in which direction move misille.
import pygame
# --- constants --- (UPPER_CASE_NAMES)
WHITE = (255,255,255)
BLACK = (0,0,0)
RED = (255,0,0)
# --- classes --- (CamelCaseNames)
# empty
# --- functions ---- (lower_case_names_
def player(screen, x, y):
pygame.draw.rect(screen, BLACK, (x, y, 30, 30))
def missile(screen, x, y):
pygame.draw.rect(screen, RED, (x, y, 10, 10))
def enemies():
pass
def gameloop(screen):
px = 700
py = 300
mx = 700
my = 300
px_change = 0
py_change = 0
p_direction = 'left'
mx_change = 0
my_change = 0
#m_direction = 'left'
game_exit = False
clock = pygame.time.Clock() ## FRAMES PER SECOND ##
while not game_exit:
# --- events ---
for event in pygame.event.get():
if event.type == pygame.QUIT:
game_exit = True
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_LEFT:
px_change = -10
p_direction = 'left'
if event.key == pygame.K_RIGHT:
px_change = 10
p_direction = 'right'
if event.key == pygame.K_UP:
py_change = -10
p_direction = 'top'
if event.key == pygame.K_DOWN:
py_change = 10
p_direction = 'down'
if event.key == pygame.K_SPACE:
mx = px
my = py
if p_direction == 'left':
mx_change = -16
my_change = 0
elif p_direction == 'right':
mx_change = 16
my_change = 0
elif p_direction == 'top':
mx_change = 0
my_change = -16
elif p_direction == 'down':
mx_change = 0
my_change = 16
if event.type == pygame.KEYUP:
if event.key == pygame.K_LEFT or event.key == pygame.K_RIGHT:
px_change = 0
if event.key == pygame.K_UP or event.key == pygame.K_DOWN:
py_change = 0
# --- changes/updates ---
px += px_change
py += py_change
mx += mx_change
my += my_change
# --- draws ----
screen.fill(WHITE)
player(screen, px, py)
missile(screen, mx, my)
pygame.display.update()
# --- FPS ---
clock.tick(30)
# --- main ---
pygame.init()
screen = pygame.display.set_mode((800,600))
gameloop(screen)
pygame.quit()
#quit()
Instead of px, py and mx,my you should use pygame.Rect() - it can be used to draw() and blit() and it has methods to check collisions.

Can't figure out why my image wont move in pygame

I'm just messing around with Pygame and I can't see what I'm doing incorrectly to make the red circle move with the arrow keys. I can't tell if it's in my main loop. I also haven't been able to find very many tutorials on sprite or looping animations with Pygame. If I for example wanted to make a square oscillate for example like a moving platform how would I do that?
import pygame
import time
## event handling varibles
player_x = 0
player_y = 0
x = 250
y = 250
## screen display
display_width = 500
display_height = 500
pygame.init()
game_screen = pygame.display.set_mode((display_width,display_height))
pygame.display.set_caption("test")
# player
def player():
pygame.draw.circle(game_screen,red,(x,y),15)
# colors
white = (255,255,255)
red = (255,0,0)
black = (0,0,0)
### main loop
dead = False
while dead != True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
dead = True
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_LEFT:
player_x = -1
elif event.key == pygame.K_RIGHT:
player_x = +1
if event.key == pygame.K_UP:
player_y = +1
elif event.key == pygame.K_DOWN:
player_y = -1
if event.type == pygame.KEYUP:
if event.key == pygame.K_LEFT or pygame.K_RIGHT:
player_x = 0
if event.key == pygame.K_UP or pygame.K_DOWN:
player_y = 0
game_screen.fill(black)
player()
pygame.display.update()
x -= player_x
y -= player_y
pygame.quit()
quit()
Your indendation is all messed up.
Your code won't do anything unless the event is QUIT... which then makes it quit.
Your boolean logic is wrong.
This is not proper syntax event.key == pygame.K_UP or pygame.K_DOWN. The order of precedence here is as follows (event.key == pygame.K_UP) or (K_DOWN). Since K_DOWN is truthy, it is always true and thus this entire statement is always true.
I think you mean: event.key == pygame.K_UP or event.key == pygame.K_DOWN
Lastly, it wont' keep moving as you say you want.
It will only move when there is an event in the queue. You can make it keep moving by generating events. Perhaps with an event timer.
Here is a fixed version, hope this helps:
import pygame
import time
## event handling varibles
player_x = 0
player_y = 0
x = 250
y = 250
## screen display
display_width = 500
display_height = 500
pygame.init()
game_screen = pygame.display.set_mode((display_width,display_height))
pygame.display.set_caption("test")
# player
def player(game_screen, red, point): # Use parameters not globals
pygame.draw.circle(game_screen, red, point, 15)
# colors
white = (255,255,255)
red = (255,0,0)
black = (0,0,0)
### main loop
pygame.time.set_timer(pygame.USEREVENT, 1) # 1 per second
dead = False
while not dead:
for event in pygame.event.get():
if event.type == pygame.QUIT:
dead = True
elif event.type == pygame.USEREVENT:
pygame.time.set_timer(pygame.USEREVENT, 1) # Set another timer for another 1 second
elif event.type == pygame.KEYDOWN:
if event.key == pygame.K_LEFT:
player_x = +10
elif event.key == pygame.K_RIGHT:
player_x = -10
elif event.key == pygame.K_UP:
player_y = +10
elif event.key == pygame.K_DOWN:
player_y = -10
elif event.type == pygame.KEYUP:
if event.key in [pygame.K_LEFT, pygame.K_RIGHT]:
player_x = 0
elif event.key in [pygame.K_UP, pygame.K_DOWN]:
player_y = 0
game_screen.fill(black)
player(game_screen,red,(x,y))
pygame.display.update()
x -= player_x
y -= player_y
pygame.quit()

Image not moving for the life of me

import pygame
# Some colors
GREEN = ( 0,255,0)
BLUE = ( 0, 0, 255)
WHITE = ( 255, 255, 255)
BLACK = ( 0, 0, 0)
pygame.init()
clock = pygame.time.Clock()
#Screen
SCREEN = pygame.display.set_mode([1000,700])
#Title
pygame.display.set_caption("Trying to move things")
#Variables
x_position = 100
y_position = 100
x_speed = 0
y_speed = 0
#Positions
image_image_positions = [x_position,y_position]
#Graphics
image_image = pygame.image.load("izzat.png").convert()
image_image.set_colorkey(BLACK)
#Main loop ____
done = False
while not done:
for event in pygame.event.get():
if event.type == pygame.QUIT:
done = True
# Keyboard commands.
elif event.type == pygame.KEYDOWN:
if event.key == pygame.K_UP:
y_speed = -5
elif event.key == pygame.K_DOWN:
y_speed = 5
elif event.key == pygame.K_w:
x_speed = -5
elif event.key == pygame.K_s:
x_speed = 5
elif event.type == pygame.KEYUP:
if event.key == pygame.K_LEFT or event.key == pygame.K_RIGHT:
x_speed = 0
elif event.key == pygame.K_UP or event.key == pygame.K_DOWN:
y_speed = 0
elif event.key == pygame.K_w or event.key == pygame.K_s:
x_speed += 0
if y_position + y_speed >=0 and y_position + y_speed + 60 <=500:
y_position += y_speed
x_position += x_speed
SCREEN.fill(GREEN)
SCREEN.blit(image_image, image_image_positions)
print(x_position)
print(y_position)
pygame.display.flip()
clock.tick(60)
pygame.quit()
Hello, I have been having a problem which I'm really not happy at because I have been trying to fix it for a while now. So basically I have a image, and I wish to move the image based on the keyboard inputs, yet whatever I try nothing works. I then wondered maybe the y and x position aren't changing at all which is why the images positions are not changing, well I did print( those positions) but it the positions are definitely changing, the variables, so I do not get how the image positions do not change at all. Then I thought maybe because it's a tuple, so I changed it to parenthesis, that also did not work. I just don't get why my image position doesn't move if the variables for the position of the image do change. Thank you if you could help me in any way. I have looked this up but I couldn't find any help. Thank you for your help if you help me!
Update__________
Ok so apparently the image_image_position stays the same despite the variables changing when I printed the positions of image_image_position. Is there any way to change them and not have them stay at 100,100 all the time and change with the variables being changed?
You haven't assigned the speeds.
image_image_positions[0] = xspeed
image_image_positions[1] = yspeed
You are only changing your variables yspeed and xspeed, but you are not setting the actual positions of the image. Add the following line before the blit:
image_image_positions = [x_position,y_position]
Full code:
import pygame
# Some colors
GREEN = ( 0,255,0)
BLUE = ( 0, 0, 255)
WHITE = ( 255, 255, 255)
BLACK = ( 0, 0, 0)
pygame.init()
clock = pygame.time.Clock()
#Screen
SCREEN = pygame.display.set_mode([1000,700])
#Title
pygame.display.set_caption("Trying to move things")
#Variables
x_position = 100
y_position = 100
x_speed = 0
y_speed = 0
#Positions
image_image_positions = [x_position,y_position]
#Graphics
image_image = pygame.image.load("izzat.png").convert()
image_image.set_colorkey(BLACK)
#Main loop ____
done = False
while not done:
for event in pygame.event.get():
if event.type == pygame.QUIT:
done = True
# Keyboard commands.
elif event.type == pygame.KEYDOWN:
if event.key == pygame.K_UP:
y_speed = -5
elif event.key == pygame.K_DOWN:
y_speed = 5
elif event.key == pygame.K_w:
x_speed = -5
elif event.key == pygame.K_s:
x_speed = 5
elif event.type == pygame.KEYUP:
if event.key == pygame.K_LEFT or event.key == pygame.K_RIGHT:
x_speed = 0
elif event.key == pygame.K_UP or event.key == pygame.K_DOWN:
y_speed = 0
elif event.key == pygame.K_w or event.key == pygame.K_s:
x_speed += 0
if y_position + y_speed >=0 and y_position + y_speed + 60 <=500:
y_position += y_speed
x_position += x_speed
image_image_positions = [x_position,y_position]
SCREEN.fill(GREEN)
SCREEN.blit(image_image, image_image_positions)
print(x_position)
print(y_position)
pygame.display.flip()
clock.tick(60)
pygame.quit()
While you ARE updating the x/y positions, this isn't changing where the image is being drawn:
SCREEN.blit(image_image, image_image_positions)
image_image_positions, is never changed throughout the life-span of your application (besides startup).
To fix this simply add the update into your loop:
image_image_positions = [x_position,y_position]

how to stop movement if the object hits the boundary in pygame

import pygame
import random
pygame.init()
black = (0,0,0)
red = (255,0,0)
display_width = 800
display_height = 600
FPS = 20
gameDisplay = pygame.display.set_mode((display_width,display_height))
pygame.display.set_caption("The Space Jumpers")
img = pygame.image.load('starship2.png')
spritesize = 50
boundlimit = 200
clock = pygame.time.Clock()
font = pygame.font.SysFont(None, 25)
def gameLoop():
gameExit = False
gameOver = False
lead_x = display_width / 2
lead_y = display_height / 2
xchange = 0
ychange = 0
randBlockX = random.randrange(0,boundlimit+1)
randBlockY = random.randrange(0,575)
while not gameExit:
gameDisplay.blit(img, [lead_x,lead_y])
pygame.display.update()
for event in pygame.event.get():
if event.type == pygame.QUIT:
gameExit = True
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_LEFT:
xchange = -spritesize / 2
ychange = 0
if event.key == pygame.K_RIGHT:
xchange = spritesize / 2
ychange = 0
if event.key == pygame.K_UP:
ychange = -spritesize / 2
xchange = 0
if event.key == pygame.K_DOWN:
ychange = spritesize / 2
xchange = 0
if event.type == pygame.KEYUP:
if event.key == pygame.K_LEFT or event.key == pygame.K_RIGHT:
xchange = 0
if event.key == pygame.K_UP or event.key == pygame.K_DOWN:
ychange = 0
lead_x += xchange
lead_y += ychange
gameDisplay.fill(black)
pygame.draw.rect(gameDisplay,red, [randBlockX, randBlockY, 600, 25])
if (lead_x+spritesize < randBlockX and randBlockY<lead_y<randBlockY+25) :
randBlockX = random.randrange(0,boundlimit+1)
randBlockY = random.randrange(0,575)
elif (lead_x+spritesize < randBlockX and randBlockY<lead_y<randBlockY+25 ):
randBlockX = random.randrange(0,boundlimit+1)
randBlockY = random.randrange(0,575)
elif (lead_x > randBlockX+600 and randBlockY<lead_y<randBlockY+25):
randBlockX = random.randrange(0,boundlimit+1)
randBlockY = random.randrange(0,575)
elif (lead_x > randBlockX+600 and randBlockY<lead_y<randBlockY+25):
randBlockX = random.randrange(0,boundlimit+1)
randBlockY = random.randrange(0,575)
clock.tick(FPS)
pygame.quit()
quit()
gameLoop()
This is my current code and in this code when the object(sprite) hits the boundary, it keeps on moving but what I want to do is, I want to stop the movement of the object when it hits the boundary, for example when the object hits the left boundary it shouldnt move left anymore. You kind of get the idea, its a simple game
Instead of using two variables (lead_x, lead_y) to store the position of the object, use a Rect. It's as simple as
gameDisplay = pygame.display.set_mode((display_width,display_height))
gameDisplay_rect = gameDisplay.get_rect()
img = pygame.image.load('starship2.png')
img_rect = img.get_rect(center=gameDisplay_rect.center)
To draw you object, simply do:
gameDisplay.blit(img, img_rect)
Now, to move your object, instead of
lead_x += xchange
lead_y += ychange
you can do
img_rect.move_ip(lead_x, lead_y)
img_rect.clamp_ip(gameDisplay_rect)
clamp_ip will then prevent your object from leaving the screen.
I think this will work:
try changing your if statement(if pygame.key == pygame.K_LEFT:) to(if pygame.key == pygame.K_LEFT and x > 0:)
i have been struggling with the same thing for a school project and have gotten it so that it stops the sprite if you touch the border, but if you spam that button you can get through. I currently have an if statement saying(If x < 0: x_change = 0), but i have not tried the one i suggested. i hope it works.
sloth's method is for sure better in many ways, but if you still want to keep your old lead_x, lead_y structure you could just add a separate statements outside of the event loop:
if lead_x <= 0:
lead_x += 10 # just use any small distance to push you back to place every frame
elif lead_x >= display_width:
lead_x -= 10
and so on for every direction.

Categories