Files
Elvenbane/eb_objects.py

284 lines
10 KiB
Python
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
from common import deepcopy, dataclass, field, random
@dataclass
class Action:
sprite_name: str
func: function
duration: float
progress: float = 0.0
#status: str = "pending"
#взаимодействие с инвентарем
#взять предмет
#бросить предмет
#передать предмет
#собрать ресурс
#активное действие с оружием
#колдовство
#class Task
@dataclass
class Object:
id: str
name: str
sprite_name: str
sprite_state: int = 0
grid_pos: tuple = None
# current_map
# pos
# weight
# effects = {}
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
sp = draw_data["sprites"][self.sprite_name][self.sprite_state]
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)
def update(self):
pass
@dataclass
class Terrain(Object):
pass
@dataclass
class Creature(Object):
direction: int = 0 # tuple?
move_progress: float = 0.0 # 0.0 = старт клетки, 1.0 = конец клетки
current_target: tuple = None # (row, col) следующая клетка
final_goal: tuple = None
move_speed: float = 0.02 # пикселей/кадр
render_offset: tuple = (0.0, 0.0)
start_pos: tuple = None # (row, col) начальная позиция сегмента пути
replan_counter: int = 0
REPLAN_INTERVAL: int = 30000
waypoints: list = field(default_factory = list)
walkable_matrix: list = field(default_factory = list)
rocks_matrix: list = field(default_factory = list)
inventory: dict = field(default_factory = dict)
quick_actions: list = field(default_factory = list)
tasks: list = field(default_factory = list)
action: Action = None
action_time: float = 0.0
action_counter: int = 0
task_counter: int = 0
new_task: list = field(default_factory = list)
interrupt_task: list = field(default_factory = list)
interrupt_action_status: str = "completed"
def replan(self, cells, pos):
from common import find_way
path = find_way(cells, pos, self.final_goal, self.walkable_matrix, self.rocks_matrix)
if path and len(path) > 1:
self.waypoints = path[1:]
self.current_target = self.waypoints[0]
else:
self.waypoints.clear()
self.current_target = None
self.final_goal = None
def calc_step(self, time_delta, cell_size, map_obj):
if self.current_target is None or not self.waypoints:
self.render_offset = (0.0, 0.0)
return
#self.replan_counter += 1
#if self.replan_counter >= self.REPLAN_INTERVAL:
# self.replan_counter = 0
# self.replan(map_obj.cells, self.start_pos)
if self.current_target is None: return
#target_row, target_col = self.current_target
#if (target_row in map_obj.cells and
# target_col < len(map_obj.cells[target_row])):
# target_cell = map_obj.cells[target_row][target_col]
#if target_cell.creature_obj is not None:
# self.current_target = None
# self.waypoints.clear()
# self.render_offset = (0.0, 0.0)
# self.replan(map_obj.cells, self.start_pos)
# return
self.move_progress += self.move_speed * time_delta * 60
self.move_progress = min(self.move_progress, 1.0)
if self.move_progress >= 1.0:
if (map_obj.move_obj('creature_obj', self.start_pos, self.current_target)):
self.grid_pos = self.current_target
else:
self.current_target = None
self.waypoints.clear()
self.render_offset = (0.0, 0.0)
#если в матрице не считаем объекты, то:
#добавляем клетку в матрицу, матрицу периодически чистим
#посчитать как дорого обходится просчёт матрицы
self.replan(map_obj.cells, self.start_pos)
#тут сделать красивый переход в одну из соседних клеток
return
if self.waypoints: self.waypoints.pop(0)
if self.waypoints:
self.start_pos = self.current_target
self.current_target = self.waypoints[0]
self.move_progress = 0.0
self.render_offset = (0.0, 0.0)
else:
#print(111111111111111)
self.current_target = None
self.final_goal = None
self.render_offset = (0.0, 0.0)
return
if self.current_target is None:
self.render_offset = (0.0, 0.0)
return
start_row, start_col = self.start_pos
target_row, target_col = self.current_target
offset_x = (target_col - start_col) * cell_size * self.move_progress
offset_y = (target_row - start_row) * cell_size * self.move_progress
self.render_offset = (offset_x, offset_y)
def move(self, cells, goal):
from common import find_way
self.final_goal = goal
path = find_way(cells, self.grid_pos, self.final_goal, self.walkable_matrix, self.rocks_matrix)
if path and len(path) > 1:
self.waypoints = path[1:]
self.current_target = self.waypoints[0]
self.move_progress = 0.0
self.start_pos = self.grid_pos
self.render_offset = (0.0, 0.0)
else:
self.final_goal = None
def create_task(self):
self.new_task = []
#add actions_default_durations dict {func1: dur1, ...}
def add_action(self, sprite_name: str, func: function, duration: float):
self.new_task.append(Action(sprite_name, func, duration))
def add_task(self):
self.tasks.append(self.new_task)
def add_interr_task(self):
pass
#param resume_on_interrupt, Bool
#if True
# save goal to buffer
#if False
# action/task_counter = 0
#clear goal/wp
def update(self, time_delta, cell_size, map_obj):
self.walkable_matrix = map_obj.walkable_matrix
self.rocks_matrix = map_obj.rocks_matrix
#quick_actions? here?
#print(self.waypoints, self.final_goal, self.action_counter, self.task_counter)
if self.final_goal is not None:
#print(2)
self.calc_step(time_delta, cell_size, map_obj)
return
if self.interrupt_task and self.interrupt_action_status == "completed":
#print(3)
self.action_time = 0.0
self.action = self.interrupt_task.pop(0)
self.interrupt_action_status = "active"
#print(f" DEBUG: tasks={len(self.tasks)}, "
# f"task_len={len(self.tasks[self.task_counter]) if self.tasks else 0}, "
# f"action={self.action is not None}")
if self.action:
#print(self.action_counter, self.task_counter)
self.action_time += time_delta
self.action.progress = min(1.0, self.action_time / self.action.duration)
if self.action_time >= self.action.duration:
self.action.func()
if self.interrupt_action_status == "active":
self.interrupt_action_status == "completed"
#if not self.inter_task and goal: move to buff_goal from self.pos (add to Object)
self.action = None
self.action_time = 0.0
elif self.tasks:
#print(6)
if self.action_counter < len(self.tasks[self.task_counter]):
self.action = self.tasks[self.task_counter][self.action_counter]
self.action_counter += 1
else:
self.task_counter += 1
self.action_counter = 0
if self.task_counter == len(self.tasks):
self.task_counter = 0
self.action = self.tasks[self.task_counter][self.action_counter]
self.action_counter += 1
self.action_time = 0.0
#elif self.tasks:
# if self.action_counter >= len(self.tasks[self.task_counter]):
# self.task_counter += 1
# self.action_counter = 0
# if self.task_counter >= len(self.tasks):
# self.task_counter = 0
#
# self.action = self.tasks[self.task_counter][self.action_counter]
# self.action_counter += 1
# self.action_time = 0.0
def patrol(self, cells, area):
goal = (random.randint(self.grid_pos[0] - area,
self.grid_pos[0] + area),
random.randint(self.grid_pos[1] - area,
self.grid_pos[1] + area))
while goal == self.grid_pos:
goal = (random.randint(self.grid_pos[0] - area,
self.grid_pos[0] + area),
random.randint(self.grid_pos[1] - area,
self.grid_pos[1] + area))
self.move(cells, goal)
def move_rand(self, cells, area_start, area_end):
goal = (random.randint(area_start, area_end), random.randint(area_start, area_end))
while goal == self.grid_pos:
goal = (random.randint(area_start, area_end), random.randint(area_start, area_end))
self.move(cells, goal)
@dataclass
class Item(Object):
# passive_abilities = {}
# active_abilities = {}
pass
@dataclass
class Container(Item):
# content = {}
pass
@dataclass
class Building(Object):
pass