71 lines
2.3 KiB
Python
71 lines
2.3 KiB
Python
import os
|
|
import threading
|
|
from math import floor
|
|
from typing import Optional
|
|
|
|
import pygame
|
|
|
|
|
|
class ImageHandler:
|
|
def __init__(self, maps_dir: str, base_size: int):
|
|
self.maps_dir: str = maps_dir
|
|
self.base_size: int = base_size
|
|
self.cache: dict = {}
|
|
self.count: int = 0
|
|
self.total: int = 0
|
|
self.loading: bool = False
|
|
|
|
t = threading.Thread(target=self.load_base_images)
|
|
t.start()
|
|
|
|
def load_base_images(self) -> None:
|
|
cache = {}
|
|
paths = os.listdir(self.maps_dir)
|
|
self.loading = True
|
|
self.count = 0
|
|
self.total = len(paths)
|
|
for path in paths:
|
|
fullpath = os.path.join(self.maps_dir, path)
|
|
name, x, y = path.split(".")[0].split("_")
|
|
cache[(int(x), int(y))] = pygame.image.load(fullpath).convert_alpha()
|
|
self.count += 1
|
|
|
|
self.cache = {
|
|
1: cache
|
|
}
|
|
self.loading = False
|
|
|
|
def get_for_pos(self, x: int, y: int, zoom: float = 1) -> Optional[pygame.Surface]:
|
|
cache = self.cache.get(zoom, {})
|
|
pos = (x, y)
|
|
if pos not in cache:
|
|
if zoom == 1:
|
|
return None
|
|
|
|
# Multiple maps per zone
|
|
elif zoom < 1:
|
|
img = pygame.Surface((self.base_size, self.base_size), pygame.SRCALPHA)
|
|
n_maps = int(1 / zoom)
|
|
sub_size = self.base_size * zoom
|
|
for sub_y in range(n_maps):
|
|
for sub_x in range(n_maps):
|
|
sub_img = self.get_for_pos(x * n_maps + sub_x, y * n_maps + sub_y, 1)
|
|
if sub_img is not None:
|
|
sub_img = pygame.transform.scale_by(sub_img, zoom)
|
|
img.blit(sub_img, [sub_x * sub_size, sub_y * sub_size])
|
|
|
|
# Zone is part of a map
|
|
else:
|
|
img = self.get_for_pos(floor(x / zoom), floor(y / zoom), 1)
|
|
if img is not None:
|
|
sub_x = x % zoom
|
|
sub_y = y % zoom
|
|
sub_size = self.base_size / zoom
|
|
img = img.subsurface([sub_x * sub_size, sub_y * sub_size, sub_size, sub_size])
|
|
img = pygame.transform.scale_by(img, zoom)
|
|
|
|
cache[pos] = img
|
|
|
|
self.cache[zoom] = cache
|
|
return cache[pos]
|