Python 3.x pyglet中的平铺贴图,fps放置

Python 3.x pyglet中的平铺贴图,fps放置,python-3.x,pyglet,Python 3.x,Pyglet,我的英语糟透了,我尽力写这个问题:D 我正在用Pyglet制作一个2D游戏,我需要制作一个平铺地图。 1个平铺=50像素x 50像素 但是当我用20个敌人绘制地图50x50时,我的fps从60fps下降到10fps,这需要很大的PC能力 每一块瓷砖和每一个敌人都是批量绘制的。 我能做些什么来提高我的游戏效率 我尝试缩放瓷砖,但我在每个瓷砖上都有一个黑色边框,我想要50×50像素的瓷砖,而不是50×50/缩放 #Create blocks 50x50 pixels and replace with

我的英语糟透了,我尽力写这个问题:D

我正在用Pyglet制作一个2D游戏,我需要制作一个平铺地图。 1个平铺=50像素x 50像素 但是当我用20个敌人绘制地图50x50时,我的fps从60fps下降到10fps,这需要很大的PC能力 每一块瓷砖和每一个敌人都是批量绘制的。 我能做些什么来提高我的游戏效率

我尝试缩放瓷砖,但我在每个瓷砖上都有一个黑色边框,我想要50×50像素的瓷砖,而不是50×50/缩放

#Create blocks 50x50 pixels and replace with image names to get what i see.
from pyglet.window import key, FPSDisplay
import pyglet
import math

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().__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.png')
        self.main_batch = pyglet.graphics.Batch()

    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 on_draw(self):
        self.clear()
        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
        self.main_batch.draw()
        self.fps_display.draw()

    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:
            pyglet.app.exit()

    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)

if __name__ == "__main__":
    window = GameWindow(window_X, window_Y, "Gra", resizable=False)
    pyglet.clock.schedule_interval(window.update, window.frame_rate)
    pyglet.app.run()
我想有至少100 x 100瓷砖,可以在60 fps的工作平铺地图。 平铺=50x50像素
如果可以绘制平铺,但只绘制屏幕上可见的平铺,不超过屏幕X,Y。

好的,那么这里的主要问题可能是
计划间隔
,它不能尽可能快地运行。主要是因为它更新场景,并触发渲染。第二个是
wall.update()
调用(我不知道您调用它的确切原因)非常慢,而且您要执行宽度*高度^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()
这给了我:

是的,速度超过2700 FPS。
而调用堆栈看起来更为均衡:

从现在开始,真正的挑战就从这里开始。
完成的任何优化都是次要的,很难找到,并且是调试的挑战


希望你有这些工具,并且了解在哪里以及为什么要查看位置:)

好的,所以这里的主要问题可能是
计划间隔
,它没有尽可能快地运行。主要是因为它更新场景,并触发渲染。第二个是
wall.update()
调用(我不知道您调用它的确切原因)非常慢,而且您要执行宽度*高度^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()
这给了我:

是的,速度超过2700 FPS。
而调用堆栈看起来更为均衡:

从现在开始,真正的挑战就从这里开始。
完成的任何优化都是次要的,很难找到,并且是调试的挑战


希望您拥有这些工具,并了解查看位置的位置和原因:)

我们至少需要了解三件事,1)如何创建这些瓷砖,2)如何更新它们的位置,3)如何渲染它们?如果你能从你的代码中删掉这三样东西,那将对我们有很大帮助。我想我知道问题出在哪里,但我想先看看这些代码:)我添加了你要求的代码。好的,我只想感谢你给我们的代码正是我们希望用户发布的代码。它是最小的,它是可执行的,它显示了问题!写一个很好的问题很好-我希望下面的解决方案对你有用。祝你的项目好运!:)(你的英语非常好)我们至少需要看三件事,1)你如何创建这些瓷砖,2)你如何更新它们的位置,3)你如何渲染它们?如果你能从你的代码中删掉这三样东西,那将对我们有很大帮助。我想我知道问题出在哪里,但我想先看看这些代码:)我添加了你要求的代码。好的,我只想感谢你给我们的代码正是我们希望用户发布的代码。它是最小的,它是可执行的,它显示了问题!写一个很好的问题很好-我希望下面的解决方案对你有用。祝你的项目好运!:)(你的英语非常好)