Pygame not drawing rectangle while clicking - python

I am new to pygame I am making a simple game. In this code, I am trying to draw a rectangle when the mouse is at a certain position but it is not drawing it works when I print anything
import pygame
pygame.init()
res = (600,600)
screen = pygame.display.set_mode(res)
pygame.display.set_caption("Tic Tac Toe")
background = (255,150,150)
color_light = (170,170,170)
color_dark = (100,100,100)
hover_color = (255, 204, 203)
width = screen.get_width()
height = screen.get_height()
def draw_line():
pygame.draw.rect(screen, line_color, (190,10,10,580))
pygame.draw.rect(screen, line_color, (390, 10, 10, 580))
pygame.draw.rect(screen, line_color, (10, 200, 580, 10))
pygame.draw.rect(screen, line_color, (10, 390, 580, 10))
def highlight():
if 10 <= mouse[0] <= 10+180 and 10 <= mouse[1] <= 10+190:
pygame.draw.rect(screen, hover_color, (10, 10, 180, 190)) # X,Y,WIDTH,HEIGHT
if 205 <= mouse[0] <= 205+180 and 10 <= mouse[1] <= 10+190:
pygame.draw.rect(screen, hover_color, (200, 10, 190, 190)) # X,Y,WIDTH,HEIGHT
if 400 <= mouse[0] <= 400+190 and 10 <= mouse[1] <= 10+190:
pygame.draw.rect(screen, hover_color, (400, 10, 190, 190)) # X,Y,WIDTH,HEIGHT
if 10 <= mouse[0] <= 10+180 and 210 <= mouse[1] <= 210+180:
pygame.draw.rect(screen, hover_color, (10, 210, 180, 180)) # X,Y,WIDTH,HEIGHT
if 200 <= mouse[0] <= 200+180 and 210 <= mouse[1] <= 210+180:
pygame.draw.rect(screen, hover_color, (200, 210, 200, 180)) # X,Y,WIDTH,HEIGHT
if 400 <= mouse[0] <= 400+190 and 210 <= mouse[1] <= 210+180:
pygame.draw.rect(screen, hover_color, (400, 210, 190, 180)) # X,Y,WIDTH,HEIGHT
if 10 <= mouse[0] <= 10+180 and 400 <= mouse[1] <= 400+200:
pygame.draw.rect(screen, hover_color, (10, 400, 180, 190)) # X,Y,WIDTH,HEIGHT
if 200 <= mouse[0] <= 200+190 and 400 <= mouse[1] <= 400+200:
pygame.draw.rect(screen, hover_color, (200, 400, 190, 190)) # X,Y,WIDTH,HEIGHT
if 400 <= mouse[0] <= 400+190 and 400 <= mouse[1] <= 400+190:
pygame.draw.rect(screen, hover_color, (400, 400, 190, 190)) # X,Y,WIDTH,HEIGHT
while True:
screen.fill(background)
mouse = pygame.mouse.get_pos()
for ev in pygame.event.get():
if ev.type == pygame.QUIT:
pygame.quit()
if ev.type == pygame.MOUSEBUTTONDOWN:
if 10 <= mouse[0] <= 10 + 180 and 10 <= mouse[1] <= 10 + 190:
pygame.draw.rect(screen,background,(10,10,180,190))
pygame.display.update()
line_color = (212, 212, 255)
draw_line()
highlight()
pygame.display.update()

To make the rectangle permanent, you need to draw the rectangle in the application loop. The event occurs only once in a single frame. Add a variable clicked = False. Set the variable when the event occurs. And draw the rectangle dependent on the state of the variable:
clicked = False
while True:
screen.fill(background)
mouse = pygame.mouse.get_pos()
for ev in pygame.event.get():
if ev.type == pygame.QUIT:
pygame.quit()
if ev.type == pygame.MOUSEBUTTONDOWN:
if 10 <= mouse[0] <= 10 + 180 and 10 <= mouse[1] <= 10 + 190:
clicked = True
line_color = (212, 212, 255)
draw_line()
highlight()
if clicked:
pygame.draw.rect(screen,background,(10,10,180,190))
pygame.display.update()
Simplify your code:
Create a list of pygame.Rect objects for the rectangles
rect_list = [pygame.Rect(10, 10, 180, 190), ...]
Create a list for the stated of the fields
clicked_list = [0 for _ in rect_list]
Use collideponit to test if the mouse is on a rectangle:
for rect in rect_list:
if rect.collidepoint(mouse):
pygame.draw.rect(screen, hover_color, rect)
Use collidepoint to evaluate whether a field is clicked and to change the state of the field
if ev.type == pygame.MOUSEBUTTONDOWN:
for i, rect in enumerate(rect_list):
if rect.collidepoint(ev.pos):
clicked_list[i] = 1
Draw the field in a loop depending on its state:
for i, rect in enumerate(rect_list):
if clicked_list[i]:
pygame.draw.rect(screen,background,rect)
Complete code:
import pygame
pygame.init()
res = (600,600)
screen = pygame.display.set_mode(res)
pygame.display.set_caption("Tic Tac Toe")
background = (255,150,150)
color_light = (170,170,170)
color_dark = (100,100,100)
hover_color = (255, 204, 203)
width = screen.get_width()
height = screen.get_height()
def draw_line():
pygame.draw.rect(screen, line_color, (190,10,10,580))
pygame.draw.rect(screen, line_color, (390, 10, 10, 580))
pygame.draw.rect(screen, line_color, (10, 200, 580, 10))
pygame.draw.rect(screen, line_color, (10, 390, 580, 10))
rect_list = [
pygame.Rect(10, 10, 180, 190),
pygame.Rect(200, 10, 180, 190),
pygame.Rect(400, 10, 180, 190),
pygame.Rect(10, 210, 180, 190),
pygame.Rect(200, 210, 180, 190),
pygame.Rect(400, 210, 180, 190),
pygame.Rect(10, 400, 180, 190),
pygame.Rect(200, 400, 180, 190),
pygame.Rect(400, 400, 180, 190)]
clicked_list = [0 for _ in rect_list]
def highlight():
for rect in rect_list:
if rect.collidepoint(mouse):
pygame.draw.rect(screen, hover_color, rect)
while True:
mouse = pygame.mouse.get_pos()
for ev in pygame.event.get():
if ev.type == pygame.QUIT:
pygame.quit()
if ev.type == pygame.MOUSEBUTTONDOWN:
for i, rect in enumerate(rect_list):
if rect.collidepoint(ev.pos):
clicked_list[i] = 1
line_color = (212, 212, 255)
screen.fill(background)
draw_line()
highlight()
for i, rect in enumerate(rect_list):
if clicked_list[i] == 1:
pygame.draw.rect(screen,background,rect)
pygame.display.update()

Related

how to get position of touch from pygame.FINGERDOWN in android? [duplicate]

Game Target is for android device.
When i add the buttons, they seem only to work one at a time, how can i make it so more button could work?
Here's the function:
def button_move(player_car):
pressed = pygame.mouse.get_pressed()
pos = pygame.mouse.get_pos()
moved = False
if pressed[0] == 1:
if 300 < pos[0] < 400 and 800 < pos[1] < 900:
player_car.move_forward()
moved = True
if 300 < pos[0] < 400 and 1100 < pos[1] < 1200:
player_car.move_backward()
moved = True
if 100 < pos[0] < 200 and 950 < pos[1] < 1050:
player_car.rotate(left=True)
if 500 < pos[0] < 600 and 950 < pos[1] < 1050:
player_car.rotate(right=True)
if not moved:
player_car.reduce_speed()
[...] they seem only to work one at a time [...]"
You only have one mouse. You have to use the "touch" events. Use the FINGERDOWN and FINGERUP event. Store the position of the finger into a dictionary when a FINGERDOWN event occurs and remove it on FINGERUP:
fingers = {}
run = True
while run:
clock.tick(60)
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
if event.type == pygame.FINGERDOWN:
x = event.x * window.get_height()
y = event.y * window.get_width()
fingers[event.finger_id] = x, y
if event.type == pygame.FINGERUP:
fingers.pop(event.finger_id, None)
# [...]
Use the positions to detect if a button is touched. Use pygame.Rect and pygame.Rect.collidepoint for the "touch" detection. e.g.:
rect = pygame.Rect(300, 800, 100, 100)
touched = False
for finger, pos in fingers.items():
if rect.collidepoint(pos):
touched = True
Minimal example:
import pygame
pygame.init()
window = pygame.display.set_mode((300, 300))
clock = pygame.time.Clock()
buttons = [
pygame.Rect(25, 25, 100, 100),
pygame.Rect(175, 25, 100, 100),
pygame.Rect(25, 175, 100, 100),
pygame.Rect(175, 175, 100, 100)]
colors = [(64, 0, 0), (64, 64, 0), (0, 64, 0), (0, 0, 64)]
colorsH = [(255, 0, 0), (255, 255, 0), (0, 255, 0), (0, 0, 255)]
fingers = {}
run = True
while run:
clock.tick(60)
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
if event.type == pygame.FINGERDOWN:
x = event.x * window.get_height()
y = event.y * window.get_width()
fingers[event.finger_id] = x, y
if event.type == pygame.FINGERUP:
fingers.pop(event.finger_id, None)
highlight = []
for i, rect in enumerate(buttons):
touched = False
for finger, pos in fingers.items():
if rect.collidepoint(pos):
touched = True
highlight.append(touched)
# the same with list comprehensions
#highlight = [any(r.collidepoint(p) for _, p in fingers.items()) for _, r in enumerate(buttons)]
window.fill(0)
for rect, color, colorH, h in zip(buttons, colors, colorsH, highlight):
c = colorH if h else color
pygame.draw.rect(window, c, rect)
pygame.display.flip()
pygame.quit()
exit()

pygame display not changing

I'm trying to write my first game in pygame and successfully made a title screen, but can't find a way to make the 'play' button take the user to the actual gameplay. I have a function dedicated to the title screen, and when the user clicks the play button it stops the title screen loop and starts the gameplay loop, although the gameplay loop code doesn't work. The title screen just freezes and the game doesn't start. I also have never used Stack overflow so I'll just paste my code here I guess:
import sys
import random
pygame.init()
# title
game_title = 'GAME-TITLE'
# set display
win = pygame.display.set_mode((750, 500))
pygame.display.set_caption(game_title)
# load images
cloud = pygame.image.load('999-cloud-clipart-free-download-transparent-png-cloud-clipart-cloud-clipart-transparent-1044_592.png')
cloud = pygame.transform.scale(cloud, (128, 72))
# clock
clock = pygame.time.Clock()
# font
pygame.font.init()
font = pygame.font.SysFont('verdanaboldttf', 60)
font_2 = pygame.font.SysFont('timesnewromanttf', 30)
# colors
red = (255, 0, 0)
blue = (0, 0, 255)
green = (0, 255, 0)
white = (255, 255, 255)
light_blue = (173, 216, 230)
blue = (48, 131, 159)
navy = (0, 0, 200)
black = (0, 0, 0)
# clouds
cloud_values = []
i = 0
while i < 10:
cloud_values.append([random.randint(-750, -80), random.randint(-50, 550)])
i += 1
def title_screen():
run_title = True
run = True
show_help = False
play_game = False
while run_title:
clock.tick(10)
pygame.draw.rect(win, light_blue, pygame.Rect(-100, -100, 1000, 1000))
play_button = pygame.draw.rect(win, blue, pygame.Rect(150, 175, 450, 75))
help_button = pygame.draw.rect(win, blue, pygame.Rect(150, 275, 450, 75))
quit_button = pygame.draw.rect(win, blue, pygame.Rect(150, 375, 450, 75))
text = font_2.render('PLAY', True, white)
text_2 = font_2.render('HELP', True, white)
text_3 = font_2.render('QUIT', True, white)
title = font.render(game_title, True, navy)
win.blit(text, (340, 197))
win.blit(text_2, (340, 297))
win.blit(text_3, (340, 397))
win.blit(title, (165, 60))
for i in range(len(cloud_values)):
win.blit(cloud, (cloud_values[i][0], cloud_values[i][1]))
cloud_values[i][0] += 10
if cloud_values[i][0] > 760:
cloud_values[i][0] = random.randint(-750, -80)
keys = pygame.key.get_pressed()
if keys[pygame.K_ESCAPE]:
run = False
pos = pygame.mouse.get_pos()
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
if event.type == pygame.MOUSEBUTTONUP:
pos = pygame.mouse.get_pos()
if pos[0] > 150 and pos[0] < 600 and pos[1] > 175 and pos[1] < 250:
play_game = True
elif pos[0] > 150 and pos[0] < 600 and pos[1] > 275 and pos[1] < 375:
show_help = True
elif pos[0] > 150 and pos[0] < 600 and pos[1] > 375 and pos[1] < 450:
run = False
if pos[0] > 150 and pos[0] < 600 and pos[1] > 175 and pos[1] < 250:
pygame.draw.rect(win, blue, pygame.Rect(145, 170, 460, 85))
win.blit(text, (340, 197))
elif pos[0] > 150 and pos[0] < 600 and pos[1] > 275 and pos[1] < 375:
pygame.draw.rect(win, blue, pygame.Rect(145, 270, 460, 85))
win.blit(text_2, (340, 297))
elif pos[0] > 150 and pos[0] < 600 and pos[1] > 375 and pos[1] < 450:
pygame.draw.rect(win, blue, pygame.Rect(145, 370, 460, 85))
win.blit(text_3, (340, 397))
if play_game or show_help or not run:
run_title = False
pygame.display.flip()
return run_title, play_game, run, show_help
def game_play():
run_game = True
run = True
x = 10
while run_game:
# set new background
pygame.draw.rect(win, light_blue, pygame.Rect(-100, -100, 1000, 1000))
# run gameplay here
return run
def show_help_screen():
show_help = True
while show_help:
pygame.draw.rect(win, light_blue, pygame.Rect(-100, -100, 1000, 1000))
# show help_screen
def show_results_screen():
run = False
show_results = True
while show_results:
pygame.draw.rect(win, light_blue, pygame.Rect(-100, -100, 1000, 1000))
# show results
return run
def run_game(run_title, play_game, run, show_help):
run = True
while run:
if play_game:
game_play()
show_results = True
elif show_help:
show_help_screen()
run_title = True
elif show_results:
run = show_results_screen()
pygame.quit()
sys.exit()
run_title, play_game, run, show_help = title_screen()
run_game(run_title, play_game, run, show_help)```
I went through your code, and I haven't seen an update once.
So since it's your first here's a quick lesson:
when there is any movement, any changes, anything that is changing on your window it won't show up unless you update it, using:
pygame.display.update()
or
pygame.display.flip()
When outputting things, think of them as layers, if you output one image, and then a second image. The first image won't show.
(That's if they are the same size but you know what I mean.)

Start screen won't work how to fix problem?

The issue that I am having is every time I run my game the start screen won't work right, for example, all click on the GO button and it won't let me start my game yet everything seems correct and in place, if anyone can please help it would very much be appreciated
import pygame, random
from time import sleep
pygame.init()
# music/sounds
CarSound = pygame.mixer.Sound("image/CAR+Peels+Out.wav")
CarSound_two = pygame.mixer.Sound("image/racing01.wav")
CarSound_three = pygame.mixer.Sound("image/RACECAR.wav")
CarSound_four = pygame.mixer.Sound("image/formula+1.wav")
Crowds = pygame.mixer.Sound("image/cheer_8k.wav")
Crowds_two = pygame.mixer.Sound("image/applause7.wav")
Crowds_three = pygame.mixer.Sound("image/crowdapplause1.wav")
music = pygame.mixer.music.load("image/Led Zeppelin - Rock And Roll (Alternate Mix) (Official Music Video).mp3")
pygame.mixer.music.play(-1)
bg = pygame.image.load('image/Crowds.png')
clock = pygame.time.Clock()
# Setting up our colors that we are going to use
GREEN = (20, 255, 140)
GREY = (210, 210, 210)
WHITE = (255, 255, 255)
RED = (255, 0, 0)
PURPLE = (255, 0, 255)
BLACKWHITE = (96, 96, 96)
BLACK = (105, 105, 105)
RGREEN = (0, 66, 37)
LIGHT_RED = (200, 0, 0)
BRIGHT_GREEN = (0, 255, 0)
DARK_BLUE = (0, 0, 139)
BLUE = (0, 0, 255)
NAVY = (0, 0 , 128)
DARK_OLIVE_GREEN = (85, 107, 47)
YELLOW_AND_GREEN = (154, 205, 50)
SCREENWIDTH = 400
SCREENHEIGHT = 500
size = (SCREENWIDTH, SCREENHEIGHT)
screen = pygame.display.set_mode(size)
pygame.display.set_caption("Car Racing")
Icon = pygame.image.load("image/redca_iconr.png")
pygame.display.set_icon((Icon))
# This will be a list that will contain all the sprites we intend to use in our game.
# all_sprites_list = pygame.sprite.Group()
# player
playerIMG = pygame.image.load("image/red_racecar.png")
playerX = 280
playerY = 450
playerCar_position = 0
# player2
playerIMG_two = pygame.image.load("image/greencar.png")
playerX_two = 150
playerY_two = 450
playerCar_position_two = 0
# player3
playerIMG_three = pygame.image.load("image/Orangecar.png")
playerX_three = 60
playerY_three = 450
playerCar_position_three = 0
# player4
playerIMG_four = pygame.image.load("image/yellowcar2.png")
playerX_four = 210
playerY_four = 450
playerCar_position_four = 0
# Putting cars to the screen
def player(x, y):
screen.blit(playerIMG, (x, y))
def player_two(x, y):
screen.blit(playerIMG_two, (x, y))
def player_three(x, y):
screen.blit(playerIMG_three, (x, y))
def player_four(x, y):
screen.blit(playerIMG_four, (x, y))
finish_text = ""
font2 = pygame.font.SysFont("Papyrus", 65)
players_finished = 0
placings = ["1st", "2nd", "3rd", "4th"]
smallfont = pygame.font.SysFont("Papyrus", 15)
normalfont = pygame.font.SysFont("arial", 25)
differntfont = pygame.font.SysFont("futura", 25)
def score(score):
text = smallfont.render("Race cars passing: " + str(score), True, RGREEN)
screen.blit(text, [145, 490])
def text_objects(text, font):
textSurface = font.render(text, True, BLACK)
return textSurface, textSurface.get_rect()
def message_display(text):
largText = pygame.font.Font("Mulish-Regular.ttf", 15)
TextSurf, TextRect = text_objects(text, largText)
TextRect.center = ((SCREENWIDTH / 1), (SCREENHEIGHT / 1))
screen.blit(TextSurf, TextRect)
text_two = normalfont.render("Start new game?", 5, (0, 66, 37))
time_to_blit = None
screen.blit(bg, (0, 0))
pygame.display.flip()
Here is my button the Quit button works fine its just the GO button that when pressed won't let me start my game my only guess could be unless I placed something in the wrong place?
def button(msg, x, y, w, h, iC, aC, action=None):
mouse = pygame.mouse.get_pos()
click = pygame.mouse.get_pressed()
print(click)
if x + w > mouse[0] > x and y + h > mouse[1] > y:
pygame.draw.rect(screen, iC, (x , y, w, h))
if click[0] == 1 and action != None:
if action == "Play":
game_loop()
elif action == "Quit":
pygame.quit()
quit()
else:
pygame.draw.rect(screen, aC, (x , y, w, h))
if 260 + 100 > mouse[0] > 260 and 40 + 50 > mouse[1] > 40:
pygame.draw.rect(screen, BLUE, (260, 40, 100, 50))
else:
pygame.draw.rect(screen, DARK_BLUE, (260, 40, 100, 50))
newtext = pygame.font.SysFont("arial", 25)
textSurf, textReact = text_objects(msg, newtext)
textReact.center = ((x + (100 / 2))), (y + (h / 2))
screen.blit(textSurf, textReact)
newtext = pygame.font.SysFont("arial", 25)
textSurf, textReact = text_objects("QUIT!", newtext)
textReact.center = ((260 + (100 / 2))), (40 + (50 / 2))
screen.blit(textSurf, textReact)
def game_intro():
intro = True
while intro:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
quit()
screen.fill(YELLOW_AND_GREEN)
text = normalfont.render("Super Racer!", 8, (0, 66, 37))
screen.blit(text, (165 - (text.get_width() / 5), 100))
button("GO!", 60, 40, 100, 50, RED, LIGHT_RED, "Play")
button("QUIT!", 260, 40, 100, 50, BLUE, DARK_BLUE, "Quit")
pygame.display.update()
clock.tick(15)
# Main game loop
def game_loop():
run = True
while run:
# Drawing on Screen
screen.fill(BLACK)
# Draw The Road
pygame.draw.rect(screen, GREY, [40, 0, 300, 500])
# Draw Line painting on the road
pygame.draw.line(screen, WHITE, [185, 0], [185, 500], 5)
# Finish line
pygame.draw.rect(screen, BLACKWHITE, [50, 50, 280, 40])
pygame.draw.line(screen, WHITE, [50, 70], [330, 70], 5)
font = pygame.font.SysFont("Impact", 20)
text = font.render("Finish line!", 2, (150, 50, 25))
screen.blit(text, (185 - (text.get_width() / 2), 45))
screen.blit(bg, (-236, -34))
screen.blit(bg, (-236, -5))
screen.blit(bg, (-235, 140))
screen.blit(bg, (-235, 240))
screen.blit(bg, (-235, 340))
screen.blit(bg, (340, -60))
screen.blit(bg, (340, -60))
screen.blit(bg, (335, 5))
screen.blit(bg, (335, 130))
screen.blit(bg, (335, 230))
screen.blit(bg, (335, 330))
screen.blit(bg, (333, 330))
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
# Number of frames per secong e.g. 60
clock.tick(60)
keys = pygame.key.get_pressed()
if keys[pygame.K_1]:
CarSound.play()
playerCar_position = -0.5
if keys[pygame.K_q]:
playerCar_position = 0.5
if keys[pygame.K_2]:
CarSound_two.play()
playerCar_position_two = -0.5
if keys[pygame.K_w]:
playerCar_position_two = 0.5
if keys[pygame.K_3]:
CarSound_three.play()
playerCar_position_three = -0.5
if keys[pygame.K_e]:
playerCar_position_three = 0.5
if keys[pygame.K_4]:
CarSound_four.play()
playerCar_position_four = -0.5
if keys[pygame.K_r]:
playerCar_position_four = 0.5
# our functions
playerY += playerCar_position
playerY_two += playerCar_position_two
playerY_three += playerCar_position_three
playerY_four += playerCar_position_four
player(playerX, playerY)
player_two(playerX_two, playerY_two)
player_three(playerX_three, playerY_three)
player_four(playerX_four, playerY_four)
finish_line_rect = pygame.Rect(50, 70, 235, 32)
game_intro()
score(players_finished)
# Did anyone cross the line?
if (finish_line_rect.collidepoint(playerX, playerY)):
if finish_text[:8] != "Player 1": # so it doesnt do this every frame the car is intersecting
inish_text = "Player 1 is " + placings[players_finished]
players_finished += 1
print("Player (one) has crossed into finish line!")
Crowds.play()
elif (finish_line_rect.collidepoint(playerX_two, playerY_two)):
if finish_text[:8] != "Player 2":
print("Player one has crossed into finish line first other car lost!")
finish_text = "Player 2 is " + placings[players_finished]
players_finished += 1
Crowds_three.play()
elif (finish_line_rect.collidepoint(playerX_three, playerY_three)):
if finish_text[:8] != "Player 3":
print("Player two has crossed into finish line first other car lost!")
finish_text = "Player 3 is " + placings[players_finished]
players_finished += 1
elif (finish_line_rect.collidepoint(playerX_four, playerY_four)):
if finish_text[:8] != "Player 4":
print("Player two has crossed into finish line first other car lost!")
finish_text = "Player 4 is " + placings[players_finished]
players_finished += 1
Crowds_two.play()
if (players_finished and finish_text):
font = pygame.font.SysFont("Impact", 15)
text = font.render(finish_text, 5, (0, 66, 37))
screen.blit(text, (90 - (text.get_width() / 2), -2))
if (finish_text):
font = pygame.font.SysFont("Impact", 20)
text = font.render('Game Over!!!', 5, (0, 66, 37))
screen.blit(text, (250 - (text.get_width() / 5), -2))
if players_finished == 4:
time_to_blit = pygame.time.get_ticks() + 5000
if time_to_blit:
print(screen.blit(text_two, (130, 460)))
if pygame.time.get_ticks() >= time_to_blit:
time_to_blit = None
pygame.quit()
In the game loop, you're not calling the screen update. You also need to render the cars in the loop.
# Main game loop
def game_loop():
print(".......GAME LOOP........")
global playerCar_position,playerCar_position_two,playerCar_position_three,playerCar_position_four
global playerY,playerY_two,playerY_three,playerY_four,playerX,playerX_two,playerX_three,playerX_four
finish_line_rect = pygame.Rect(50, 70, 235, 32)
finish_text = ""
players_finished = 0
time_to_blit = 0
run = True
while run:
# Drawing on Screen
screen.fill(BLACK)
# Draw The Road
pygame.draw.rect(screen, GREY, [40, 0, 300, 500])
# Draw Line painting on the road
pygame.draw.line(screen, WHITE, [185, 0], [185, 500], 5)
# Finish line
pygame.draw.rect(screen, BLACKWHITE, [50, 50, 280, 40])
pygame.draw.line(screen, WHITE, [50, 70], [330, 70], 5)
font = pygame.font.SysFont("Impact", 20)
text = font.render("Finish line!", 2, (150, 50, 25))
screen.blit(text, (185 - (text.get_width() / 2), 45))
#.............
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
# Number of frames per secong e.g. 60
clock.tick(60)
keys = pygame.key.get_pressed()
if keys[pygame.K_1]:
# CarSound.play()
playerCar_position = -0.5
if keys[pygame.K_q]:
playerCar_position = 0.5
if keys[pygame.K_2]:
# CarSound_two.play()
playerCar_position_two = -0.5
if keys[pygame.K_w]:
playerCar_position_two = 0.5
if keys[pygame.K_3]:
# CarSound_three.play()
playerCar_position_three = -0.5
if keys[pygame.K_e]:
playerCar_position_three = 0.5
if keys[pygame.K_4]:
# CarSound_four.play()
playerCar_position_four = -0.5
if keys[pygame.K_r]:
playerCar_position_four = 0.5
# our functions
playerY += playerCar_position
playerY_two += playerCar_position_two
playerY_three += playerCar_position_three
playerY_four += playerCar_position_four
player(playerX, playerY)
player_two(playerX_two, playerY_two)
player_three(playerX_three, playerY_three)
player_four(playerX_four, playerY_four)
# Did anyone cross the line?
if (finish_line_rect.collidepoint(playerX, playerY)):
if finish_text[:8] != "Player 1": # so it doesnt do this every frame the car is intersecting
finish_text = "Player 1 is " + placings[players_finished]
players_finished += 1
print("Player (one) has crossed into finish line!")
# Crowds.play()
elif (finish_line_rect.collidepoint(playerX_two, playerY_two)):
if finish_text[:8] != "Player 2":
print("Player one has crossed into finish line first other car lost!")
finish_text = "Player 2 is " + placings[players_finished]
players_finished += 1
# Crowds_three.play()
elif (finish_line_rect.collidepoint(playerX_three, playerY_three)):
if finish_text[:8] != "Player 3":
print("Player two has crossed into finish line first other car lost!")
finish_text = "Player 3 is " + placings[players_finished]
players_finished += 1
elif (finish_line_rect.collidepoint(playerX_four, playerY_four)):
if finish_text[:8] != "Player 4":
print("Player two has crossed into finish line first other car lost!")
finish_text = "Player 4 is " + placings[players_finished]
players_finished += 1
# Crowds_two.play()
if (players_finished and finish_text):
print("ft:", finish_text)
font = pygame.font.SysFont("Impact", 15)
textrect = font.render(finish_text, False, (0, 66, 37))
print('x', (SCREENWIDTH - text.get_width()) / 2)
screen.blit(textrect, (0,0))
screen.blit(textrect, ((SCREENWIDTH - textrect.get_width()) // 2, -5))
if (finish_text):
font = pygame.font.SysFont("Impact", 20)
text = font.render('Game Over!!!', 5, (0, 66, 37))
screen.blit(text, (250 - (text.get_width() / 5), -2))
if players_finished == 4:
time_to_blit = pygame.time.get_ticks() + 5000
if time_to_blit:
screen.blit(text_two, (130, 460))
if pygame.time.get_ticks() >= time_to_blit:
time_to_blit = 0
pygame.display.update()
clock.tick(60)
game_intro()
score(players_finished)
pygame.quit()
Try:
if action == "Play":
game_loop()
return
I think there is something wrong with your indentation of the code. You have pygame.quit() at the global level. So, you run pygame.init(), then define some functions, then pygame.quit()
Comment out the pygame.quit() line and see what happens.

Implementing timer in pygame

I want to add timer to my game, where it starts to count from 0 when I start the game and when i touch yellow rectangle (finish line) it stops and it says in what time I finished my level. I tried to do something, but I am having trouble because "while" confuses me and I can't figure out how to get a time correctly in seconds.
Here is the code:
import pygame
import sys
import time
pygame.init()
pygame.display.set_caption("Protostar")
screen_width, screen_height = 1200, 600
screen = pygame.display.set_mode((screen_width, screen_height))
clock = pygame.time.Clock()
BLUE = pygame.Color('dodgerblue3')
ORANGE = pygame.Color('sienna3')
BLACK = (0, 0, 0)
WHITE = (255, 255, 255)
RED = (255, 0, 0)
GREEN = (13, 255, 0)
DARK_GREEN = (0, 225, 0)
BRIGHT_GREEN = (0, 255, 0)
YELLOW = (255, 255, 0)
font = pygame.font.Font(None, 25)
frame_rate = 60
image1 = pygame.image.load("/Users/xy/Desktop/menupy2.png")
class Walls(pygame.Rect):
def __init__(self, x, y, w, h):
super().__init__(x, y, w, h)
class LeftRedRect(pygame.Rect):
def __init__(self, x, y, w, h, vel):
# Calling the __init__ method of the parent class
super().__init__(x, y, w, h)
self.vel = vel
def update(self):
self.x += self.vel # Moving
if self.right > 600 or self.left < 320: # If it's not in this area
self.vel = -self.vel # Inverting the direction
class RightRedRect(pygame.Rect):
def __init__(self, x, y, w, h, vel):
super().__init__(x, y, w, h)
self.vel = vel
def update(self):
self.x += self.vel
if self.right > 1180 or self.left < 620:
self.vel = -self.vel
class UpAndDownRedRect(pygame.Rect):
def __init__(self, x, y, w, h, vel):
super().__init__(x, y, w, h)
self.vel = vel
def update(self):
self.y += self.vel
if self.top < 20 or self.bottom > 535:
self.vel = -self.vel
def quit_game():
pygame.quit()
sys.exit()
def message_display(text):
largeText = pygame.font.Font(None, 115)
screen.blit(largeText.render(text, True, BLUE), (370, 250))
pygame.display.update()
pygame.time.wait(1000)
def text_objects(text, font):
textSurface = font.render(text, True, BLACK)
return textSurface, textSurface.get_rect()
def button(msg, x, y, w, h, ic, ac, action = None):
mouse = pygame.mouse.get_pos()
click = pygame.mouse.get_pressed()
if x + w > mouse[0] > x and y + h > mouse[1] > y:
pygame.draw.rect(screen, ac, (x, y, w, h))
if click[0] == 1 and action is not None:
action()
else:
pygame.draw.rect(screen, ic, (x, y, w, h))
smallText = pygame.font.Font("freesansbold.ttf",35)
textSurf, textRect = text_objects(msg, smallText)
textRect.center = ((x+(w/2)), (y+(h/2)))
screen.blit(textSurf, textRect)
def restart():
next_scene = None
def start_game():
nonlocal next_scene
next_scene = menu
while True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
quit_game()
if next_scene is not None:
return next_scene
screen.fill(WHITE)
largeText = pygame.font.Font(None, 115)
screen.blit(largeText.render("You lost", True, BLUE), (445, 75))
button("Restart", 525, 250, 150, 60, DARK_GREEN, BRIGHT_GREEN, start_game)
button("Quit", 525, 350, 150, 60, DARK_GREEN, BRIGHT_GREEN, quit_game)
pygame.display.flip()
clock.tick(60)
def victory_screen():
next_scene = None
def start_game():
nonlocal next_scene
next_scene = menu
while True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
quit_game()
if next_scene is not None:
return next_scene
screen.fill(WHITE)
largeText = pygame.font.Font(None, 115)
screen.blit(largeText.render("Congratulations!", True, BLUE), (270, 80))
largeText = pygame.font.Font(None, 60)
screen.blit(largeText.render("You beat the game!", True, BLUE), (410, 180))
button("Restart", 525, 300, 150, 60, DARK_GREEN, BRIGHT_GREEN, start_game)
button("Quit", 525, 400, 150, 60, DARK_GREEN, BRIGHT_GREEN, quit_game)
pygame.display.flip()
clock.tick(frame_rate)
def instructions_screen():
next_scene = None
def start_game():
nonlocal next_scene
next_scene = menu
while True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
quit_game()
if next_scene is not None:
return next_scene
screen.fill(WHITE)
largeText = pygame.font.Font(None, 115)
smallText = pygame.font.Font(None, 60)
screen.blit(largeText.render("Instructions", True, BLUE), (362, 50))
screen.blit(smallText.render("Goal of the game: Reach the yellow rectangle", True, BLACK), (148, 150))
screen.blit(smallText.render("How to move: Upper arrow - up", True, BLACK), (148, 210))
screen.blit(smallText.render("Lower arrow - down", True, BLACK), (429, 250))
screen.blit(smallText.render("Left arrow - left", True, BLACK), (429, 290))
screen.blit(smallText.render("Right arrow - right", True, BLACK), (429, 330))
button("Play", 525, 430, 150, 60, DARK_GREEN, BRIGHT_GREEN, start_game)
pygame.display.flip()
clock.tick(60)
def front_page():
next_scene = None
def start_game():
nonlocal next_scene
next_scene = menu
def show_instructions_screen():
nonlocal next_scene
next_scene = instructions_screen
while True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
quit_game()
if next_scene is not None:
return next_scene
screen.fill(WHITE)
screen.blit(image1, (0,0))
largeText = pygame.font.Font(None, 140)
screen.blit(largeText.render("Protostar", True, BLUE), (389, 50))
button("Play", 525, 200, 150, 60, DARK_GREEN, BRIGHT_GREEN, start_game)
button("Quit", 525, 400, 150, 60, DARK_GREEN, BRIGHT_GREEN, quit_game)
button("Info", 525, 300, 150, 60, DARK_GREEN, BRIGHT_GREEN, show_instructions_screen)
pygame.display.flip()
clock.tick(frame_rate)
def menu():
vel = 4
vel_left = 5
vel_right = -5
vel_up = 7
player = pygame.Rect(40, 45, 30, 30)
finish_line = pygame.Rect(620, 535, 560, 45)
walls = [
Walls(0, 0, 1200, 20), Walls(0, 0, 20, 600),
Walls(0, 580, 1200, 20), Walls(1180, 0, 20, 600),
Walls(300, 0, 20, 530), Walls(20, 100, 230, 20),
Walls(70, 200, 230, 20), Walls(20, 300, 230, 20),
Walls(70, 400, 230, 20), Walls(600, 100, 20, 500)
]
leftredrects = [
LeftRedRect(320, 120, 30, 30, vel_left),
LeftRedRect(320, 240, 30, 30, vel_left),
LeftRedRect(320, 360, 30, 30, vel_left),
LeftRedRect(570, 180, 30, 30, vel_right),
LeftRedRect(570, 300, 30, 30, vel_right),
LeftRedRect(570, 420, 30, 30, vel_right)
]
rightredrects = [
RightRedRect(1140, 120, 30, 30, vel_left),
RightRedRect(1140, 240, 30, 30, vel_left),
RightRedRect(1140, 360, 30, 30, vel_left),
RightRedRect(620, 180, 30, 30, vel_right),
RightRedRect(620, 300, 30, 30, vel_right),
RightRedRect(620, 420, 30, 30, vel_right),
]
upanddownredrects = [
UpAndDownRedRect(620, 20, 30, 30, vel_up),
UpAndDownRedRect(752, 505, 30, 30, vel_up),
UpAndDownRedRect(885, 20, 30, 30, vel_up),
UpAndDownRedRect(1016, 505, 30, 30, vel_up),
UpAndDownRedRect(1150, 20, 30, 30, vel_up)
]
while True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
quit_game()
keys = pygame.key.get_pressed()
# Player coordinates
if keys[pygame.K_LEFT] and player.x > 0:
player.x -= vel
if keys[pygame.K_RIGHT] and player.x < 1200 - player.width:
player.x += vel
if keys[pygame.K_UP] and player.y > 0:
player.y -= vel
if keys[pygame.K_DOWN] and player.y < 600 - player.height:
player.y += vel
# Game logic
for wall in walls:
# Check if the player rectangle collides with a wall rectangle
if player.colliderect(wall):
print("Game over")
message_display("Game Over")
return restart
for rect in rightredrects:
rect.update() # Movement and bounds checking
if player.colliderect(rect):
print("Game over")
message_display("Game Over")
return restart
for rect in leftredrects:
rect.update()
if player.colliderect(rect):
print("Game over")
message_display("Game Over")
return restart
for rect in upanddownredrects:
rect.update()
if player.colliderect(rect):
print("Game over")
message_display("Game Over")
return restart
if player.colliderect(finish_line):
print("You beat the game")
return victory_screen
# Drawing everything
screen.fill(WHITE)
pygame.draw.rect(screen, YELLOW, finish_line)
for wall in walls:
pygame.draw.rect(screen, BLACK, wall)
for rect in rightredrects:
pygame.draw.rect(screen, RED, rect)
for rect in leftredrects:
pygame.draw.rect(screen, RED, rect)
for rect in upanddownredrects:
pygame.draw.rect(screen, RED, rect)
pygame.draw.rect(screen, GREEN, player)
pygame.display.flip()
clock.tick(60)
def main():
scene = front_page
while scene is not None:
scene = scene()
main()
pygame.quit()
I think you can use the pygame.time.get_ticks() function which returns the number of milliseconds since pygame.init() was called.
I hope it helps you.

Clicking buttons in pygame

So I have created a small menu that contains a "Start" button and a "quit" button. Obviously what I want is when I click Start, it starts the game loop, and when I hit quit, it quits the game. I already coded something, but it doesn't work. I think the problem is that I don't have a function for game loop and quit.
Here is the whole code:
import pygame
pygame.init()
win = pygame.display.set_mode((1200, 600))
pygame.display.set_caption("WALTHER")
clock = pygame.time.Clock()
BLACK = (0, 0, 0)
WHITE = (255,255,255)
RED = (255, 0, 0)
GREEN = (13, 255, 0)
YELLOW = (0, 255, 20)
BRIGHT_YELLOW = (255, 255, 20)
player = pygame.Rect(40, 45, 30, 30)
vel = 4
vel_left = 5
vel_right = -5
class MovingRect(pygame.Rect):
def __init__(self, x, y, w, h, vel):
# Call the __init__ method of the parent class.
super().__init__(x, y, w, h)
self.vel = vel
def update(self):
self.x += self.vel # Move.
if self.right > 600 or self.left < 320: # If it's not in this area.
self.vel = -self.vel # Invert the direction.
def text_objects(text, font):
textSurface = font.render(text, True, BLACK)
return textSurface, textSurface.get_rect()
def button(msg, x, y, w, h, ic, ac, action = None):
mouse = pygame.mouse.get_pos()
click = pygame.mouse.get_pressed()
if x + w > mouse[0] > x and y + h > mouse[1] > y:
pygame.draw.rect(win, ac, (x, y, w, h))
if click[0] == 1 and action != None:
if action == "Quit":
pygame.quit()
else:
pygame.draw.rect(win, ic, (x, y, w, h))
smallText = pygame.font.Font("freesansbold.ttf",50)
textSurf, textRect = text_objects(msg, smallText)
textRect.center = ((x+(w/2)), (y+(h/2)))
win.blit(textSurf, textRect)
def game_intro():
intro = True
while intro:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
win.fill(WHITE)
largeText2 = pygame.font.Font('freesansbold.ttf', 115)
TextSurf, TextRect = text_objects("Red Square", largeText2)
TextRect.center = ((600), (100))
win.blit(TextSurf, TextRect)
button("Start", 525, 250, 150, 60, YELLOW, BRIGHT_YELLOW)
button("Quit", 525, 350, 150, 60, YELLOW, BRIGHT_YELLOW)
pygame.display.update()
clock.tick(15)
def message_display(text):
largeText = pygame.font.Font(None , 115)
win.blit(largeText.render(text, True, (RED)), (370,250))
pygame.display.update()
pygame.time.wait(2000)
pygame.quit()
rotatingrects = [
pygame.Rect(630, 300, 250, 20),
pygame.Rect(920, 300, 250, 20)
]
movingrects = [
MovingRect(320, 120, 30, 30, vel_left),
MovingRect(320, 240, 30, 30, vel_left),
MovingRect(320, 360, 30, 30, vel_left),
MovingRect(570, 180, 30, 30, vel_right),
MovingRect(570, 300, 30, 30, vel_right),
MovingRect(570, 420, 30, 30, vel_right)
]
walls = [
pygame.Rect(0, 0, 1200, 20), pygame.Rect(0, 0, 20, 600),
pygame.Rect(0, 580, 1200, 20), pygame.Rect(1180, 0, 20, 600),
pygame.Rect(300, 0, 20, 530), pygame.Rect(20, 100, 230, 20),
pygame.Rect(70, 200, 230, 20), pygame.Rect(20, 300, 230, 20),
pygame.Rect(70, 400, 230, 20), pygame.Rect(600, 100, 20, 500)
]
run = True
while run:
# Handle the events.
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
game_intro()
keys = pygame.key.get_pressed()
# Update the player coordinates.
if keys[pygame.K_LEFT] and player.x > 0:
player.x -= vel
if keys[pygame.K_RIGHT] and player.x < 1200 - player.width:
player.x += vel
if keys[pygame.K_UP] and player.y > 0:
player.y -= vel
if keys[pygame.K_DOWN] and player.y < 600 - player.height:
player.y += vel
# Game logic for walls and moving objects
for wall in walls:
# Check if the player rect collides with a wall rect.
if player.colliderect(wall):
print("Game over")
message_display("Game Over")
for movingrect in movingrects:
movingrect.update() # Movement and bounds checking.
if player.colliderect(movingrect):
print("Game over")
message_display("Game Over")
for rotatingrect in rotatingrects:
if player.colliderect(rotatingrect):
print("Game over")
# Drawing everything
win.fill(WHITE)
pygame.draw.rect(win, RED, player)
# Drawing walls and moving objects
for rotatingrect in rotatingrects:
pygame.draw.rect(win, BLACK, rotatingrect)
for wall in walls:
pygame.draw.rect(win, BLACK, wall)
for movingrect in movingrects:
pygame.draw.rect(win, GREEN, movingrect)
pygame.display.update()
clock.tick(60)
pygame.quit()
I think the problem is here:
if x + w > mouse[0] > x and y + h > mouse[1] > y:
pygame.draw.rect(win, ac, (x, y, w, h))
if click[0] == 1 and action != None:
if action == "Quit":
pygame.quit()
else:
pygame.draw.rect(win, ic, (x, y, w, h))
I just want to do if action == "Start":
play the game
if action == "Quit":
quit the game
Define two callback functions which you need to pass as the action argument to the button function.
In the quit_game function, you can call pygame.quit and sys.exit to close the window. The start_game function needs to be defined in the game_intro function, because we have to access the intro variable, with the help of the nonlocal keyword, and set it to False, so that the game_intro function will be terminated and the main loop can start.
def button(msg, x, y, w, h, ic, ac, action=None):
mouse = pygame.mouse.get_pos()
click = pygame.mouse.get_pressed()
if x + w > mouse[0] > x and y + h > mouse[1] > y:
pygame.draw.rect(win, ac, (x, y, w, h))
if click[0] == 1 and action is not None:
action() # Call the callback function.
# etc. ...
def quit_game():
pygame.quit()
sys.exit() # `import sys` at the top of the file.
def game_intro():
intro = True
def start_game():
# Set the intro variable in the enclosing scope to False.
nonlocal intro
intro = False
while intro:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
win.fill(WHITE)
largeText2 = pygame.font.Font('freesansbold.ttf', 115)
TextSurf, TextRect = text_objects("Red Square", largeText2)
TextRect.center = ((600), (100))
win.blit(TextSurf, TextRect)
# Pass the two callback functions to `button`.
button("Start", 525, 250, 150, 60, YELLOW, BRIGHT_YELLOW, start_game)
button("Quit", 525, 350, 150, 60, YELLOW, BRIGHT_YELLOW, quit_game)
pygame.display.update()
clock.tick(15)
Also, don't call game_intro inside the main while loop.
game_intro()
run = True
while run:

Categories