python - 如何让我的 pygade 代码运行得更快?它仅以 4fps 运行
问题描述
我正在尝试在 pygame 中制作一个简单的 2d 游戏,由于某种原因,它只能以 4fps.h 运行,这导致它非常滞后和不稳定。我查看了其他建议 convert() 的问题,但我没有任何图像。有什么办法让它更快??我希望它至少运行 40 fps。我目前正在研究 MacO。到目前为止,这是我的代码:
import math
import sys
import pygame
from pygame.locals import *
pygame.init()
BLACK = (0,0,0)
WHITE = (255,255,255)
GREEN = (0,255,0)
RED = (255,0,0)
BLUE=(0,0,255)
PI = 3.141592653
font = pygame.font.SysFont('Times',12, True,False)
def write_text(text, pos,color):
hi = font.render(text, True,color)
screen.blit(hi, pos)
def draw_label_rect(text,color,object):
pygame.draw.rect(screen, object.color, object.Display_Rect)
hi =font.render( text, True, color)
center_x = object.pos[0]+ 1/2*object.width
center_y =object.pos[1] + 1/2 * object.length
text_width = hi.get_width()
text_height = hi.get_height()
screen.blit(hi, (math.floor(center_x-1/2*text_width),math.floor(center_y-1/2*text_height)))
def draw_image_label_rect_centered(image, color, pos,scale_factor):
pygame.draw.rect(screen, color,pos)
image = pygame.image.load(image).convert_alpha()
width = image.get_width()
height = image.get_height()
image2 = pygame.transform.smoothscale(image,(math.floor(width*scale_factor),math.floor(height*scale_factor)))
new_width = image2.get_width()
new_height = image2.get_height()
center_x = pos[0]+ 1/2*pos[2]
center_y =pos[1] + 1/2 * pos[3]
screen.blit(image2, (center_x-1/2*new_width, center_y-1/2*new_height))
def draw_image_label_rect_behind(image, color, pos,scale_factor):
pygame.draw.rect(screen, color,pos)
image = pygame.image.load(image).convert_alpha()
width = image.get_width()
height = image.get_height()
image2 = pygame.transform.smoothscale(image,(math.floor(width*scale_factor),math.floor(height*scale_factor)))
center_x = pos[0]+ 1/2*pos[2]
new_width = image2.get_width()
screen.blit(image2, (center_x-1/2*new_width, pos[3]+pos[1]+1))
size = (1500, 700)
background = pygame.display.set_mode(size)
screen = pygame.surface.Surface((10000, 10000))
pygame.display.set_caption("HI")
done = False
clock = pygame.time.Clock()
FPS = 120
scroll_y = 0
scroll_x = 0
originalmousex = None
originalmousey = None
Rects= []
Objects = []
class Camera():
def __init__(self):
self.x = 5000
self.y = 5000
self.distance_x = 750
self.distance_y = 350
def move(self,offset_x,offset_y):
self.x +=offset_x
self.y +=offset_y
for i in Objects:
i.screenpos=(i.pos[0]-self.x+750,i.pos[1]-self.y+350)
i.virtual_rect = pygame.Rect(i.screenpos[0],i.screenpos[1],i.width,i.length)
def zoom_in(self):
self.distance_x = math.floor(self.distance_x * 0.95)
self.distance_y = math.floor( self.distance_y * 0.95)
def zoom_out(self):
self.distance_x = math.floor(self.distance_x * 1.05)
self.distance_y = math.floor(self.distance_y * 1.05)
def subsurfacing(self):
self.camera_surface = screen.subsurface((self.x- self.distance_x,self.y - self.distance_y,2*self.distance_x,2*self.distance_y))
background.blit(pygame.transform.smoothscale(self.camera_surface,(1500,700)),(0,0))
main_camera = Camera()
class InfantryRect():
def __init__(self,number, color,formation,pos):
self.number = number
self.color = color
self.formation = formation
class_formation = self.formation
self.pos = pos
self.moving = False
self.movingto = None
self.startmovingframe = None
self.screenpos = (self.pos[0]-main_camera.x+750,self.pos[1]-main_camera.y+350)
if self.formation == 'line':
lengthy = 25
self.Display_Rect = pygame.Rect(self.pos[0],self.pos[1],lengthy*2,(self.number//lengthy)*2)
self.length = self.Display_Rect.height
self.width = self.Display_Rect.width
self.virtual_rect = pygame.Rect(self.screenpos[0],self.screenpos[1],self.width,self.length)
self.speed = 1
def display(self):
if self.formation== 'line':
pygame.draw.rect(screen,self.color,[self.pos[0],self.pos[1],self.width,self.length])
hi = font.render(str(self.number),True,(255,225,64))
center_x = self.pos[0]+ 1/2*self.width
center_y =self.pos[1] + 1/2 * self.length
text_width = hi.get_width()
text_height = hi.get_height()
screen.blit(hi, (math.floor(center_x-1/2*text_width),math.floor(center_y-1/2*text_height)))
def movingcreating(self,position):
self.distance = math.hypot(position[0]-self.virtual_rect.x,position[1]-self.virtual_rect.y)
if self.distance!=0:
self.dx = ((position[0]-self.virtual_rect.x)/self.distance)*self.speed
self.dy = ((position[1]-self.virtual_rect.y)/self.distance)*self.speed
def move(self,position):
if self.distance!=0:
self.pos = (self.pos[0]+self.dx,self.pos[1]+self.dy)
self.virtual_rect = pygame.Rect(int(self.pos[0]-main_camera.x+750),int(self.pos[1]-main_camera.y+350),self.width,self.length)
self.Display_Rect = pygame.Rect(int(self.pos[0]),int(self.pos[1]),self.width,self.length)
self.movingcreating(position)
TestInf = InfantryRect(100,RED,'line',[5000,5000])
Objects.append(TestInf)
count = 0
width = screen.get_width()
length = screen.get_height()
clock = pygame.time.Clock()
z_is_pressed = False
x_is_pressed = False
up_is_pressed = False
down_is_pressed = False
right_is_pressed = False
left_is_pressed = False
mouse_button_holding = False
frames = 0
while not done:
for event in pygame.event.get():
if event.type == pygame.QUIT:
done = True
elif event.type == pygame.MOUSEBUTTONDOWN:
mouse_pos = event.pos
for i in Objects:
if i.virtual_rect.collidepoint(mouse_pos):
print('Hello')
mouse_button_holding = i
break
if mouse_button_holding==False:
mouse_button_holding = 'scrolling'
originalmousex = mouse_pos[0]
originalmousey = mouse_pos[1]
elif event.type == pygame.MOUSEBUTTONUP:
if mouse_button_holding!= False and mouse_button_holding!='scrolling':
mouse_button_holding.movingto = (event.pos[0] -0.5*mouse_button_holding.width-main_camera.x+5000 , event.pos[1]-0.5*mouse_button_holding.length-main_camera.y+5000)
mouse_button_holding.movingcreating(event.pos)
mouse_button_holding.moving = True
mouse_button_holding.startmovingframe = frames
mouse_button_holding = False
originalmousex = None
originalmousey = None
mouse_button_holding = False
elif event.type == pygame.KEYDOWN:
if event.key == pygame.K_z:
z_is_pressed = True
elif event.key ==pygame.K_x:
x_is_pressed = True
elif event.key == pygame.K_UP:
up_is_pressed = True
elif event.key == pygame.K_DOWN:
down_is_pressed = True
elif event.key == pygame.K_RIGHT:
right_is_pressed = True
elif event.key == pygame.K_LEFT:
left_is_pressed = True
elif event.type == pygame.KEYUP:
if event.key == pygame.K_z:
z_is_pressed = False
elif event.key ==pygame.K_x:
x_is_pressed = False
if mouse_button_holding=='scrolling':
main_camera.move(-(pygame.mouse.get_pos()[0]-originalmousex),-(pygame.mouse.get_pos()[1]-originalmousey))
originalmousex = pygame.mouse.get_pos()[0]
originalmousey = pygame.mouse.get_pos()[1]
if z_is_pressed:
main_camera.zoom_in()
if x_is_pressed:
main_camera.zoom_out()
background.fill(BLACK)
screen.fill(BLACK)
# pygame.draw.line(screen, GREEN, [0, 0], [100, 100], 5)
#for y_offset in range(0, 100, 10):
#pygame.draw.line(screen,RED,[0,10+y_offset],[100,110+y_offset],5)
#draw_label_rect('Hello',RED,[250,250,50,50],WHITE)
TestInf.display()
for i in Objects:
if i.moving:
i.move(i.movingto)
main_camera.subsurfacing()
print(clock.get_fps())
clock.tick(60)
pygame.display.update()
frames+=1
pygame.quit()
解决方案
主要问题是,screen
是pygame.Surface
一个大小为 10000x10000 的对象。这个表面在每一帧中都会被清除,这就是导致性能影响的原因:
screen = pygame.surface.Surface((10000, 10000))
screen.fill(BLACK)
由于表面的一小部分(次表面)blit
位于屏幕上,
def subsurfacing(self): self.camera_surface = screen.subsurface((self.x- self.distance_x,self.y - self.distance_y,2*self.distance_x,2*self.distance_y)) background.blit(pygame.transform.smoothscale(self.camera_surface,(1500,700)),(0,0))
不必screen
在每一帧中清除整个 Surface。只需通过以下方式清除稍后绘制到窗口中的区域pygame.draw.rect
:
class Camera():
# [...]
def clearsubsurface(self, color):
px = self.x- self.distance_x,self.y - self.distance_y
py = 2*self.distance_x,2*self.distance_y
pygame.draw.rect(screen, color, (px, py))
while not done:
# [...]
#screen.fill(BLACK) <--- DELETE
main_camera.clearsubsurface(BLACK)
# [...]
推荐阅读
- wordpress - cpanel cron作业和wordpress
- python - 被网站禁止后如何在 Scrapy 中发送 fetch('%URL%')?
- wpf - AvalonDock:从 LayoutContent 获取控制权
- java - 使用 mvc 移交构造函数时线程“JavaFX 应用程序线程”中的异常
- c# - TFS REST API 通过代码与浏览器返回不同的结果
- android - 图像显示在应用程序上,但不在小部件 remoteViews 上
- javascript - 如何访问其中包含破折号(-)的对象属性
- typescript - 交叉口到最受限制的类型
- azure - 在 Azure 机器学习中,日志文件存储在哪里?
- c++ - 在 async_read_until 条纹空间之后提高从流缓冲区中读取的 asio