How to move an image in pygame/python with keypress? - python

I am making a Pong game in Python. To do this, I am using pygame. I am trying to make an image move continuously on a keypress. I have tried multiple methods, but none have worked. here is my code for the movement:
import pygame, sys
from pygame.locals import *
import time
try: #try this code
pygame.init()
FPS = 120 #fps setting
fpsClock = pygame.time.Clock()
#window
DISPLAYSURF = pygame.display.set_mode((1000, 900), 0, 32)
pygame.display.set_caption('Movement with Keys')
WHITE = (255, 255, 255)
wheatImg = pygame.image.load('gem4.png')
wheatx = 10
wheaty = 10
direction = 'right'
pygame.mixer.music.load('overworld 8-bit.WAV')
pygame.mixer.music.play(-1, 0.0)
#time.sleep(5)
#soundObj.stop()
while True: #main game loop
DISPLAYSURF.fill(WHITE)
bign = pygame.event.get()
for event in bign:
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_d:
pygame.mixer.music.stop()
keys_pressed = key.get_pressed()
if keys_pressed[K_d]:
wheatx += 20
#events = pygame.event.get()
#for event in events:
# if event.type == pygame.KEYDOWN:
# if event.key == pygame.K_p:
# pygame.mixer.music.stop()
# time.sleep(1)
# pygame.mixer.music.load('secondscreen.wav')
# pygame.mixer.music.play()
DISPLAYSURF.blit(wheatImg, (wheatx, wheaty))
pygame.display.update()
fpsClock.tick(FPS)
for event in pygame.event.get():
if event.type == QUIT:
pygame.quit()
sys.exit()
Indentation is normal, I am new to stackoverflow! I have an except, which is why the try is there. Thanks for the help!

This code will move the image down upon the down arrow key being pressed and up if the up arrow key is pressed (should you not be changing the Y-axis and wheaty if the user presses the down key rather than altering wheatx ?). Do similar for the other arrow keys.
while True:
DISPLAYSURF.fill(WHITE)
bign = pygame.event.get()
for event in bign:
if event.type == QUIT:
pygame.quit()
sys.exit()
elif event.type == pygame.KEYDOWN:
pygame.mixer.music.stop()
if event.key == pygame.K_DOWN:
wheaty +=20
elif event.key == pygame.K_UP:
wheaty -= 20
DISPLAYSURF.blit(wheatImg, (wheatx, wheaty))
pygame.display.update()
fpsClock.tick(FPS)

Related

Continuous Movement in Pygame

I am trying to make a ship on the surface move continuously on screen but it only accepts one key press at a time. I have tried all solutions online and they aren't working.
import pygame
#initialize the pygame module
pygame.init()
#set the window size
screen = pygame.display.set_mode((1280, 720))
#change the title of the window
pygame.display.set_caption("Space Invaders")
#change the icon of the window
icon = pygame.image.load("alien.png")
pygame.display.set_icon(icon)
#add the ship to the window
shipx = 608
shipy = 620
def ship(x, y):
ship = pygame.image.load("spaceship.png").convert()
screen.blit(ship, (x,y))
running = True
while running:
#background screen color
screen.fill((0, 0, 0))
#render the ship on the window
ship(shipx,shipy)
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
keys = pygame.key.get_pressed()
if keys[pygame.K_LEFT]:
shipx -= 30
if keys[pygame.K_RIGHT]:
shipx += 30
pygame.display.update()
I'm still new to Pygame. How can I fix this?
Its a matter of Indentation. pygame.key.get_pressed() has to be done in the application loop rather than the event loop. Note, the event loop is only executed when
event occurs, but the application loop is executed in every frame:
running = True
while running:
# [...]
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
#<--| INDENTATION
keys = pygame.key.get_pressed()
if keys[pygame.K_LEFT]:
shipx -= 30
if keys[pygame.K_RIGHT]:
shipx += 30
# [...]
The problem that I found is that your application is replying only on one key pressed, not on a continuous movement. When you set the pygame.key.set_repeat function like in the example below, everything should be running smoothly.
import sys
import pygame
#initialize the pygame module
pygame.init()
#set the window size
screen = pygame.display.set_mode((1280, 720))
# Images
ship_img = pygame.image.load("spaceship.png")
ship_rect = ship_img.get_rect()
def draw():
screen.blit(ship_img, ship_rect)
pygame.key.set_repeat(10)
while True:
#background screen color
screen.fill((0, 0, 0))
for event in pygame.event.get():
if event.type == pygame.QUIT:
sys.exit()
keys = pygame.key.get_pressed()
if keys[pygame.K_LEFT]:
ship_rect = ship_rect.move((-30, 0))
if keys[pygame.K_RIGHT]:
ship_rect = ship_rect.move((30, 0))
#render the ship on the window
draw()
pygame.display.update()
For me, if I need to move an object in Pygame continuously, a velocity variable can be assigned to control the speed.
Here is part of the code for my robot movement program inside of the game_on loop:
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
# Detect keyboard input on your computer check if it is the direction keys
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_LEFT:
print("Left arrow is pressed")
robotX_speed = -60
if event.key == pygame.K_RIGHT:
print("Right arrow is pressed")
robotX_speed = 60
if event.key == pygame.K_UP:
print("Up arrow is pressed")
robotY_speed = -60
if event.key == pygame.K_DOWN:
print("Down arrow is pressed")
robotY_speed = 60
if event.type == pygame.KEYUP:
if event.key == pygame.K_LEFT or event.key == pygame.K_RIGHT:
print("Keystoke L/R has been released")
robotX_speed = 0
if event.type == pygame.K_DOWN or event.key == pygame.K_UP:
print("Keystoke Up/Down has been released")
robotY_speed = 0
# update the coordinates in the while loop
robotX += robotX_speed
robotY += robotY_speed
Hope these codes can help you!

Why does my pygame window freeze and crash?

Whenever I try to run my program it freezes up and crashes. I'm not a master pygame coder, but I'm almost sure its something to do with my main loop. It's supposed to allow the user to move left and right using arrow keys. I've tried adding a clock and changing the size of the screen but that didn't work. Here is the code:
import pygame
import sys
import random
import time
pygame.init()
screen = pygame.display.set_mode((500,500))
events = pygame.event.get()
clock = pygame.time.Clock()
x = 50
y = 50
game_over = False
while not game_over:
for event in events:
if event.type != pygame.QUIT:
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_RIGHT:
x += 5
elif event.key == pygame.K_LEFT:
x -= 5
else:
sys.exit()
screen.fill((0,0,0))
pygame.draw.rect(screen, (255,255,255), (x,y,50,50))
clock.tick(30)
pygame.display.update()
The code needs to process the event queue continuously, otherwise your operating environment will consider your window to be non-responsive (locked up). Your code is almost there, except it only fetches the new events once, but this needs to be done every iteration of the main loop.
import pygame
import sys
pygame.init()
screen = pygame.display.set_mode((500,500))
clock = pygame.time.Clock()
x = 50
y = 50
game_over = False
while not game_over:
events = pygame.event.get() # <<-- HERE handle every time
for event in events:
if event.type != pygame.QUIT:
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_RIGHT:
x += 5
elif event.key == pygame.K_LEFT:
x -= 5
else:
sys.exit()
screen.fill((0,0,0))
pygame.draw.rect(screen, (255,255,255), (x,y,50,50))
clock.tick(30)
pygame.display.update()
You cant do foe event in events, as when you call pygame.events.get(), you are updating them, you are updating them once and looping over them every frame, you need to use for event in pygame.event.get(): so you are calling the function every frame and updating the events every frame
unless you were trying to do this?
events = pygame.event.get
...
for event in events():
which does the same as above

Keydown event for Pygame

I just want to move a block left and right but don't now why the keydown code isn't getting through. When I open the program it just shows the the 'tank' in its position but you can't move it with left or right keys.
import pygame, sys
from pygame.locals import *
WINDOW_WIDTH = 800
WINDOW_HEIGHT = 600
TANK_SIZE = 20
BLACK = (0 ,0 ,0 )
WHITE = (255,255,255)
def drawArena():
DISPLAYSURF.fill(BLACK)
def drawTank(tank):
pygame.draw.rect(DISPLAYSURF, WHITE, tank)
def main():
pygame.init()
global DISPLAYSURF
DISPLAYSURF = pygame.display.set_mode((WINDOW_WIDTH, WINDOW_HEIGHT))
pygame.display.set_caption('Tanks')
tankX = 200
tankY = 200
tank = pygame.Rect(tankX, tankY, TANK_SIZE, TANK_SIZE)
drawArena()
drawTank(tank)
while True:
for event in pygame.event.get():
if event.type == QUIT:
pygame.quit()
sys.exit()
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_LEFT:
tankX -= 20
if event.key == pygame.K_RIGHT:
tankX += 20
drawArena()
drawTank(tank)
pygame.display.update()
if __name__ == '__main__':
main()
this is because updated tankX values do not affect the tank object. there are many ways to make it work. for example, inserting a re-initialization of tank in the while True loop:
import pygame, sys
from pygame.locals import *
WINDOW_WIDTH = 800
WINDOW_HEIGHT = 600
TANK_SIZE = 20
BLACK = (0 ,0 ,0 )
WHITE = (255,255,255)
def drawArena():
DISPLAYSURF.fill(BLACK)
def drawTank(tank):
pygame.draw.rect(DISPLAYSURF, WHITE, tank)
def main():
pygame.init()
global DISPLAYSURF
DISPLAYSURF = pygame.display.set_mode((WINDOW_WIDTH, WINDOW_HEIGHT))
pygame.display.set_caption('Tanks')
tankX = 200
tankY = 200
tank = pygame.Rect(tankX, tankY, TANK_SIZE, TANK_SIZE)
drawArena()
drawTank(tank)
while True:
for event in pygame.event.get():
if event.type == QUIT:
pygame.quit()
sys.exit()
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_LEFT:
tankX -= 20
if event.key == pygame.K_RIGHT:
tankX += 20
tank = pygame.Rect(tankX, tankY, TANK_SIZE, TANK_SIZE)
drawArena()
drawTank(tank)
pygame.display.update()
if __name__ == '__main__':
main()
You should not update the tankX and tankY variables as this doesn't affect the tank Rect object. You don't need to re-initialize the tank object as this is probably a waste of resources. A more efficient way is to just directly update the x and y values of the tank object using it's move_ip() function.
In your main loop...
while True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
sys.exit()
if event.type == pygame.KEYDOWN:
if event.type == pygame.K_LEFT:
tank.move_ip(-20, 0)
if event.type == pygame.K_RIGHT:
tank.move_ip(20, 0)
drawArena()
drawTank(tank)
pygame.display.update()

Detecting and distinguishing keys in PyGame

bg = "lv1.jpg"
ch = "char.png"
import pygame, sys
from pygame.locals import *
pygame.init()
screen = pygame.display.set_mode((640, 400), 0, 32)
background = pygame.image.load(bg).convert()
char = pygame.image.load(ch).convert_alpha()
clock = pygame.time.Clock()
charspeed = 0
charx = 100
chary = 200
running = True
while running:
for event in pygame.event.get():
if event.type == QUIT:
running = False
pygame.quit()
sys.exit()
if event.type== KEYDOWN:
if event.type == K_LEFT:
charspeed = -100
elif event.type == K_RIGHT:
charspeed = +100
if event.type== KEYUP:
if event.key==K_LEFT:
charspeed=0
elif event.key==K_RIGHT:
charspeed=0
screen.blit(background, (0,0))
milli = clock.tick()
seconds = milli/1000.
chardm = seconds*charspeed
charx += chardm
screen.blit(char, (charx, chary))
pygame.display.update()
For some reason the charspeed wont increment by 100 when i press down on the right key. I am trying to make a game with a clock but it doesn't seem to work. I am very new to pygame as you can see so Plz help!
The problem is here:
if event.type== KEYDOWN:
if event.type == K_LEFT:
charspeed = -100
elif event.type == K_RIGHT:
charspeed = +100
The event.type is KEYDOWN, so it can't also be K_RIGHT.
What you want is event.key == K_RIGHT.
See the pygame.event docs for details.

Moving an object left and right

I have a problem with Python and pygame: I have no idea how to make a simple paddle move left and right. Basically I am working on a pong type game for my first project.
After reading a few articles online I thought of a way of how to do this. The code I have so far is:
PADDLE_WIDTH = 50
PADDLE_HEIGHT = 10
paddleSpeedX = 0
p1Paddle = pygame.Rect(10, 430, PADDLE_WIDTH, PADDLE_HEIGHT)
PADDLE_COLOR = pygame.color.Color("red")
while True:
for event in pygame.event.get():
if event.type == KEYDOWN:
if event.key == K_LEFT:
p1Paddle.right = p1Paddle.left + paddleSpeedX - 10
if event.key == K_RIGHT:
p1Paddle.left = p1Paddle.left + paddleSpeedX + 10
if event.type == QUIT:
pygame.quit()
sys.exit()
pygame.display.update()
pygame.display.update()
After entering this code the game runs but I still cannot move the paddle left and right.
How can I do this?
Pygame raises a KEYDOWN event only once, when you first hit a key.
Unfortunately, it won't continue to raise a KEYDOWN event, so what's happening is that your paddle is jerking over only once, and won't move again unless you keep spamming the left or right key.
Instead, what you could do is set a velocity when you recieve a KEYDOWN event, and set it back to zero when you get KEYUP, like so:
while True:
for event in pygame.event.get():
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_LEFT:
p1Paddle.x_velocity = -10
elif event.key == pygame.K_RIGHT:
p1Paddle.x_velocity = 10
if event.type == pygame.KEYUP:
if event.key in [pygame.K_LEFT, pygame.K_RIGHT]:
# if either the left or right arrow keys are released
p1Paddle.x_velocity = 0
if event.type == pygame.QUIT:
pygame.quit()
sys.exit()
p1Paddle.x_distance += p1Paddle.x_velocity
# other stuff here
# drawing code here
pygame.display.update()
(I also changed some of your variable names, since I couldn't figure out what p1Paddle.left and p1Paddle.right were -- I hope you don't mind).
I have made some additions and modifications to make your code work.
In each frame (iteration of loop) you must erase the screen and redraw the paddle. This is to make sure the paddle is redrawn with new coordinates when the LEFT/RIGHT arrows are pressed.
Notice that I change p1Paddle.left instead of p1Paddle.right when LEFT is pressed.
import pygame, sys
from pygame import *
pygame.init()
screen = pygame.display.set_mode((640, 480))
pygame.display.set_caption('Paddle Movement')
PADDLE_WIDTH = 50
PADDLE_HEIGHT = 10
paddleSpeedX = 0
p1Paddle = pygame.Rect(10, 430, PADDLE_WIDTH, PADDLE_HEIGHT)
PADDLE_COLOR = pygame.color.Color("red")
while True:
# clear screen with black color
screen.fill( (0,0,0) )
for event in pygame.event.get():
if event.type == KEYDOWN:
if event.key == K_LEFT:
p1Paddle.left = p1Paddle.left + paddleSpeedX - 10
if event.key == K_RIGHT:
p1Paddle.left = p1Paddle.left + paddleSpeedX + 10
if event.type == QUIT:
pygame.quit()
sys.exit()
pygame.display.update()
# draw the paddle
screen.fill( PADDLE_COLOR, p1Paddle );
pygame.display.update()
A more elegant solution would be the one below
import pygame, sys
from pygame import *
pygame.init()
screen = pygame.display.set_mode((640, 480))
pygame.display.set_caption('Paddle Movement')
PADDLE_WIDTH = 50
PADDLE_HEIGHT = 10
paddleSpeedX = 0
p1Paddle = pygame.Rect(10, 430, PADDLE_WIDTH, PADDLE_HEIGHT)
PADDLE_COLOR = pygame.color.Color("red")
# clock object that will be used to make the game
# have the same speed on all machines regardless
# of the actual machine speed.
clock = pygame.time.Clock()
while True:
# limit the demo to 50 frames per second
clock.tick( 50 );
# clear screen with black color
screen.fill( (0,0,0) )
for event in pygame.event.get():
if event.type == QUIT:
pygame.quit()
sys.exit()
pygame.display.update()
keys = pygame.key.get_pressed()
if keys[K_LEFT]:
p1Paddle.left = p1Paddle.left + paddleSpeedX - 5
if keys[K_RIGHT]:
p1Paddle.left = p1Paddle.left + paddleSpeedX + 5
# draw the paddle
screen.fill( PADDLE_COLOR, p1Paddle );
pygame.display.update()
Notice that I check the key press using pygame.key.get_pressed(). It allows to make a smooth movement as we check the key state and don't wait for an event to occur.
I added a clock object to limit the frame rate to 50 FPS (frames per second).
Please try both approaches.

Categories

Resources