Я пишу 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()