From 5874d6982fa517929740c7c82aad30d05ec5bde3 Mon Sep 17 00:00:00 2001 From: MpakobecEx Date: Thu, 22 Oct 2026 00:51:31 +0500 Subject: [PATCH] Queue battle feedback animations with skip --- IMPLEMENTATION_CHECKLIST.md | 4 +- .../Assets/Vanguard/Runtime/UI/BattleView.cs | 70 +++++++++++++++++-- client/README.md | 2 +- docs/HANDOFF.md | 2 +- docs/SESSION-STATE.md | 2 +- 5 files changed, 68 insertions(+), 12 deletions(-) diff --git a/IMPLEMENTATION_CHECKLIST.md b/IMPLEMENTATION_CHECKLIST.md index 5f82afb..a83882f 100644 --- a/IMPLEMENTATION_CHECKLIST.md +++ b/IMPLEMENTATION_CHECKLIST.md @@ -283,8 +283,8 @@ - [x] Boost: выбор карты заднего ряда как поддержки перед атакой. - [x] Event-фидбек: атака, guard, drive, урон, heal, retire, perfect guard. - [x] Отображение силы/крита из `MatchView`; модификаторы уже посчитаны сервером. -- [ ] Очередь анимаций строго по событиям сервера: ride, call, attack, drive, damage, retire, boost, guard. -- [ ] Скип/ускорение анимаций. +- [x] Очередь event-анимаций и кнопка «Пропустить анимации». +- [ ] Полноценные move/attack/drive/damage-анимации карт и стола. - [x] Таймер хода, индикатор реконнекта, кнопка сдачи (базово). - [x] Экран результата: победа/поражение; Gold/XP и «ещё матч» — дальше. - [x] Догон состояния по `resync`/snapshot после реконнекта (без переигрывания анимаций). diff --git a/client/Assets/Vanguard/Runtime/UI/BattleView.cs b/client/Assets/Vanguard/Runtime/UI/BattleView.cs index 3402fbf..0de2c94 100644 --- a/client/Assets/Vanguard/Runtime/UI/BattleView.cs +++ b/client/Assets/Vanguard/Runtime/UI/BattleView.cs @@ -48,6 +48,9 @@ namespace Vanguard.UI private float _feedbackTime; private float _feedbackDuration; private Color _feedbackColor; + private readonly Queue _feedbackQueue = new Queue(); + private Button _skipFeedback; + private bool _feedbackPlaying; private readonly List _logLines = new List(); private GameConnection _connection; @@ -129,6 +132,11 @@ namespace Vanguard.UI _status.horizontalOverflow = HorizontalWrapMode.Wrap; UiKit.SetPreferredHeight(_status, 74f); + _skipFeedback = UiKit.CreateButton( + right, "SkipFeedback", "Пропустить анимации", SkipFeedback, 15); + UiKit.SetPreferredHeight(_skipFeedback, 38f); + _skipFeedback.gameObject.SetActive(false); + var logTitle = UiKit.CreateText( right, "LogTitle", "Журнал", 16, new Color(0.72f, 0.80f, 0.94f), TextAnchor.MiddleLeft); logTitle.fontStyle = FontStyle.Bold; @@ -182,9 +190,12 @@ namespace Vanguard.UI _showAllIntents = false; _logLines.Clear(); RebuildLog(); + _feedbackQueue.Clear(); + _feedbackPlaying = false; _feedbackTime = 0f; _feedback.gameObject.SetActive(false); _flash.gameObject.SetActive(false); + _skipFeedback.gameObject.SetActive(false); _topInfo.text = (info.DeckName ?? string.Empty) + " · " + info.MatchId; SetStatus("Подключаемся к матчу…", Muted); _root.gameObject.SetActive(true); @@ -209,6 +220,7 @@ namespace Vanguard.UI _result.gameObject.SetActive(false); _feedback.gameObject.SetActive(false); _flash.gameObject.SetActive(false); + _skipFeedback.gameObject.SetActive(false); _view = null; } @@ -226,23 +238,40 @@ namespace Vanguard.UI private void ShowFeedback(string text, Color color, float duration = 1.25f, bool flash = false) { - _feedback.text = text; - _feedbackColor = color; - _feedbackDuration = duration; - _feedbackTime = duration; + _feedbackQueue.Enqueue(new FeedbackStep(text, color, duration, flash)); + if (!_feedbackPlaying) + StartNextFeedback(); + } + + private void StartNextFeedback() + { + if (_feedbackQueue.Count == 0) + { + _feedbackPlaying = false; + _skipFeedback.gameObject.SetActive(false); + return; + } + + var step = _feedbackQueue.Dequeue(); + _feedbackPlaying = true; + _feedback.text = step.Text; + _feedbackColor = step.Color; + _feedbackDuration = step.Duration; + _feedbackTime = step.Duration; _feedback.gameObject.SetActive(true); _feedback.rectTransform.localScale = Vector3.one * 1.12f; + _skipFeedback.gameObject.SetActive(true); - if (flash) + if (step.Flash) { _flash.gameObject.SetActive(true); - _flash.color = new Color(color.r, color.g, color.b, 0.22f); + _flash.color = new Color(step.Color.r, step.Color.g, step.Color.b, 0.22f); } } private void UpdateFeedback() { - if (_feedbackTime <= 0f) + if (!_feedbackPlaying) return; _feedbackTime -= Time.unscaledDeltaTime; @@ -260,6 +289,33 @@ namespace Vanguard.UI _feedback.gameObject.SetActive(false); if (_flash != null) _flash.gameObject.SetActive(false); + StartNextFeedback(); + } + + private void SkipFeedback() + { + _feedbackQueue.Clear(); + _feedbackPlaying = false; + _feedbackTime = 0f; + _feedback.gameObject.SetActive(false); + _flash.gameObject.SetActive(false); + _skipFeedback.gameObject.SetActive(false); + } + + private readonly struct FeedbackStep + { + public FeedbackStep(string text, Color color, float duration, bool flash) + { + Text = text; + Color = color; + Duration = duration; + Flash = flash; + } + + public string Text { get; } + public Color Color { get; } + public float Duration { get; } + public bool Flash { get; } } private RectTransform BuildResultPanel(Transform parent) diff --git a/client/README.md b/client/README.md index b566668..550170a 100644 --- a/client/README.md +++ b/client/README.md @@ -65,7 +65,7 @@ http://localhost:5080 - Боевой gray-box: доска, рука, часы, кнопки всех легальных интентов, сдача с подтверждением и экран результата. - Боевой UX: клик по картам/зонам, подсветка целей, сгруппированные - действия, журнал событий и подсказки. + действия, журнал событий и подсказки; event-анимации с очередью и скипом. - Карты в бою и коллекции: процедурные арты по клану, рамка, имя, ранг, триггер, сила/крит, REST и рубашка для скрытых карт. - Реальные арты: `CardImageService` ищет `Resources/CardArt/{imageKey}`; diff --git a/docs/HANDOFF.md b/docs/HANDOFF.md index d223853..56b6cba 100644 --- a/docs/HANDOFF.md +++ b/docs/HANDOFF.md @@ -754,7 +754,7 @@ Battle; Boot и общие сервисы остаются персистент `tools/import_card_art.py`. - Boost UI: клик по своему `SUP`-слоту выбирает поддержку, затем цель. - Event-фидбек: всплывающие атака/guard/drive/урон/heal/retire, не - блокирует ввод. + блокирует ввод; очередь событий и кнопка «Пропустить анимации». - Боевой UX: клик по карте/зоне, подсветка целей, отдельная группировка действий, журнал последних событий и подсказки выбора. - Поле: `R V R` / `R R R` у каждого игрока, зона урона слева, колода и diff --git a/docs/SESSION-STATE.md b/docs/SESSION-STATE.md index 3894493..7b4cb7a 100644 --- a/docs/SESSION-STATE.md +++ b/docs/SESSION-STATE.md @@ -61,7 +61,7 @@ (+soul), справа колода и ниже дроп; у противника зеркально; между полями — зона защиты со щитом и проверками. - Анимации: event-фидбек (атака, guard, drive, урон, retire, heal) поверх - стола, не блокирует ввод. + стола, не блокирует ввод; очередь событий + кнопка «Пропустить анимации». - Реальные арты: `imageKey` из `/api/cards` + `CardImageService` ищет `Resources/CardArt/{imageKey}`. Скачаны все 124 арта. Импорт: `tools/import_card_art.py`.