Pthyon
Pthyon

Reputation: 172

How do I clear my game screen and move to a new scene when "play" is clicked

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

Answers (2)

Rabbid76
Rabbid76

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

Karl Knechtel
Karl Knechtel

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

Related Questions