diff --git a/src/core/animation_manager.py b/src/core/animation_manager.py index 071361f..6d44d39 100644 --- a/src/core/animation_manager.py +++ b/src/core/animation_manager.py @@ -23,6 +23,7 @@ def __init__(self, label: QLabel, config=None): self.cached_pixmap = None self.last_size = QSize(0, 0) self.main_window = self.label.window() + self.current_fps = 12 # Таймер для процедурной SVG анимации self.anim_timer = QTimer() @@ -169,6 +170,17 @@ def play_state(self, state, force=False): self.current_state = state + # Динамический FPS в зависимости от состояния + fps = 12 + if state == "sleeping": + fps = 4 + elif state in ["overheat", "shaking"]: + fps = 20 + + self.current_fps = fps + if self.anim_timer.isActive(): + self.anim_timer.start(1000 // fps) + # Если выбран скин, пробуем загрузить его SVG версию if self.skin != "default": svg_path = os.path.join(ANIMATIONS_DIR, "svg_skins", f"cat_{self.skin}.svg") diff --git a/src/core/input_manager.py b/src/core/input_manager.py index ac23bb7..7b9802a 100644 --- a/src/core/input_manager.py +++ b/src/core/input_manager.py @@ -58,6 +58,8 @@ def __init__(self, pet_window, data_store=None): self.last_mouse_time = 0 self.last_mouse_pos = (0, 0) + self.last_pet_mouse_pos = (0, 0) + self.last_pet_time = 0 self.last_input_time = time.time() self.last_purr_time = 0 self.laser_mode = False @@ -165,7 +167,7 @@ def add_points(self, points): # Сохраняем в БД только когда накопилось 10 очков (примерно каждые 10 сек активной работы) if self.pending_points >= 10: - self.flush_points() + self.flush_all() # Проверка уровня (визуально можно чаще, используя буферизованные очки) virtual_total = self.last_affection_points + self.pending_points @@ -178,10 +180,6 @@ def add_points(self, points): self.db.log_event("level_up", f"Уровень повышен до {new_level}") self.check_for_achievements() - def flush_points(self): - """Устарело: используйте flush_all""" - self.flush_all() - def flush_all(self): """Записывает все накопленные данные (очки и статистику) в базу данных.""" if not self.db: @@ -322,7 +320,7 @@ def handle_mouse(self, x, y): self.last_mouse_pos = (x, y) self.last_mouse_time = now - # Проверка "поглаживания" + # Проверка "поглаживания" (Petting) pet_pos = self.window.get_cached_pos() center_x = pet_pos.x() + self.window.width() // 2 center_y = pet_pos.y() + self.window.height() // 2 @@ -332,14 +330,25 @@ def handle_mouse(self, x, y): # Оптимизация: сравнение квадрата расстояния (порог 60px -> 3600) if dist_sq_pet < 3600: - if self.window.animation_manager.current_state not in ["playing", "hunting", "shaking"]: - self.window.animation_manager.play_state("playing") - self.pending_stats["petting_count"] += 1 - if self.pending_stats["petting_count"] % 5 == 0: - self.check_for_achievements() - if now - self.last_purr_time > 2.0: - self.window.sound_manager.play_sound("purr") - self.last_purr_time = now + # Требуем движения мыши для поглаживания (минимум 30px) и кулдаун 0.5с + p_dx = x - self.last_pet_mouse_pos[0] + p_dy = y - self.last_pet_mouse_pos[1] + p_dist_sq = p_dx * p_dx + p_dy * p_dy + + if p_dist_sq > 900 and (now - self.last_pet_time) > 0.5: + if self.window.animation_manager.current_state not in ["playing", "hunting", "shaking"]: + self.window.animation_manager.play_state("playing") + + self.pending_stats["petting_count"] += 1 + self.last_pet_time = now + self.last_pet_mouse_pos = (x, y) + + if self.pending_stats["petting_count"] % 5 == 0: + self.check_for_achievements() + + if now - self.last_purr_time > 2.0: + self.window.sound_manager.play_sound("purr") + self.last_purr_time = now def toggle_laser_mode(self): self.laser_mode = not self.laser_mode diff --git a/src/ui/main_window.py b/src/ui/main_window.py index 3d1c574..30c157d 100644 --- a/src/ui/main_window.py +++ b/src/ui/main_window.py @@ -59,6 +59,10 @@ def __init__(self, config_manager=None): # Начальный размер self.resize(self.original_size) + # Применяем прозрачность из конфига + if self.config: + self.setWindowOpacity(self.config.get("opacity") / 100.0) + self.sound_manager = SoundManager(self.config) # Анимация для перемещения окна (охота) diff --git a/src/ui/settings_dialog.py b/src/ui/settings_dialog.py index 17c1a0f..e230858 100644 --- a/src/ui/settings_dialog.py +++ b/src/ui/settings_dialog.py @@ -61,6 +61,13 @@ def __init__(self, config, parent=None): self.skin_combo.setCurrentIndex(index) layout.addWidget(self.skin_combo) + # Прозрачность + layout.addWidget(QLabel("Прозрачность окна:")) + self.opacity_slider = QSlider(Qt.Horizontal) + self.opacity_slider.setRange(20, 100) + self.opacity_slider.setValue(self.config.get("opacity")) + layout.addWidget(self.opacity_slider) + # Кнопки btn_layout = QHBoxLayout() save_btn = QPushButton("Сохранить") diff --git a/src/ui/stats_dialog.py b/src/ui/stats_dialog.py index 24852a4..3d70f23 100644 --- a/src/ui/stats_dialog.py +++ b/src/ui/stats_dialog.py @@ -45,12 +45,14 @@ def setup_progress_tab(self, widget): # Общие очки и KPS в одной строке stats_row = QHBoxLayout() points_label = QLabel(f"Всего: {points} ❤️") + stats_row.addWidget(points_label) max_kps = self.db.get_stat("max_kps") - kps_label = QLabel(f"Рекорд скорости: {max_kps} кл/сек ⚡") - kps_label.setAlignment(Qt.AlignCenter) - kps_label.setStyleSheet("color: #555; font-size: 11px; margin-bottom: 5px;") - layout.addWidget(kps_label) + kps_label = QLabel(f"Рекорд: {max_kps} ⚡") + kps_label.setStyleSheet("color: #555; font-size: 12px;") + stats_row.addStretch() + stats_row.addWidget(kps_label) + layout.addLayout(stats_row) # Прогресс бар if points_for_next_level > 0: