您可以在不打开 pygame window 的情况下导入 pygame 脚本吗(直到您想要为止?)

Can you import a pygame script without opening a pygame window (until you want to?)

所以,我有一个名为 run.py 的游戏,是我用 pygame 制作的,在大多数情况下,它运行良好。我正在尝试为我所有的 pygame 制作一个启动器。但是当我导入它时,它立即打开一个空白window。在我调用 run.main()

之前,我什么都不想发生
import tkinter as tk
import run

WIN = tk.Tk()


WIN.mainloop()
run.main()

我知道发生这种情况是因为在我的 pygame 脚本中我将 window 设置在一个函数之外,当我打开一个 tkinter window 它离开 pygame window 打开直到我关闭 tkinter 一个。但是我希望原始游戏在没有这个启动器的情况下也能正常工作。

这是我的 pygame:

的代码
import pygame , random

pygame.init()

# This is where it opens the window
WIDTH , HEIGHT = 900 , 500
WIN = pygame.display.set_mode((WIDTH , HEIGHT))
pygame.display.set_caption('game')

BLOCK_MOVEMENT_TIMER_EVENT = pygame.USEREVENT + 1
BLOCK_MOVEMENT_TIME_DELAY = 15
pygame.time.set_timer(BLOCK_MOVEMENT_TIMER_EVENT , BLOCK_MOVEMENT_TIME_DELAY)

BLOCK_CREATE_TIMER_EVENT = pygame.USEREVENT + 2
BLOCK_CREATE_TIME_DELAY = 1500
pygame.time.set_timer(BLOCK_CREATE_TIMER_EVENT, BLOCK_CREATE_TIME_DELAY)

FPS = 60

#colors
WHITE = (255 , 255 ,255)
BLACK = (0 , 0 , 0)
RED = (255 , 0 , 0)

BIGFONT = pygame.font.Font('Retro.ttf' , 65)
SMALLFONT = pygame.font.Font('Retro.ttf' , 20)

FLOOR = pygame.Rect(0 , 400 , 900 , 5)

class Player:
    def __init__(self):
        self.size = 20
        self.x = 75
        self.y = 380
        self.jumping = False
        self.fall = False
        self.update_rect()
        self.score = 0

    def update_rect(self):
        self.rect = pygame.Rect(self.x , self.y , self.size , self.size)

    def jump(self):
        pressed = pygame.key.get_pressed()
        if pressed[pygame.K_SPACE] and not self.fall:
            self.jumping = True
        
        if self.jumping:
            self.y -= 3
            if self.y < 300:
                self.y = 300
                self.fall = True
                self.jumping = False

        if self.fall:
            self.y += 3
            if self.y > 380:
                self.y = 380
                self.fall = False
        
        self.update_rect()

player = Player()

class Obstacles:
    def __init__(self , width , height):
        self.x = 900
        self.y = HEIGHT - height - 100
        self.width = width
        self.height = height
        self.update_rect()

    def update_rect(self):
        self.rect = pygame.Rect(self.x , self.y , self.width , self.height)

def move_obstacles(obstacle_list):
    for obstacle in obstacle_list:
        obstacle.x -= 3
        if obstacle.x < -100:
            obstacle_list.pop(0)
            player.score += 1
        
        obstacle.update_rect()

def add_obstacle(obstacle_list):
    obstacle1 = Obstacles(20 , 40)
    obstacle2 = Obstacles(75 , 20)
    obstacle3 = Obstacles(35 , 35)
    obstacle4 = Obstacles(50 , 25)
    obstacle5 = Obstacles(80 , 10)
    obstacle6 = Obstacles(40 , 20)
    obstacle7 = Obstacles(20 , 30)

    obstacle_options = [obstacle1 , obstacle2 , obstacle3 , obstacle4 , obstacle5 , obstacle6 , obstacle7]

    obstacle_list.append(obstacle_options[random.randint(0,6)])

def is_game_over(obstacle_list):
    for obstacle in obstacle_list:
        if player.rect.colliderect(obstacle):
            return True

def game_over():
    running = False
    while not running:
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                running = True
                quit()
            if event.type == pygame.KEYDOWN:
                if event.key == pygame.K_r:
                    player.score = 0
                    main()
                    break
                if event.key == pygame.K_e:
                    running = True
                    quit()

        WIN.fill(BLACK)
        game_over = BIGFONT.render('GAME OVER', False, WHITE)
        WIN.blit(game_over , (200 , 175))

        instructions = SMALLFONT.render(f'You scored {player.score}. Press R to restart or E to exit' , False , WHITE)
        WIN.blit(instructions , (145 , 290))

        pygame.display.flip()

def draw_window(obstacle_list , is_game_over):
    WIN.fill(BLACK)
    pygame.draw.rect(WIN , WHITE , FLOOR)

    pygame.draw.rect(WIN , WHITE , player.rect)

    for obstacle in obstacle_list:
        pygame.draw.rect(WIN , RED , obstacle.rect)
    
    score_counter = BIGFONT.render(f'SCORE  {player.score}', False, (255, 255, 255))
    WIN.blit(score_counter , (240 , 100))

    pygame.display.flip()

def main():
    clock = pygame.time.Clock()
    
    obstacle_list = []

    done = False
    while not done:
        clock.tick(FPS)
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                done = True
                quit()
            if event.type == pygame.KEYDOWN:
                if event.key == pygame.K_e:
                    done = True
                    quit()
            if event.type == BLOCK_MOVEMENT_TIMER_EVENT:
                move_obstacles(obstacle_list)
            if event.type == BLOCK_CREATE_TIMER_EVENT:
                add_obstacle(obstacle_list)

        draw_window(obstacle_list , is_game_over(obstacle_list))
        player.jump()
        is_game_over(obstacle_list)

        if is_game_over(obstacle_list):
            game_over()
            done = True
        pygame.display.flip()

if __name__ == '__main__':
    main()

如果这个问题没有意义,我很抱歉,但我们将不胜感激。

是的。首先 pygame 不会初始化游戏 window 直到你调用 pygame.display.set_mode((width, height)).

因此您可以将 run.py 内的所有游戏逻辑移动到一个函数中,例如...

def my_game_name():
    pygame.init()

    WIDTH , HEIGHT = 900 , 500
    WIN = pygame.display.set_mode((WIDTH , HEIGHT))
    ...

    class Player:
        ...

    def move_obstacles(obstacle_list):
        ...

    def main():
        ...

然后在你的内心main.py你可以做到这一点。

import run

# When you're ready to run the game
run.my_game_name()

我建议您 做的第二个选择是...

里面main.py

#TK button clicked to start game
def start_my_game():
    import run # Window is shown here
    run.main() # Game logic begins

我不会推荐这个,因为你依赖 import 在后台设置东西,这就是你现在遇到问题的原因。