Files
Apollo3D_SE/behaviors/custom/keyframe/kick/kick.py

92 lines
2.9 KiB
Python
Raw Normal View History

import os
from numbers import Real
from behaviors.behavior import Behavior
from behaviors.custom.keyframe.keyframe import KeyframeSkill
class Kick(Behavior):
SHORT_MAX_DISTANCE: float = 1.8
MID_MAX_DISTANCE: float = 4.5
TEN_METER_MIN_DISTANCE: float = 8.0
DEFAULT_DISTANCE: float = 3.0
def __init__(self, agent):
super().__init__(agent)
base_dir = os.path.dirname(__file__)
self.short_kick = KeyframeSkill(
agent=agent,
file=os.path.join(base_dir, "kick_short.yaml"),
)
self.mid_kick = KeyframeSkill(
agent=agent,
file=os.path.join(base_dir, "kick_mid.yaml"),
)
self.long_kick = KeyframeSkill(
agent=agent,
file=os.path.join(base_dir, "kick_long.yaml"),
)
self.ten_meter_kick = KeyframeSkill(
agent=agent,
file=os.path.join(base_dir, "kick_10m.yaml"),
)
self.current_kick: KeyframeSkill | None = None
self.should_reset_kick: bool = True
self.should_execute_neutral: bool = True
def execute(self, reset: bool, *args, **kwargs) -> bool:
if reset:
kick_distance = self._extract_kick_distance(*args, **kwargs)
self.current_kick = self._choose_kick_from_distance(kick_distance)
self.should_reset_kick = True
self.should_execute_neutral = True
if self.current_kick is None:
self.current_kick = self.mid_kick
if self.should_execute_neutral:
neutral_finished = self.agent.skills_manager.execute(
"Neutral",
)
self.should_reset_kick = False
if not neutral_finished:
return False
self.should_execute_neutral = False
self.should_reset_kick = True
has_finished = self.current_kick.execute(reset=self.should_reset_kick)
self.should_reset_kick = False
return has_finished
def _extract_kick_distance(self, *args, **kwargs) -> float:
distance_candidates = (
kwargs.get("distance"),
kwargs.get("kick_distance"),
kwargs.get("target_distance"),
kwargs.get("ball_to_target_distance"),
args[0] if args else None,
)
for candidate in distance_candidates:
if isinstance(candidate, Real):
return float(max(0.0, candidate))
return self.DEFAULT_DISTANCE
def _choose_kick_from_distance(self, distance: float) -> KeyframeSkill:
if distance <= self.SHORT_MAX_DISTANCE:
return self.short_kick
if distance <= self.MID_MAX_DISTANCE:
return self.mid_kick
if distance >= self.TEN_METER_MIN_DISTANCE:
return self.ten_meter_kick
return self.long_kick
def is_ready(self, *args) -> bool:
return True