Reputation: 172
I dont know how I can use my button function to either overlay the background.jpg back over the buttons or wipe the current screen and put the background back in place after the scene has been cleared.
import pygame
pygame.init()
screen = pygame.display.set_mode((800, 600))
clock = pygame.time.Clock()
BLACK = (0, 0, 0)
BACKGROUND = (200, 230, 234)
WHITE = (255, 255, 255)
HOVER_COLOUR = (50, 70, 90)
# Text Variables
FONT = pygame.font.SysFont ("Times New Norman", 60)
TEXT = FONT.render ("", True, WHITE)
background_images = pygame.image.load("background.jpg").convert()
screen.blit(background_images, [0,0])
screen.blit(TEXT, (150, 50))
# Text & Rectangles construction
text1 = FONT.render("PlAY", True, WHITE)
text2 = FONT.render("CONTROLS", True, WHITE)
text3 = FONT.render("DIFFICULTY", True, WHITE)
text4 = FONT.render("SCOREBOARD", True, WHITE)
rect1 = pygame.Rect(250,200,300,80)
rect2 = pygame.Rect(250,300,300,80)
rect3 = pygame.Rect(250,400,300,80)
rect4 = pygame.Rect(250,500,300,80)
# The button construction arry. Text and Rectangle
buttons = [
[text1, rect1, BACKGROUND, 1],
[text2, rect2, BACKGROUND, 2],
[text3, rect3, BACKGROUND, 3],
[text4, rect4, BACKGROUND, 4],
]
# Function for button printing (testing)
def on_button(buttons):
print(buttons[3])
def game_intro():
while True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
return
elif event.type == pygame.MOUSEMOTION:
for button in buttons:
# Uses collisionpoint to detect mouse position collisions
if button[1].collidepoint(event.pos):
# Set the button's colour to the hover colour.
button[2] = HOVER_COLOUR
else:
# resets the colour to normal.
button[2] = BACKGROUND
# Button Controls
elif event.type == pygame.MOUSEBUTTONDOWN:
for button in buttons:
# Uses collisionpoint to detect mouse position collisions
if button[1].collidepoint(event.pos):
on_button(button)
if button == buttons[0]:
screen.fill(0,0,0)
# Draws the buttons with their current colours (normal & collisions)
for text, rect, colour, button_id in buttons:
pygame.draw.rect(screen, colour, rect)
screen.blit(text, rect)
pygame.display.flip()
clock.tick(15)
#Run Game
game_intro()
pygame.quit()
As you can see the operation:
if button == buttons[0]:
screen.fill(0,0,0)
Is what im currently working with. The if statement works fine and iv tested its feedback with print operations but i cannot work it with Pygame functions.
Upvotes: 2
Views: 456
Reputation: 210978
The issue is caused by
screen.fill(0,0,0)
because the 2nd parameter to pygame.Surface.fill()
is assumed to be a rectangle (e.g. pygame.Rect
), which limits the fill to a specific area.
The 1st parameter to pygame.Surface.fill()
has to be a RGB sequence, RGBA sequence or a color index.
So it has to be
screen.fill( (0,0,0) )
or
screen.fill(0)
The buttons are still they, because they are drawn continuously in every frame:
for text, rect, colour, button_id in buttons: pygame.draw.rect(screen, colour, rect) screen.blit(text, rect)
Add a global state variable (play
) which is set when the play button is pressed. Change the state in the function on_button
, use the global
statement to change the value of the globale variable play
. Draw the scene dependent on the state:
play = False
def on_button(buttons):
global play
play = buttons[3] == 1
print(buttons[3], play)
def game_intro():
# [...]
if play:
screen.fill(0)
# [...]
else:
for text, rect, colour, button_id in buttons:
pygame.draw.rect(screen, colour, rect)
screen.blit(text, rect)
pygame.display.flip()
clock.tick(15)
Upvotes: 1
Reputation: 61527
To directly answer the question:
if button[1].collidepoint(event.pos):
on_button(button)
if button == buttons[0]:
screen.fill(0,0,0)
Check your indentation. For each button, the code does the .collidepoint
check and possibly calls on_button
, and then it also checks which button is being examined - regardless of the .collidepoint
result.
if button[1].collidepoint(event.pos):
on_button(button)
if button == buttons[0]:
screen.fill(0,0,0)
Now the screen.fill
only happens if both conditions are true - i.e. the button being examined is buttons[0]
, and the event.pos
(i.e., the place where the user clicked) is inside that button.
But to deal with the problem - you really should use something more sophisticated to represent your buttons. Basically, what we would like to happen is for the on_button
code to make the decision of what is done when the button is clicked, according to which button it is. To make that work smoothly, the buttons
info needs to include something that tells on_button
what to do.
Python allows us to do a neat trick here: names of things are just names, even if the thing being named is a function - and that means, for example, that we can put those names in a list, and then pull them out and use them to call the function. For example, if we had a function that explains what the Play button should do:
def do_play():
# up to you ;)
And then set up the button to store that name, instead of a button ID:
play_button = [text1, rect1, BACKGROUND, do_play]
Now we can have on_button figure it out for us:
def on_button(button):
button[3]()
When the .collidepoint
test passes for that button, it gets passed to on_button
, which looks up the function name do_play
and calls that function. Simple :)
(The next level of sophistication is to use a class to represent the Button information instead of a plain list.)
You might also find some useful ideas here:
How to make buttons in python/pygame?
https://www.pygame.org/tags/button
Upvotes: 0