Хорошо, поэтому основная проблема здесь, вероятно, schedule_interval
, которая работает не так быстро, как это возможно.Главным образом потому, что он обновляет сцену и вызывает рендеринг для запуска.Второй - wall.update()
call (который я точно не знаю, почему вы звоните) очень медленный, и вы делаете это ширина * высота ^ 2 раза.И это очень неэффективно.
Для этого есть быстрый обходной путь.И ниже предложенный способ сделать это.
#Create blocks 50x50 pixels and replace with image names to get what i see.
from pyglet.window import key, FPSDisplay
import pyglet
import math
import time
Background = pyglet.graphics.OrderedGroup(0)
Walls_Group = pyglet.graphics.OrderedGroup(1)
def preload_image(image):
img = pyglet.image.load('images/' + image)
return img
map_x = 50
map_y = 50
window_X = 1500
window_Y = 900
class GameWindow(pyglet.window.Window):
def __init__(self, *args, **kwargs):
super(GameWindow, self).__init__(*args, **kwargs)
self.set_location(100, 30)
self.frame_rate = 1.0 / 100.0
self.fps_display = FPSDisplay(self)
self.fps_display.label.font_size = 30
self.player_speed = 550
self.right = False
self.left = False
self.up = False
self.down = False
self.map_load = False
self.Walls_load = False
self.map_scale = 1
self.wall = preload_image('block.png')
self.wall_list = []
self.map_1_list = []
self.sprite = preload_image('Grass_Green.jpg')
self.main_batch = pyglet.graphics.Batch()
self.alive = True
self.last_scheduled_update = time.time()
if not self.map_load:
self.Mapka(map_x, map_y)
self.map_load = True
if not self.Walls_load:
self.Walls()
self.Walls_load = True
def Mapka(self, x_size, y_size):
for Y in range(y_size):
for X in range(x_size):
self.map_1_list.append(pyglet.sprite.Sprite(self.sprite, x=X * (self.sprite.width*self.map_scale), y=Y * (self.sprite.height*self.map_scale), batch=self.main_batch, group=Background))
for i in self.map_1_list:
i.scale = self.map_scale
def Walls(self):
self.times = math.ceil(map_x * (self.sprite.width*self.map_scale) / self.wall.width) # Oblicza ilość ścian na dolnej części
# mapy z zaokrągleniem
self.times_y = math.ceil(map_y * (self.sprite.height*self.map_scale) / self.wall.height)
for x in range(int(self.times)):
self.wall_list.append(
pyglet.sprite.Sprite(self.wall, x=x * self.wall.width, y=0, batch=self.main_batch, group=Walls_Group))
self.wall_list.append(
pyglet.sprite.Sprite(self.wall, x=x * self.wall.width, y=(self.times_y - 1) * self.wall.height,
batch=self.main_batch, group=Walls_Group))
for y in range(int(self.times_y)):
self.wall_list.append(
pyglet.sprite.Sprite(self.wall, x=0, y=y * self.wall.height, batch=self.main_batch, group=Walls_Group))
self.wall_list.append(pyglet.sprite.Sprite(self.wall, x=self.times * self.wall.width - self.wall.width,
y=y * self.wall.height, batch=self.main_batch,
group=Walls_Group))
def render(self):
self.clear()
self.main_batch.draw()
self.fps_display.draw()
self.flip()
def on_key_press(self, symbol, modifiers):
if symbol == key.D:
self.right = True
if symbol == key.A:
self.left = True
if symbol == key.W:
self.up = True
if symbol == key.S:
self.down = True
if symbol == key.ESCAPE: # [ESC]
self.alive = 0
self.update(1)
def on_key_release(self, symbol, modifiers):
if symbol == key.D:
self.right = False
if symbol == key.A:
self.left = False
if symbol == key.W:
self.up = False
if symbol == key.S:
self.down = False
def update_space(self, dt):
for space in self.map_1_list:
space.update()
space.y -= 0 * dt
if self.right:
space.x -= self.player_speed * dt
if self.left:
space.x += self.player_speed * dt
if self.up:
space.y -= self.player_speed * dt
if self.down:
space.y += self.player_speed * dt
def update_wall(self, dt):
for wall in self.wall_list:
wall.update()
if self.right:
wall.x -= self.player_speed * dt
if self.left:
wall.x += self.player_speed * dt
if self.up:
wall.y -= self.player_speed * dt
if self.down:
wall.y += self.player_speed * dt
def update(self, dt):
self.update_wall(dt)
self.update_space(dt)
def run(self):
while self.alive == 1:
if time.time() - self.last_scheduled_update > 0.25:
self.update(time.time() - self.last_scheduled_update)
self.last_scheduled_update = time.time()
self.render()
# -----------> This is key <----------
# This is what replaces pyglet.app.run()
# but is required for the GUI to not freeze
#
event = self.dispatch_events()
if __name__ == "__main__":
window = GameWindow(window_X, window_Y, "Gra", resizable=False)
window.run()
Это минимальное изменение в коде, но вы меняете встроенный планировщик своим собственным циклом событий, вы отвечаете за время и критериидля бега self.update()
.В этом случае он запускается каждые 0.25
секунд с интервалом и после срабатывания каждого on_keypress
.
Нет причин обновлять позиции спрайтов, если вы не перемещаетесь.Или в будущем, когда враги / объекты будут выполнять действия.
Я получу устойчивые 144 FPS с этим кодом.
Но здесь есть еще кое-что ... поэтому я оставлю длительнымсовет , который поможет вам решить будущие шейки бутылок.И я продемонстрирую, как вы будете его использовать.
Выполнение вышеуказанных команд даст вам что-то вроде этого:
И это ясно показывает, что основной цикл цикличен как _wait_vsync
.
Что заставило меня понять, что я забыл проверить самую очевидную вещь - проблему здесь.И это то, что вы и я забыли vsync=False
к объекту окна.
Решение здесь:
window = GameWindow(window_X, window_Y, "Gra", resizable=False, vsync=False)
Что дает мне:
Да, это выше 2700 FPS.
И стек вызовов выглядит намного более ровным:
С этого момента и здесь начинаются настоящие проблемы.
Любая сделанная оптимизация будет незначительной, трудной для поиска и сложной для отладки.
Надеюсь, у вас есть инструменты и вы поймете, где и почемусмотреть на места:)