Загрузить файлы в «/»
This commit is contained in:
250
entity_behavior.py
Normal file
250
entity_behavior.py
Normal file
@@ -0,0 +1,250 @@
|
||||
|
||||
|
||||
from typing import List, Dict, Tuple
|
||||
|
||||
import math
|
||||
|
||||
|
||||
|
||||
class EntityBehavior:
|
||||
|
||||
def __init__(self):
|
||||
|
||||
pass
|
||||
|
||||
|
||||
|
||||
def process_behaviors(self, state, dt: float) -> List[Dict]:
|
||||
|
||||
actions = []
|
||||
|
||||
if not hasattr(state, 'entities'):
|
||||
|
||||
return actions
|
||||
|
||||
|
||||
|
||||
for entity in state.entities:
|
||||
|
||||
if entity.get('type') == 'unit':
|
||||
|
||||
entity_actions = self._process_unit_behavior(state, entity, dt)
|
||||
|
||||
actions.extend(entity_actions)
|
||||
|
||||
elif entity.get('type') == 'building':
|
||||
|
||||
entity_actions = self._process_building_behavior(state, entity, dt)
|
||||
|
||||
actions.extend(entity_actions)
|
||||
|
||||
|
||||
|
||||
return actions
|
||||
|
||||
|
||||
|
||||
def _process_unit_behavior(self, state, entity: Dict, dt: float) -> List[Dict]:
|
||||
|
||||
actions = []
|
||||
|
||||
current_state = entity.get('state', 'idle')
|
||||
|
||||
|
||||
|
||||
if current_state == 'moving':
|
||||
|
||||
if self._has_reached_target(entity):
|
||||
|
||||
actions.append({'type': 'change_state', 'entity_id': entity['id'], 'new_state': 'idle'})
|
||||
|
||||
else:
|
||||
|
||||
self._continue_movement(entity, dt)
|
||||
|
||||
|
||||
|
||||
elif current_state == 'attacking':
|
||||
|
||||
target_id = entity.get('target_id')
|
||||
|
||||
target = self._find_entity_by_id(state, target_id)
|
||||
|
||||
if not target or target.get('health', 0) <= 0:
|
||||
|
||||
actions.append({'type': 'change_state', 'entity_id': entity['id'], 'new_state': 'idle'})
|
||||
|
||||
else:
|
||||
|
||||
if self._is_in_attack_range(entity, target):
|
||||
|
||||
actions.append({'type': 'deal_damage', 'attacker_id': entity['id'], 'target_id': target_id, 'damage': entity.get('attack_power', 10)})
|
||||
|
||||
else:
|
||||
|
||||
entity['target_x'] = target['x']
|
||||
|
||||
entity['target_y'] = target['y']
|
||||
|
||||
actions.append({'type': 'change_state', 'entity_id': entity['id'], 'new_state': 'moving'})
|
||||
|
||||
|
||||
|
||||
elif current_state == 'gathering':
|
||||
|
||||
target_id = entity.get('target_id')
|
||||
|
||||
target = self._find_entity_by_id(state, target_id)
|
||||
|
||||
if not target or target.get('type') != 'resource':
|
||||
|
||||
actions.append({'type': 'change_state', 'entity_id': entity['id'], 'new_state': 'idle'})
|
||||
|
||||
else:
|
||||
|
||||
if self._is_in_gather_range(entity, target):
|
||||
|
||||
gather_rate = entity.get('gather_rate', 5)
|
||||
|
||||
actions.append({'type': 'gather_resources', 'gatherer_id': entity['id'], 'resource_id': target_id, 'amount': gather_rate})
|
||||
|
||||
else:
|
||||
|
||||
entity['target_x'] = target['x']
|
||||
|
||||
entity['target_y'] = target['y']
|
||||
|
||||
actions.append({'type': 'change_state', 'entity_id': entity['id'], 'new_state': 'moving'})
|
||||
|
||||
|
||||
|
||||
return actions
|
||||
|
||||
|
||||
|
||||
def _process_building_behavior(self, state, entity: Dict, dt: float) -> List[Dict]:
|
||||
|
||||
actions = []
|
||||
|
||||
if not entity.get('completed', False):
|
||||
|
||||
build_progress = entity.get('build_progress', 0) + dt
|
||||
|
||||
build_time = entity.get('build_time', 0)
|
||||
|
||||
if build_progress >= build_time:
|
||||
|
||||
actions.append({'type': 'building_completed', 'entity_id': entity['id']})
|
||||
|
||||
else:
|
||||
|
||||
actions.append({'type': 'building_progress', 'entity_id': entity['id'], 'progress': build_progress})
|
||||
|
||||
|
||||
|
||||
return actions
|
||||
|
||||
|
||||
|
||||
def pathfind(self, entity: Dict, target_pos: Tuple[float, float], map_tiles: List[List[Dict]]) -> List[Tuple[float, float]]:
|
||||
|
||||
start_pos = (entity['x'], entity['y'])
|
||||
|
||||
path = [start_pos, target_pos]
|
||||
|
||||
return path
|
||||
|
||||
|
||||
|
||||
def _has_reached_target(self, entity: Dict) -> bool:
|
||||
|
||||
if 'target_x' not in entity or 'target_y' not in entity:
|
||||
|
||||
return True
|
||||
|
||||
|
||||
|
||||
dx = entity['target_x'] - entity['x']
|
||||
|
||||
dy = entity['target_y'] - entity['y']
|
||||
|
||||
distance = math.sqrt(dx*dx + dy*dy)
|
||||
|
||||
|
||||
|
||||
return distance < 5.0
|
||||
|
||||
|
||||
|
||||
def _continue_movement(self, entity: Dict, dt: float) -> None:
|
||||
|
||||
if 'target_x' not in entity or 'target_y' not in entity:
|
||||
|
||||
return
|
||||
|
||||
|
||||
|
||||
dx = entity['target_x'] - entity['x']
|
||||
|
||||
dy = entity['target_y'] - entity['y']
|
||||
|
||||
distance = math.sqrt(dx*dx + dy*dy)
|
||||
|
||||
|
||||
|
||||
if distance > 0:
|
||||
|
||||
speed = entity.get('speed', 50.0)
|
||||
|
||||
move_dist = speed * dt
|
||||
|
||||
entity['x'] += (dx / distance) * move_dist
|
||||
|
||||
entity['y'] += (dy / distance) * move_dist
|
||||
|
||||
|
||||
|
||||
def _is_in_attack_range(self, entity: Dict, target: Dict) -> bool:
|
||||
|
||||
dx = target['x'] - entity['x']
|
||||
|
||||
dy = target['y'] - entity['y']
|
||||
|
||||
distance = math.sqrt(dx*dx + dy*dy)
|
||||
|
||||
attack_range = entity.get('attack_range', 50.0)
|
||||
|
||||
|
||||
|
||||
return distance <= attack_range
|
||||
|
||||
|
||||
|
||||
def _is_in_gather_range(self, entity: Dict, target: Dict) -> bool:
|
||||
|
||||
dx = target['x'] - entity['x']
|
||||
|
||||
dy = target['y'] - entity['y']
|
||||
|
||||
distance = math.sqrt(dx*dx + dy*dy)
|
||||
|
||||
gather_range = entity.get('gather_range', 20.0)
|
||||
|
||||
|
||||
|
||||
return distance <= gather_range
|
||||
|
||||
|
||||
|
||||
def _find_entity_by_id(self, state, entity_id: int) -> Dict:
|
||||
|
||||
if hasattr(state, 'entities'):
|
||||
|
||||
for entity in state.entities:
|
||||
|
||||
if entity.get('id') == entity_id:
|
||||
|
||||
return entity
|
||||
|
||||
return None
|
||||
|
||||
Reference in New Issue
Block a user