From 15027497ee468b43674708706191b5085cba23b0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lukas=20Br=C3=BCbach?= Date: Tue, 11 Aug 2026 01:39:44 +0200 Subject: [PATCH] [Game] Animate arrows with a draw-on effect on creation --- .../src/game_graphics/board/arrow_item.cpp | 51 ++++++++++++++++++- .../src/game_graphics/board/arrow_item.h | 5 ++ cockatrice/src/game_graphics/game_scene.cpp | 1 + 3 files changed, 56 insertions(+), 1 deletion(-) diff --git a/cockatrice/src/game_graphics/board/arrow_item.cpp b/cockatrice/src/game_graphics/board/arrow_item.cpp index ce8967bb5..665bfea89 100644 --- a/cockatrice/src/game_graphics/board/arrow_item.cpp +++ b/cockatrice/src/game_graphics/board/arrow_item.cpp @@ -13,6 +13,7 @@ #include #include #include +#include #include #include #include @@ -91,10 +92,11 @@ void ArrowItem::updatePath(const QPointF &endPoint) prepareGeometryChange(); if (lineLength < 30) { path = QPainterPath(); + centerLine = QPainterPath(); } else { QPointF c(lineLength / 2, qTan(phi * M_PI / 180) * lineLength); - QPainterPath centerLine; + centerLine = QPainterPath(); centerLine.moveTo(0, 0); centerLine.quadTo(c, QPointF(lineLength, 0)); @@ -125,6 +127,32 @@ void ArrowItem::updatePath(const QPointF &endPoint) setTransform(QTransform().rotate(-line.angle())); } +void ArrowItem::startDrawAnimation() +{ + if (!SettingsCache::instance().userInterface().getAnimationsEnabled() || centerLine.isEmpty()) { + return; + } + + drawProgress = 0.0; + if (drawTimer == nullptr) { + drawTimer = new QTimer(this); + connect(drawTimer, &QTimer::timeout, this, [this] { + if (!SettingsCache::instance().userInterface().getAnimationsEnabled()) { + drawProgress = 1.0; + drawTimer->stop(); + } else { + drawProgress += 0.08; + if (drawProgress >= 1.0) { + drawProgress = 1.0; + drawTimer->stop(); + } + } + update(); + }); + } + drawTimer->start(20); +} + void ArrowItem::paint(QPainter *painter, const QStyleOptionGraphicsItem * /*option*/, QWidget * /*widget*/) { QColor paintColor(data->color); @@ -133,8 +161,29 @@ void ArrowItem::paint(QPainter *painter, const QStyleOptionGraphicsItem * /*opti } else { paintColor.setAlpha(150); } + + painter->save(); + if (drawProgress < 1.0 && !path.isEmpty()) { + QRectF pr = path.boundingRect(); + qreal revealX = pr.left() + pr.width() * drawProgress; + QPainterPath clip; + clip.addRect(QRectF(pr.left() - 100, pr.top() - 100, revealX - pr.left() + 200, pr.height() + 200)); + painter->setClipPath(clip); + } painter->setBrush(paintColor); painter->drawPath(path); + + if (drawProgress < 1.0 && !centerLine.isEmpty()) { + const QPointF impulse = centerLine.pointAtPercent(drawProgress); + QRadialGradient glow(impulse, 10); + glow.setColorAt(0, QColor(255, 255, 255, 230)); + glow.setColorAt(0.4, paintColor); + glow.setColorAt(1, QColor(paintColor.red(), paintColor.green(), paintColor.blue(), 0)); + painter->setPen(Qt::NoPen); + painter->setBrush(glow); + painter->drawEllipse(impulse, 8, 8); + } + painter->restore(); } void ArrowItem::mousePressEvent(QGraphicsSceneMouseEvent *event) diff --git a/cockatrice/src/game_graphics/board/arrow_item.h b/cockatrice/src/game_graphics/board/arrow_item.h index 1c306e065..1e5082d35 100644 --- a/cockatrice/src/game_graphics/board/arrow_item.h +++ b/cockatrice/src/game_graphics/board/arrow_item.h @@ -11,6 +11,7 @@ class CardItem; class QGraphicsSceneMouseEvent; class PlayerLogic; +class QTimer; class ArrowItem : public QObject, public QGraphicsItem { @@ -21,6 +22,9 @@ signals: private: QPainterPath path; + QPainterPath centerLine; + qreal drawProgress = 1.0; + QTimer *drawTimer = nullptr; protected: QSharedPointer data; @@ -38,6 +42,7 @@ public: void delArrow(); void updatePath(); void updatePath(const QPointF &endPoint); + void startDrawAnimation(); void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) override; [[nodiscard]] QRectF boundingRect() const override diff --git a/cockatrice/src/game_graphics/game_scene.cpp b/cockatrice/src/game_graphics/game_scene.cpp index db2088104..b214dc2d8 100644 --- a/cockatrice/src/game_graphics/game_scene.cpp +++ b/cockatrice/src/game_graphics/game_scene.cpp @@ -495,6 +495,7 @@ void GameScene::addArrow(QSharedPointer data) } auto *arrow = new ArrowItem(data, startCard, targetItem); + arrow->startDrawAnimation(); addItem(arrow); arrowRegistry.insert(data, arrow); connect(arrow, &ArrowItem::requestDeletion, this, &GameScene::requestArrowDeletion);