Как очистить игровой экран и перейти на новую сцену при нажатии «play» - PullRequest
2 голосов
/ 02 апреля 2019

Я не знаю, как использовать функцию кнопок, чтобы либо наложить background.jpg поверх кнопок, либо стереть текущий экран и вернуть фон на место после очистки сцены.

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

Как видите операция:

if button == buttons[0]:
screen.fill(0,0,0)

Это то, с чем я сейчас работаю. Оператор if работает нормально, и я проверил его обратную связь с операциями печати, но я не могу работать с функциями Pygame.

Ответы [ 2 ]

1 голос
/ 02 апреля 2019

Проблема вызвана

screen.fill(0,0,0)

, поскольку предполагается, что 2-й параметр, равный pygame.Surface.fill(), представляет собой прямоугольник (например, pygame.Rect), который ограничивает заливку определенной областью.

Первым параметром pygame.Surface.fill() должна быть последовательность RGB, последовательность RGBA или индекс цвета.

Так должно быть

screen.fill( (0,0,0) )

или

screen.fill(0)

Кнопки все еще они, потому что они отображаются непрерывно в каждом кадре:

for text, rect, colour, button_id in buttons:
    pygame.draw.rect(screen, colour, rect)
    screen.blit(text, rect)

Добавить глобальную переменную состояния (play), которая устанавливается при нажатии кнопки воспроизведения. Измените состояние в функции on_button, используйте оператор global , чтобы изменить значение глобальной переменной play. Нарисуйте сцену в зависимости от состояния:

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)
0 голосов
/ 02 апреля 2019

Чтобы прямо ответить на вопрос:

if button[1].collidepoint(event.pos):
    on_button(button)
if button == buttons[0]:
    screen.fill(0,0,0)

Проверьте ваши отступы. Для каждой кнопки код проверяет .collidepoint и, возможно, вызывает on_button, а затем проверяет, какая кнопка проверяется - независимо от результата .collidepoint .

if button[1].collidepoint(event.pos):
    on_button(button)
    if button == buttons[0]:
        screen.fill(0,0,0)

Теперь screen.fill происходит только в том случае, если оба условия выполняются - то есть проверяемая кнопка - buttons[0], а event.pos (то есть место, где пользователь нажал) находится внутри этой кнопки.


Но чтобы справиться с проблемой - вам действительно нужно использовать что-то более сложное для представления своих кнопок. По сути, мы хотели бы, чтобы код on_button принимал решение о том, что будет сделано при нажатии кнопки, в зависимости от того, какая это кнопка. Чтобы это работало гладко, информация buttons должна содержать что-то, что говорит on_button, что делать.

Python позволяет нам сделать хитрый трюк: имена вещей являются просто именами, даже если именуемая вещь является функцией - и это означает, например, что мы можем поместить эти имена в список, а затем извлечь их и использовать их для вызова функции. Например, если бы у нас была функция, которая объясняет, что должна делать кнопка Play:

def do_play():
    # up to you ;)

И затем установите кнопку для сохранения этого имени вместо идентификатора кнопки:

play_button = [text1, rect1, BACKGROUND, do_play]

Теперь мы можем с помощью on_button выяснить это:

def on_button(button):
    button[3]()

Когда тест .collidepoint проходит для этой кнопки, он передается в on_button, который ищет имя функции do_play и вызывает эту функцию. Просто:)

(Следующим уровнем сложности является использование класса для представления информации о кнопке вместо простого списка.)

Вы также можете найти здесь несколько полезных идей:

Как сделать кнопки в python / pygame?

https://www.pygame.org/tags/button

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...