如何使我的 pygade 代码 运行 更快?它只有 运行ning 4fps
How to make my pygade code run faster? It is only running at 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
表面。稍后通过 pygame.draw.rect
:
清除被绘制到 window 中的区域
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)
# [...]
我正在尝试在 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
表面。稍后通过 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)
# [...]