Добавление меню с кнопками в Pygame - PullRequest
2 голосов
/ 17 января 2020

Я очень долго пытаюсь добавить меню в свою игру, но оно не появляется. Появляется экран, но он пустой и содержит только слова, но не содержит кнопок, поэтому, где бы я ни щелкал, он ведет на одну и ту же страницу. Как экран показывает, но кнопки не появляются, и я не уверен, почему. Как добавить кнопку для параметров?

background = pygame.image.load('background.png')
backgroundX = 0
backgroundX2 = background.get_width()
homeScreen = pygame.image.load('home_screen.png')
obstacle = pygame.image.load('obstacle.png')
obstacleX = 0
obstacleX2 = obstacle.get_width()
instructions = pygame.image.load('instructions.png')

# frame rate
clock = pygame.time.Clock()


# use procedure for game window rather than using it within loop
def redrawGameWindow():
    # background images for right to left moving screen
    screen.blit(background, (backgroundX, 0))
    screen.blit(background, (backgroundX2, 0))
    man.draw(screen)
    screen.blit(obstacle, (obstacleX, 400))
    screen.blit(obstacle, (obstacleX2, 400))
    pygame.display.flip()
    pygame.display.update()


# create class for character (object)
class player(object):
    def __init__(self, x, y, width, height):  # initialize attributes
        self.x = x
        self.y = y
        self.width = width
        self.height = height
        self.left = True
        self.right = True
        self.isJump = False
        self.stepCount = 0
        self.jumpCount = 10
        self.standing = True

    def draw(self, screen):
        if self.stepCount + 1 >= 27:  # 9 sprites, with 3 frames - above 27 goes out of range
            self.stepCount = 0

        if not self.standing:
            if self.left:
                screen.blit(leftDirection[self.stepCount // 5], (self.x, self.y), )
                self.stepCount += 1
            elif self.right:
                screen.blit(rightDirection[self.stepCount // 5], (self.x, self.y), )
                self.stepCount += 1
        else:
            if self.right:
                screen.blit(rightDirection[0], (self.x, self.y))  # using index, include right faced photo
            else:
                screen.blit(leftDirection[0], (self.x, self.y))


class enlargement(object):
    def __init__(self, x, y, radius, color, facing):
        self.x = x
        self.y = y
        self.radius = radius
        self.color = color
        self.facing = facing

    def draw(self, screen):
        pygame.draw.circle(screen, self.color, (self.x, self.y), self.radius, 1)


man = player(200, 313, 64, 64)

font = pygame.font.Font(None, 75)  # font for home screen
instructionsFont = pygame.font.Font(None, 30)  # font for instructions page

# HOME SCREEN

font = pygame.font.Font(None, 75)  # font for home screen
instructionsFont = pygame.font.Font(None, 30)  # font for instructions page

display_instructions = True
homePage = 1
play_page = 2

done = False

while not done and display_instructions:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            done = True
        if event.type == pygame.MOUSEBUTTONDOWN:
            homePage += 1
            if homePage == 3:
                display_instructions = False

    # background
    screen.blit(homeScreen, (0, 0))

    if homePage == 1:
        text = font.render("Star Keeper", True, white)
        screen.blit(text, [115, 40])

        text = font.render("Home", True, white)
        screen.blit(text, [180, 130])

        text = font.render("Instructions", True, white)
        screen.blit(text, [100, 220])

        text = font.render("Play", True, white)
        screen.blit(text, [200, 300])

    if homePage == 2:
        # Draw instructions, page 2
        text1 = instructionsFont.render("Welcome to Star Keeper", True, white)
        text2 = instructionsFont.render("The objective of the game", True, white)
        text3 = instructionsFont.render("is to jump over obstacles using ", True, white)
        text4 = instructionsFont.render("the space key. Hitting an obstacle", True, white)
        text5 = instructionsFont.render("will cause you to lose. Good luck!", True, white)

        screen.blit(text1, [130, 50])
        screen.blit(text2, [130, 100])
        screen.blit(text3, [93, 150])
        screen.blit(text4, [93, 200])
        screen.blit(text5, [93, 250])

    # Limit to 60 frames per second
    clock.tick(60)

    # Go ahead and update the screen with what we've drawn.
    pygame.display.flip()
    pygame.display.update()

#  main loop

speed = 30  # NEW
man = player(200, 410, 64, 64)  # set main character attributes
run = True
while run:
        screen.fill(white)

        clock.tick(30)
        pygame.display.update()
        redrawGameWindow()  # call procedure
        clock.tick(speed)  # NEW
        backgroundX -= 1.4  # Move both background images back
        backgroundX2 -= 1.4
        obstacleX -= 1.4
        obstacleX2 -= 1.4

        if backgroundX < background.get_width() * -1:  # If our background is at the -width then reset its position
            backgroundX = background.get_width()

        if backgroundX2 < background.get_width() * -1:
            backgroundX2 = background.get_width()

        if obstacleX < obstacle.get_width() * -10:
            obstacleX = obstacle.get_width

        if obstacleX2 < obstacle.get_width() * -10:
            obstacleX2 = obstacle.get_width()

        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                run = False
                pygame.quit()
                quit()

        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                run = False
        keys = pygame.key.get_pressed()
        if keys[pygame.K_LEFT]:
            man.left = True
            man.right = False
            man.standing = False  # false, because man is walking
        # verify that character is within window parameters
        elif keys[pygame.K_RIGHT]:
            man.right = True
            man.left = False
            man.standing = False  # false, because man is walking
        else:
            man.standing = True
            man.stepCount = 0

        if not man.isJump:
            if keys[pygame.K_SPACE]:
                man.isJump = True  # when jumping, man shouldn't move directly left or right
                man.right = False
                man.left = False
                man.stepCount = 0
        else:
            if man.jumpCount >= -10:
                neg = 1
                if man.jumpCount < 0:
                    neg = -1
                man.y -= (man.jumpCount ** 2) * .5 * neg  # to jump use parabola
                man.jumpCount -= 1
            else:
                man.isJump = False
                man.jumpCount = 10

pygame.quit()

1 Ответ

1 голос
/ 17 января 2020

Вы копируете текст, но кнопка требует чего-то большего, чем только текст. Также необходимы размер и положение, которые вы можете сохранить в pygame.Rect() и которые можно использовать для рисования фона / прямоугольника кнопки (pygame.draw.rect()) и проверки столкновения с мышью (button.rect.collidepoint(event.pos)).


В этом примере используются три функции:

button_create - для создания pygame.Rect() с размером и позицией и для создания поверхности с текстом (но без фона).

button_draw - для нарисовать фон кнопки / rectanlge и нарисовать текст на этом прямоугольнике

button_check - проверить столкновение между мышью и кнопкой - изменить цвет и запустить назначенную функцию.

#!/usr/bin/env python3

import pygame

# --- constants --- (UPPER_CASE_NAMES)

WHITE = (255,255,255)
BLACK = (  0,  0,  0)

RED   = (255,  0,  0)
GREEN = (  0,255,  0)
BLUE  = (  0,  0,255)

YELLOW = (255,255, 0)

# --- classes --- (CamelCaseNanes)

# empty

# --- functions --- (lower_case_names_

def button_create(text, rect, inactive_color, active_color, action):

    font = pygame.font.Font(None, 40)

    button_rect = pygame.Rect(rect)

    text = font.render(text, True, BLACK)
    text_rect = text.get_rect(center=button_rect.center)

    return [text, text_rect, button_rect, inactive_color, active_color, action, False]


def button_check(info, event):

    text, text_rect, rect, inactive_color, active_color, action, hover = info

    if event.type == pygame.MOUSEMOTION:
        # hover = True/False   
        info[-1] = rect.collidepoint(event.pos)

    elif event.type == pygame.MOUSEBUTTONDOWN:
        if hover and action:      
            action()


def button_draw(screen, info):

    text, text_rect, rect, inactive_color, active_color, action, hover = info

    if hover:
        color = active_color
    else:
        color = inactive_color

    pygame.draw.rect(screen, color, rect)
    screen.blit(text, text_rect)

# ---

def on_click_button_1():
    global stage
    stage = 'game'

    print('You clicked Button 1')

def on_click_button_2():
    global stage
    stage = 'options'

    print('You clicked Button 2')

def on_click_button_3():
    global stage
    global running

    stage = 'exit'
    running = False

    print('You clicked Button 3')

def on_click_button_return():
    global stage
    stage = 'menu'

    print('You clicked Button Return')

# --- main ---  (lower_case_names)

# - init -

pygame.init()
screen = pygame.display.set_mode((800,600))
screen_rect = screen.get_rect()

# - objects -

stage = 'menu'

button_1 = button_create("GAME", (300, 100, 200, 75), RED, GREEN, on_click_button_1)
button_2 = button_create("OPTIONS", (300, 200, 200, 75), RED, GREEN, on_click_button_2)
button_3 = button_create("EXIT", (300, 300, 200, 75), RED, GREEN, on_click_button_3)

button_return = button_create("RETURN", (300, 400, 200, 75), RED, GREEN, on_click_button_return)

# - mainloop -

running = True

while running:

    # - events -

    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            running = False

        if stage == 'menu':
            button_check(button_1, event)
            button_check(button_2, event)
            button_check(button_3, event)
        elif stage == 'game':
            button_check(button_return, event)
        elif stage == 'options':
            button_check(button_return, event)
        #elif stage == 'exit':
        #    pass

    # - draws -

    screen.fill(BLACK)

    if stage == 'menu':
        button_draw(screen, button_1)
        button_draw(screen, button_2)
        button_draw(screen, button_3)
    elif stage == 'game':
        button_draw(screen, button_return)
    elif stage == 'options':
        button_draw(screen, button_return)
    #elif stage == 'exit':
    #    pass

    pygame.display.update()

# - end -

pygame.quit()

enter image description here


Другой метод - создать class Button с методами __init__() (вместо od button_create), draw() и handle_event() (или check()) - так может быть похоже на класс Player или pygame.sprite.Sprite

...