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()
Related
I'm currently trying to build a game through vscode using pygame lib.
My code to move character around with keyboard arrow keys won't apply to my module.
My module won't close even though I click exit button or esc.
Any thoughts why its not working?
import pygame
import os
pygame.init()
screen_width = 480
screen_height = 640
screen = pygame.display.set_mode((screen_width,screen_height))
pygame.display.set_caption("June's Game")
background = pygame.image.load("D:/Python/pygame_basic/background.png")
character = pygame.image.load("D:/Python/pygame_basic/character.png")
character_size = character.get_rect().size
character_width = character_size[0]
character_height = character_size[1]
character_x_position = (screen_width / 2) - (character_width / 2)
character_y_position = screen_height - character_height
to_x = 0
to_y = 0
running = True #게임이 진행중인가
while running:
for event in pygame.event.get():
if event == pygame.QUIT:
running = False
if event == pygame.KEYDOWN:
if event.key == pygame.K_LEFT:
to_x -= 5
elif event.key == pygame.K_RIGHT:
to_x += 5
elif event.key == pygame.K_UP:
to_y -= 5
elif event.key == pygame.K_DOWN:
to_y += 5
if event == pygame.KEYUP:
if event.key == pygame.K_LEFT or event.key == pygame.K_RIGHT:
to_x = 0
elif event.key == pygame.K_UP or event.key == pygame.K_DOWN:
to_y = 0
character_x_position += to_x
character_y_position += to_y
#screen.fill((0,0,255))
screen.blit(background, (0,0))
screen.blit(character, (character_x_position,character_y_position))
pygame.display.update()
pygame.quit()
i coudln't get it to work
event is an object. You have to get the type of the event, e.g.:
if event == pygame.KEYDOWN
if event.type == pygame.KEYDOWN:
You have to limit the frames per second to limit CPU usage with pygame.time.Clock.tick and to control the speed of the game. Otherwise, the player moves much too fast and immediately disappears from the screen. The method tick() of a pygame.time.Clock object, delays the game in that way, that every iteration of the loop consumes the same period of time.
clock = pygame.time.Clock()
running = True
while running:
clock.tick(100)
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_LEFT:
to_x -= 5
elif event.key == pygame.K_RIGHT:
to_x += 5
elif event.key == pygame.K_UP:
to_y -= 5
elif event.key == pygame.K_DOWN:
to_y += 5
if event.type == pygame.KEYUP:
if event.key == pygame.K_LEFT or event.key == pygame.K_RIGHT:
to_x = 0
elif event.key == pygame.K_UP or event.key == pygame.K_DOWN:
to_y = 0
character_x_position += to_x
character_y_position += to_y
#screen.fill((0,0,255))
screen.blit(background, (0,0))
screen.blit(character, (character_x_position,character_y_position))
pygame.display.update()
However, there is a better method to move an object when a key is held down (See How can I make a sprite move when key is held down):
to_x = 0
to_y = 0
speed = 5
clock = pygame.time.Clock()
running = True
while running:
clock.tick(100)
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
keys = pygame.key.get_pressed()
to_x = (keys[pygame.K_RIGHT] - keys[pygame.K_LEFT]) * speed
to_y = (keys[pygame.K_DOWN] - keys[pygame.K_UP]) * speed
character_x_position += to_x
character_y_position += to_y
screen.blit(background, (0,0))
screen.blit(character, (character_x_position,character_y_position))
pygame.display.update()
This question already has answers here:
How can I make a sprite move when key is held down
(6 answers)
Closed 1 year ago.
right now it just moves in the direction i tell it to put it just stops. How do i go about making it KEEP going in the direction I inputted by? And make it constantly go in the direction, but be able to control how fast it moves, right now i want it to move every 4 minutes
import pygame
from pygame.locals import *
pygame.init()
surface = pygame.display.set_mode((600, 600))
background = pygame.image.load('back.png')
surface.blit(background, (0, 0))
block = pygame.image.load('block.png').convert()
block_y = 0
block_x = 0
surface.blit(block, (block_x, block_y))
def draw():
surface.blit(background, (0, 0))
surface.blit(block, (block_x, block_y))
pygame.display.flip()
direction = ''
pygame.display.flip()
running = True
while running:
for event in pygame.event.get():
if event.type == KEYDOWN:
if event.key == K_ESCAPE:
running = False
if event.key == K_UP:
block_y -= 10
draw()
if event.key == K_DOWN:
block_y += 10
draw()
if event.key == K_LEFT:
block_x -= 10
draw()
if event.key == K_RIGHT:
block_x += 10
draw()
elif event.type == QUIT:
running = False
```
Here's an option with minimal changes to your program. I changed the event handlers to update speed variables, which update the position in an added update() function. The speeds are zeroed when the key is released. I've also removed the duplicated draw() functions. Note this code is untested.
import pygame
from pygame.locals import *
pygame.init()
surface = pygame.display.set_mode((600, 600))
background = pygame.image.load('back.png')
surface.blit(background, (0, 0))
block = pygame.image.load('block.png').convert()
block_y = 0
block_x = 0
speed_x = 0
speed_y = 0
surface.blit(block, (block_x, block_y))
def draw():
surface.blit(background, (0, 0))
surface.blit(block, (block_x, block_y))
pygame.display.flip()
def update():
"""Update game state"""
block_x += speed_x
block_y += speed_y
direction = ''
pygame.display.flip()
clock = pygame.time.Clock()
running = True
while running:
for event in pygame.event.get():
if event.type == KEYDOWN:
if event.key == K_ESCAPE:
running = False
elif event.key == K_UP:
speed_y -= 10
elif event.key == K_DOWN:
speed_y += 10
elif event.key == K_LEFT:
speed_x -= 10
elif event.key == K_RIGHT:
speed_x += 10
elif event.type == KEYUP:
if event.key in (K_DOWN, K_UP):
speed_y = 0
elif event.key in (K_LEFT, K_RIGHT):
speed_x = 0
elif event.type == QUIT:
running = False
update()
draw()
clock.tick(60) # limit frame rate to 60 FPS
EDIT: Added frame rate limiting
Use pygame.key.get_pressed() instead of the KEYDOWN event.
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 sequence 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
running = True
while running:
for event in pygame.event.get():
if event.type == KEYDOWN:
if event.key == K_ESCAPE:
running = False
elif event.type == QUIT:
running = False
keys = pygame.key.get_pressed()
if keys[pygame.K_UP]:
block_y -= 10
if keys[pygame.K_DOWN]:
block_y += 10
if keys[pygame.K_LEFT]:
block_x -= 10
if keys[pygame.K_RIGHT]:
block_x += 10
draw()
The code can be further simplified:
running = True
while running:
for event in pygame.event.get():
if event.type == KEYDOWN:
if event.key == K_ESCAPE:
running = False
elif event.type == QUIT:
running = False
keys = pygame.key.get_pressed()
block_x += (keys[pygame.K_RIGHT] - keys[pygame.K_LEFT]) * 10
block_y += (keys[pygame.K_DOWN] - keys[pygame.K_UP]) * 10
draw()
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()
I started watching a youtube video series on learning pygame by sentdex.
I have been following all his steps and i got to the point where i had a car(the image) and it was on a white screen. But, when i put in the functions to be able to move the car. Next time i ran it I could not see my car. I noticed that I could see it for a split second when i closed the screen.I have tried searching this question every way that i could think of. It is probably a small stupid mistake on my part. Thank you in advance
import pygame
pygame.init()
display_width = 800
display_height = 600
black = (0,0,0)
white = (255,255,255)
gameDisplay = pygame.display.set_mode((display_width, display_height))
pygame.display.set_caption('A bit Racey')
clock = pygame.time.Clock()
carImg = pygame.image.load('racecar.png')
def car(x, y):
gameDisplay.blit(carImg,(x,y))
x = (display_width * 0.45)
y = (display_height * 0.6)
x_change = 0
crashed = False
while not crashed:
for event in pygame.event.get():
if event.type == pygame.QUIT:
crashed = True
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_LEFT:
x_change = -5
if event.key == pygame.K_RIGHT:
x_change = 5
if event.type == pygame.KEYUP:
if event.key == pygame.K_LEFT or event.key == pygame.K_RIGHT:
x_change = 0
x += x_change
gameDisplay.fill(white)
car(x,y)
pygame.display.update()
clock.tick(60)
pygame.quit()
quit()
Your indentation is messed up. Everything from for event in pygame.event.get(): to clock.tick(60) should be indented to show that it fits inside the while not crashed: loop. Also, crashed = True should be indented to show that it is inside the if event.type == pygame.QUIT: statement. In addition, the pygame.KEYDOWN and pygame.KEYUP comparisons should be inside your for event in pygame.event.get(): loop. Finally, you can improve speed by changing some of the ifs to elifs. This is the corrected version of the last section of your code:
while not crashed:
for event in pygame.event.get():
if event.type == pygame.QUIT:
crashed = True
elif event.type == pygame.KEYDOWN:
if event.key == pygame.K_LEFT:
x_change = -5
elif event.key == pygame.K_RIGHT:
x_change = 5
elif event.type == pygame.KEYUP:
if event.key == pygame.K_LEFT or event.key == pygame.K_RIGHT:
x_change = 0
x += x_change
gameDisplay.fill(white)
car(x, y)
pygame.display.update()
clock.tick(60)
pygame.quit()
quit()
I am kinda stuck with a supposed to be simple code to check if the user has pressed "w" or "s".
Below you can see my code:
import pygame
pygame.init()
while True:
for event in pygame.event.get():
if event.type == pygame.KEYDOWN and event.key == pygame.K_w:
print('Forward')
elif event.type == pygame.KEYDOWN and event.key == pygame.K_s:
print('Backward')
Am I forgetting something here?
Thanks!
A window needs to be created to receive key presses, the following works.
import pygame
import sys
pygame.init()
pygame.display.set_mode((100, 100))
while True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
sys.exit()
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_w:
print('Forward')
elif event.key == pygame.K_s:
print('Backward')
This is what seems to me the most simple and understandable way to do it:
import pygame
pygame.init()
pygame.display.set_mode((300, 300))
running = True
while running:
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
pygame.quit()
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_w:
print('Forward')
elif event.key == pygame.K_s:
print('Backward')
Instead of using the sys.exit() method I prefer to just use pygame.quit()
it is no good to ask the gamer to keep hitting w to get the response. If you want to read the "pressed" state. You could consider the followings:
from pygame import *
import time
flag = False # The flag is essential.
DONE = False
screen = display.set_mode((500,500)) # 1180, 216
count=0
while not DONE:
event.pump() # process event queue
keys = key.get_pressed() # It gets the states of all keyboard keys.
#print("%d"%count,keys)
count+=1
if keys[ord('w')]: # And if the key is K_DOWN:
print("%d w down"%count)
if keys[ord('s')]: # And if the key is K_DOWN:
print("%d s down"%count)
time.sleep(0.1)
Try this:
import pygame
pygame.init()
key = pygame.key.get_pressed()
while True:
for event in pygame.event.get():
if event.type == KEYDOWN and event.key == pygame.K_w:
print('Forward')
elif event.type == KEYDOWN and event.key == pygame.K_s:
print('Backward')
Sample code to understand how key press events work.
import pygame
from pygame.locals import *
def main():
pygame.init()
pygame.display.set_caption("Move Box With Arrow Keys")
wndsize = (320, 240)
display = pygame.display.set_mode(wndsize)
x = 5
y = 5
black = (0, 0, 0)
white = (255, 255, 255)
rectpos = (x, y)
rectdim = (50, 50)
while True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
quit()
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_RIGHT:
x += 5
print("K_RIGHT")
if event.key == pygame.K_LEFT:
x -= 5
print("K_LEFT")
if event.key == pygame.K_UP:
y -= 5
print("K_UP")
if event.key == pygame.K_DOWN:
y += 5
print("K_DOWN")
# Don't allow coords below 0
if 0 > x:
x = 5
if 0 > y:
y = 5
# Don't allow overflow
if x + rectdim[0] > wndsize[0]:
x = wndsize[0] - rectdim[0] - 5
if y + rectdim[1] > wndsize[1]:
y = wndsize[1] - rectdim[1] - 5
rectpos = (x, y)
display.fill(white)
rect = pygame.draw.rect(display, black, ((rectpos), (rectdim)))
pygame.display.update()
main()
This might work:
from pygame import *
init()
if key.get_pressed()[K_w] == True:
print('Forwards')
if key.get_pressed()[K_s] == True:
print('Backwards')`