[Game] Animate arrows with a draw-on effect on creation

This commit is contained in:
Lukas Brübach 2026-08-11 01:39:44 +02:00
parent 12fb19ef06
commit 15027497ee
3 changed files with 56 additions and 1 deletions

View file

@ -13,6 +13,7 @@
#include <QGraphicsScene> #include <QGraphicsScene>
#include <QGraphicsSceneMouseEvent> #include <QGraphicsSceneMouseEvent>
#include <QPainter> #include <QPainter>
#include <QTimer>
#include <QtMath> #include <QtMath>
#include <libcockatrice/card/card_info.h> #include <libcockatrice/card/card_info.h>
#include <libcockatrice/protocol/pb/command_attach_card.pb.h> #include <libcockatrice/protocol/pb/command_attach_card.pb.h>
@ -91,10 +92,11 @@ void ArrowItem::updatePath(const QPointF &endPoint)
prepareGeometryChange(); prepareGeometryChange();
if (lineLength < 30) { if (lineLength < 30) {
path = QPainterPath(); path = QPainterPath();
centerLine = QPainterPath();
} else { } else {
QPointF c(lineLength / 2, qTan(phi * M_PI / 180) * lineLength); QPointF c(lineLength / 2, qTan(phi * M_PI / 180) * lineLength);
QPainterPath centerLine; centerLine = QPainterPath();
centerLine.moveTo(0, 0); centerLine.moveTo(0, 0);
centerLine.quadTo(c, QPointF(lineLength, 0)); centerLine.quadTo(c, QPointF(lineLength, 0));
@ -125,6 +127,32 @@ void ArrowItem::updatePath(const QPointF &endPoint)
setTransform(QTransform().rotate(-line.angle())); 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*/) void ArrowItem::paint(QPainter *painter, const QStyleOptionGraphicsItem * /*option*/, QWidget * /*widget*/)
{ {
QColor paintColor(data->color); QColor paintColor(data->color);
@ -133,8 +161,29 @@ void ArrowItem::paint(QPainter *painter, const QStyleOptionGraphicsItem * /*opti
} else { } else {
paintColor.setAlpha(150); 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->setBrush(paintColor);
painter->drawPath(path); 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) void ArrowItem::mousePressEvent(QGraphicsSceneMouseEvent *event)

View file

@ -11,6 +11,7 @@
class CardItem; class CardItem;
class QGraphicsSceneMouseEvent; class QGraphicsSceneMouseEvent;
class PlayerLogic; class PlayerLogic;
class QTimer;
class ArrowItem : public QObject, public QGraphicsItem class ArrowItem : public QObject, public QGraphicsItem
{ {
@ -21,6 +22,9 @@ signals:
private: private:
QPainterPath path; QPainterPath path;
QPainterPath centerLine;
qreal drawProgress = 1.0;
QTimer *drawTimer = nullptr;
protected: protected:
QSharedPointer<const ArrowData> data; QSharedPointer<const ArrowData> data;
@ -38,6 +42,7 @@ public:
void delArrow(); void delArrow();
void updatePath(); void updatePath();
void updatePath(const QPointF &endPoint); void updatePath(const QPointF &endPoint);
void startDrawAnimation();
void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) override; void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) override;
[[nodiscard]] QRectF boundingRect() const override [[nodiscard]] QRectF boundingRect() const override

View file

@ -495,6 +495,7 @@ void GameScene::addArrow(QSharedPointer<ArrowData> data)
} }
auto *arrow = new ArrowItem(data, startCard, targetItem); auto *arrow = new ArrowItem(data, startCard, targetItem);
arrow->startDrawAnimation();
addItem(arrow); addItem(arrow);
arrowRegistry.insert(data, arrow); arrowRegistry.insert(data, arrow);
connect(arrow, &ArrowItem::requestDeletion, this, &GameScene::requestArrowDeletion); connect(arrow, &ArrowItem::requestDeletion, this, &GameScene::requestArrowDeletion);