Python “几个屏幕”;重叠“;皮加梅

Python “几个屏幕”;重叠“;皮加梅,python,pygame,Python,Pygame,我今天开始用pygame编程一个游戏。背景是一种网格,您将在其上玩游戏。但我注意到,通过一个while循环来更新屏幕,网格每次都会被重新绘制,这是一种资源浪费,因为那里没有任何变化。现在我考虑不在后台更新网格屏幕,而是创建一个新的屏幕来播放,该屏幕将被更新。但后来我遇到了一个问题:当pygame启动一个新屏幕时,最后一个屏幕关闭。 那么,每次重新绘制游戏板是明智之举,还是有另一种方法可以让您在不更新项目的情况下将其保留在后台?非常感谢你的帮助。遵循代码和(错误的)方法 main.py impor

我今天开始用pygame编程一个游戏。背景是一种网格,您将在其上玩游戏。但我注意到,通过一个while循环来更新屏幕,网格每次都会被重新绘制,这是一种资源浪费,因为那里没有任何变化。现在我考虑不在后台更新网格屏幕,而是创建一个新的屏幕来播放,该屏幕将被更新。但后来我遇到了一个问题:当pygame启动一个新屏幕时,最后一个屏幕关闭。 那么,每次重新绘制游戏板是明智之举,还是有另一种方法可以让您在不更新项目的情况下将其保留在后台?非常感谢你的帮助。遵循代码和(错误的)方法

main.py

import field, game
import ctypes


# Variables
def main():
    width, height = ctypes.windll.user32.GetSystemMetrics(0), ctypes.windll.user32.GetSystemMetrics(1)
    width_scale, height_scale = 5 / 10, 9 / 10
    black = (0, 0, 0)
    white = (255, 255, 255)
    background_color = (214, 237, 255)
    refresh_rate = 60
    field_size = [10, 18]

    screen = pg.display.set_mode([int(width * width_scale), int(height * height_scale)], pg.NOFRAME)

    while True:
        for event in pg.event.get():
            if event.type == pg.KEYDOWN:
                pass
        screen.fill(background_color)
        box_size = field.draw_boxes(screen.get_width(), screen.get_height(), field_size, screen)
        field.draw_next_hand()
        pg.display.flip()

        game.main(width, height, box_size, field_size)



if __name__ == '__main__':
    main()
    pg.quit()
field.py

import pygame as pg


def draw_boxes(w, h, size, screen):
    global start_x, box_size, g_screen, grey, s
    g_screen = screen
    s = size
    box_size = int(w / 2 / (size[0]+1))
    start_x = int(w / 2 - size[0] / 2 * box_size)
    grey = (122, 122, 122)


    for column in range(0, size[0], 1):
        for row in range(0, size[1], 1):
            pg.draw.rect(screen, grey, [start_x + column * box_size, box_size + row * box_size, box_size, box_size], width= 1)

    return box_size

def draw_next_hand():
    global box_size, start_x, g_screen, grey
    next_hand_size = 4
    next_hand_distance = 1

    for column in range(0, next_hand_size, 1):
        for row in range(0, next_hand_size, 1):
            pg.draw.rect(g_screen, grey, [start_x - 2*box_size*next_hand_distance - column * box_size, box_size + row * box_size, box_size, box_size], width=1)
            pg.draw.rect(g_screen, grey, [start_x + box_size*s[0] + box_size * next_hand_distance + column * box_size, box_size + row * box_size, box_size, box_size], width=1)

game.py

import pygame as pg
from main import main

def main(width, height, box_size, f_size):

    # Variables
    white = (255, 255, 255)
    black = (0, 0, 0)
    grey = (122, 122, 122)
    refresh_rate = 60


    g_screen = pg.display.set_mode([int(f_size[0] * box_size), int(f_size[1] * box_size)], pg.NOFRAME)
    while True:
        g_screen.fill(white)
        pg.display.flip()
        pg.time.delay(refresh_rate)

在我添加新屏幕之前,我使用了“pg.time.delay(refresh_rate)”而不是“game.main()”,这导致背景不断被重新绘制,所以我尝试在其上绘制另一个屏幕,当然这不起作用^^


我已经发现了一些关于堆栈溢出的条目,但它们不符合我的问题,因为有人建议更改屏幕,例如main=False和game=True,但这不会阻止重新绘制棋盘。有几种方法可以提高背景图像的性能

  • 绘制一次-可以将背景图像存储在曲面对象中,因此只需生成一次。Pygame将在隐藏或最小化时保留屏幕
  • 仅重绘更新的部分-在屏幕上设置一个剪切矩形,以便在重绘背景时仅刷新某些像素
  • 仅在需要时重新绘制-需要游戏循环,但您可以有条件地重新渲染背景
  • 高效绘图-使用
    pygame.time.Clock().tick()方法减慢游戏循环
这里有一个简短的程序来说明这些要点。它仅在圆圈背景上显示当前日期\时间

import pygame as pg
import time
from datetime import datetime as dt
from random import randint

WIDTH = 480
HEIGHT = 600

pg.init()
screen = pg.display.set_mode((WIDTH, HEIGHT))

def rnd(rg): # save some typing
   return randint(0,rg)

font_name = pg.font.match_font('arial')

def draw_text(surf, text, size, x, y): # draw text on screen in rect
    font = pg.font.Font(font_name, size)
    text_surface = font.render(text, True, (rnd(255),rnd(255),rnd(255)))
    text_rect = text_surface.get_rect()
    text_rect.midtop = (x, y)
    surf.blit(text_surface, text_rect)

def make_bg():  # create background image
   surf_bg = pg.Surface((WIDTH, HEIGHT))
   surf_bg.fill((0,0,0)) # start with black
   for i in range(500):  # 500 circles
      pg.draw.circle(surf_bg,(rnd(255),rnd(255),rnd(255)), (rnd(WIDTH),rnd(HEIGHT)), 15+rnd(50))
   return surf_bg

surf_bg = make_bg()  # generate circles once, store surface object

#initial background
screen.blit(surf_bg, screen.get_rect()) # draw background, only needed once in Windows
screen.set_clip((10, HEIGHT/2 - 20, WIDTH-10, HEIGHT/2 + 20)) # set active region on screen

lasttick = pg.time.get_ticks() # milliseconds since init

while True:
   pg.time.Clock().tick(5)  # run loop 5 times per second
   pg.event.get()  # required in Windows for OS events
   if pg.key.get_pressed()[pg.K_SPACE]: quit()  # press space to quit
   if (pg.time.get_ticks() - lasttick < 1000): continue # only redraw time each second
   lasttick = pg.time.get_ticks()  
   
   screen.blit(surf_bg, screen.get_rect())  # background, update clip region only
   draw_text(screen, str(dt.now()), 30, WIDTH / 2, HEIGHT / 2 - 10) # draw time
   pg.display.flip() # swap screen buffer
将pygame导入为pg
导入时间
从日期时间导入日期时间作为dt
从随机导入randint
宽度=480
高度=600
第init页()
屏幕=pg.display.set_模式((宽度、高度))
def rnd(rg):#保存一些键入内容
返回randint(0,rg)
font\u name=pg.font.match\u font('arial')
def draw_text(冲浪、文本、大小、x、y):#在屏幕上以矩形绘制文本
font=pg.font.font(字体名称、大小)
text\u surface=font.render(text,True,(rnd(255)、rnd(255)、rnd(255)))
text_rect=text_surface.get_rect()
text_rect.midtop=(x,y)
冲浪板(文字表面,文字直线)
def make_bg():#创建背景图像
表面(宽度、高度)
冲浪背景填充((0,0,0))#从黑色开始
对于范围(500)内的i:#500个圆
pg.draw.圆(表面背景,(径向直径(255),径向直径(255),径向直径(255)),(径向直径(宽度),径向直径(高度)),15+径向直径(50))
返回surf_bg
surf_bg=生成_bg()#生成一次圆,存储曲面对象
#初始背景
screen.blit(surf_bg,screen.get_rect())35;在Windows中只需绘制一次背景
屏幕。设置剪辑((10,高度/2-20,宽度-10,高度/2+20))#在屏幕上设置活动区域
lasttick=pg.time.get_ticks()#自初始化以来的毫秒数
尽管如此:
pg.time.Clock().勾选(5)#每秒运行循环5次
pg.event.get()#Windows中操作系统事件需要
如果按下pg.key.get_()[pg.K_SPACE]:退出()#按空格退出
if(pg.time.get_ticks()-lasttick<1000):继续#每秒只重新绘制时间
lasttick=pg.time.get_ticks()
screen.blit(surf_bg,screen.get_rect())#背景,仅更新剪辑区域
绘制文字(屏幕,str(dt.now()),30,宽/2,高/2-10)#绘制时间
pg.display.flip()#交换屏幕缓冲区

通常在每一帧中重新绘制场景。在一个简单的游戏中,这似乎是无用的,也是对资源的浪费,但在现代游戏中,几乎每一帧都有变化的动态场景中,这并没有什么区别。不要浪费时间。一个简单的方法是仅在一个帧中处理了至少一个事件时才更新显示。