I'm making a game where a moving cube at the top of the screen will fire a cube down the screen at certain intervals. How would I do this. For example, I want it so that every 1 second the moving cube will fire a projectile down the screen towards the player icon and when it reaches past the screen, it will respawn where the moving cube is and be able to fire again.
This is what I have so far.
import pygame
pygame.init()
screen = pygame.display.set_mode((280, 800))
pygame.display.set_caption("Cube Run")
icon = pygame.image.load("cube.png")
pygame.display.set_icon(icon)
player_icon = pygame.image.load("cursor.png")
player_x = 128
player_y = 750
player_x_change = 0
cube_1 = pygame.image.load("rectangle.png")
cube1_x = 128
cube1_y = 0
cube1_x_change = 0.8
cube_fire = pygame.image.load("rectangle.png")
cube_fire_x = 0
cube_fire_y = 0
cube_y_change = 1.5
cube_fire_state = "ready"
def player(player_x, player_y):
screen.blit(player_icon, (player_x, player_y))
def cube(cube1_x, cube1_y):
screen.blit(cube_1, (cube1_x, cube1_y))
def cube_enemy(cube_fire_x, cube_fire_y):
screen.blit(cube_fire, (cube_fire_x, cube_fire_y))
running = True
while running:
screen.fill((255, 255, 255))
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_RIGHT:
player_x_change += 0.7
if event.key == pygame.K_LEFT:
player_x_change -= 0.7
if event.type == pygame.KEYUP:
if event.key == pygame.K_RIGHT or pygame.K_LEFT:
player_x_change = 0
player_x += player_x_change
if player_x < 0:
player_x = 0
elif player_x > 280-32:
player_x = 280-32
cube1_x += cube1_x_change
if cube1_x > 248:
cube1_x_change = -1
cube1_x += cube1_x_change
elif cube1_x < 0:
cube1_x_change = 1
cube1_x += cube1_x_change
cube_fire_x += cube1_x
cube_enemy(cube_fire_x, cube_fire_y)
player(player_x, player_y)
cube(cube1_x, cube1_y)
pygame.display.update()
You can register events with pygame.time.set_timer. Create a new event and set how many milliseconds should pass before it's fired. This event will then appear at the set intervall.
FIRE_EVENT = pygame.USEREVENT + 1 # This is just a integer.
OTHER_EVENT = pygame.USEREVENT + 2 # This is how you define more events.
pygame.time.set_timer(FIRE_EVENT, 1000) # 1000 milliseconds is 1 seconds.
Then in your event loop, you check for this event and do whatever you want.
for event in pygame.event.get():
if event.type == pygame.QUIT:
quit()
elif event.type == FIRE_EVENT: # Will appear once every second.
make_square_fire()
When you want to disable the event, just set the interval to 0.
pygame.time.set_timer(FIRE_EVENT, 0)
In your code, you don't include a time manager of any kind – which means your code will run as fast as possible, an you can't really control how fast that will be, it will really depend on the machine it is working and on the CPU load, among other things.
Basically, you want to purposely wait within your program just the right amount of time so you can dynamically adapt to the execution speed. You could implement this by yourself (it isn't that hard, and there are plenty of tutorials out there), but to take a first glance of it, you could use pygame.Clock:
first, create a clock with clock = pygame.Clock().
Then, within your main loop, call eta = clock.tick(FPS), where FPS represents the target frame rate you want your application to run (you can simply fix it to 60 at the start of your program if don't really know what value you want it to be), and the eta variable measures the time elapsed (in milliseconds) since last tick call.
Next, to have something happen, say, every second, just keep a counter:
counter = 1000 # in ms
clock = pygame.Clock()
while True:
# do what you want
eta = clock.tick(FPS)
counter -= eta
if counter < 0:
# trigger the event
counter += 1000
# don't set it directly like
# counter = 1000
# to keep track of margin
Related
So im trying to make tetris that also records players movement and then plays it back, think of it as a replay function.
I have tried implementing keyboard library ,but the problem with it is that when I try to record(recorded_events = keyboard.record("esc")) it the whole game freezes until i press "esc" and when i try to play it back it, it freezes and does nothing.
Thing that I have noticed is if I put print statement next to the playback it prints the whole keyboard input while the game was frozen ,but its unable to play it back anyways.
IDK what to do
My code fragment which takes input and ticks and puts them in the text file.
if event.key == pygame.K_DOWN:
increaseGravity = True
u = " s\n"
time = str(pygame.time.get_ticks())
e = time + "," + u
f.writelines(str(e))
and the code part that is responsible for the playback!
if event.key == pygame.K_h:
f = open("m.txt", "r")
currtick = pygame.time.get_ticks()
for x in f:
b = x.split(',')
cc = int(b[0])
if cc == currtick:
print(" works")
keyboard.press_and_release(b[1].strip)
and this is how the text file looks, the first are the tick and the second movement made
1453, d
1763, d
2752, a
Following advice :
if event.key == pygame.K_h:
currtick = pygame.time.get_ticks()
for x in keyList:
# Variable that counts
cx = 0
# current tick time combined with the movment tick
cc = (int(keyList[cx][0])) + currtick
# puts key id into xx variable
xx= int(keyList[cx][1])
#prints both
print(keyList[cx][0],keyList[cx][1])
#adds +1 to cx
cx =+ 1
# if current tick + time when pressed is equal to current game tick it executes print and presses the key
if cc == currtick:
print(" works")
if(xx == 1073741904):
keyboard.press_release('a')
I've created an example that can record and then replay events with roughly the same time between events.
When the left mouse button is pressed, recording is enabled and KEYDOWN events are appended to a list, along with the time they occurred. Left-clicking again disables recording. Right-clicking will start playback of recorded events by scheduling a custom event to occur. When that event occurs, the recorded event is inserted into the event queue. Then the timer is set with the time difference between the event that has just been posted and the next event.
import time
import random
import pygame
CUSTOM_PLAYBACK_EVENT = pygame.USEREVENT + 1
def queue_next_event(event_list, event_index):
"""Set a timer for the next playback event"""
if event_index == 0:
timer_duration = 100 # effectively immediate
else:
elapsed_time = event_list[event_index][1] - event_list[event_index - 1][1]
timer_duration = round(elapsed_time * 1000) # convert to milliseconds
pygame.time.set_timer(CUSTOM_PLAYBACK_EVENT, timer_duration)
print(f"{time.time()} Set timer for {timer_duration} ms")
class Block(pygame.sprite.Sprite):
def __init__(self, size, pos):
pygame.sprite.Sprite.__init__(self)
self.size = size
self.image = pygame.Surface([size[0], size[1]])
self.image.fill(pygame.color.Color("blueviolet"))
self.rect = self.image.get_rect()
self.rect[0] = pos[0]
self.rect[1] = pos[1]
# initially stationary
self.speedx = 0
self.speedy = 0
def update(self):
"""Move, but stay within window bounds"""
width, height = screen.get_size()
if not (self.size[0] // 2) < self.rect.center[0] < (width - self.size[0] // 2):
self.speedx *= -1 # reverse direction
self.rect.x += self.speedx
if not (self.size[1] // 2) < self.rect.center[1] < (height - self.size[1] // 2):
self.speedy *= -1 # reverse direction
self.rect.y += self.speedy
def draw(self, screen):
# Add this draw function so we can draw individual sprites
screen.blit(self.image, self.rect)
def handle_event(self, event):
# update speeds based one keypress
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_LEFT:
self.speedx -= 1
elif event.key == pygame.K_RIGHT:
self.speedx += 1
elif event.key == pygame.K_UP:
self.speedy -= 1
elif event.key == pygame.K_DOWN:
self.speedy += 1
elif event.key == pygame.K_SPACE:
self.speedx = 0
self.speedy = 0
else:
pass
# initialise screen
screen = pygame.display.set_mode((800, 800), pygame.RESIZABLE | pygame.NOFRAME)
pygame.init()
sprite_list = pygame.sprite.Group()
# create a cube at a random position
cube = Block((80, 80), (random.randint(100, 700), random.randint(100, 700)))
clock = pygame.time.Clock()
# variables for recording
recording = False
playback = False
playback_index = 0
recorded_events = []
run = True
while run:
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
elif event.type == pygame.KEYDOWN:
if event.key == pygame.K_ESCAPE:
run = False
else:
# handle the event
cube.handle_event(event)
if recording:
# save the event and the time
recorded_events.append((event, time.time())) # event
elif event.type == pygame.MOUSEBUTTONDOWN:
if event.button == 1: # Left click
recording = not recording # toggle recording
elif event.button == 3: # Right click toggles playback
playback = not playback
if playback:
if recorded_events:
playback_index = 0 # always start playback at zero
queue_next_event(recorded_events, playback_index)
else:
playback = False # can't playback no events
else: # disable playback timer
pygame.time.set_timer(CUSTOM_PLAYBACK_EVENT, 0)
elif event.type == CUSTOM_PLAYBACK_EVENT:
pygame.time.set_timer(CUSTOM_PLAYBACK_EVENT, 0) # disable playback timer
# post the next event
pygame.event.post(recorded_events[playback_index][0])
playback_index += 1
if playback_index < len(recorded_events):
queue_next_event(recorded_events, playback_index)
else:
playback = False
# clear the screen
screen.fill(pygame.Color("white"))
# update sprites
cube.update()
# draw sprites
cube.draw(screen)
# refresh display
pygame.display.update()
clock.tick(60) # limit to 60 FPS
pygame.quit()
The recorded events aren't cleared, so if you stop and start recording there'll be a larger gap, there's a debug print statement to help keep track of things. Ideally there'd be some visual indication of recording and playback.
I am trying to make a python window for my game from my laptop in pygame... however when I try to close the window I get an error message saying "not responding" im not sure why that if I thought i had done everything right.... the code is below any help is needed.
Thanks!
import pygame
from sys import exit
pygame.init()
screen = pygame.display.set_mode((800,400))
clock = pygame.time.Clock()
sky_surface = pygame.image.load("bg_desert.png").convert()
snail_surface = pygame.image.load("snailWalk1.png").convert_alpha()
player_surf = pygame.image.load("p1_walk01.png")
snail_x_pos = 600
while True:
pygame.time.set_timer(snail_x_pos, 100)
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
exit()
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_LEFT:
print("hello")
snail_x_pos -=4
if snail_x_pos < -100: snail_x_pos = 800
screen.blit(sky_surface,(0,0))
screen.blit(snail_surface,(snail_x_pos,350))
screen.blit(player_surf,(80, 200))
pygame.display.update()
clock.tick(60)
All problem makes
pygame.time.set_timer(snail_x_pos, 100)
which you run inside loop.
If I remove it then it closes without problem.
Every set_timer creates new timer which sends event every 100ms (again and again). If you run it in loop then you create hundreds timers.
You should run it only once - before loop - and it will repeatly send event which you can get in for-loop.
Problem is also that you use it in wrong way - you use snail position but it should user_id and time in milliseconds.
my_event_id = pygame.USEREVENT + 1
pygame.time.set_timer(my_event_id, 500) # 500ms = 0.5s
and later you can use it to move snail
elif event.type == my_event_id:
print('0.5 second')
snail_x_pos -= 4
Here my version with other changes.
I use Surfaces instead images so everyone can simply copy and run it.
I also use pygame.Rect to keep position and size - it has useful values (ie. .center to get/set center position) and functions (ie. to detect colisions). I use .left and .right to move snake to right side of window when it leaves window on left side.
import pygame
pygame.init()
screen = pygame.display.set_mode((800,400))
sky_surface = pygame.Surface((800, 100))
sky_surface.fill((0,0,255))
sky_surface_rect = sky_surface.get_rect()
snail_surface = pygame.Surface((100, 10))
snail_surface.fill((0,255,0))
snail_surface_rect = snail_surface.get_rect()
snail_surface_rect.x = 600
snail_surface_rect.y = 350
player_surf = pygame.Surface((10, 50))
player_surf.fill((255,0,0))
player_surf_rect = player_surf.get_rect()
player_surf_rect.x = 80
player_surf_rect.y = 200
clock = pygame.time.Clock()
my_event_id = pygame.USEREVENT + 1
pygame.time.set_timer(my_event_id, 500) # 500ms = 0.1s
while True:
# - events -
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
exit()
elif event.type == pygame.KEYDOWN:
if event.key == pygame.K_LEFT:
print("hello")
elif event.type == my_event_id:
print('0.5 second')
# move snake
snail_surface_rect.x -= 4
# use this event to slow down player
pressed = pygame.key.get_pressed()
if pressed[pygame.K_LEFT]:
player_surf_rect.x -= 4
elif pressed[pygame.K_RIGHT]:
player_surf_rect.x += 4
# - updates -
if snail_surface_rect.right < 0:
snail_surface_rect.left = 800
# - draw -
screen.fill((0,0,0)) # clear screen
screen.blit(sky_surface, sky_surface_rect)
screen.blit(snail_surface, snail_surface_rect)
screen.blit(player_surf, player_surf_rect)
pygame.display.update()
clock.tick(60)
this is my game play function with the main loop. The issue is that my timer with the inclusion of clock.tick(60) counts down from 100 (the assigned value) but at a pace slower than seconds (about 2 seconds). Without clock.tick(60) the countdown starts at 100 then immediately jumps to 97 then continues at a pace of just a little longer than seconds. All i'm aware of is that apart from clock.tick(60), milliseconds += clock.tick(60) has an effect aswell. is there a way to ensure the countdown starts at 100 and has second intervals without negatively effecting the much needed fps? If any more code such is needed then i'm happy to submit it.
Note: I've removed some unnecessary details for this post hence the seemingly unused global variables
def Gameplay():
global P1_sped
global P1_speed
global P2_sped
global P2_speed
global Touch
global player1_Lives
global player2_Lives
global P1_score
global P2_score
global done
Player_1_turn = True
Player_2_turn = False
P1_Turns = 3
P2_Turns = 3
resetTimer = 100
clock = pygame.time.Clock()
seconds = 100
milliseconds = 0
P1_sped = P1_sped + 1
P1_speed = P1_speed - 1
print(P1_sped, "sped")
print(P1_speed, "speed")
Countdown = True
done = False
while not done:
for event in pygame.event.get():
if event.type == pygame.QUIT:
done = True
# Keydown movement bindings
elif event.type == pygame.KEYDOWN:
if event.key == pygame.K_LEFT:
P2.changespeed(P2_speed, 0)
if event.key == pygame.K_RIGHT:
P2.changespeed(P2_sped, 0)
if event.key == pygame.K_UP:
P2.changespeed(0, P2_speed)
if event.key == pygame.K_DOWN:
P2.changespeed(0, P2_sped)
if event.key == pygame.K_a:
P1.changespeed(P1_speed, 0)
if event.key == pygame.K_d:
P1.changespeed(P1_sped, 0)
if event.key == pygame.K_w:
P1.changespeed(0, P1_speed)
if event.key == pygame.K_s:
P1.changespeed(0, P1_sped)
# Keyup movement bindings
elif event.type == pygame.KEYUP:
if event.key == pygame.K_LEFT:
P2.changespeed(P2_sped, 0)
if event.key == pygame.K_RIGHT:
P2.changespeed(P2_speed, 0)
if event.key == pygame.K_UP:
P2.changespeed(0, P2_sped)
if event.key == pygame.K_DOWN:
P2.changespeed(0, P2_speed)
if event.key == pygame.K_a:
P1.changespeed(P1_sped, 0)
if event.key == pygame.K_d:
P1.changespeed(P1_speed, 0)
if event.key == pygame.K_w:
P1.changespeed(0, P1_sped)
if event.key == pygame.K_s:
P1.changespeed(0, P1_speed)
#milliseconds += clock.tick_busy_loop(60) #returns the time since the last time we called the function, and limits the frame rate to 60FPS
milliseconds += clock.tick(60)
# Applying an update to the sprites
all_sprite_list.update()
# Backgorund colour
screen.fill(D_BLUE)
# Applying the sprites
all_sprite_list.draw(screen)
# The countdown used before the game starts
if Countdown == True:
screen.blit(THREE, (SCREEN_WIDTH/2-53.5,SCREEN_HEIGHT/2-91.5))
pygame.display.update()
time.sleep(1)
screen.fill(D_BLUE)
all_sprite_list.draw(screen)
#pygame.draw.rect(screen, BLACK,(SCREEN_WIDTH/2-250,SCREEN_HEIGHT/2-250,500,500))
screen.blit(TWO, (SCREEN_WIDTH/2-52,SCREEN_HEIGHT/2-88.5))
pygame.display.update()
time.sleep(1)
screen.fill(D_BLUE)
all_sprite_list.draw(screen)
#pygame.draw.rect(screen, BLACK,(SCREEN_WIDTH/2-250,SCREEN_HEIGHT/2-250,500,500))
screen.blit(ONE, (SCREEN_WIDTH/2-39,SCREEN_HEIGHT/2-87))
pygame.display.update()
time.sleep(1)
Countdown = False
if milliseconds > 1000:
seconds -= 1
milliseconds -= 1000
if seconds == 0:
#Countdown = True
P1.reset(500, 500)
P2.reset(800, 500)
if Player_1_turn:
P1_score += 1000
P1_Turns -= 1
Countdown = True
seconds = resetTimer
if P1_Turns == 0:
Text("GameOver Player1", 100, WHITE, SCREEN_WIDTH/2, SCREEN_HEIGHT/2-350)
pygame.display.update()
time.sleep(1)
Player_2_turn = True
Player_1_turn = False
else:
#if Player_2_turn == True or Player_1_turn == False:
P2_score += 1000
P2_Turns -= 1
Countdown = True
seconds = resetTimer
if P2_Turns == 0:
Text("GameOver Player2", 100, WHITE, SCREEN_WIDTH/2, SCREEN_HEIGHT/2-350)
pygame.display.update()
time.sleep(1)
#GameEnd()
CharSel()
#print(P1_score, "P1 score")
#print(P2_score, "P2 score")
Text(seconds, 100, WHITE, SCREEN_WIDTH/2, SCREEN_HEIGHT/2-350)
pygame.display.flip()
# Used for fps
clock.tick(60)
StartScreen()
pygame.quit()
You call clock.tick(60) twice in your main loop. Once where you do milliseconds += clock.tick(60) and once at the end of the loop. If you read the docs, you will see this 'This method should be called once per frame. It will compute how many milliseconds have passed since the previous call. If you pass the optional framerate argument the function will delay to keep the game running slower than the given ticks per second'.
So if you call it twice per loop the effect will be to have the loop execute at half the expected frame rate. Since you are calling it with 60, that means that you frame rate is actually going to be 30 frames per second.
Also, the return is the amount of time since the last time it was called. Since you call it twice, the call at the top of the loop will return the time since the call at the bottom of the loop, not since the last call from the top of the loop. So it is only going to be counting about half the time in your game loop, which accounts for why you are trying to count 1 second worth but 2 seconds are elapsing.
You need to remove one of the two calls to clock.tick(60)
EDIT:
You have the Countdown == True section that uses up 3 seconds on initial startup. That countdown takes place between the first milliseconds += clock.tick(60) and the following clock.tick(60). Those 3 seconds get returned and then hidden by the clock.tick(60), whereas without that they will be returned as 3000 ms to the milliseconds += clock.tick(60) and so cause the time displayed to quickly drop down by those 3 seconds.
You could probably hide that time loss by adding a clock.tick() right after the Countdown = False inside the if Countdown == True block.
I've got a variable that increases when the user presses a button.
When the user presses another button, I'd like to set that variable to 0,
but not instantly-- I'd like it to tick down over the course of a few seconds.
During this time I'd like the user to be able to perform other actions-- hence why I'm not using sleep.
I've looked at using pygame's events, time.clock, etc., but I can't seem to get this to work. Here is what I've tried so far:
import pygame, sys, math
from pygame.locals import *
pygame.init()
pygame.font.init()
scrw = 640
scrh = 480
screen = pygame.display.set_mode((scrw, scrh))
ttwist = 0
recentering = False
fps = 15
clock = pygame.time.Clock()
my_font = pygame.font.SysFont("arial", 12)
while True:
for event in pygame.event.get():
if event.type == QUIT:
pygame.quit()
sys.exit()
pressed = pygame.key.get_pressed()
if not recentering:
if pressed[pygame.K_d]:
ttwist +=1
if pressed[pygame.K_a]:
ttwist -=1
RECENTERTORSOEVENT = USEREVENT
if event.type == pygame.KEYDOWN and event.key == pygame.K_BACKSLASH:
recentering = True
pygame.time.set_timer(RECENTERTORSOEVENT, 1000*abs(ttwist))
if ttwist == 0:
recentering = False
if event.type == USEREVENT:
if ttwist < 0:
ttwist += 1
elif ttwist > 0:
ttwist -= 1
drawtext = my_font.render("TTWIST:"+str(ttwist), True, (255,255,255),(0,0,0))
screen.blit(drawtext,(10,130))
pygame.display.update()
clock.tick(fps)
What am i doing wrong?
You are on the right track, but some parts of the code need to be changed:
All the if event.type == ... blocks should be inside of the event loop.
RECENTERTORSOEVENT = USEREVENT should be defined above the while loop (but that doesn't cause problems).
You're setting the time interval for the RECENTERTORSOEVENT way too high: 1000*abs(ttwist). That means, if the ttwist is 10, you're setting it to 10.000 ms (10 seconds). Just set it to a constant value like 100 ms.
When the ttwist is recentered, call pygame.time.set_timer(RECENTERTORSOEVENT, 0) to stop the timer.
Fill the screen each frame screen.fill((30, 30, 30)), otherwise you see artifacts because the font surface keeps changing its size.
import sys
import pygame
pygame.init()
screen = pygame.display.set_mode((640, 480))
my_font = pygame.font.SysFont('arial', 22)
clock = pygame.time.Clock()
ttwist = 0
RECENTERTORSOEVENT = pygame.USEREVENT
while True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
sys.exit()
elif event.type == pygame.KEYDOWN:
if event.key == pygame.K_r:
print('recentering')
# Start to add the USEREVENT every 100 ms.
pygame.time.set_timer(RECENTERTORSOEVENT, 100)
elif event.type == RECENTERTORSOEVENT:
ttwist += 1 if ttwist < 0 else -1
if ttwist == 0:
print('done')
# Stop to add the USEREVENT to the queue.
pygame.time.set_timer(RECENTERTORSOEVENT, 0)
pressed = pygame.key.get_pressed()
if pressed[pygame.K_d]:
ttwist += 1
if pressed[pygame.K_a]:
ttwist -= 1
screen.fill((30, 30, 30))
drawtext = my_font.render(
'TTWIST: {}'.format(ttwist), True, (255, 255, 255))
screen.blit(drawtext, (10, 130))
pygame.display.update()
clock.tick(30)
ttwist += 1 if ttwist < 0 else -1 is a conditional expression and does basically the same as:
if ttwist < 0:
ttwist += 1
elif ttwist > 0:
ttwist -= 1
My while loops only maintains the movement for the sprite while the cursor is moving inside of the screen. I've tried reorganizing some of the screen.blits and display.update() and display.flip(). I can't seem to figure out why the character stops after a change in one pixel instead of continuing like it I intended.
background_image = 'Terrain_Grass_First.png'
import pygame, sys
from pygame.locals import *
pygame.init()
pygame.display.set_caption('Hans')
screen_width = 600
screen_height = 400
screen = pygame.display.set_mode((screen_width, screen_height),0,32)
pygame.mouse.set_visible(False)
sprite = pygame.image.load('Hans_front_still.png').convert_alpha()
x,y = (0,0)
movex, movey = (0,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_ESCAPE:
pygame.quit()
sys.exit()
if event.key == K_w:
y = -1
elif event.key == K_a:
x = -1
elif event.key == K_s:
y = +1
elif event.key == K_d:
x = +1
elif event.type == KEYUP:
if event.key == K_w:
y = 0
elif event.key == K_a:
x = 0
elif event.key == K_s:
y = 0
elif event.key == K_d:
x = 0
movex += x
movey += y
screen.fill((0,0,0))
screen.blit(sprite,(movex,movey))
pygame.display.flip()
Your loop blocks on pygame.event.get.
You don't schedule any events of your own.
So, you do nothing until the OS has an event (mouse move, redraw, etc.) to give you.
And, even if you fixed that, you're calling movex += x once per event. So, when the OS is throwing a lot of events at you, your sprite will go zipping madly across the screen, but when the events are coming more slowly, it will crawl along. That's almost never what you want.
An easy fix for both problems is to just schedule your own events. For example, with pygame.time.set_timer(), you can make sure you get an event every, say, 250 milliseconds, and you can only move the sprite on those events. For example:
timer_event = pygame.USEREVENT + 1
pygame.time.set_timer(timer_event, 250)
while True:
for event in pygame.event.get():
# ...
elif event.type == timer_event:
movex += x
movey += y
Another alternative is to design your game with a fixed framerate.
A trivial example looks like this:
FRAME_TIME = 50 # 50ms = 20fps
next_frame_time = pygame.time.get_ticks() + FRAMES
while True:
while True:
event = pygame.event.poll()
if event.type == pygame.NOEVENT:
break
elif # ...
pygame.display.flip()
now = pygame.time.get_ticks()
if now < next_frame_time:
pygame.time.wait(next_frame_time - now)
next_frame_time += FRAMES
Now you can just move every 5th frame.
A realistic example has to deal with missed frames, too many events in the queue, choose between wait and delay appropriately, etc.
But I'd go with the event-driven version with a timer instead of a fixed-framerate version in most cases, especially if you're already going down that line.
The only problem is your Indentation!
The fifth and sixth lines from the bottom have wrong indentation, and you need to delete them.
These two lines:
movex += x
movey += y
should be:
movex += x
movey += y
And it works