Python 优化对象显示(gamedev)
相关代码,简化:Python 优化对象显示(gamedev),python,pygame,Python,Pygame,相关代码,简化: 类字符: 定义初始化(自): self.projectles=[] def喷射(自): self.projectles.append(sparket()) def牵引(自): 对于自射弹中的射弹: pygame.draw.rect()#args在这里似乎不相关 draw()每当产生射弹时,游戏速度都会非常慢 我的问题是: 我可以加快列表迭代过程吗? 我能实现比列表更好的方法吗? 我在哪里可以放一些多线程在这个 编辑: shoot()每帧最多调用一次(在键绑定时触发),并且投射
类字符:
定义初始化(自):
self.projectles=[]
def喷射(自):
self.projectles.append(sparket())
def牵引(自):
对于自射弹中的射弹:
pygame.draw.rect()#args在这里似乎不相关
draw()
每当产生射弹时,游戏速度都会非常慢
我的问题是:
我可以加快列表迭代过程吗?
我能实现比列表更好的方法吗?
我在哪里可以放一些多线程在这个
编辑:
shoot()
每帧最多调用一次(在键绑定时触发),并且投射物列表迭代两次(更新和绘制步骤)
游戏使用单个投射物时会变得非常迟缓,当投射物达到一定距离(地图限制)并从列表中删除时,游戏会再次变得流畅
我可以加快列表迭代过程吗
没有,但可能您对列表的迭代次数过多。调用draw()
时,投射物有多大
我能实现比列表更好的方法吗
使用PyGoGAME时,应考虑使用<代码> SpRITE < /C>和<代码>组< /代码>类。使用
组
而不是列表。这提供了一些方便的功能,比如在不同的层上绘制精灵,抽象更新和绘制,以及使用kill()
等轻松删除精灵
我在哪里可以放一些多线程在这个
我99.9%确定您实际上不需要多线程
您的问题是类的更新方法:
def update(self, camera):
self.posW += self.speed * self.dirW * Clock().tick(FPS)
self.posH += self.speed * self.dirH * Clock().tick(FPS)
self.rect = (self.posW, self.posH, 20, 20)
在这里,您将创建一个新的时钟
实例,并为每个投射物
实例每帧调用勾选
两次,这将暂停游戏每帧多次
您应该做的是创建一次时钟
实例,每帧只调用一次勾选
,并将结果值向下传递给精灵以调整其速度
我更改了您的代码以使用游戏的Sprite
类,并删除了许多文件:
camera.py:
import pygame
class CameraAwareLayeredUpdates(pygame.sprite.LayeredUpdates):
def __init__(self, target, world_size, screen_size):
super().__init__()
self.target = target
self.cam = pygame.Vector2(0, 0)
self.world_size = world_size
self.screen_size = screen_size
if self.target:
self.add(target)
def update(self, *args):
super().update(*args)
if self.target:
x = -self.target.rect.center[0] + self.screen_size[0]/2
y = -self.target.rect.center[1] + self.screen_size[1]/2
self.cam += (pygame.Vector2((x, y)) - self.cam) * 0.07
self.cam.x = max(-(self.world_size[0]-self.screen_size[0]), min(0, self.cam.x))
self.cam.y = max(-(self.world_size[1]-self.screen_size[1]), min(0, self.cam.y))
def draw(self, surface):
spritedict = self.spritedict
surface_blit = surface.blit
dirty = self.lostsprites
self.lostsprites = []
dirty_append = dirty.append
init_rect = self._init_rect
for spr in self.sprites():
rec = spritedict[spr]
newrect = surface_blit(spr.image, spr.rect.move(self.cam))
if rec is init_rect:
dirty_append(newrect)
else:
if newrect.colliderect(rec):
dirty_append(newrect.union(rec))
else:
dirty_append(newrect)
dirty_append(rec)
spritedict[spr] = newrect
return dirty
game.py:
import pygame
from lib.camera import CameraAwareLayeredUpdates
TILESIZE = 50
WORLD_SIZE_IN_TILES = 30, 16
WORLD_SIZE = [v*TILESIZE for v in WORLD_SIZE_IN_TILES]
SCREEN_SIZE = 800, 500
class Actor(pygame.sprite.Sprite):
def __init__(self, game, *args, **kwargs):
super().__init__(*args)
self.game = game
self.image = pygame.Surface(kwargs.get('size', (50, 50)))
self.image.fill(pygame.Color(kwargs.get('color', 'blue')))
self.rect = self.image.get_rect()
self.pos = pygame.Vector2(kwargs.get('pos', self.rect.center))
self.rect.center = [int(x) for x in self.pos]
self.vel = pygame.Vector2(kwargs.get('vel', (0, 0)))
def update(self, dt, events):
self.pos += (self.vel * dt/10)
self.rect.center = [int(x) for x in self.pos]
class Character(Actor):
def __init__(self, game, *args, **kwargs):
super().__init__(game, *args, **kwargs)
self.facing = pygame.Vector2(0, 1)
def update(self, dt, events):
for event in events:
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_SPACE:
self.game.add(Actor,
pos=self.rect.center,
vel=self.facing * 10,
color='blue',
size=(20, 20))
pressed = pygame.key.get_pressed()
self.vel.x, self.vel.y = 0, 0
if pressed[pygame.K_a]: self.vel.x = -1
if pressed[pygame.K_d]: self.vel.x = 1
if pressed[pygame.K_w]: self.vel.y = -1
if pressed[pygame.K_s]: self.vel.y = 1
if self.vel.length() > 0:
self.facing = pygame.Vector2(self.vel)
self.facing.normalize_ip()
self.vel *= 5
super().update(dt, events)
class Tilemap(pygame.sprite.Sprite):
def __init__(self):
super().__init__()
self._layer = -100
self.tilesH = WORLD_SIZE_IN_TILES[1]
self.tilesW = WORLD_SIZE_IN_TILES[0]
self.map = [
'white' for i in range(self.tilesH * self.tilesW)
]
for i in range(self.tilesH):
for j in range(self.tilesW):
if i * j == 0 or i == self.tilesH - 1 or j == self.tilesW - 1:
self.map[i * j] = 'grey'
self.image = self.render()
self.rect = self.image.get_rect()
def update(self, *args):
pass
def render(self):
surf = pygame.Surface(WORLD_SIZE)
for i in range(self.tilesH):
for j in range(self.tilesW):
rect = (j * TILESIZE, i * TILESIZE, TILESIZE, TILESIZE)
pygame.draw.rect(surf, pygame.Color(self.map[i * j]), rect)
return surf
class Game:
def __init__(self):
pygame.init()
pygame.display.set_caption("SANTARENA")
self.screen = pygame.display.set_mode(SCREEN_SIZE)
self.clock = pygame.time.Clock()
player = Character(self, color='red', pos=self.screen.get_rect().center)
self.all_sprites = CameraAwareLayeredUpdates(player, WORLD_SIZE, SCREEN_SIZE)
self.all_sprites.add(Tilemap())
def add(self, clazz, **kwargs):
instance = clazz(self, self.all_sprites, **kwargs)
return instance
def start(self):
dt = 0
while True:
events = pygame.event.get()
for event in events:
if event.type == pygame.QUIT:
return
self.all_sprites.update(dt, events)
self.all_sprites.draw(self.screen)
pygame.display.update()
dt = self.clock.tick(60)
我一定会把这些课程查出来。它可能很好地解决了我的问题,但我仍然更新了这个问题。@Pypaut你的射弹是矩形的吗?奇怪的是,一个单一的会导致滞后。也许发布你的完整代码(如果不是太多的话)。只链接我的代码可以吗python/lib/*
。我当然还不习惯python的方式。给人印象深刻的我期待着更新这一切。非常感谢。