P.S. to previous commit: instead of Sprite flow load_sprites function was changed: gathering the number of sprites with the same names before second _ and hold it at sprites dict. also now sprites must be named as objectname_action_number. Main commit - full sprites support, with caching, transparency and smooth scaling. drawing function moved to Object methods

This commit is contained in:
shiva404
2026-02-15 21:23:02 +03:00
parent ab58803373
commit f679dde81f
12 changed files with 637 additions and 838 deletions

Binary file not shown.

View File

@@ -3,4 +3,10 @@ import json
import uuid import uuid
from dataclasses import dataclass, field 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)

File diff suppressed because it is too large Load Diff

View File

@@ -3,20 +3,17 @@ import eb_objects
import eb_terrain_objects import eb_terrain_objects
import eb_creature_objects import eb_creature_objects
cell_classes = {"Ground": eb_terrain_objects.Ground} cell_classes = {"grass_small": eb_terrain_objects.Ground,
"sword_default": eb_objects.Item}
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")
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.scale(image, new_size)
@dataclass @dataclass
class Cell: class Cell:
terrain_obj: any terrain_obj: any
#item_obj: any item_obj: None = None
#creature_obj: any creature_obj: None = None
is_target: bool = False is_target: bool = False
@dataclass @dataclass
@@ -41,32 +38,34 @@ class Map:
for line in range(len(buff)): for line in range(len(buff)):
self.cells[line] = [] self.cells[line] = []
for cell in buff[str(line)]: for cell in buff[str(line)]:
final_cell = Cell(cell_classes[cell["type"]](**cell["cell"]["terrain_obj"])) final_cell = deepcopy(Cell(cell_classes[cell["terrain_obj"]["sprite_name"]](**cell["terrain_obj"])))
if cell["item_obj"]:
final_cell.item_obj = deepcopy(cell_classes[cell["item_obj"]["sprite_name"]](**cell["item_obj"]))
self.cells[line].append(deepcopy(final_cell)) self.cells[line].append(deepcopy(final_cell))
def draw(self, screen, current_frame, grid = True):
for l in range(len(self.cells)):
for i, cell in enumerate(self.cells[l]):
x = int((i * self.size + self.cam_x) * self.scale)
y = int((l * self.size + self.cam_y) * self.scale)
w = int(self.size * self.scale - self.cell_dist)
h = int(self.size * self.scale - self.cell_dist)
# add if scale != prev_scale: no scale
# current frame to decide, upgrade sprite or not sprite_state
scaled = scale_image(self.sprites[cell.terrain_obj.sprite_name][cell.terrain_obj.sprite_state], self.scale)
scaled_rect = scaled.get_rect(center = (x + w/2, y + h/2))
screen.blit(scaled, scaled_rect)
if cell.terrain_obj.sprite_state == len(self.sprites[cell.terrain_obj.sprite_name]) - 1:
if current_frame % self.sprites_refresh == 0:
cell.terrain_obj.sprite_state = 0
elif current_frame % self.sprites_refresh == 0:
cell.terrain_obj.sprite_state += 1
if grid: def draw_map(self, screen, current_frame, grid = True):
pygame.draw.rect(screen, self.color, pygame.Rect(x, y, w, h), self.bord) for j in range(len(self.cells)):
for i, cell in enumerate(self.cells[j]):
dd = {"x": int((i * self.size + self.cam_x) * self.scale),
"y": int((j * self.size + self.cam_y) * self.scale),
"w": int(self.size * self.scale - self.cell_dist),
"h": int(self.size * self.scale - self.cell_dist),
"spr_up": current_frame % self.sprites_refresh,
"sprites": self.sprites, "scale": self.scale,
"screen": screen}
cell.terrain_obj.draw(dd)
if cell.item_obj:
cell.item_obj.draw(dd)
if cell.creature_obj:
cell.creature_obj.draw(dd)
#if grid:
# pygame.draw.rect(screen, self.color, pygame.Rect(dd["x"], dd["y"], dd["w"], dd["h"]), self.bord)
@dataclass @dataclass
class Engine: class Engine:
@@ -88,7 +87,7 @@ class Engine:
def load_sprites(self, folder_path = sprites_dir): def load_sprites(self, folder_path = sprites_dir):
self.sprites = {} self.sprites = {}
files = [f for f in os.listdir(folder_path) if f.lower().endswith('.png')] files = [f for f in os.listdir(folder_path) if f.lower().endswith('.png')]
#TOTAL SLOR - REWRITE THIS FUNC PLS
groups = {} groups = {}
for f in files: for f in files:
name = os.path.splitext(f)[0] name = os.path.splitext(f)[0]
@@ -125,7 +124,7 @@ class Engine:
# fill the screen with a color to wipe away anything from last frame # fill the screen with a color to wipe away anything from last frame
self.screen.fill("chartreuse4") self.screen.fill("chartreuse4")
easy_map.draw(self.screen, current_frame + 1) easy_map.draw_map(self.screen, current_frame + 1)
if unlock: if unlock:
keys = pygame.key.get_pressed() keys = pygame.key.get_pressed()

View File

@@ -1,5 +1,4 @@
from common import dataclass, field from common import dataclass, scale_image
@dataclass @dataclass
class Object: class Object:
@@ -7,7 +6,29 @@ 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: None = None
def draw(self, draw_data):
if draw_data["spr_up"] == 0:
if self.sprite_state == len(draw_data["sprites"][self.sprite_name]) - 1:
self.sprite_state = 0
else:
self.sprite_state += 1
if self.sprite_cache is None:
self.sprite_cache = draw_data["sprites"][self.sprite_name][self.sprite_state]
if self.sprite_scale != draw_data["scale"]:
self.sprite_scale = draw_data["scale"]
self.sprite_cache = scale_image(draw_data["sprites"][self.sprite_name][self.sprite_state], draw_data["scale"])
rect = self.sprite_cache.get_rect(center = (draw_data["x"] + draw_data["w"] /2, draw_data["y"] + draw_data["h"]/ 2))
else:
rect = self.sprite_cache.get_rect(center = (draw_data["x"] + draw_data["w"] /2, draw_data["y"] + draw_data["h"]/ 2))
draw_data["screen"].blit(self.sprite_cache, rect)
@dataclass @dataclass
class Terrain(Object): class Terrain(Object):
pass pass
@@ -15,6 +36,7 @@ class Terrain(Object):
@dataclass @dataclass
class Creature(Object): class Creature(Object):
pass pass
#status
#actions #actions
#tasks #tasks
#items #items

10
main.py
View File

@@ -20,11 +20,19 @@ if __name__ == "__main__":
# деревня на соседской локации и торговля с ней # деревня на соседской локации и торговля с ней
# перемещение по воде, течение # перемещение по воде, течение
#техдолг:
#проверить дефолтдикт field и None = None
# проверить у ллм на ошибки - РЕГУЛЯРНАЯ АКТИВНОСТЬ: # проверить у ллм на ошибки - РЕГУЛЯРНАЯ АКТИВНОСТЬ:
# - deepcopy + # - deepcopy +
# - общие + # - общие +
main() main()
# P.S. to previous commit:
#instead of Sprite flow load_sprites function was changed: #instead of Sprite flow load_sprites function was changed:
#gathering the number of sprites with the same names before second _ and hold it at #gathering the number of sprites with the same names before second _ and hold it at
#sprites dict. also now sprites must be named as objectname_action_number #sprites dict. also now sprites must be named as objectname_action_number
#
# Main commit - full sprites support, with caching, transparency and smooth scaling
# drawing function moved to Object methods

BIN
res/items/sword.jfif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

View File

@@ -5,7 +5,7 @@ width = 10
height = 8 height = 8
grass_def = {"id": "1", "name": "2", "sprite_name": "grass_small"} grass_def = {"id": "1", "name": "2", "sprite_name": "grass_small"}
cell_def = {"type": "Ground", "cell": {"terrain_obj": grass_def, "creature_obj": {}, "item_obj": {}}} cell_def = {"terrain_obj": grass_def, "item_obj": {}, "creature_obj": {}}
out = {} out = {}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 65 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.8 KiB