Добавлен новый класс Camera. Что заставляет мое приложение pyglet работать медленно? - PullRequest
0 голосов
/ 02 декабря 2019

Я пишу RPG-игру с открытым миром, и она находится на очень ранних стадиях.

Я пытаюсь написать класс камеры, который показывает разные части света.

Вернотеперь я получаю только 15 кадров в секунду, тогда как в предыдущих частях разработки я мог рендерить больше объектов со скоростью около 50 кадров в секунду. Теоретически, мой класс камеры должен помочь ускорить время, необходимое для рендеринга каждого кадра.

Я просто хотел еще одну пару глаз на код (простите, насколько это грязно / неэффективно), чтобы я мог получитьпонимание того, что именно вызывает замедление, и некоторые идеи о том, как я мог бы это исправить.

import pyglet
from pyglet.window import key
from pyglet import clock
from PIL import Image
from PIL import ImageOps
import random
pyglet.options['debug_gl'] = False

pyglet.resource.path = ['../resources']
pyglet.resource.reindex()
win_w = 1280
win_h = 720
if win_w == 1440: #90px
    scale_factor = 1 
elif win_w == 1080: #67.5px
    scale_factor = 0.75
elif win_h == 720: #45px
    scale_factor = 0.5
fps = 0
debug = True


game_window = pyglet.window.Window(width=win_w, height=win_h, caption="Townie", vsync=True)
#Control Dictionary
c_dict = {"down" : False, "up" : False, "left" : False, "right" : False}
mx = 0
my = 0


def center_image(image):
    """Sets an image's anchor point to its center"""
    image.anchor_x = image.width // 2
    image.anchor_y = image.height // 2

def pointinside(point,t):
    px = point[0]
    py = point[1]
    if (px >= t.x) and px <= (t.x + t.width):
        if (py >= t.y) and py <= (t.y + t.height):
            return True
        else:
            return False
    else:
        return False

def overlapping(a,b):
    bl = (a.x,a.y)
    br = ((a.x + a.width),(a.y))
    tl = ((a.x),(a.y + a.height))
    tr = ((a.x + a.width),(a.y + a.height))
    if pointinside(bl,b) or pointinside(br,b) or pointinside(tl,b) or pointinside(tr,b):
        return True
    else:
        return False



class Area:
    def __init__(self,name,pallete,pos):
        self.name = name
        self.pallete = pallete
        self.position = pos

bg_batch = pyglet.graphics.Batch()
fg_batch = pyglet.graphics.Batch()
grid = []

label = pyglet.text.Label("",font_name='Arial',font_size=12,x=10, y=(win_h-20),batch=fg_batch)
mouse_x_label = pyglet.text.Label("X: ",font_name='Arial',font_size=12,x=10, y=(win_h-40),batch=fg_batch)
mouse_y_label = pyglet.text.Label("Y: ",font_name='Arial',font_size=12,x=10, y=(win_h-60),batch=fg_batch)
mouse_x_label.color = (0,0,255,255)
mouse_y_label.color = (255,0,0,255)
area_name_label = pyglet.text.Label("",font_name='Arial',font_size=12,x=10, y=(win_h-80),batch=fg_batch)
output_label = pyglet.text.Label("",font_name='Arial',font_size=12,x=10, y=(win_h-100),batch=fg_batch)


gs = pyglet.resource.image("grid_square.png")
grass = pyglet.resource.image("grass.png")
sunflower = pyglet.resource.image("sun_flower.png")
sunflower2 = pyglet.resource.image("sun_flower_2.png")
#water = pyglet.resource.image("water.png")
water_seq = [pyglet.resource.image("water.png"),pyglet.resource.image("water2.png"),pyglet.resource.image("water3.png"),pyglet.resource.image("water4.png"),pyglet.resource.image("water3.png"),pyglet.resource.image("water2.png")]
water_anim = pyglet.image.Animation.from_image_sequence(water_seq, 0.2, loop=True)
road = pyglet.resource.image("road.png")
road_stripe = pyglet.resource.image("road1.png")
road_grass_top =  pyglet.resource.image("road_grass_on_top.png")
road_grass_bottom =  pyglet.resource.image("road_grass_on_bottom.png")
brick = pyglet.resource.image("brick.png")
brick_front = pyglet.resource.image("brick_front.png")
brick_top = pyglet.resource.image("brick_top.png")
sand = pyglet.resource.image("sand.png")

green = (0, 127, 14, 255)
lime = (76,255,0,255)
red = (255,0,0,255)
dark_red = (127,0,0,255)
blue = (0, 19, 127, 255)
navy = (33,0,127,255)
magenta = (255,0,220,255)
cyan = (0,255,255,255)
dark_cyan = (0,165,165,255)
yellow = (255,216,0,255)
dark_yellow = (224,187,0,255)
pink = (255,127,237,255)
purple = (127,0,110,255)
orange = (255,106,0,255)
dark_orange = (160,64,0,255)
black = (0,0,0,255)

start_pallete = [(green,grass,False),
                 (blue,water_anim,True),
                 (magenta,road_stripe,False),
                 (cyan,road_grass_top,False),
                 (dark_cyan,road_grass_bottom,False),
                 (yellow,road,False),
                 (black,gs,False),
                 (orange,sunflower,False),
                 (dark_orange,sunflower2,False),
                 (pink,brick_front,True),
                 (purple,brick_top,True),
                 (red,brick,True),
                 (dark_yellow,sand,False)]

active_area = Area("Starting Area",start_pallete,(0,0))
map_image = Image.open("../resources/map.png")
map_image = ImageOps.flip(map_image) #Pyglet draws from the bottom left, so we have to flip the image.
pix = map_image.load()

class Tile(pyglet.sprite.Sprite):
    def __init__(self,img,xpos,ypos,batch_name,collides,world_pos):
        super().__init__(img,x=xpos,y=ypos,batch=batch_name)
        self.col = collides
        self.world_pos = world_pos
    def update(self,dt):
        pass

for x in range(0,map_image.width):
    grid.append([])
    for y in range(0,map_image.height):
        for p in active_area.pallete:
            if p[0] == pix[x,y]:
                grid[x].append(Tile(p[1],xpos=(x*26+1),ypos=(y*26+1),batch_name=bg_batch,collides=p[2],world_pos=(x,y)))

#Define Player Animations
walking_down_seq = [pyglet.resource.image("brendan_3_scaled.png"),pyglet.resource.image("brendan_1_scaled.png"),pyglet.resource.image("brendan_2_scaled.png"),pyglet.resource.image("brendan_1_scaled.png")]
walking_up_seq = [pyglet.resource.image("brendan_3_scaled_uw.png"),pyglet.resource.image("brendan_1_scaled_uw.png"),pyglet.resource.image("brendan_2_scaled_uw.png"),pyglet.resource.image("brendan_1_scaled_uw.png")]
walking_left = [pyglet.resource.image("brendan_3_scaled_s.png"),pyglet.resource.image("brendan_1_scaled_s.png"),pyglet.resource.image("brendan_2_scaled_s.png"),pyglet.resource.image("brendan_1_scaled_s.png")]
walking_right = [pyglet.resource.image("brendan_3_scaled_s2.png"),pyglet.resource.image("brendan_1_scaled_s2.png"),pyglet.resource.image("brendan_2_scaled_s2.png"),pyglet.resource.image("brendan_1_scaled_s2.png")]

walking_down_anim = pyglet.image.Animation.from_image_sequence(walking_down_seq, 0.15, loop=True)
walking_up_anim = pyglet.image.Animation.from_image_sequence(walking_up_seq, 0.15, loop=True)
walking_left_anim = pyglet.image.Animation.from_image_sequence(walking_left, 0.15, loop=True)
walking_right_anim = pyglet.image.Animation.from_image_sequence(walking_right, 0.15, loop=True)

standing_d = pyglet.resource.image("brendan_1_scaled.png")
standing_u = pyglet.resource.image("brendan_1_scaled_uw.png")
standing_l = pyglet.resource.image("brendan_1_scaled_s.png")
standing_r = pyglet.resource.image("brendan_1_scaled_s2.png")


class Camera:
    def __init__(self):
        self.center = (50,49)
        self.res = (30,30)

    def update(self,time):
        global bg_batch
        global grid
        bg_batch = pyglet.graphics.Batch()
        ix = 0
        iy = 0
        for x in range(0,self.res[0]):
            for y in range(0,self.res[1]):               
                tryx = int(self.center[0] - self.res[0]/2 + x)
                tryy = int(self.center[1] - self.res[1]/2 + y)     
                cursor = grid[int(self.center[0] - self.res[0]/2) + x][int(self.center[1] - self.res[1]/2) + y]                               
                cursor.batch = bg_batch
                cursor.update(time)
                cursor.x = cursor.width*ix
                cursor.y = cursor.width*iy
                iy += 1
            ix += 1
            iy = 0


class player(pyglet.sprite.Sprite):
    def __init__(self,img,xpos,ypos):
        super().__init__(img,x=xpos,y=ypos)
        self.scale = 0.08
        self.speed = 115
        self.state = ("standing",2.0)
        self.col = False
    # def colliding(self,t):
    #     left = False
    #     right = False
    #     top = False
    #     bottom = False
    #     if t.col:
    #         if (self.x >= t.x and self.x <= (t.x + t.width)):
    #             left = True
    #         if (self.y >= t.y and self.y <= (t.y + t.height)):
    #             top = True
    #         if (self.x + self.width >= t.x and self.x + self.width <= (t.x + t.width)):
    #             right = True
    #         if (self.y + self.height/2 >= t.y and self.y + self.height/2 <= (t.y + t.height)):
    #             bottom = True

    #         if (left and top) or (right and top) or (right and bottom) or (left and bottom):
    #             return True
    #         else:
    #             return False
    #     else:
    #         return False

    def update(self,dt):
        col = False
        old_p = (self.x,self.y)
        if c_dict["down"]:
            if self.image != walking_down_anim:
                self.image = walking_down_anim
            self.y += -self.speed * dt
            self.state = ("walking",2.0)
        elif c_dict["up"]:
            if self.image != walking_up_anim:
                self.image = walking_up_anim
            self.y += self.speed * dt
            self.state = ("walking",0.0)
        elif c_dict["left"]:
            if self.image != walking_left_anim:
                self.image = walking_left_anim
            if not col:
                self.x += -self.speed * dt
                self.state = ("walking",3.0)
        elif c_dict["right"]:
            if self.image != walking_right_anim:
                self.image = walking_right_anim
            self.x += self.speed * dt
            self.state = ("walking",1.0)

        self.col = False         
        # for t in grid:
        #     if t.col:
        #         if overlapping(player,t):
        #             self.col = True

        # #Make it where if the player walks off the edge of the screen, they appear on the opposite side.
        # if self.x > win_w and self.image == walking_right_anim:
        #     self.x = 0 - self.width
        # if self.y > win_h and self.image == walking_up_anim:
        #     self.y = 0 - self.height

        # if self.y <= 0 - self.height and self.image == walking_down_anim:
        #     self.y = win_h + self.height
        # if self.x <= 0 - self.width and self.image == walking_left_anim:
        #     self.x = win_w + self.width





player = player(standing_d,win_w/2,win_h/2)
player.x += -player.width/2 #completely center
player.world_pos = (50,49)
camera = Camera()

def draw_main():
    game_window.clear()
    bg_batch.draw()
    player.draw()
    if debug:
        fg_batch.draw()


def update_main(time):
    global fps
    fps = fps + 1
    player.update(time)
    camera.update(time)
    label.text = str(int(pyglet.clock.get_fps()))
    mouse_x_label.text = "X: " + str(mx)
    mouse_y_label.text = "Y: " + str(my)
    #area_name_label.text = active_area.name
    if int(label.text) >= 60:
        label.color = (0,255,0,255)
    elif int(label.text) >= 56 and int(label.text) < 60:
        label.color = (255,255,0,255)
    elif int(label.text) <= 55:
        label.color = (255,0,0,255)



@game_window.event
def on_draw():
    draw_main()

@game_window.event
def on_key_press(symbol, modifiers):
    global debug
    if symbol == key.DOWN:
        c_dict["down"] = True
    elif symbol == key.UP:
        c_dict["up"] = True
    elif symbol == key.LEFT:
        c_dict["left"] = True
    elif symbol == key.RIGHT:
        c_dict["right"] = True
    elif symbol == key.D and not debug:
        debug = True
    elif symbol == key.D and debug:
        debug = False 

@game_window.event
def on_key_release(symbol, modifiers):
    if symbol == key.DOWN:
        c_dict["down"] = False
        player.image = standing_d
        player.state = ("standing",2.0)
        camera.center = (camera.center[0], camera.center[1] - 1)
    elif symbol == key.UP:
        c_dict["up"] = False
        player.image = standing_u
        player.state = ("standing",0.0)
        camera.center = (camera.center[0], camera.center[1] + 1)
    elif symbol == key.LEFT:
        c_dict["left"] = False
        player.image = standing_l
        player.state = ("standing",3.0)
        camera.center = (camera.center[0] - 1, camera.center[1])
    elif symbol == key.RIGHT:
        c_dict["right"] = False
        player.image = standing_r
        player.state = ("standing",2.0)
        camera.center = (camera.center[0] + 1, camera.center[1])

@game_window.event
def on_mouse_motion(x, y, dx, dy):
    global mx
    global my
    mx = x
    my = y 

pyglet.clock.schedule_interval(update_main, 1.0/120.0)
pyglet.app.run()
...