708 lines
22 KiB
Python
708 lines
22 KiB
Python
"""
|
|
事件处理器模块
|
|
负责处理游戏事件并触发相应的触觉反馈
|
|
"""
|
|
|
|
import time
|
|
from typing import Dict, Any, List, Optional, Callable
|
|
import threading
|
|
|
|
class HapticEventHandler:
|
|
"""
|
|
触觉事件处理器
|
|
负责处理游戏事件并触发相应的触觉反馈
|
|
"""
|
|
|
|
def __init__(self, plugin):
|
|
"""
|
|
初始化触觉事件处理器
|
|
|
|
Args:
|
|
plugin: 触觉反馈系统插件实例
|
|
"""
|
|
self.plugin = plugin
|
|
self.enabled = False
|
|
self.initialized = False
|
|
|
|
# 事件映射配置
|
|
self.event_mapping = {
|
|
# 游戏事件到触觉效果的映射
|
|
'player_jump': {
|
|
'effect': 'impulse',
|
|
'intensity': 0.6,
|
|
'frequency': 40.0,
|
|
'duration': 0.1,
|
|
'device': 'feet'
|
|
},
|
|
'player_land': {
|
|
'effect': 'rumble',
|
|
'intensity': 0.8,
|
|
'frequency': 30.0,
|
|
'duration': 0.2,
|
|
'device': 'feet'
|
|
},
|
|
'player_take_damage': {
|
|
'effect': 'explosion',
|
|
'intensity': 1.0,
|
|
'frequency': 50.0,
|
|
'duration': 0.5,
|
|
'device': 'body'
|
|
},
|
|
'player_heal': {
|
|
'effect': 'pulse',
|
|
'intensity': 0.5,
|
|
'frequency': 25.0,
|
|
'duration': 0.3,
|
|
'device': 'chest'
|
|
},
|
|
'weapon_fire': {
|
|
'effect': 'click',
|
|
'intensity': 0.7,
|
|
'frequency': 80.0,
|
|
'duration': 0.05,
|
|
'device': 'hands'
|
|
},
|
|
'weapon_reload': {
|
|
'effect': 'buzz',
|
|
'intensity': 0.4,
|
|
'frequency': 35.0,
|
|
'duration': 0.4,
|
|
'device': 'hands'
|
|
},
|
|
'enemy_hit': {
|
|
'effect': 'click',
|
|
'intensity': 0.5,
|
|
'frequency': 60.0,
|
|
'duration': 0.08,
|
|
'device': 'hands'
|
|
},
|
|
'enemy_death': {
|
|
'effect': 'explosion',
|
|
'intensity': 0.9,
|
|
'frequency': 45.0,
|
|
'duration': 0.6,
|
|
'device': 'body'
|
|
},
|
|
'pickup_item': {
|
|
'effect': 'pulse',
|
|
'intensity': 0.3,
|
|
'frequency': 20.0,
|
|
'duration': 0.2,
|
|
'device': 'hands'
|
|
},
|
|
'door_open': {
|
|
'effect': 'buzz',
|
|
'intensity': 0.3,
|
|
'frequency': 15.0,
|
|
'duration': 0.3,
|
|
'device': 'hands'
|
|
},
|
|
'door_close': {
|
|
'effect': 'click',
|
|
'intensity': 0.4,
|
|
'frequency': 25.0,
|
|
'duration': 0.1,
|
|
'device': 'hands'
|
|
},
|
|
'explosion': {
|
|
'effect': 'explosion',
|
|
'intensity': 1.0,
|
|
'frequency': 35.0,
|
|
'duration': 1.0,
|
|
'device': 'body'
|
|
},
|
|
'ui_button_click': {
|
|
'effect': 'click',
|
|
'intensity': 0.3,
|
|
'frequency': 100.0,
|
|
'duration': 0.05,
|
|
'device': 'hands'
|
|
},
|
|
'ui_button_hover': {
|
|
'effect': 'soft_rumble',
|
|
'intensity': 0.1,
|
|
'frequency': 10.0,
|
|
'duration': 0.1,
|
|
'device': 'hands'
|
|
}
|
|
}
|
|
|
|
# 事件优先级配置
|
|
self.event_priority = {
|
|
'player_take_damage': 100,
|
|
'explosion': 90,
|
|
'enemy_death': 80,
|
|
'player_land': 70,
|
|
'weapon_fire': 60,
|
|
'player_jump': 50,
|
|
'enemy_hit': 40,
|
|
'pickup_item': 30,
|
|
'door_open': 20,
|
|
'door_close': 20,
|
|
'ui_button_click': 10,
|
|
'ui_button_hover': 5,
|
|
'player_heal': 40,
|
|
'weapon_reload': 30
|
|
}
|
|
|
|
# 事件队列
|
|
self.event_queue = []
|
|
self.event_queue_lock = threading.Lock()
|
|
|
|
# 事件抑制配置
|
|
self.event_suppression = {
|
|
'enable_suppression': True,
|
|
'suppression_time': 0.1, # 秒
|
|
'suppressed_events': set()
|
|
}
|
|
|
|
# 事件组合配置
|
|
self.event_combination = {
|
|
'enable_combination': True,
|
|
'combination_window': 0.5, # 秒
|
|
'max_combined_events': 5
|
|
}
|
|
|
|
# 状态跟踪
|
|
self.event_state = {
|
|
'last_event_time': {},
|
|
'combined_events': [],
|
|
'active_events': {}
|
|
}
|
|
|
|
# 统计信息
|
|
self.stats = {
|
|
'events_received': 0,
|
|
'events_processed': 0,
|
|
'events_suppressed': 0,
|
|
'events_combined': 0,
|
|
'haptic_effects_triggered': 0
|
|
}
|
|
|
|
# 回调函数
|
|
self.event_callbacks = {
|
|
'event_received': [],
|
|
'event_processed': [],
|
|
'event_suppressed': [],
|
|
'event_combined': []
|
|
}
|
|
|
|
print("✓ 触觉事件处理器已创建")
|
|
|
|
def initialize(self) -> bool:
|
|
"""
|
|
初始化触觉事件处理器
|
|
|
|
Returns:
|
|
是否初始化成功
|
|
"""
|
|
try:
|
|
self.initialized = True
|
|
print("✓ 触觉事件处理器初始化完成")
|
|
return True
|
|
|
|
except Exception as e:
|
|
print(f"✗ 触觉事件处理器初始化失败: {e}")
|
|
import traceback
|
|
traceback.print_exc()
|
|
return False
|
|
|
|
def enable(self) -> bool:
|
|
"""
|
|
启用触觉事件处理器
|
|
|
|
Returns:
|
|
是否启用成功
|
|
"""
|
|
try:
|
|
if not self.initialized:
|
|
print("✗ 触觉事件处理器未初始化")
|
|
return False
|
|
|
|
self.enabled = True
|
|
print("✓ 触觉事件处理器已启用")
|
|
return True
|
|
|
|
except Exception as e:
|
|
print(f"✗ 触觉事件处理器启用失败: {e}")
|
|
import traceback
|
|
traceback.print_exc()
|
|
return False
|
|
|
|
def disable(self):
|
|
"""禁用触觉事件处理器"""
|
|
try:
|
|
self.enabled = False
|
|
print("✓ 触觉事件处理器已禁用")
|
|
|
|
except Exception as e:
|
|
print(f"✗ 触觉事件处理器禁用失败: {e}")
|
|
import traceback
|
|
traceback.print_exc()
|
|
|
|
def finalize(self):
|
|
"""清理触觉事件处理器资源"""
|
|
try:
|
|
self.disable()
|
|
self.event_mapping.clear()
|
|
self.event_queue.clear()
|
|
self.event_state.clear()
|
|
self.event_callbacks.clear()
|
|
self.initialized = False
|
|
print("✓ 触觉事件处理器资源已清理")
|
|
|
|
except Exception as e:
|
|
print(f"✗ 触觉事件处理器资源清理失败: {e}")
|
|
import traceback
|
|
traceback.print_exc()
|
|
|
|
def update(self, dt: float):
|
|
"""
|
|
更新触觉事件处理器状态
|
|
|
|
Args:
|
|
dt: 时间增量
|
|
"""
|
|
try:
|
|
if not self.enabled:
|
|
return
|
|
|
|
# 处理事件队列
|
|
self._process_event_queue()
|
|
|
|
# 更新事件状态
|
|
self._update_event_state()
|
|
|
|
except Exception as e:
|
|
print(f"✗ 触觉事件处理器更新失败: {e}")
|
|
import traceback
|
|
traceback.print_exc()
|
|
|
|
def _process_event_queue(self):
|
|
"""处理事件队列"""
|
|
try:
|
|
with self.event_queue_lock:
|
|
if not self.event_queue:
|
|
return
|
|
|
|
# 获取事件并清空队列
|
|
events_to_process = self.event_queue[:]
|
|
self.event_queue.clear()
|
|
|
|
# 处理每个事件
|
|
for event in events_to_process:
|
|
self._process_event(event)
|
|
|
|
except Exception as e:
|
|
print(f"✗ 事件队列处理失败: {e}")
|
|
|
|
def _update_event_state(self):
|
|
"""更新事件状态"""
|
|
try:
|
|
current_time = time.time()
|
|
|
|
# 清理过期的抑制事件
|
|
suppression_time = self.event_suppression['suppression_time']
|
|
expired_suppressions = [
|
|
event_type for event_type, timestamp in
|
|
self.event_suppression['suppressed_events']
|
|
if current_time - timestamp > suppression_time
|
|
]
|
|
|
|
for event_type in expired_suppressions:
|
|
self.event_suppression['suppressed_events'].discard(event_type)
|
|
|
|
# 清理过期的组合事件
|
|
combination_window = self.event_combination['combination_window']
|
|
self.event_state['combined_events'] = [
|
|
event for event in self.event_state['combined_events']
|
|
if current_time - event.get('timestamp', 0) <= combination_window
|
|
]
|
|
|
|
except Exception as e:
|
|
print(f"✗ 事件状态更新失败: {e}")
|
|
|
|
def handle_event(self, event_type: str, event_data: Dict[str, Any] = None) -> bool:
|
|
"""
|
|
处理事件
|
|
|
|
Args:
|
|
event_type: 事件类型
|
|
event_data: 事件数据
|
|
|
|
Returns:
|
|
是否处理成功
|
|
"""
|
|
try:
|
|
if not self.enabled:
|
|
return False
|
|
|
|
# 创建事件对象
|
|
event = {
|
|
'type': event_type,
|
|
'data': event_data or {},
|
|
'timestamp': time.time(),
|
|
'priority': self.event_priority.get(event_type, 50)
|
|
}
|
|
|
|
# 添加到事件队列
|
|
with self.event_queue_lock:
|
|
self.event_queue.append(event)
|
|
|
|
# 触发事件接收回调
|
|
self._trigger_event_callback('event_received', {
|
|
'event': event
|
|
})
|
|
|
|
self.stats['events_received'] += 1
|
|
return True
|
|
|
|
except Exception as e:
|
|
print(f"✗ 事件处理失败: {e}")
|
|
return False
|
|
|
|
def _process_event(self, event: Dict[str, Any]):
|
|
"""
|
|
处理单个事件
|
|
|
|
Args:
|
|
event: 事件对象
|
|
"""
|
|
try:
|
|
event_type = event['type']
|
|
event_data = event['data']
|
|
timestamp = event['timestamp']
|
|
|
|
# 检查事件抑制
|
|
if self.event_suppression['enable_suppression']:
|
|
if event_type in [e[0] for e in self.event_suppression['suppressed_events']]:
|
|
# 事件被抑制
|
|
self.stats['events_suppressed'] += 1
|
|
|
|
# 触发抑制回调
|
|
self._trigger_event_callback('event_suppressed', {
|
|
'event': event
|
|
})
|
|
return
|
|
|
|
# 添加到抑制列表
|
|
self.event_suppression['suppressed_events'].add((event_type, timestamp))
|
|
|
|
# 检查事件组合
|
|
if self.event_combination['enable_combination']:
|
|
self._handle_event_combination(event)
|
|
|
|
# 处理事件映射
|
|
if event_type in self.event_mapping:
|
|
self._trigger_haptic_effect(event_type, event_data)
|
|
|
|
# 触发事件处理回调
|
|
self._trigger_event_callback('event_processed', {
|
|
'event': event
|
|
})
|
|
|
|
self.stats['events_processed'] += 1
|
|
|
|
except Exception as e:
|
|
print(f"✗ 单个事件处理失败: {e}")
|
|
|
|
def _handle_event_combination(self, event: Dict[str, Any]):
|
|
"""
|
|
处理事件组合
|
|
|
|
Args:
|
|
event: 事件对象
|
|
"""
|
|
try:
|
|
current_time = time.time()
|
|
combination_window = self.event_combination['combination_window']
|
|
|
|
# 添加到组合事件列表
|
|
self.event_state['combined_events'].append(event)
|
|
|
|
# 保持列表大小
|
|
if len(self.event_state['combined_events']) > self.event_combination['max_combined_events']:
|
|
self.event_state['combined_events'].pop(0)
|
|
|
|
# 检查是否达到组合条件
|
|
if len(self.event_state['combined_events']) >= 3:
|
|
# 检查时间窗口
|
|
oldest_event = self.event_state['combined_events'][0]
|
|
if current_time - oldest_event['timestamp'] <= combination_window:
|
|
# 触发组合事件回调
|
|
self._trigger_event_callback('event_combined', {
|
|
'events': self.event_state['combined_events'].copy()
|
|
})
|
|
|
|
self.stats['events_combined'] += 1
|
|
|
|
# 清空组合事件列表
|
|
self.event_state['combined_events'].clear()
|
|
|
|
except Exception as e:
|
|
print(f"✗ 事件组合处理失败: {e}")
|
|
|
|
def _trigger_haptic_effect(self, event_type: str, event_data: Dict[str, Any]):
|
|
"""
|
|
触发触觉效果
|
|
|
|
Args:
|
|
event_type: 事件类型
|
|
event_data: 事件数据
|
|
"""
|
|
try:
|
|
if not self.plugin.haptic_manager:
|
|
return
|
|
|
|
# 获取效果配置
|
|
effect_config = self.event_mapping.get(event_type)
|
|
if not effect_config:
|
|
return
|
|
|
|
# 提取效果参数
|
|
effect_type = effect_config['effect']
|
|
intensity = effect_config['intensity']
|
|
frequency = effect_config['frequency']
|
|
duration = effect_config['duration']
|
|
device_type = effect_config.get('device')
|
|
|
|
# 获取设备ID
|
|
device_id = None
|
|
if device_type and self.plugin.device_manager:
|
|
devices = self.plugin.device_manager.get_devices_by_type(device_type)
|
|
if devices:
|
|
device_id = devices[0]['id']
|
|
|
|
# 应用事件数据中的参数覆盖
|
|
if 'intensity' in event_data:
|
|
intensity *= event_data['intensity']
|
|
if 'frequency' in event_data:
|
|
frequency *= event_data['frequency']
|
|
if 'duration' in event_data:
|
|
duration *= event_data['duration']
|
|
|
|
# 播放触觉效果
|
|
effect_id = self.plugin.haptic_manager.play_effect(
|
|
effect_type=effect_type,
|
|
device_id=device_id,
|
|
intensity=intensity,
|
|
duration=duration,
|
|
frequency=frequency,
|
|
parameters={
|
|
'event_type': event_type,
|
|
'event_data': event_data
|
|
}
|
|
)
|
|
|
|
if effect_id >= 0:
|
|
self.stats['haptic_effects_triggered'] += 1
|
|
print(f"✓ 触觉效果已触发: {event_type} -> {effect_type}")
|
|
|
|
except Exception as e:
|
|
print(f"✗ 触觉效果触发失败: {e}")
|
|
|
|
def register_event_mapping(self, event_type: str, effect_config: Dict[str, Any]) -> bool:
|
|
"""
|
|
注册事件映射
|
|
|
|
Args:
|
|
event_type: 事件类型
|
|
effect_config: 效果配置
|
|
|
|
Returns:
|
|
是否注册成功
|
|
"""
|
|
try:
|
|
self.event_mapping[event_type] = effect_config
|
|
print(f"✓ 事件映射已注册: {event_type}")
|
|
return True
|
|
except Exception as e:
|
|
print(f"✗ 事件映射注册失败: {e}")
|
|
return False
|
|
|
|
def unregister_event_mapping(self, event_type: str) -> bool:
|
|
"""
|
|
注销事件映射
|
|
|
|
Args:
|
|
event_type: 事件类型
|
|
|
|
Returns:
|
|
是否注销成功
|
|
"""
|
|
try:
|
|
if event_type in self.event_mapping:
|
|
del self.event_mapping[event_type]
|
|
print(f"✓ 事件映射已注销: {event_type}")
|
|
return True
|
|
else:
|
|
print(f"✗ 事件映射不存在: {event_type}")
|
|
return False
|
|
except Exception as e:
|
|
print(f"✗ 事件映射注销失败: {e}")
|
|
return False
|
|
|
|
def set_event_priority(self, event_type: str, priority: int) -> bool:
|
|
"""
|
|
设置事件优先级
|
|
|
|
Args:
|
|
event_type: 事件类型
|
|
priority: 优先级值
|
|
|
|
Returns:
|
|
是否设置成功
|
|
"""
|
|
try:
|
|
self.event_priority[event_type] = priority
|
|
print(f"✓ 事件优先级已设置: {event_type} = {priority}")
|
|
return True
|
|
except Exception as e:
|
|
print(f"✗ 事件优先级设置失败: {e}")
|
|
return False
|
|
|
|
def set_event_suppression(self, config: Dict[str, Any]) -> bool:
|
|
"""
|
|
设置事件抑制配置
|
|
|
|
Args:
|
|
config: 配置字典
|
|
|
|
Returns:
|
|
是否设置成功
|
|
"""
|
|
try:
|
|
self.event_suppression.update(config)
|
|
print(f"✓ 事件抑制配置已更新: {self.event_suppression}")
|
|
return True
|
|
except Exception as e:
|
|
print(f"✗ 事件抑制配置设置失败: {e}")
|
|
return False
|
|
|
|
def set_event_combination(self, config: Dict[str, Any]) -> bool:
|
|
"""
|
|
设置事件组合配置
|
|
|
|
Args:
|
|
config: 配置字典
|
|
|
|
Returns:
|
|
是否设置成功
|
|
"""
|
|
try:
|
|
self.event_combination.update(config)
|
|
print(f"✓ 事件组合配置已更新: {self.event_combination}")
|
|
return True
|
|
except Exception as e:
|
|
print(f"✗ 事件组合配置设置失败: {e}")
|
|
return False
|
|
|
|
def get_event_mapping(self) -> Dict[str, Dict[str, Any]]:
|
|
"""
|
|
获取事件映射
|
|
|
|
Returns:
|
|
事件映射字典
|
|
"""
|
|
return self.event_mapping.copy()
|
|
|
|
def get_event_priority(self) -> Dict[str, int]:
|
|
"""
|
|
获取事件优先级
|
|
|
|
Returns:
|
|
事件优先级字典
|
|
"""
|
|
return self.event_priority.copy()
|
|
|
|
def get_event_suppression_config(self) -> Dict[str, Any]:
|
|
"""
|
|
获取事件抑制配置
|
|
|
|
Returns:
|
|
配置字典
|
|
"""
|
|
return self.event_suppression.copy()
|
|
|
|
def get_event_combination_config(self) -> Dict[str, Any]:
|
|
"""
|
|
获取事件组合配置
|
|
|
|
Returns:
|
|
配置字典
|
|
"""
|
|
return self.event_combination.copy()
|
|
|
|
def _trigger_event_callback(self, callback_type: str, data: Dict[str, Any]):
|
|
"""
|
|
触发事件回调
|
|
|
|
Args:
|
|
callback_type: 回调类型
|
|
data: 回调数据
|
|
"""
|
|
try:
|
|
if callback_type in self.event_callbacks:
|
|
for callback in self.event_callbacks[callback_type]:
|
|
try:
|
|
callback(data)
|
|
except Exception as e:
|
|
print(f"✗ 事件回调执行失败: {e}")
|
|
except Exception as e:
|
|
print(f"✗ 事件回调触发失败: {e}")
|
|
|
|
def register_event_callback(self, callback_type: str, callback: Callable):
|
|
"""
|
|
注册事件回调
|
|
|
|
Args:
|
|
callback_type: 回调类型
|
|
callback: 回调函数
|
|
"""
|
|
try:
|
|
if callback_type in self.event_callbacks:
|
|
self.event_callbacks[callback_type].append(callback)
|
|
print(f"✓ 事件回调已注册: {callback_type}")
|
|
else:
|
|
print(f"✗ 无效的回调类型: {callback_type}")
|
|
except Exception as e:
|
|
print(f"✗ 事件回调注册失败: {e}")
|
|
|
|
def unregister_event_callback(self, callback_type: str, callback: Callable):
|
|
"""
|
|
注销事件回调
|
|
|
|
Args:
|
|
callback_type: 回调类型
|
|
callback: 回调函数
|
|
"""
|
|
try:
|
|
if callback_type in self.event_callbacks:
|
|
if callback in self.event_callbacks[callback_type]:
|
|
self.event_callbacks[callback_type].remove(callback)
|
|
print(f"✓ 事件回调已注销: {callback_type}")
|
|
except Exception as e:
|
|
print(f"✗ 事件回调注销失败: {e}")
|
|
|
|
def get_stats(self) -> Dict[str, int]:
|
|
"""
|
|
获取统计信息
|
|
|
|
Returns:
|
|
统计信息字典
|
|
"""
|
|
return self.stats.copy()
|
|
|
|
def reset_stats(self):
|
|
"""重置统计信息"""
|
|
try:
|
|
self.stats = {
|
|
'events_received': 0,
|
|
'events_processed': 0,
|
|
'events_suppressed': 0,
|
|
'events_combined': 0,
|
|
'haptic_effects_triggered': 0
|
|
}
|
|
print("✓ 事件处理器统计信息已重置")
|
|
except Exception as e:
|
|
print(f"✗ 事件处理器统计信息重置失败: {e}") |