Pygame: Player won't move when key is held down - python

Just starting out in pygame and trying to get a simple dot to move around the screen when you hold down the arrow keys. Currently, it only moves when you press the key, but you'd have to repeatedly press it.
import random
import pygame
import keyboard
import time
from pygame.locals import *
class Player:
def __init__(self):
self.x = 150
self.y = 150
pygame.init()
screen = pygame.display.set_mode((400, 300))
pygame.display.set_caption("Smile, you're beautiful!")
player = Player()
while True:
pygame.time.Clock().tick(60)
for event in pygame.event.get():
if event.type == QUIT:
exit()
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_RIGHT:
player.x += 5
if event.key == pygame.K_DOWN:
player.y += 5
if event.key == pygame.K_LEFT:
player.x -= 5
if event.key == pygame.K_UP:
player.y -= 5
pygame.event.pump()
pygame.display.flip()
pygame.display.update()
screen.fill((0,0,0))
pygame.draw.circle(screen, (180, 180, 180), (player.x, player.y), 5)
Also, I'd appreciate any tips you might have regarding my current code that may be improved upon or changed to make more efficient.

You need to use pygame.key.get_pressed rather than the key down events. This way you know which keys are currently being pressed on every tick
while True:
pressed = pygame.key.get_pressed()
if pressed[pygame.K_RIGHT]:
player.x += 5
if pressed[pygame.K_DOWN]:
player.y += 5
if pressed[pygame.K_LEFT]:
player.x -= 5
if pressed[pygame.K_UP]:
player.y -= 5

Related

Pygame player can jump for as long as it wants [duplicate]

This question already has answers here:
How to do a variable jump height based on how long key is held in Pygame
(1 answer)
How to make a character jump in Pygame?
(1 answer)
Closed last year.
I'm trying to make a jumping method for my player in pygame. It goes up but I can just hold the space bar key down and it will go up for as long as I want and I don't know how to prevent it. Here's the code for my player class:
import pygame
class Player(pygame.sprite.Sprite):
def __init__(self, pos):
super().__init__()
self.image = pygame.Surface((32, 64))
self.image.fill('blue')
self.rect = self.image.get_rect(topleft = pos)
self.direction = pygame.math.Vector2(0, 0)
self.speed = 8
self.jump_speed = -16
self.gravity = 0.8
def get_input(self):
keys = pygame.key.get_pressed()
if keys[pygame.K_RIGHT] or keys[pygame.K_d]:
self.direction.x = 1
elif keys[pygame.K_LEFT] or keys[pygame.K_a]:
self.direction.x = -1
else:
self.direction.x = 0
if keys[pygame.K_SPACE] or keys[pygame.K_w] or keys[pygame.K_UP]:
self.jump()
def apply_gravity(self):
self.direction.y += self.gravity
self.rect.y += self.direction.y
def jump(self):
self.direction.y = self.jump_speed
def update(self):
self.get_input()
The jump event changes the way the player is moving. When a key is released, then that speed is not reverted. Use the pygame keydown event, and then the keyup event.
import pygame
from pygame.locals import *
#Your code
while True:
#Your event loop code
for event in pygame.event.get():
if event.type == KEYDOWN:
if event.key == K_SPACE:
player.jump()
if event.type == KEYUP:
if event.key == K_SPACE:
player.revert_jump()
if event.type == QUIT:
pygame.quit()
exit()

Is there a way to make the square move continuously by just pressing 1 time? [duplicate]

This question already has an answer here:
How to get if a key is pressed pygame [duplicate]
(1 answer)
Closed 1 year ago.
click here to see the image
PROGRAMING LANGUAGE THAT I USE IS PYTHON
As on the photo,i have a character(square) and i want when i press the left, right, up, down keys, it has to keep moving in that direction until it hits the wall then stops.But when i press those keys, it only moves once and not continuously like i thought.how to make it move continuously
import pygame
pygame.init()
clock = pygame.time.Clock()
#display
window = pygame.display.set_mode((600,600))
caption = pygame.display.set_caption('SwipeIt')
#player
square = pygame.image.load('asset/square.png').convert_alpha()
square_rect = square.get_rect(center = (100,150))
#wall
wall1 = pygame.image.load('asset/wall1.png').convert()
wall2 = pygame.image.load('asset/wall2.png').convert()
screw = pygame.image.load('asset/screw.png').convert()
white = (255,252,252)
gravity = 0.25
swipe = 0
loop = True
while loop:
print(window)
window.fill(white)
#wall
window.blit(wall1,(0,0))
window.blit(wall2,(0,0))
window.blit(wall2,(565,0))
window.blit(wall1,(0,566))
window.blit(screw,(0,0))
window.blit(screw,(0,566))
window.blit(screw,(565,0))
window.blit(screw,(565,566))
#player
window.blit(square,(square_rect))
for event in pygame.event.get():
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_DOWN:
swipe += gravity
square_rect.centery += swipe
if event.key == pygame.K_UP:
swipe -= gravity
square_rect.centery -= swipe
if event.key == pygame.K_RIGHT:
swipe += gravity
square_rect.centerx += swipe
if event.key == pygame.K_LEFT:
swipe -= gravity
square_rect.centerx -= swipe
if event.type == pygame.QUIT:
loop = False
pygame.display.flip()
pygame.display.update()
clock.tick(120)
If you need, here is the link to download the files I have used .
''https://www.mediafire.com/file/ilogoklz3t9abpa/asset.rar/file''
I've made a snake game before and how I did it is by using a variable called direction.
Here is a little snippet from it.
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
quit()
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_UP:
direction = "up"
if event.key == pygame.K_DOWN:
direction = "down"
if event.key == pygame.K_RIGHT:
direction = "right"
if event.key == pygame.K_LEFT:
direction = "left"
Then I would check the current direction and change the position depending on the direction.
For example:
one would be
if direction == "up":
player_y += 5

How to use Keyup in pygame [duplicate]

This question already has answers here:
How to get keyboard input in pygame?
(11 answers)
Closed 1 year ago.
I'm an extremely new programmer, so could you please explain everything that you do in depth.
here's my code for testing(please note that the indents are all wrong):
import pygame
pygame.init()
win = pygame.display.set_mode((500,500))
pygame.display.set_caption("First Game")
x = 50
y = 50
width = 40
height = 60
vel = 5
run = True
while run:
pygame.time.delay(100)
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
for event in pygame.event.get():
if event.type == pygame.KEYUP:
if event.key == pygame.K_UP:
y -= vel
if event.key == pygame.K_DOWN:
y += vel
if event.key == pygame.K_RIGHT:
x += vel
if event.key == pygame.K_LEFT:
x -= vel
win.fill((0,0,0))
pygame.draw.rect(win, (255,0,0), (x, y, width, height))
pygame.display.update()
pygame.quit()
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. Handle all the events in one event loop:
run = True
while run:
pygame.time.delay(100)
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
if event.type == pygame.KEYUP:
if event.key == pygame.K_UP:
y -= vel
if event.key == pygame.K_DOWN:
y += vel
if event.key == pygame.K_RIGHT:
x += vel
if event.key == pygame.K_LEFT:
x -= vel
win.fill((0,0,0))
pygame.draw.rect(win, (255,0,0), (x, y, width, height))
pygame.display.update()
The pygame.KEYUP event occurs only once, when a button is released. If you want to achieve a continuously movement, then you've to evaluate the current state of a key. The states of all keyboard buttons can be retrieved by pygame.key.get_pressed().
Use .tick() of pygame.time.Clock to limit the frame rate, rather than pygame.time.delay. e.g.:
import pygame
pygame.init()
win = pygame.display.set_mode((500,500))
pygame.display.set_caption("First Game")
clock = pygame.time.Clock()
x, y, width, height = 50, 50, 40, 60
vel = 5
run = True
while run:
clock.tick(60)
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
keys = pygame.key.get_pressed()
if keys[pygame.K_UP]:
y -= vel
if keys[pygame.K_DOWN]:
y += vel
if keys[pygame.K_RIGHT]:
x += vel
if keys[pygame.K_LEFT]:
x -= vel
win.fill((0,0,0))
pygame.draw.rect(win, (255,0,0), (x, y, width, height))
pygame.display.update()
pygame.quit()

Projectiles only move if i hold the fire key down

Previously in my projectiles module, I had a class that handled each direction of fire seperately (a class for firing up, down, left and right) and this did it's job. However, now that I'm trying to incorporate shot speed and other things into the class, having 4 seperate classes is just too messy and so I tried to trim it down so that I only have one class for all projectiles fired.
However, now that I have done this, when I fire a projectile, it will only move so long as I am holding the fire button ('a' key if firing left) down. Also, if I fire left, then fire right, the projectile that was previously travelling left will begin to travel right instead.
My question is; How do I handle the projectiles so that when I fire one, it no longer accepts updates and travels in a straight line?
This is my working code;
Main game module
import pygame
from constants import *
from player import Player
from Projectile import Projectiles
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(0, 0)
projectile.rect.x = player.rect.x
projectile.rect.y = player.rect.y
elif event.key == pygame.K_RIGHT:
projectile = Projectiles(0, 0)
projectile.rect.x = player.rect.x
projectile.rect.y = player.rect.y
elif event.key == pygame.K_UP:
projectile = Projectiles(0, 0)
projectile.rect.x = player.rect.x
projectile.rect.y = player.rect.y
elif event.key == pygame.K_DOWN:
projectile = Projectiles(0, 0)
projectile.rect.x = player.rect.x
projectile.rect.y = player.rect.y
try:
if projectile:
projectile_list.add(projectile)
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.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(object):
def __init__(self, x, y):
super().__init__()
self.image = pygame.Surface([4, 4])
self.image.fill(RED)
self.rect = self.image.get_rect()
def update(self):
key = pygame.key.get_pressed()
if key[pygame.K_UP]:
self.rect.y -= 5
if key[pygame.K_DOWN]:
self.rect.y += 5
if key[pygame.K_LEFT]:
self.rect.x -= 5
if key[pygame.K_RIGHT]:
self.rect.x += 5
As always any help would be much appreciated!
The first problem is that you only create ONE projectile. Your class is called Projectiles which is misleading because it's only one object not multiple. This causes the projectile to be controlled even after firing.
Also, the reason why the projectile only moves while you press a key is that in the update() method, you only add to the projectiles x or y coordinate when e.g. key[pygame.K_UP]: is true.
So, to fix this issues you will have to change the way your game handles projectiles.
If I understand your question right, you want to have multiple projectiles at once.
The way to implement this is to use a collection of projectiles.
Game
//nothing changed till here
elif event.key == pygame.K_LEFT:
p = Projectile(player.rect.x, player.rect.y, -5, 0)
projectile_list.add(p)
elif event.key == pygame.K_RIGHT:
p = Projectile(player.rect.x, player.rect.y, 5, 0)
projectile_list.add(p)
elif event.key == pygame.K_UP:
p = Projectile(player.rect.x, player.rect.y, 0, -5)
projectile_list.add(p))
elif event.key == pygame.K_DOWN:
p = Projectile(player.rect.x, player.rect.y, 0, 5)
projectile_list.add(p)
// moved the part where you append the projectile to in the if statement
# ----- 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()
Projectile:
import pygame
from constants import *
// projectile needs to extend Sprite
class Projectile(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
Im not so familiar with Pygame but I hope this will help you at least somehow.
I have never used PyGame but one can see that your update() method in the Projectiles class depends on key press while it should depend on elapsed time instead.
Your projectile moves 5 units per key press, not 5 units per game tick once launched.

Pygame not checking keyevents after another happens

I am moving a sprite on the x-axis. It is properly moving left and right. When I press both LEFT and RIGHT at the same time it stop moving properly.
I am trying to make it when a user presses both keys and then lets go of one, for it to continue moving in the direction still pressed.
Weirdly it works while I holding right and letting go of left. It continues moving right.
When I hold left and tap right it stops moving until I press right again.
I commented out some ideas I had to make this work, but they failed me.
I am sure its a simple fix or a logic failure on my part.
I have worked a couple hours on this.
Thanks for responses ahead of time.
import pygame
import time
import random
import sys
import math
pygame.init()
displayWidth = 1200
displayHeight = 800
white = (255,255,255)
black = (0,0,0)
gameDisplay = pygame.display.set_mode((displayWidth, displayHeight))
pygame.display.set_caption('Game 3')
clock = pygame.time.Clock()
class firstSquare:
def __init__(self,player_x,player_y):
self.x = player_x
self.y = player_y
self.width = 100
self.height = 100
def render(self):
pygame.draw.rect(gameDisplay, white,(self.x, self.y, self.width, self.height))
class secondSquare:
def __init__(self,cpu_x,cpu_y):
self.x = cpu_x
self.y = cpu_y
self.width = 100
self.height = 100
def render(self):
pygame.draw.rect(gameDisplay, white,(self.x, self.y, self.width, self.height))
player = firstSquare(300,300)
cpu = secondSquare(100,100)
def gameLoop():
### variables##
player_x = 100
player_y = 100
x = 100
y = 100
movement_x = 0
movement_y = 0
frame_rate = 0
frame_table = 0
inGame = True
while inGame:
for event in pygame.event.get():
if event.type == pygame.QUIT:
inGame = False
pygame.quit()
sys.exit()
keyPressed= pygame.key.get_pressed()
#### this is moving the player on x-axis##
if keyPressed[pygame.K_LEFT]:
movement_x = -5
if event.type == pygame.KEYUP:
if event.key == pygame.K_LEFT:
movement_x = 0
if keyPressed[pygame.K_RIGHT]:
movement_x = 5
if event.type == pygame.KEYUP:
if event.key == pygame.K_RIGHT:
movement_x = 0
### two keys at once won't move the player###
if keyPressed[pygame.K_LEFT] and keyPressed[pygame.K_RIGHT]:
movement_x = 0
### pressing one key and letting go the other will continue movement
## if keyPressed[pygame.K_LEFT] and keyPressed[pygame.K_RIGHT]:
## if event.type == pygame.KEYUP:
## if event.key == pygame.K_LEFT:
## movement_x = 5
## print("left dropped")
## if keyPressed[pygame.K_RIGHT] and keyPressed[pygame.K_LEFT]:
## if event.type == pygame.KEYUP:
## if event.key == pygame.K_RIGHT:
## movement_x = -5
## print("Right dropped")
gameDisplay.fill(black)
player.render()
cpu.render()
player.x += movement_x
pygame.display.update()
clock.tick(60)
gameLoop()
pygame.quit()
quit()
I think what you need is this:
if keyPressed[pygame.K_LEFT]:
movement_x = -5
if event.type == pygame.KEYUP:
if event.key == pygame.K_LEFT and movement_x < 0:
movement_x = 0
if keyPressed[pygame.K_RIGHT]:
movement_x = 5
if event.type == pygame.KEYUP:
if event.key == pygame.K_RIGHT and movement_x > 0:
movement_x = 0
And that would be it... Hope it helps.
Try to use the following code in your movement:
if keyPressed[pygame.K_LEFT]:
movement_x = -5
elif keyPressed[pygame.K_RIGHT]:
movement_x = +5
elif event.type == pygame.KEYUP:
if event.key == pygame.K_LEFT:
movement_x = 0
elif event.type == pygame.KEYUP:
if event.key == pygame.K_RIGHT:
movement_x = 0

Categories