【问题标题】:Several screens "overlapping" pygame几个屏幕“重叠”pygame
【发布时间】:2020-09-02 01:41:22
【问题描述】:

我今天开始用 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)

游戏.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 更改屏幕,但这不会阻止董事会从被重绘

【问题讨论】:

  • 在每一帧中重绘场景是很常见的。在一个简单的游戏中,这可能看起来毫无用处并且浪费资源,但在具有动态场景的现代游戏中并没有什么不同,其中几乎每一帧都有变化。不要浪费你的时间。
  • 一种简单的方法是仅在帧中至少处理一个事件时更新显示。

标签: python pygame


【解决方案1】:

有几种方法可以提高背景图片的性能。

  • 绘制一次 - 您可以将背景图像存储在表面对象中,因此只需要生成一次。 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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-08-24
    相关资源
    最近更新 更多