pygame hold key to move - python

I'm trying to move the player left in the four main directions, but it only moves when pressed not held down, so I have to repeatedly press the button to move across the screen and up and down don't work.
import pygame
#Start pygame
pygame.init()
#Window/Screen/Display
display_x = 1280
display_y = 720
display = pygame.display.set_mode((display_x,display_y))
pygame.display.set_caption('Platforms')
clock = pygame.time.Clock()
#Colors
black = (0,0,0)
green = (1,166,17)
#Images
character = pygame.image.load('character.gif')
def chrctr(x,y):
display.blit(character,(x,y))
x_c = (display_x / 2)
y_c = (display_y / 2)
x_change = 0
y_change = 0
floor_1 = pygame.image.load('wood.jpg')
def floor(x,y):
display.blit(floor_1,(x,y))
x = (display_x * 0)
y = (display_y * 0.9)
not_dead=True
while not_dead:
for event in pygame.event.get():
if (event.type==pygame.QUIT):
not_dead=False
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_LEFT:
x_change = - 5
elif event.key == pygame.K_RIGHT:
x_change = 5
if event.key == pygame.K_UP:
y_change = - 5
elif event.key == pygame.K_DOWN:
y_change = 5
if event.type == pygame.KEYUP:
if event.key == pygame.K_LEFT or event.key == pygame.K_RIGHT:
x_change = 5
x_c += x_change
if event.type == pygame.KEYUP:
if event.key == pygame.K_UP or event.key == pygame.K_DOWN:
y_change = 0
y_c += y_change
display.fill(green)
pygame.draw.rect(display, black, [0, 550, 200, 50])
pygame.draw.rect(display, black, [0, 450, 200, 50])
pygame.draw.rect(display, black, [0, 350, 200, 50])
pygame.draw.rect(display, black, [0, 250, 200, 50])
pygame.draw.rect(display, black, [0, 150, 200, 50])
pygame.draw.rect(display, black, [0, 50, 200, 50])
pygame.draw.rect(display, black, [1080, 550, 200, 50])
pygame.draw.rect(display, black, [1080, 450, 200, 50])
pygame.draw.rect(display, black, [1080, 350, 200, 50])
pygame.draw.rect(display, black, [1080, 250, 200, 50])
pygame.draw.rect(display, black, [1080, 150, 200, 50])
pygame.draw.rect(display, black, [1080, 50, 200, 50])
floor(0,display_y * 0.9)
floor(236, display_y * 0.9)
floor(472, display_y * 0.9)
floor(708, display_y * 0.9)
floor(944, display_y * 0.9)
floor(1180, display_y * 0.9)
chrctr(x_c, y_c)
pygame.display.update()
clock.tick(60)
print ("Hello")
pygame.quit()

Ok so I made a simple demo where your character (hero) is centered in the screen and you can move him around with the arrow keys. Since there was a lot of refactoring, let me know what stuff I need to clear up in the comments and I will add explanations to this answer.
import pygame
import sys
class Character(object):
def __init__(self, x=0, y=0, speed=0):
self.x = x
self.y = y
self.speed = speed
self.image = pygame.image.load('hero.png')
def get_size(self):
return self.image.get_size()
def draw(self):
display.blit(self.image, (self.x, self.y))
pygame.init()
(width, height) = (800, 600)
display = pygame.display.set_mode((width, height))
pygame.display.set_caption('Platforms')
clock = pygame.time.Clock()
hero = Character(speed=5)
hero_width, hero_height = hero.get_size()
hero.x = width/2.0 - hero_width/2.0
hero.y = height/2.0 - hero_height/2.0
black = (0,0,0)
pressed_keys = {"left": False, "right": False, "up": False, "down": False}
while True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
sys.exit()
elif event.type == pygame.KEYDOWN:
if event.key == pygame.K_LEFT:
pressed_keys["left"] = True
if event.key == pygame.K_RIGHT:
pressed_keys["right"] = True
if event.key == pygame.K_UP:
pressed_keys["up"] = True
if event.key == pygame.K_DOWN:
pressed_keys["down"] = True
elif event.type == pygame.KEYUP:
if event.key == pygame.K_LEFT:
pressed_keys["left"] = False
if event.key == pygame.K_RIGHT:
pressed_keys["right"] = False
if event.key == pygame.K_UP:
pressed_keys["up"] = False
if event.key == pygame.K_DOWN:
pressed_keys["down"] = False
if pressed_keys["left"]:# == True is implied here
hero.x -= hero.speed
if pressed_keys["right"]:
hero.x += hero.speed
if pressed_keys["up"]:
hero.y -= hero.speed
if pressed_keys["down"]:
hero.y += hero.speed
display.fill(black)
hero.draw()
pygame.display.update()
clock.tick(60)
EDIT:
I see that the pressed_keys dictionary caused some confusion, so I will explain that. You might want to read something like this if my explanation is unclear.
Dictionaries in python are basically like physical dictionaries in real life. Say you are looking up a word like "aardvark" (a key) and want to know what it means. You would open the dictionary book and find the definition (a value) of "aardvark." Dictionaries are simply a bunch of these key:value pairs.
When I initially created the pressed_keys variable, I defined four key:value pairs, one for each of the directions. The keys were left, right, up, and down while the corresponding values were all False. This should make sense since at the beginning of the game, we are not pressing any buttons and the player is not moving. Lines of code like pressed_keys["left"] = True update the value that matches with the key left in pressed_keys whenever a keypress occurs according to pygame.
After I get all of the events that happened in pygame (window closing, mouse movement, keyboard presses, etc.) at that particular instant of time, I now can check the status of my pressed_keys dictionary. If the value that corresponds to the dictionary key left is True, then I simply shift the hero's x-position left a little. The same is true for all of the other directions.

Related

After the screen is blitted how to make a rectangle when there is already an existing moving rectangle?

I am making this game in PyGame and I have a moving rectangle, So I want to make another rectangle which is drawn to the screen when I press the Space Bar. So I have tried adding the if statement but it doesn't work as the screen fills as soon as the Rectangle is drawn. Can anyone tell me how to draw the rectangle after the screen is filled with a color?
Here is my code
import pygame
from pygame.locals import *
pygame.init()
screenwidth = 1200
screenheight = 500
screen = pygame.display.set_mode((screenwidth, screenheight))
pygame.display.set_caption('Bullepacito')
def _rect():
run = False
while not run:
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = True
if event.type == pygame.KEYDOWN:
if event.type == pygame.K_SPACE:
pygame.draw.rect(screen, (255, 0, 255), pygame.Rect(400, 400, 20, 20))
def gameloop():
run = False
shooterx = 350
shootery = 350
while not run:
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = True
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_LEFT:
shooterx -= 5
if event.key == pygame.K_RIGHT:
shooterx += 5
screen.fill((30, 30, 30))
pygame.draw.rect(screen, (255, 0, 255), pygame.Rect(shooterx, shootery, 50, 50))
# Code to draw the rectangle on key press
pygame.display.update()
gameloop()
Set a boolean state (draw_rect) when SPACE is pressed and draw the rectangle depending on the state:
import pygame
from pygame.locals import *
pygame.init()
screenwidth = 1200
screenheight = 500
screen = pygame.display.set_mode((screenwidth, screenheight))
pygame.display.set_caption('Bullepacito')
def gameloop():
run = False
shooterx = 350
shootery = 350
draw_rect = False
while not run:
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = True
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_LEFT:
shooterx -= 5
if event.key == pygame.K_RIGHT:
shooterx += 5
if event.key == pygame.K_SPACE:
draw_rect = True
screen.fill((30, 30, 30))
pygame.draw.rect(screen, (255, 0, 255), pygame.Rect(shooterx, shootery, 50, 50))
if draw_rect:
pygame.draw.rect(screen, (255, 0, 255), pygame.Rect(400, 400, 20, 20))
pygame.display.update()
gameloop()

Where do I insert set caption?

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()

Can someone please tell me where am I wrong in this python code?

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()

Pygame: How to "lose" game when sprite runs into its trail

I created a snake-like game in which the user moves the sprite, and the sprite leaves a trail. If the user runs into the trail he's created, I'd like the game to end, and the player to lose.
One idea I had was to somehow track past positions of the sprite (maybe in a list), and then create an 'if' statement that would lead to a game loss (However, I'm was a little unclear on how to do that).
I received an answer to this question that coded for this list:
"I think you could declare a two dimensional list like this:
pastPositions = [[400, 300]]
Then every time the player's position moves, check the list:
for row in pastPositions:
If (player.rect.x == pastPositions[row][0] and player.rect.y == >pastPositions[row][1]):
done = true # game over
If the player hasn't been there yet, then add that position to the list.
pastPositions.append([player.rect.x, player.rect.y])"
This looks like it should work, but when I try to run the code (in Python Interactive), I get an error message that reads: "line 86, in if player.rect.x == astPositions[row][0] and player.rect.y == pastPositions[row][1]: IndexError: list index out of range" – Gal 2 days ago
What would you suggest I change the range to so that this doesn't happen? I tried setting it to the width and height of the pygame window.
import pygame
BLACK = (0, 0, 0)
WHITE = (255, 255, 255)
class Player(pygame.sprite.Sprite):
def __init__(self, x, y):
super().__init__()
self.image = pygame.Surface([15, 15])
self.image.fill(WHITE)
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
pygame.init()
screen = pygame.display.set_mode([800, 600])
pygame.display.set_caption('The Etch-a-Sketch Game')
myfont = pygame.font.SysFont('Times', 20)
textsurface = myfont.render('This is the Etch-a-Sketch Game', False, (255, 255, 255))
screen.blit(textsurface,(0,0))
myfont = pygame.font.SysFont('Times', 15)
textsurface = myfont.render('Feel free to draw, but if you cross your own path, you will die.', False, (255, 255, 255))
screen.blit(textsurface,(0,20))
player = Player(400, 300)
all_sprites_list = pygame.sprite.Group()
all_sprites_list.add(player)
clock = pygame.time.Clock()
done = False
while not done:
for event in pygame.event.get():
if event.type == pygame.QUIT:
done = True
elif event.type == pygame.KEYDOWN:
if event.key == pygame.K_LEFT:
player.changespeed(-3, 0)
elif event.key == pygame.K_RIGHT:
player.changespeed(3, 0)
elif event.key == pygame.K_UP:
player.changespeed(0, -3)
elif event.key == pygame.K_DOWN:
player.changespeed(0, 3)
elif event.type == pygame.KEYUP:
if event.key == pygame.K_LEFT:
player.changespeed(3, 0)
elif event.key == pygame.K_RIGHT:
player.changespeed(-3, 0)
elif event.key == pygame.K_UP:
player.changespeed(0, 3)
elif event.key == pygame.K_DOWN:
player.changespeed(0, -3)
player.update()
all_sprites_list.draw(screen)
pygame.display.flip()
clock.tick(75)
pygame.quit ()
I think you could declare a two dimensional list like this:
pastPositions = [[400, 300]]
Then every time the player's position moves, check the list:
for row in pastPositions:
if (player.rect.x == row[0] and player.rect.y == row[1]):
done = true # game over
If the player hasn't been there yet, then add that position to the list.
pastPositions.append([player.rect.x, player.rect.y])
Are you looking for something like that?

How to make an image appear and disappear randomly?

I have a problem, in fact my mole image appears but doesn't disappear. I just want one mole to appear and disappear 10 seconds later and another mole appears etc.. That's my code:
If I do a time.delay(10) my code crashes.
I have tried a million things but I'm stuck right now. Can you help me please? I don't know how to do that.
import pygame
import random
import time
pygame.init()
display_width = 600
display_height = 480
gameDisplay = pygame.display.set_mode((display_width, display_height))
fond = pygame.image.load("fond.bmp").convert()
gameDisplay.blit(fond, (0, 0))
pygame.display.set_caption('Tape Taupe')
clock = pygame.time.Clock()
BAMimg = pygame.image.load('Marteau.png')
gameIcon = pygame.image.load('Taupe.png').convert_alpha()
pygame.display.set_icon(gameIcon)
BAMimg_width = 73
perso1 = pygame.image.load("troutaup.png").convert_alpha()
gameDisplay.blit(perso1, (160, 55))
perso2 = pygame.image.load("troutaup.png").convert_alpha()
gameDisplay.blit(perso2, (320, 55))
perso3 = pygame.image.load("troutaup.png").convert_alpha()
gameDisplay.blit(perso3, (480, 55))
perso4 = pygame.image.load("troutaup.png").convert_alpha()
gameDisplay.blit(perso4, (160, 200))
perso5 = pygame.image.load("troutaup.png").convert_alpha()
gameDisplay.blit(perso4, (320, 200))
perso6 = pygame.image.load("troutaup.png").convert_alpha()
gameDisplay.blit(perso4, (480, 200))
perso7 = pygame.image.load("troutaup.png").convert_alpha()
gameDisplay.blit(perso4, (160, 350))
perso8 = pygame.image.load("troutaup.png").convert_alpha()
gameDisplay.blit(perso4, (320, 350))
perso9 = pygame.image.load("troutaup.png").convert_alpha()
gameDisplay.blit(perso4, (480, 350))
pygame.display.update()
def BAMImg(x, y):
gameDisplay.blit(BAMImg, (x, y))
x = (display_width * 0.45)
y = (display_height * 0.8)
def game_loop():
x = (display_width * 0.45)
y = (display_height * 0.8)
x_change = 0
y_change = 0
gameExit = False
while not gameExit:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
quit()
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
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_UP:
y_change = -5
if event.key == pygame.K_DOWN:
y_change = 5
if event.type == pygame.KEYUP:
if event.key == pygame.K_UP or event.key == pygame.K_DOWN:
y_change = 0
BAMimg(x, y)
x += x_change
y += y_change
Taupe = pygame.image.load("Taupe.png").convert_alpha()
coordinates = random.choice([[160, 55], [320, 55], [480, 55], [160, 200], [320, 200], [480, 200], [160, 350], [320, 350],[480, 350]])
gameDisplay.blit(Taupe, coordinates)
pygame.display.update()
clock.tick(60)
game_loop()
pygame.quit()
You can use the pygame.time.set_timer function to add an event to the event queue after a specified time interval. The event types are actually just ints and you can define your own events in this way: CHANGE_COORDINATES = pygame.USEREVENT + 1
Then check in the event loop if this event was in the event queue and call random.choice to get the new coordinates.
There were some more problems with the code that I've fixed in the example below:
import pygame
import random
pygame.init()
display_width = 600
display_height = 480
gameDisplay = pygame.display.set_mode((display_width, display_height))
clock = pygame.time.Clock()
Taupe = pygame.Surface((50, 50))
Taupe.fill((30, 90, 230))
BAMimg = pygame.Surface((73, 73))
BAMimg.fill((230, 90, 30))
# We use this custom event for our timer.
CHANGE_COORDINATES = pygame.USEREVENT + 1
# This function had almost the same name as the BAMimg variable
# and you tried to blit the function itself not the image here.
def display_BAMImg(x, y):
gameDisplay.blit(BAMimg, (x, y))
x = display_width * 0.45
y = display_height * 0.8
def game_loop():
x = display_width * 0.45
y = display_height * 0.8
coordinates_list = [
[160, 55], [320, 55], [480, 55], [160, 200],
[320, 200], [480, 200], [160, 350],
[320, 350], [480, 350],
]
x_change = 0
y_change = 0
coordinates = random.choice(coordinates_list)
# This means after 2000 milliseconds a `CHANGE_COORDINATES`
# event will be added to the event queue.
pygame.time.set_timer(CHANGE_COORDINATES, 2000)
gameExit = False
while not gameExit:
for event in pygame.event.get():
if event.type == pygame.QUIT:
gameExit = 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.key == pygame.K_UP:
y_change = -5
elif event.key == pygame.K_DOWN:
y_change = 5
elif event.type == pygame.KEYUP:
if event.key == pygame.K_LEFT or event.key == pygame.K_RIGHT:
x_change = 0
elif event.key == pygame.K_UP or event.key == pygame.K_DOWN:
y_change = 0
# Check if a `CHANGE_COORDINATES` event was in the
# event queue and if yes, call random.choice to get
# new coordinates.
elif event.type == CHANGE_COORDINATES:
coordinates = random.choice(coordinates_list)
# The following lines should not be in the event loop.
gameDisplay.fill((30, 30, 30)) # Clear the display each frame.
display_BAMImg(x, y)
x += x_change
y += y_change
gameDisplay.blit(Taupe, coordinates)
pygame.display.update()
clock.tick(60)
game_loop()
pygame.quit()

Categories