簡體   English   中英

如何在pygame中創建新窗口?

[英]How to make new window in pygame?

我一直在使用pygame制作游戲,並發現在此游戲中需要新窗口。 游戲截圖

當男孩與其中一家公司(Web Canape,Smolenskiye Brillianty ...)發生碰撞時,必須打開新窗口在該處進行測驗。 主要游戲也需要繼續工作,因為男孩的任務是遍及所有公司。

有人可以幫我解決這個問題嗎?
可能可以使用新模塊(例如PyQt5或Tkinter)以免終止整個游戲。

https://github.com/TotumRevolutum/shadows-game

import sys
from map import *
import pygame.display


pygame.init()    

WIDTH = 11 * 100
HEIGHT = 7 * 100
clock = pygame.time.Clock()


def text_show(number):
    intro_text_1 = ["Привет! Меня зовут Емеля.", "Я приглашаю тебя на         День",
                "Теней на предприятия", "Смоленской области.", " ", " ДАЛЕЕ"]
intro_text_2 = ['"День Теней" - это день,', "в течение которого школьники",
                "могут лично следить за работой ", "специалистов с целью проверки",
                "правильности выбора профессии.", " ДАЛЕЕ"]
intro_text_3 = ['Мы с тобой будем определяться', "с профессией по принципу ",
                'индукции от "частного" к "общему",', 'от "предприятия" к "профессии."',
                "", " ДАЛЕЕ"]
intro_text_4 = ['В конце Дня Теней', "ты сможешь выбрать предприятие,",
                'на котором хотел бы работать!', '',
                "", " ДАЛЕЕ"]
if number == 1:
    text = intro_text_1
elif number == 2:
    text = intro_text_2
elif number == 3:
    text = intro_text_3
else:
    text = intro_text_4

back = Background('bg/boy_start.png', [0, 0])
screen.blit(back.image, back.rect)
font = pygame.font.SysFont("Typewriter", 33)
tmp = 0
for line in text:
    if line == " ДАЛЕЕ":
        lines = font.render(line, 1, pygame.Color('red'))
    else:
        lines = font.render(line, 1, pygame.Color('black'))
    display_rect = lines.get_rect()
    tmp += 10
    display_rect.y = 140 + tmp
    display_rect.x = 640
    tmp += display_rect.height
    screen.blit(lines, display_rect)

while True:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            sys.exit()
        elif event.type == pygame.MOUSEBUTTONDOWN:
            return
    pygame.display.flip()
    clock.tick(30)


text_show(1)
text_show(2)
text_show(3)
text_show(4)
running = True
generate_level(load_level())

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

keys = pygame.key.get_pressed()
move_boy(keys, player_group)

all_sprites.draw(screen)
tiles_group.draw(screen)
player_group.draw(screen)
pygame.display.flip()
clock.tick(60)
# other parts are located in the git 
# https://github.com/TotumRevolutum/shadows-game

您不需要也不需要新窗口。 只需創建另一個Surface / Sprite呈現文本並處理事件。

這是我一起砍的一個簡單例子。 請注意注釋,因為它們解釋了正在發生的事情:

import pygame
import pygame.freetype

# So our game has 2 states.
# Either we're in the world and run around;
# or we're displaying a menu and the player has to make a choice.
WORLD = 0
MENU = 1

# from https://www.pygame.org/docs/ref/freetype.html#pygame.freetype.Font.render_to
def word_wrap(surf, text, font, color=(0, 0, 0)):
    font.origin = True
    words = text.split(' ')
    width, height = surf.get_size()
    line_spacing = font.get_sized_height() + 2
    x, y = 0, line_spacing
    space = font.get_rect(' ')
    for word in words:
        bounds = font.get_rect(word)
        if x + bounds.width + bounds.x >= width:
            x, y = 0, y + line_spacing
        if x + bounds.width + bounds.x >= width:
            raise ValueError("word too wide for the surface")
        if y + bounds.height - bounds.y >= height:
            raise ValueError("text to long for the surface")
        font.render_to(surf, (x, y), None, color)
        x += bounds.width + space.width
    return x, y

# This sprite handles the menu.
# It renders a box and a text and listens for key presses.
# If a key we're interessed in is pressed, we call the callback function.
class TextMenu(pygame.sprite.Sprite):
    def __init__(self, font, text, listen_to, callback):
        super().__init__()
        self.image = pygame.Surface((400, 400))
        self.image.fill(pygame.Color('white'))
        self.image.fill(pygame.Color('black'), self.image.get_rect().inflate((-50, -50)))
        self.rect = self.image.get_rect(topleft=(50, 50))
        word_wrap(self.image.subsurface(self.image.get_rect().inflate((-100, -100))), text, font, pygame.Color('white'))
        self.callback = callback
        self.listen_to = listen_to

    def update(self, events, dt):
        for e in events:
            if e.type == pygame.KEYDOWN and e.key in self.listen_to:
                self.callback(self, e.key)

# This sprite represents a building the player can "walk in" to trigger 
# a menu pop up. In this case, we want the user to either press 1 or 2.
# Then we change the color, because why not, something should happen.
class House(pygame.sprite.Sprite):
    def __init__(self, pos, player, show_text):
        super().__init__()
        self.image = pygame.Surface((64, 64))
        self.image.fill(pygame.Color('darkred'))
        self.rect = self.image.get_rect(center=pos)
        self.show_text = show_text
        self.player = player
        # Since the menu is triggered when the player touches the building,
        # we don't want an endless loop, so we need a flag that prevents
        # the menu until the player "leaves the building"
        self.triggered = False

    def change_color(self, key):
        if key == pygame.K_1:
            self.image.fill(pygame.Color('yellow'))
        if key == pygame.K_2:
            self.image.fill(pygame.Color('darkblue'))

    def update(self, events, dt):
        if pygame.sprite.collide_rect(self, self.player):
            if not self.triggered:
                self.show_text('Welcome, little blue rect. Please press (1) or (2).', (pygame.K_1, pygame.K_2), self.change_color)
                self.triggered = True
        else:
            self.triggered = False

# This is the player. 
# Does basically nothing but run around
class Player(pygame.sprite.Sprite):
    def __init__(self):
        super().__init__()
        self.image = pygame.Surface((32, 32))
        self.image.fill(pygame.Color('dodgerblue'))
        self.rect = self.image.get_rect()
        self.pos = pygame.Vector2((100, 200))

    def update(self, events, dt):
        pressed = pygame.key.get_pressed()
        move = pygame.Vector2((0, 0))
        if pressed[pygame.K_w]: move += (0, -1)
        if pressed[pygame.K_a]: move += (-2, 0)
        if pressed[pygame.K_s]: move += (0, 2)
        if pressed[pygame.K_d]: move += (2, 0)
        if move.length() > 0: move.normalize_ip()
        self.pos += move*(dt/5)
        self.rect.center = self.pos

def main():
    pygame.init()
    screen = pygame.display.set_mode((500, 500))
    font = pygame.freetype.SysFont(None, 32)
    clock = pygame.time.Clock()
    dt = 0

    player = Player()

    # keep track of the state we're in.
    # we start in the WORLD state, a.k.a. running around.
    # the state just tells us which sprites are "active", 
    # a.k.a. if they are updated by calling thier update function
    state = WORLD

    # sprite group for all MENU-sprites
    menu_sprites = pygame.sprite.Group()

    # sprite group for all WORLD-sprites
    sprites = pygame.sprite.Group(player)

    # this function allows other sprites to trigger a menu
    def show_text(text, listen_to, callback):

        # this function is called by the menu.
        # we change the state back to world and kill the TextMenu sprite
        def wrapped_callback(sprite, *args):
            nonlocal state
            state = WORLD
            callback(*args)
            sprite.kill()

        # so when this function is called , let's switch to the MENU state
        nonlocal state
        state = MENU
        # add the TextMenu sprite to the menu_sprites group so it "lives"
        menu_sprites.add(TextMenu(font, text, listen_to, wrapped_callback))

    # create some buildings. They are all the same...
    for pos in ((300, 300), (200, 400), (100, 100)):
        sprites.add(House(pos, player, show_text))

    while True:
        events = pygame.event.get()
        for e in events:
            if e.type == pygame.QUIT:
                return

        # see which sprites are "active". The WORLD sprites or the MENU sprites
        if state == WORLD:
            sprites.update(events, dt)
        else:
            menu_sprites.update(events, dt)

        screen.fill((30, 30, 30))
        sprites.draw(screen)
        menu_sprites.draw(screen)
        pygame.display.update()
        dt = clock.tick(60)

if __name__ == '__main__':
    main()

在此處輸入圖片說明

請注意如何將所有游戲邏輯完全分開,並且這種方法還可以輕松添加其他狀態,例如暫停功能或菜單。

當然,還有其他許多方法可以做到這一點,但是您會明白的。 有關如何在游戲中實現不同狀態的另一種想法,也許看看這個問題

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM