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()
Related
So, I've been doing a python program for movement and gravity, and everything works OK, but i doesn't set the caption and i really dont know why. I tried to insert it in the end, but doesn't work neither. Is it that i need to write it on another place, or other type of problem?
import pygame, sys
WIDTH, HEIGHT = 500, 350
pygame.init()
pygame.display.set_caption('gravity movement')
window = pygame.display.set_mode((WIDTH, HEIGHT), 32, 0)
clock = pygame.time.Clock()
player = pygame.Rect(30, 30, 32, 32)
player_speed = 5
#movement
def move(rect, x, y):
rect.x += x
rect.y += y
#Add gravity
def gravity(rect, g_force= 6):
rect.y += g_force
if rect.y + rect.h >= HEIGHT:
rect.y = HEIGHT - rect.h
x, y = 0,0
while True:
clock.tick(60)#means that for every second (at most) 60 frames should pass
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_LEFT:
x = -player_speed
if event.key == pygame.K_RIGHT:
x = player_speed
if event.key == pygame.K_UP:
y = -20
if event.type == pygame.KEYUP:
if event.key == pygame.K_LEFT:
x = 0
if event.key == pygame.K_RIGHT:
x = 0
if event.key == pygame.K_UP:
y = 0
#Draw
window.fill((0, 0, 20))
pygame.draw.rect(window, (255, 24, 10), player)
#definitive movement
move(player, x= x, y=y)
gravity(player)
pygame.display.flip()
The problem you're facing is because of setting flags to 32 over here:
window = pygame.display.set_mode((WIDTH, HEIGHT), 32, 0) #Flags = 32 , depth = 0
Just change flags to 0 and it will be alright
So it should be
window = pygame.display.set_mode((WIDTH, HEIGHT))
You can read more about flags and depth here
and so the final code should look something like this :
import pygame, sys
WIDTH, HEIGHT = 500, 350
pygame.init()
pygame.display.set_caption('gravity movement')
window = pygame.display.set_mode((WIDTH, HEIGHT))
clock = pygame.time.Clock()
player = pygame.Rect(30, 30, 32, 32)
player_speed = 5
#movement
def move(rect, x, y):
rect.x += x
rect.y += y
#Add gravity
def gravity(rect, g_force= 6):
rect.y += g_force
if rect.y + rect.h >= HEIGHT:
rect.y = HEIGHT - rect.h
x, y = 0,0
while True:
clock.tick(60)#means that for every second (at most) 60 frames should pass
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_LEFT:
x = -player_speed
if event.key == pygame.K_RIGHT:
x = player_speed
if event.key == pygame.K_UP:
y = -20
if event.type == pygame.KEYUP:
if event.key == pygame.K_LEFT:
x = 0
if event.key == pygame.K_RIGHT:
x = 0
if event.key == pygame.K_UP:
y = 0
#Draw
window.fill((0, 0, 20))
pygame.draw.rect(window, (255, 24, 10), player)
#definitive movement
move(player, x= x, y=y)
gravity(player)
pygame.display.flip()
This question already has answers here:
How to get keyboard input in pygame?
(11 answers)
How can I make a sprite move when key is held down
(6 answers)
Closed 2 years ago.
I asked previously about my code I am doing for my a level coursework and I was able to fix one problem but a solution offered for me not being able to move my sprites I could not fix. I copied out this code but it still didn't work, I have highlighted this section between **
My screen loads the home screen function but when the game loop runs it loads the base but doesn't do any more.
import pygame
import random
import time
#define variables
WIDTH = 1080
HEIGHT =720
FPS = 30
x1 = WIDTH/2.25
y1 = HEIGHT/2.5
x2 = WIDTH/20
y2 = HEIGHT/2.5
xbut = 475
ybut1 = 300
ybut2 = 400
gameTitle = 'Hungry Ghosts'
xChange1 = 0
yChange1 = 0
xChange2 = 0
yChange2 = 0
running = True
#define colours
WHITE = (255,255,255)
BLACK = (0,0,0)
MEGAN = (123,57,202)
MOLLIE = (244,11,12)
KATIE = (164,12,69)
#initialise pygame and window
pygame.init()
pygame.mixer.init()
pygame.font.init()
screen =pygame.display.set_mode((WIDTH,HEIGHT))
pygame.display.set_caption('Hungry Ghosts')
clock = pygame.time.Clock()
#load immages
home_image = pygame.image.load(('homescreen.jpg'))
game_image = pygame.image.load(('gamescreen.jpg'))
player1_image = pygame.image.load(('player 1.png')).convert_alpha()
player2_image = pygame.image.load(('player 2.png')).convert_alpha()
position = (0,0)
screen.blit(home_image, position)
startBut = pygame.image.load('startbutton.jpg').convert()
instructionBut = pygame.image.load('instructionbutton.jpg').convert()
#define functions
def textObjects(gameTitle, font):
textSurface = font.render(gameTitle,True, WHITE)
pygame.display.update()
return textSurface, textSurface.get_rect()
def titleText(gameTitle):
textForTitle = pygame.font.Font('VCR_OSD_MONO_1.001.ttf',115)
TextSurf, TextRect = textObjects(gameTitle, textForTitle)
TextRect.center = ((WIDTH/2),(HEIGHT/6))
screen.blit(TextSurf,TextRect)
pygame.display.update()
def startButton(xbut,ybut1):
screen.blit(startBut,(xbut,ybut1))
pygame.display.update()
def instructionButton(xbut,ybut2):
screen.blit(instructionBut,(xbut,ybut2))
pygame.display.update()
def character1(x1,y1):
screen.blit(player1_image,(x1,y1))
def character2(x,y):
screen.blit(player2_image,(x,y))
def homeScreen():
global running
start = False
home = True
while running and not start:
clock.tick(FPS)
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
if event.type == pygame.MOUSEBUTTONDOWN:
if startBut.get_rect(topleft = (xbut, ybut1)).collidepoint(event.pos) :
print('clicked on button')
start = True
titleText(gameTitle)
startButton(xbut,ybut1)
instructionButton(xbut,ybut2)
pygame.display.flip()
*******************************************************************
def gameLoop():
global running
global x1, y2, x2, y2, xChange1, yChange1, xChange2, yChange2
while running:
clock.tick(FPS)
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_LEFT:
xChange = -5
elif event.key == pygame.K_RIGHT:
xChange = 5
if event.type == pygame.KEYUP:
if event.key == pygame.K_LEFT or event.key == pygame.K_RIGHT:
xChange = 0
x1 += xChange1
screen.blit(game_image,(0,0))
character1(x1,y1)
character2(x2,y2)
pygame.display.flip()
*********************************************************************
#movement
for event in pygame.event.get():
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_LEFT:
xChange1 = -5
elif event.key == pygame.K_RIGHT:
xChange1 = 5
if event.type == pygame.KEYUP:
if event.key == pygame.K_LEFT or event.key == pygame.K_RIGHT:
xChange1 = 0
x1 += xChange1
#calling functions
homeScreen()
gameLoop()
pygame.quit()
There is typo. The name of the variable is xChange1 rather than xChange. Furthermore read Faster version of pygame.event.get() and just implement 1 event loop:
def gameLoop():
global running
global x1, y1, x2, y2, xChange1, yChange1, xChange2, yChange2
while running:
clock.tick(FPS)
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_LEFT:
xChange1 = -5
elif event.key == pygame.K_RIGHT:
xChange1 = 5
elif event.key == pygame.K_a:
xChange2 = -5
elif event.key == pygame.K_d:
xChange2 = 5
if event.type == pygame.KEYUP:
if event.key == pygame.K_LEFT or event.key == pygame.K_RIGHT:
xChange1 = 0
if event.key == pygame.K_a or event.key == pygame.K_d:
xChange2 = 0
x1 += xChange1
x2 += xChange2
screen.blit(game_image,(0,0))
character1(x1,y1)
character2(x2,y2)
pygame.display.flip()
#calling functions
homeScreen()
gameLoop()
pygame.quit()
However I recommend to use pygame.key.get_pressed() rather than the keyboard events.
The keyboard events (see pygame.event module) occur only once when the state of a key changes. The KEYDOWN event occurs once every time a key is pressed. KEYUP occurs once every time a key is released. Use the keyboard events for a single action or a step-by-step movement.
pygame.key.get_pressed() returns a list with the state of each key. If a key is held down, the state for the key is True, otherwise False. Use pygame.key.get_pressed() to evaluate the current state of a button and get continuous movement:
def gameLoop():
global running
global x1, y1, x2, y2
while running:
clock.tick(FPS)
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
keys = pygame.key.get_pressed()
x1 += (keys[pygame.K_RIGHT] - keys[pygame.K_LEFT]) * 5
y1 += (keys[pygame.K_DOWN] - keys[pygame.K_UP]) * 5
x2 += (keys[pygame.K_d] - keys[pygame.K_a]) * 5
y2 += (keys[pygame.K_s] - keys[pygame.K_w]) * 5
screen.blit(game_image,(0,0))
character1(x1,y1)
character2(x2,y2)
pygame.display.flip()
#calling functions
homeScreen()
gameLoop()
pygame.quit()
Here's a simple pygame code where I inserted a screen, a pink rectangle and tried moving it.
The rectangle in the pygame window isn't moving.
Which means the code inside '**' isn't working.
How do I solve that?
import pygame, sys
pygame.init()
width = 800
height = 600
pink = (244,133,227)
player_pos = [400, 300]
player_size = 50
screen = pygame.display.set_mode((width,height))
game_over = False
while not game_over:
for event in pygame.event.get():
if event.type == pygame.QUIT:
sys.exit()
** if event.type == pygame.KEYDOWN:
x = player_pos[0]
y = player_pos[1]
if event.type == pygame.K_LEFT:
x -= player_size
elif event.type == pygame.K_RIGHT:
x += player_size
player_pos = [x, y]
screen.fill((0,0,0)) **
pygame.draw.rect(screen, pink, (player_pos[0], player_pos[1], player_size, player_size))
pygame.display.update()
The key is stored in the key attribute, rather then the type attribute. See pygame.event:
if event.type== pygame.K_LEFT:
if event.key == pygame.K_LEFT:
See the example:
import pygame, sys
pygame.init()
width = 800
height = 600
pink = (244,133,227)
player_pos = [400, 300]
player_size = 50
screen = pygame.display.set_mode((width,height))
game_over = False
while not game_over:
for event in pygame.event.get():
if event.type == pygame.QUIT:
sys.exit()
if event.type == pygame.KEYDOWN:
x = player_pos[0]
y = player_pos[1]
if event.key == pygame.K_LEFT:
x -= player_size
elif event.key == pygame.K_RIGHT:
x += player_size
player_pos = [x, y]
screen.fill((0,0,0))
pygame.draw.rect(screen, pink, (player_pos[0], player_pos[1], player_size, player_size))
pygame.display.update()
This question already has an answer here:
How do I continuously trigger an action at certain time intervals? Enemy shoots constant beam instead of bullets in pygame [duplicate]
(1 answer)
Closed 2 years ago.
So I wrote my code and everything works how I want it to for now.
The only problem is that my bullet or fireball teleports to the location I set it to.
I am wondering if there is a way to make it look like its actually moving towards the destination using pygame and whatnot.
Thanks a ton!
(width, height) = (1300,800)
screen = pygame.display.set_mode((width, height))
playerImage = pygame.image.load('player.png')
fireballImage = pygame.image.load('fireball.png')
pygame.display.set_caption('Game')
transparent = (0, 0, 0, 0)
#Fireball stats
def player(x ,y):
screen.blit(playerImage, (x, y))
pygame.display.flip()
def fireball(x, y):
screen.blit(fireballImage, (fb_x,fb_y))
pygame.display.flip()
fireball_state = "ready"
print('created')
fb_x = x = width * 0.45
fb_y = y = height * 0.8
x_change = 0
y_change = 0
fb_x_change = 0
fb_y_change = 0
pressed = pygame.key.get_pressed()
#mainloop
running = True
while running:
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_d:
x_change = 1
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_a:
x_change = -1
if event.type == pygame.KEYUP:
if event.key == pygame.K_a or event.key == pygame.K_d:
x_change = 0
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_w:
y_change = -2
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_s:
y_change = 2
if event.type == pygame.KEYUP:
if event.key == pygame.K_w or event.key == pygame.K_s:
y_change = 0
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_SPACE:
fb_y_change = -400
if event.type == pygame.KEYUP:
if event.key == pygame.K_SPACE:
fb_y_change = 0
x += x_change
y += y_change
fireball(x,y)
fb_x = x
fb_y = y
screen.fill((255,255,255))
player(x,y)
fb_x += fb_x_change
fb_y += fb_y_change
fireball(fb_x,fb_y)
pygame.display.update()
First of all remove pygame.display.flip() from player and fireball. That casuse flickering. A single pygame.display.update() at the end of the application loop is sufficient.
Note, the fireballs have to be blit at (x, y) rather than (fb_x, fb_y)
def player(x ,y):
screen.blit(playerImage, (x, y))
def fireball(x, y):
screen.blit(fireballImage, (x, y))
fireball_state = "ready"
Further more use pygame.time.Clock() / tick() to control the flops per second (FPS):
clock = pygame.time.Clock()
#mainloop
running = True
while running:
clock.tick(FPS)
Add a list for the fire balls:
fireballs = []
Spawn a new fireball when space is pressed:
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_SPACE:
fireballs.append([x, y, 0, -2])
Update and draw the fireballs in a loop:
for fb in fireballs:
fb[0] += fb[2]
fb[1] += fb[3]
for fb in fireballs:
fireball(fb[0],fb[1])
See the example:
fireballs = []
FPS = 60
clock = pygame.time.Clock()
running = True
while running:
clock.tick(FPS)
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_SPACE:
fireballs.append([x, y, 0, -2])
pressed = pygame.key.get_pressed()
if pressed[pygame.K_w]:
y -= 2
if pressed[pygame.K_s]:
y += 2
if pressed[pygame.K_a]:
x -= 2
if pressed[pygame.K_d]:
x += 2
for i in range(len(fireballs)-1, -1, -1):
fb = fireballs[i]
fb[0] += fb[2]
fb[1] += fb[3]
if fb[1] < 0:
del fireballs[i]
screen.fill((255,255,255))
player(x,y)
for fb in fireballs:
fireball(fb[0],fb[1])
pygame.display.update()
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