How would I detect NO KEY PRESS / No Input in Python? - python

I am making a simple box moving "game" to learn the pygame import, but I would like to set the box back to gray after there are no keys pressed.
import pygame
from pygame.locals import *
pygame.init()
width = 400
height = 400
screen = pygame.display.set_mode((width,height))
done = False
clock = pygame.time.Clock()
color = (150, 150, 150)
x = 0
y = 0
while not done:
for event in pygame.event.get():
if event.type == pygame.QUIT:
done = True
if event.type == pygame.KEYDOWN and event.key == pygame.K_SPACE:
is_blue = not is_blue
pressed = pygame.key.get_pressed()
if pressed[pygame.K_UP] or pressed[pygame.K_w] and y > 0:
y -= 3
color = (0,0,255)
if pressed[pygame.K_DOWN] or pressed[pygame.K_s] and y+60 < height: #Adding 60 because height of block = 60
y += 3
color = (255,255,0)
if pressed[pygame.K_LEFT] or pressed[pygame.K_a] and x > 0:
x -= 3
color = (0,255,0)
if pressed[pygame.K_RIGHT] or pressed[pygame.K_d] and x+60 < width: #Adding 60 because width of block = 60
x += 3
color = (255,0,0)
screen.fill((0, 0, 0))
pygame.draw.rect(screen, color, pygame.Rect(x, y, 60, 60))
pygame.display.flip()
clock.tick(60)

Just add the set of the color=(150,150,150) inside the while loop(:
Put it as the first line inside the loop.

Related

I'm trying to detect the collision between two moving Rects in pygame

So I keep trying to detect two different moving rects in pygame colliding but its just constantly registering a collision. As in the console constantly print lose, but the enemy isn't even touching the ball. The effect I want is just a simple game where the ball has to avoid the tack so that the ball doesn't pop.
import pygame
import sys
import math
import random
pygame.init()
size = width, height = 800, 600
white = 255, 255, 255
red = 255, 0, 0
clock = pygame.time.Clock()
screen = pygame.display.set_mode(size)
character = pygame.image.load("intro_ball.gif")
charrect = character.get_rect()
x = 340
y = 480
enemy = pygame.image.load("ho.png")
enrect = enemy.get_rect()
ex = random.randint(0, 690)
ey = 0
lose = False
while 1:
clock.tick(60)
for event in pygame.event.get():
if event.type == pygame.QUIT: sys.exit()
if ey >= 600 and lose != True:
ey = 0
ex = random.randint(0, 690)
collide = pygame.Rect.colliderect(charrect, enrect)
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_RIGHT and x < 690:
x += 4
if event.key == pygame.K_LEFT and x > 0:
x -= 4
if collide:
lose = True
else: lose = False
if lose == True: print("lose")
ey += 2
screen.fill(white)
screen.blit(enemy, (ex, ey))
screen.blit(character, (x, y))
pygame.display.update()
pygame.Surface.get_rect.get_rect() returns a rectangle with the size of the Surface object, that always starts at (0, 0) since a Surface object has no position. A Surface is blit at a position on the screen. The position of the rectangle can be specified by a keyword argument. For example, the top lelft of the rectangle can be specified with the keyword argument topleft. These keyword argument are applied to the attributes of the pygame.Rect before it is returned (see pygame.Rect for a full list of the keyword arguments):
while 1:
# [...]
charrect = character.get_rect(topleft = (x, y))
enrect = enemy.get_rect(topleft = (ex, ey))
collide = pygame.Rect.colliderect(charrect, enrect)
# [...]
On the other hand you do not need the variables x, y, ex, ey at all. Use the features of the pygame.Rect objects.
Additionally read How can I make a sprite move when key is held down
Minimal example:
import pygame, sys, math, random
pygame.init()
size = width, height = 800, 600
white = 255, 255, 255
red = 255, 0, 0
clock = pygame.time.Clock()
screen = pygame.display.set_mode(size)
#character = pygame.image.load("intro_ball.gif")
character = pygame.Surface((20, 20))
character.fill((0, 255, 0))
charrect = character.get_rect(topleft = (340, 480))
#enemy = pygame.image.load("ho.png")
enemy = pygame.Surface((20, 20))
enemy.fill((255, 0, 0))
enrect = enemy.get_rect(topleft = (random.randint(0, 690), 0))
lose = False
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()
charrect.x += (keys[pygame.K_RIGHT] - keys[pygame.K_LEFT]) * 4
charrect.clamp_ip(screen.get_rect())
enrect.y += 2
if enrect.y >= 600 and lose != True:
enrect.y = 0
enrect.x = random.randint(0, 690)
collide = pygame.Rect.colliderect(charrect, enrect)
if collide:
lose = True
else:
lose = False
if lose == True:
print("lose")
screen.fill(white)
screen.blit(enemy, enrect)
screen.blit(character, charrect)
pygame.display.update()
pygame.quit()
exit()

Mouse clicked on random image in python [duplicate]

This question already has an answer here:
Why is my collision test always returning 'true' and why is the position of the rectangle of the image always wrong (0, 0)?
(1 answer)
Closed 2 years ago.
I am beginner in python. Recently i am doing a pygame poject. I want to make a game where the screen will show an image in a random position, and after 0.3 seconds, the image will move to another random position again. The player will repeatedly click on the position-changed image with the mouse and the score will increase. Even if I do everything, clicking with the mouse does not increase the score.
Here is my code:
pygame.init()
width = 500
height = 500
score = 0
display = pygame.display.set_mode((width, height))
pygame.display.set_caption("Tapping")
image = pygame.image.load('spaceship.png').convert()
sides = ['Top', 'Botom', 'left', 'Right']
weights = [width, width, height, height]
posx = random.randint(50, 450)
posy = random.randint(20, 460)
tsp = 1.2
Mousex = 0
Mousey = 0
def image_view(x, y):
display.blit(image, (x, y))
run = True
while run:
display.fill((153, 255, 187))
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
if event.type == pygame.MOUSEBUTTONDOWN:
Mousex, Mousey = event.pos
if image.get_rect().collidepoint(posx, posy):
score += 1
side = random.choices(sides, weights)[0]
if side == 'Top':
posx = random.randrange(100, 300)
posy = random.randrange(20, 100)
time.sleep(tsp)
elif side == 'Botom':
posx = random.randrange(350, 430)
posy = random.randrange(250, 450)
time.sleep(tsp)
elif side == 'left':
posx = random.randrange(20, 250)
posy = random.randrange(20, 250)
time.sleep(tsp)
elif side == 'Right':
posx = random.randrange(280, 450)
posy = random.randrange(280, 450)
time.sleep(tsp)
print(score)
image_view(posx, posy)
pygame.display.update()
You have to evaluate if the mouse is on the image. Note, a pygame.Surface has no position. It is blit at a position. Hence the position of the pygame.Rect object, which is returned by get_rect() is (0, 0).
You have to set the position by a keyword argument (e.g. image.get_rect(topleft = (posx, posy))). Finally you can use collidepoint() to evaluate if the mouse cursor (Mousex, Mousey) is on the region of the display, where the image is currently placed:
if event.type == pygame.MOUSEBUTTONDOWN:
Mousex, Mousey = event.pos
image_rect = image.get_rect(topleft = (posx, posy))
if image_rect.collidepoint(Mousex, Mousey):
score += 1
Further more, time.sleep(tsp) prevents the system from responding. Never delay the main application loop.
Use pygame.time.get_ticks() to get get the time in milliseconds. Add a variable next_choice_time. The time indicates when the position of the image has to be changed. Set a new time when the position of the image is changed:
next_choice_time = 0
while run:
current_time = pygame.time.get_ticks()
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
if event.type == pygame.MOUSEBUTTONDOWN:
Mousex, Mousey = event.pos
image_rect = image.get_rect(topleft = (posx, posy))
if image_rect.collidepoint(Mousex, Mousey):
score += 1
next_choice_time = current_time
if current_time >= next_choice_time:
next_choice_time = current_time + 300 # 300 milliseconds == 0.3 seconds
side = random.choices(sides, weights)[0]
# [...]
See the example:
import pygame
import random
pygame.init()
width = 500
height = 500
score = 0
display = pygame.display.set_mode((width, height))
pygame.display.set_caption("Tapping")
image = pygame.image.load('spaceship.png').convert()
sides = ['Top', 'Botom', 'left', 'Right']
weights = [width, width, height, height]
posx = random.randint(50, 450)
posy = random.randint(20, 460)
tsp = 1.2
Mousex = 0
Mousey = 0
def image_view(x, y):
display.blit(image, (x, y))
run = True
next_choice_time = 0
while run:
current_time = pygame.time.get_ticks()
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
if event.type == pygame.MOUSEBUTTONDOWN:
Mousex, Mousey = event.pos
image_rect = image.get_rect(topleft = (posx, posy))
if image_rect.collidepoint(Mousex, Mousey):
score += 1
next_choice_time = current_time
print(score)
if current_time >= next_choice_time:
next_choice_time = current_time + 300 # 300 milliseconds == 0.3 seconds
side = random.choices(sides, weights)[0]
if side == 'Top':
posx = random.randrange(100, 300)
posy = random.randrange(20, 100)
elif side == 'Botom':
posx = random.randrange(350, 430)
posy = random.randrange(250, 450)
elif side == 'left':
posx = random.randrange(20, 250)
posy = random.randrange(20, 250)
elif side == 'Right':
posx = random.randrange(280, 450)
posy = random.randrange(280, 450)
display.fill((153, 255, 187))
image_view(posx, posy)
pygame.display.update()

How to check if a rectangle is off of the pygame screen

I am remaking the game Snake with pygame.
How do I detect if the square is outside the screen?
I am using x = and y = to move the square.
This is the code so far:
import pygame, sys, random
from pygame.locals import *
pygame.init()
movement_x = movement_y = 0
RED = (240, 0, 0)
GREEN = (0, 255, 0)
ran = [0,25,50,75,100,125,150,175,200,225,250,275,300,325,350,375,400,425,450,475,500]
ax = 0
ay = 0
x = 0
y = 0
sizex = 500
sizey = 500
tilesize = 25
screen = pygame.display.set_mode((sizex,sizey))
pygame.display.set_caption('Snake')
pygame.display.set_icon(pygame.image.load('images/tile.png'))
tile = pygame.image.load('images/tile.png')
tile = pygame.transform.scale(tile, (tilesize, tilesize))
clock = pygame.time.Clock()
vel_x = 0
vel_y = 0
ap = True
while True:
for event in pygame.event.get():
if event.type == QUIT:
pygame.quit()
sys.exit()
for row in range(sizex):
for column in range(sizey):
screen.blit(tile,(column*tilesize, row*tilesize,tilesize,tilesize))
for event in pygame.event.get():
if event.type == KEYDOWN:
if event.key == K_UP:
vel_y = -25
vel_x = 0
elif event.key == K_DOWN:
vel_y = 25
vel_x = 0
elif event.key == K_LEFT:
vel_x = - 25
vel_y = 0
elif event.key == K_RIGHT:
vel_x= 25
vel_y = 0
if ap:
pygame.draw.rect(screen, GREEN, pygame.Rect(ax,ay,tilesize,tilesize))
y += vel_y
x += vel_x
if x == ax and y == ay:
pygame.draw.rect(screen, GREEN, pygame.Rect(ax,ay,tilesize,tilesize))
ax = random.choice(ran)
ay = random.choice(ran)
pygame.draw.rect(screen, RED, pygame.Rect(x,y,tilesize,tilesize))
pygame.display.flip()
clock.tick(100)
If a point is inside a rectangle can be checked by pygame.Rect.collidepoint().
The rectangle is defined by the bounds of the screen and the point is the new position of the head of the snake:
inBounds = pygame.Rect(0, 0, sizex, sizey).collidepoint(x+vel_x, y+vel_y)
if inBounds:
y += vel_y
x += vel_x

pygame function only works once, doesn't loop

I have a pause menu for a game im working on for school. If the user clicks 'p' it launches the pause menu. And the pause menu has a function that if a user clicks a button the user will be launched back into the game. Problem is after they are launched into the game the 'p' function to pause doesn't work anymore. I'm not sure if i looped it correctly.
the pong game
import pygame
black = (0,0,0)
white = (255,255,255)
pygame.init()
size = 800,600
screen = pygame.display.set_mode(size)
pygame.display.set_caption("Basketball Shootout")
done = False
clock = pygame.time.Clock()
def player1(x1, y1, xsize, ysize):
pygame.draw.rect(screen, black, [x1, y1, xsize, ysize])
def player2(x2, y2, xsize, ysize):
pygame.draw.rect(screen, black, [x2,y2,xsize,ysize])
def ball(ballx, bally):
pygame.draw.circle(screen, black, [ballx,bally],20)
def Score1(score1):
font = pygame.font.Font("Minecraft.ttf" ,50)
text = font.render(str(score1), True, white)
screen.blit(text, [160, 550])
def Score2(score2):
font = pygame.font.Font("Minecraft.ttf" ,50)
text = font.render(str(score2), True, white)
screen.blit(text, [610, 550])
x1 = 20
y1 = 175
xsize = 35
ysize = 150
speed1 = 0
x2 = 740
y2 = 175
speed2 = 0
ballx = 550
bally = 250
speedx = 8
speedy = 5
score1 = 0
score2 = 0
bg = pygame.image.load("pongbg2.png")
rect1 = pygame.Rect(50,510,100,50)
def pausescreen():
import pausescreen
display_game = True
game_page = 1
while not done:
for event in pygame.event.get():
if event.type == pygame.QUIT:
done = True
pygame.draw.rect(screen, (255, 255, 255), rect1)
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_w:
speed1 = -10
if event.key == pygame.K_s:
speed1 = 10
if event.key == pygame.K_UP:
speed2 = -10
if event.key == pygame.K_DOWN:
speed2 = 10
if event.type == pygame.KEYUP:
if event.key == pygame.K_w:
speed1 = 0
if event.key == pygame.K_s:
speed1 = 0
if event.key == pygame.K_UP:
speed2 = 0
if event.key == pygame.K_DOWN:
speed2 = 0
if event.key == pygame.K_p:
pausescreen()
screen.blit(bg, (0, 0))
player1(x1, y1, xsize, ysize)
player2(x2, y2, xsize, ysize)
ball(ballx,bally)
Score1(score1)
Score2(score2)
y1 += speed1
y2 += speed2
ballx += speedx
bally += speedy
if y1 < 0:
y1 = 0
if y1 > 350:
y1 = 350
if y2 < 0:
y2 = 0
if y2 > 350:
y2 = 350
if ballx+20 > x2 and bally-20 > y2 and bally+20 < y2+ysize and ballx < x2+3:
speedx = -speedx
if ballx-20 < x1+35 and bally-20 > y1 and bally+20 < y1+ysize and ballx > x1+38:
speedx = -speedx
if bally > 477 or bally < 23:
speedy = -speedy
if ballx < 13:
score2 += 1
ballx = 350
bally = 250
if ballx > 750:
score1 += 1
ballx = 350
bally = 250
pygame.display.flip()
clock.tick(60)
pygame.quit()
now here is my pause menu code.
import pygame
import sys
# Define some colors
BLACK = (0, 0, 0)
WHITE = (255, 255, 255)
GREEN = (0, 255, 0)
RED = (255, 0, 0)
pygame.init()
# Set the height and width of the screen
size = [800, 600 ]
screen = pygame.display.set_mode(size)
pygame.display.set_caption("Basketball Shootout")
# Loop until the user clicks the close button.
done = False
# Used to manage how fast the screen updates
clock = pygame.time.Clock()
#Rectangles
rect1 = pygame.Rect(300,300,205,80)
rect2 = pygame.Rect(300,400,205,80)
#Font
font3 = pygame.font.Font("Minecraft.ttf", 40)
def playerpong():
import playerpong
while not done:
for event in pygame.event.get():
if event.type == pygame.QUIT:
done = True
screen.fill(BLACK)
pygame.draw.rect(screen, GREEN, rect1)
pygame.draw.rect(screen, RED, rect2)
if event.type == pygame.MOUSEBUTTONDOWN:
if event.button == 1:
if rect1.collidepoint(event.pos):
playerpong()
if rect2.collidepoint(event.pos):
pygame.quit()
clock.tick(60)
pygame.display.update()
pygame.quit()
The problem is that you are importing your pause screen from another program which creates a problem as you can import a library only once. You can try to put your pause screen code in the function instead of calling it but if you insist, you can put your pause_screen code in a function and do a from pausescreen import name_of_function so whenever you need to call that code just write name_of_funtion()

How can I create an interactive object in pygame?

In a pygame program I am creating, I have need for an interactive object on the screen that will call a function when the player character moves onto it and presses the enter key. Here is the code I have so far:
import pygame
pygame.init()
screen = pygame.display.set_mode((800, 600))
done = False
x = 30
y = 30
clock = pygame.time.Clock()
while not done:
for event in pygame.event.get():
if event.type == pygame.QUIT:
done = True
pressed = pygame.key.get_pressed()
if pressed[pygame.K_UP] and y > 0: y -= 5
if pressed[pygame.K_DOWN] and y < 600 - 60: y += 5
if pressed[pygame.K_LEFT] and x > 0: x -= 5
if pressed[pygame.K_RIGHT] and x < 800 - 60: x += 5
screen.fill((0, 0, 0))
color = (0, 128, 255)
pygame.draw.rect(screen, color, pygame.Rect(x, y, 60, 60))
myfont = pygame.font.SysFont("monospace", 15)
label = myfont.render("Start the experiment simulator", 1, (255,255,255))
screen.blit(label, (100, 100))
label2 = myfont.render("Start the quiz", 1, (255,255,255))
screen.blit(label2, (550, 100))
label3 = myfont.render("Quit game", 1, (255,255,255))
screen.blit(label3, (350, 400))
pygame.draw.rect(screen, red, pygame.Rect(600, 125, 30, 30))
pygame.draw.rect(screen, red, pygame.Rect(225, 125, 30, 30))
pygame.draw.rect(screen, red, pygame.Rect(375, 425, 30, 30))
pygame.display.flip()
clock.tick(60)
At the moment, the object is just a test so would be best to be a small red rectangle, about half the size of the player, that I can replace with an icon later on. This rectangle should be placed below the 'quit game' label on the pygame window and quit the game when interacted with. This is one method that I have tried so far:
if pressed[pygame.K_RETURN] and x >= 375 or x <= 405 and y >=425 or y <= 455:
pygame.display.quit()
pygame.quit()
sys.exit()
Where theoretically the system checks if the user is in a specific area and has pressed the enter key before performing the command.
You can check for collision, using pygame's colliderect
First, create three rects that will represent your three option rects :
simulator_rect = pygame.Rect(600, 125, 30, 30)
quiz_rect = pygame.Rect(225, 125, 30, 30)
quit_rect = pygame.Rect(375, 425, 30, 30)
Next, we'll create a rect that will represent the blue selector rect :
selector_rect = pygame.Rect(50, 50, 60, 60)
So now you've got rects that are created only once, instead of unnamed rects that are created every time
Now, for the actual collision detection :
# Check to see if the user presses the enter key
if pressed[pygame.K_RETURN]:
# Check to see if the selection rect
# collides with any other rect
for rect in option_rects:
if selector_rect.colliderect(rect):
if rect == simulator_rect:
# Do simulations stuff!
print('Simulating!')
elif rect == quiz_rect:
# Do quizzing stuff!
print('Quizzing!')
elif rect == quit_rect:
# Quit!
done = True
Final code :
import pygame
pygame.init()
screen = pygame.display.set_mode((800, 600))
done = False
x = 30
y = 30
clock = pygame.time.Clock()
# RGB values for red
red = (255, 0 ,0)
# Your three button rects :
simulator_rect = pygame.Rect(225, 125, 30, 30)
quiz_rect = pygame.Rect(600, 125, 30, 30)
quit_rect = pygame.Rect(375, 425, 30, 30)
# These represent your three option rects
option_rects = [simulator_rect, quiz_rect, quit_rect]
# Your blue selector rect
selector_rect = pygame.Rect(50, 50, 60, 60)
# The 50, 50 xy coords are temporary
while not done:
for event in pygame.event.get():
if event.type == pygame.QUIT:
done = True
pressed = pygame.key.get_pressed()
if pressed[pygame.K_UP] and y > 0: y -= 5
if pressed[pygame.K_DOWN] and y < 600 - 60: y += 5
if pressed[pygame.K_LEFT] and x > 0: x -= 5
if pressed[pygame.K_RIGHT] and x < 800 - 60: x += 5
# Set the slector rect's coords to x/y
selector_rect.x, selector_rect.y = x, y
screen.fill((0, 0, 0))
color = (0, 128, 255)
pygame.draw.rect(screen, color, selector_rect)
myfont = pygame.font.SysFont("monospace", 15)
label = myfont.render("Start the experiment simulator", 1, (255,255,255))
screen.blit(label, (100, 100))
label2 = myfont.render("Start the quiz", 1, (255,255,255))
screen.blit(label2, (550, 100))
label3 = myfont.render("Quit game", 1, (255,255,255))
screen.blit(label3, (350, 400))
# Use our created rects
pygame.draw.rect(screen, red, simulator_rect)
pygame.draw.rect(screen, red, quiz_rect)
pygame.draw.rect(screen, red, quit_rect)
# Check to see if the user presses the enter key
if pressed[pygame.K_RETURN]:
# Check to see if the selection rect
# collides with any other rect
for rect in option_rects:
# Add rects as needed
if selector_rect.colliderect(rect):
if rect == simulator_rect:
# Do simulations stuff!
print('Simulating!')
elif rect == quiz_rect:
# Do quizzing stuff!
print('Quizzing!')
elif rect == quit_rect:
# Quit!
done = True
pygame.display.flip()
clock.tick(60)
This does add some complication to your program, but at least it's a rock solid method that you can add features too, and that will remain robust.
Answer to my own question, I managed to make my first attempt work by adding brackets around the x and y checks in this section:
and x >= 375 or x <= 405 and y >=425 or y <= 455:
So that it now reads:
and (x >= 375 and x <= 405) and (y >= 425 and y <= 455):
I just create a system for interactable object and it easy to scale.
listBox = [] # this list used to store all object inside
listBox.append(("text", pos, size, bgColor, textColor, InteractAction))
# add dumy object to the list, "text" can be empty if you dont want.
def InteractAction(mousePos): # sample action used to tie to object
print("do somehthing")
def newDrawBox(IableO):
pygame.draw.rect(gameDisplay, IableO[3],(IableO[1][0], IableO[1][1], IableO[2][0], IableO[2][1]))
text = basicfont.render(str(IableO[0]), True,IableO[4], None)
textrect = text.get_rect()
textrect.centerx = IableO[1][0] + IableO[2][0] / 2
textrect.centery = IableO[1][1] + IableO[2][1] / 2
gameDisplay.blit(text, textrect)
while not gameExit:
for event in pygame.event.get():
if event.type == pygame.QUIT:
gameExit = True
elif event.type == pygame.MOUSEBUTTONDOWN:
Mouse[event.button] = 1
Mouse[0] = (event.pos[0], event.pos[1])
elif event.type == pygame.MOUSEBUTTONUP:
Mouse[event.button] = 0
Mouse[0] = (event.pos[0], event.pos[1])
#-------- check if mouse is click on any object in the list of Interatable object
if Mouse[1] == 1:
for x in listBox:
if x[1][0] < Mouse[0][0] < x[1][0] + x[2][0] and x[1][1] < Mouse[0][1] < x[1][1] + x[2][1]:
x[5](Mouse[0])
#---- draw all object -----
for x in listBox:
newDrawBox(x)

Categories

Resources