Finally fixed sprite caching. For now it works only for one map, need to develop mapmanager and have a list of cached sprites for each map.
This commit is contained in:
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -5,12 +5,6 @@ from dataclasses import dataclass, field
|
|||||||
from copy import deepcopy
|
from copy import deepcopy
|
||||||
import pygame
|
import pygame
|
||||||
|
|
||||||
|
|
||||||
def scale_image(image, n):
|
|
||||||
orig_size = image.get_size()
|
|
||||||
new_size = (int(orig_size[0] * n), int(orig_size[1] * n))
|
|
||||||
return pygame.transform.smoothscale(image, new_size)
|
|
||||||
|
|
||||||
def path_exists(data, path):
|
def path_exists(data, path):
|
||||||
current = data
|
current = data
|
||||||
for key in path:
|
for key in path:
|
||||||
|
|||||||
77
eb_engine.py
77
eb_engine.py
@@ -12,6 +12,10 @@ cell_classes = {"grass_small": eb_terrain_objects.Ground,
|
|||||||
main_dir = os.path.dirname(os.path.abspath(__file__))
|
main_dir = os.path.dirname(os.path.abspath(__file__))
|
||||||
sprites_dir = os.path.join(main_dir, "res", "sprites")
|
sprites_dir = os.path.join(main_dir, "res", "sprites")
|
||||||
|
|
||||||
|
#class MapManager
|
||||||
|
#class Event
|
||||||
|
#class EventManager
|
||||||
|
|
||||||
@dataclass
|
@dataclass
|
||||||
class Cell:
|
class Cell:
|
||||||
terrain_obj: any
|
terrain_obj: any
|
||||||
@@ -23,16 +27,16 @@ class Cell:
|
|||||||
class Map:
|
class Map:
|
||||||
name: str
|
name: str
|
||||||
sprites: dict
|
sprites: dict
|
||||||
sprites_refresh: int = 60
|
sprites_refresh: int = 60
|
||||||
cells: dict = field(default_factory = dict)
|
cells: dict = field(default_factory = dict)
|
||||||
color: str = "gray57"
|
color: str = "gray57"
|
||||||
target_color: str = "gold"
|
target_color: str = "gold"
|
||||||
size: int = 150
|
size: int = 150
|
||||||
bord: int = 3
|
bord: int = 3
|
||||||
scale: float = 1
|
scale: float = 1
|
||||||
cam_x: int = 0
|
cam_x: int = 0
|
||||||
cam_y: int = 0
|
cam_y: int = 0
|
||||||
cell_dist: int = 1
|
cell_dist: int = 1
|
||||||
|
|
||||||
def __post_init__(self):
|
def __post_init__(self):
|
||||||
self.cells = {}
|
self.cells = {}
|
||||||
@@ -60,8 +64,10 @@ class Map:
|
|||||||
"screen": screen}
|
"screen": screen}
|
||||||
|
|
||||||
cell.terrain_obj.draw(dd)
|
cell.terrain_obj.draw(dd)
|
||||||
|
|
||||||
if cell.item_obj:
|
if cell.item_obj:
|
||||||
cell.item_obj.draw(dd)
|
cell.item_obj.draw(dd)
|
||||||
|
|
||||||
if cell.creature_obj:
|
if cell.creature_obj:
|
||||||
cell.creature_obj.draw(dd)
|
cell.creature_obj.draw(dd)
|
||||||
|
|
||||||
@@ -70,20 +76,25 @@ class Map:
|
|||||||
|
|
||||||
@dataclass
|
@dataclass
|
||||||
class Engine:
|
class Engine:
|
||||||
sprites: dict = field(default_factory = dict)
|
sprites: dict = field(default_factory = dict)
|
||||||
screen: pygame.Surface = ((1, 1))
|
cached_sprites: dict = field(default_factory = dict)
|
||||||
width: int = 1600
|
screen: pygame.Surface = ((1, 1))
|
||||||
height: int = 800
|
width: int = 1600
|
||||||
camera_step: int = 10
|
height: int = 800
|
||||||
scale_step: float = 0.01
|
camera_step: int = 10
|
||||||
|
scale_step: float = 0.01
|
||||||
|
spr_scale: float = 1
|
||||||
|
|
||||||
def __post_init__(self):
|
def __post_init__(self):
|
||||||
self.sprites = {}
|
self.sprites = {}
|
||||||
pygame.init()
|
pygame.init()
|
||||||
pygame.display.set_caption('Elvenbane')
|
pygame.display.set_caption('Elvenbane')
|
||||||
self.screen = pygame.display.set_mode((self.width, self.height), pygame.HWSURFACE | pygame.DOUBLEBUF)
|
self.screen = pygame.display.set_mode((self.width, self.height), pygame.HWSURFACE | pygame.DOUBLEBUF)
|
||||||
self.load_sprites()
|
|
||||||
print("The engine has started. Sprites were successfully loaded.\n")
|
print("The engine has started. Sprites were successfully loaded.\n")
|
||||||
|
self.load_sprites()
|
||||||
|
print("Sprites were successfully loaded.\n")
|
||||||
|
self.cached_sprites = deepcopy(self.sprites)
|
||||||
|
print("Sprites were successfully cached.\n")
|
||||||
|
|
||||||
def load_sprites(self, folder_path = sprites_dir):
|
def load_sprites(self, folder_path = sprites_dir):
|
||||||
self.sprites = {}
|
self.sprites = {}
|
||||||
@@ -104,8 +115,20 @@ class Engine:
|
|||||||
for num, f in items
|
for num, f in items
|
||||||
]
|
]
|
||||||
|
|
||||||
|
def scale_image(self, image):
|
||||||
|
orig_size = image.get_size()
|
||||||
|
new_size = (int(orig_size[0] * self.spr_scale), int(orig_size[1] * self.spr_scale))
|
||||||
|
return pygame.transform.smoothscale(image, new_size)
|
||||||
|
|
||||||
|
def scale_sprites(self):
|
||||||
|
for sp_name, sprite_list in self.sprites.items():
|
||||||
|
for i, sprite in enumerate(sprite_list):
|
||||||
|
scaled = self.scale_image(sprite)
|
||||||
|
self.cached_sprites[sp_name][i] = scaled
|
||||||
|
|
||||||
|
|
||||||
def main_loop(self):
|
def main_loop(self):
|
||||||
easy_map = Map("def_map.json", self.sprites)
|
easy_map = Map("def_map.json", self.cached_sprites)
|
||||||
#sp = eb_objects.Sprite(self.sprites, "elf_watching")
|
#sp = eb_objects.Sprite(self.sprites, "elf_watching")
|
||||||
#gr = pygame.image.load(file_path).convert_alpha()
|
#gr = pygame.image.load(file_path).convert_alpha()
|
||||||
|
|
||||||
@@ -119,16 +142,16 @@ class Engine:
|
|||||||
|
|
||||||
# profiling
|
# profiling
|
||||||
|
|
||||||
process = psutil.Process(os.getpid())
|
#process = psutil.Process(os.getpid())
|
||||||
gc.collect()
|
#gc.collect()
|
||||||
mem_before = process.memory_info().rss / 1024
|
#mem_before = process.memory_info().rss / 1024
|
||||||
|
|
||||||
while running:
|
while running:
|
||||||
#pygame.event.clear()
|
#pygame.event.clear()
|
||||||
if global_counter % 1000 == 0:
|
#if global_counter % 1000 == 0:
|
||||||
gc.collect()
|
# gc.collect()
|
||||||
mem_after = process.memory_info().rss / 1024
|
# mem_after = process.memory_info().rss / 1024
|
||||||
print(f"Leak: {mem_after - mem_before:.1f} KB per 1000 frames")
|
# print(f"Leak: {mem_after - mem_before:.1f} KB per 1000 frames")
|
||||||
|
|
||||||
# poll for events
|
# poll for events
|
||||||
# pygame.QUIT event means the user clicked X to close your window
|
# pygame.QUIT event means the user clicked X to close your window
|
||||||
@@ -154,8 +177,12 @@ class Engine:
|
|||||||
easy_map.cam_x -= self.camera_step
|
easy_map.cam_x -= self.camera_step
|
||||||
if keys[pygame.K_q]:
|
if keys[pygame.K_q]:
|
||||||
easy_map.scale += self.scale_step
|
easy_map.scale += self.scale_step
|
||||||
|
self.spr_scale += self.scale_step
|
||||||
|
self.scale_sprites()
|
||||||
if keys[pygame.K_e] and easy_map.scale >= self.scale_step:
|
if keys[pygame.K_e] and easy_map.scale >= self.scale_step:
|
||||||
easy_map.scale -= self.scale_step
|
easy_map.scale -= self.scale_step
|
||||||
|
self.spr_scale -= self.scale_step
|
||||||
|
self.scale_sprites()
|
||||||
if keys[pygame.K_ESCAPE]:
|
if keys[pygame.K_ESCAPE]:
|
||||||
running = False
|
running = False
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
from common import deepcopy, dataclass, field, scale_image, path_exists
|
from common import deepcopy, dataclass, field, path_exists
|
||||||
|
|
||||||
@dataclass
|
@dataclass
|
||||||
class Object:
|
class Object:
|
||||||
@@ -6,37 +6,15 @@ class Object:
|
|||||||
name: str
|
name: str
|
||||||
sprite_name: str
|
sprite_name: str
|
||||||
sprite_state: int = 0
|
sprite_state: int = 0
|
||||||
#sprite_scale: int = 1
|
|
||||||
#sprite_cache: dict = field(default_factory = dict)
|
|
||||||
#sprite_cache_upd: int = 100
|
|
||||||
#
|
|
||||||
#def cache_sprite(self, sprites):
|
|
||||||
# if self.sprite_name not in self.sprite_cache:
|
|
||||||
# self.sprite_cache[self.sprite_name] = {}
|
|
||||||
# self.sprite_cache[self.sprite_name][self.sprite_state] = deepcopy(sprites[self.sprite_name][self.sprite_state])
|
|
||||||
#
|
|
||||||
#def scale_cached(self, draw_data):
|
|
||||||
# if self.sprite_scale != draw_data["scale"]:
|
|
||||||
# self.sprite_scale = draw_data["scale"]
|
|
||||||
# self.sprite_cache[self.sprite_name][self.sprite_state] = deepcopy(scale_image(draw_data["sprites"][self.sprite_name][self.sprite_state], draw_data["scale"]))
|
|
||||||
|
|
||||||
|
|
||||||
def draw(self, draw_data):
|
def draw(self, draw_data):
|
||||||
#if draw_data["global_counter"] > self.sprite_cache_upd:
|
|
||||||
# self.sprite_cache = {}
|
|
||||||
|
|
||||||
if draw_data["spr_up"] == 0:
|
if draw_data["spr_up"] == 0:
|
||||||
if self.sprite_state == len(draw_data["sprites"][self.sprite_name]) - 1:
|
if self.sprite_state == len(draw_data["sprites"][self.sprite_name]) - 1:
|
||||||
self.sprite_state = 0
|
self.sprite_state = 0
|
||||||
else:
|
else:
|
||||||
self.sprite_state += 1
|
self.sprite_state += 1
|
||||||
|
|
||||||
#if path_exists(self.sprite_cache, [self.sprite_name, self.sprite_state]):
|
sp = draw_data["sprites"][self.sprite_name][self.sprite_state]
|
||||||
# self.scale_cached(draw_data)
|
|
||||||
#else:
|
|
||||||
# self.cache_sprite(draw_data["sprites"])
|
|
||||||
|
|
||||||
sp = scale_image(draw_data["sprites"][self.sprite_name][self.sprite_state], draw_data["scale"])
|
|
||||||
rect = sp.get_rect(center = (draw_data["x"] + draw_data["w"] /2, draw_data["y"] + draw_data["h"]/ 2))
|
rect = sp.get_rect(center = (draw_data["x"] + draw_data["w"] /2, draw_data["y"] + draw_data["h"]/ 2))
|
||||||
draw_data["screen"].blit(sp, rect)
|
draw_data["screen"].blit(sp, rect)
|
||||||
|
|
||||||
|
|||||||
3
main.py
3
main.py
@@ -17,6 +17,7 @@ if __name__ == "__main__":
|
|||||||
# - кнопка отключить сетку
|
# - кнопка отключить сетку
|
||||||
# - строка ввода
|
# - строка ввода
|
||||||
# - клик
|
# - клик
|
||||||
|
# - вывод stdout на отдельную панель, полный экран, потом масштабирование всего под размер экрана
|
||||||
# Поиск пути, очередь задач для существ
|
# Поиск пути, очередь задач для существ
|
||||||
# Редактор карты
|
# Редактор карты
|
||||||
# Охотник -> деревня
|
# Охотник -> деревня
|
||||||
@@ -37,5 +38,5 @@ if __name__ == "__main__":
|
|||||||
#size = width, height = 640, 480
|
#size = width, height = 640, 480
|
||||||
## Use HWSURFACE and DOUBLEBUF flags
|
## Use HWSURFACE and DOUBLEBUF flags
|
||||||
#screen = pygame.display.set_mode(size, pygame.HWSURFACE | pygame.DOUBLEBUF)
|
#screen = pygame.display.set_mode(size, pygame.HWSURFACE | pygame.DOUBLEBUF)
|
||||||
# кэширование спрайтов - скалировать сразу все на уровне движка!
|
|
||||||
# изучить pypmler
|
# изучить pypmler
|
||||||
|
# настроить логирование всего
|
||||||
Reference in New Issue
Block a user