Animate idle character frames

This commit is contained in:
2026-05-28 10:48:54 +08:00
parent 4cfeb5022c
commit 69c3d34ae8
2 changed files with 48 additions and 7 deletions
+38 -6
View File
@@ -29,6 +29,7 @@ QString previewImagePath()
PetWindow::PetWindow(QWidget *parent)
: QWidget(parent)
, m_imageLabel(new QLabel(this))
, m_currentFrameIndex(0)
, m_dragging(false)
, m_alwaysOnTop(true)
{
@@ -43,6 +44,10 @@ PetWindow::PetWindow(QWidget *parent)
layout->setContentsMargins(0, 0, 0, 0);
layout->addWidget(m_imageLabel);
connect(&m_animationTimer, &QTimer::timeout, this, [this]() {
advanceIdleFrame();
});
loadInitialImage();
}
@@ -112,14 +117,38 @@ void PetWindow::loadInitialImage()
const CharacterState *idleState = package.state(QStringLiteral("idle"));
if (idleState != nullptr && !idleState->framePaths.isEmpty())
{
setDisplayImage(idleState->framePaths.first());
startIdleAnimation(*idleState);
return;
}
setDisplayImage(previewImagePath());
setDisplayImage(previewImagePath(), true);
}
void PetWindow::setDisplayImage(const QString &imagePath)
void PetWindow::startIdleAnimation(const CharacterState &idleState)
{
m_animationTimer.stop();
m_idleFrames = idleState.framePaths;
m_currentFrameIndex = 0;
setDisplayImage(m_idleFrames.at(m_currentFrameIndex), true);
const int intervalMs = qMax(1, 1000 / idleState.fps);
m_animationTimer.start(intervalMs);
}
void PetWindow::advanceIdleFrame()
{
if (m_idleFrames.isEmpty())
{
m_animationTimer.stop();
return;
}
m_currentFrameIndex = (m_currentFrameIndex + 1) % m_idleFrames.size();
setDisplayImage(m_idleFrames.at(m_currentFrameIndex), false);
}
void PetWindow::setDisplayImage(const QString &imagePath, bool centerWindow)
{
QPixmap pixmap(imagePath);
if (pixmap.isNull())
@@ -134,10 +163,13 @@ void PetWindow::setDisplayImage(const QString &imagePath)
m_imageLabel->setPixmap(scaled);
resize(scaled.size());
if (const QScreen *screen = QGuiApplication::primaryScreen())
if (centerWindow)
{
const QRect available = screen->availableGeometry();
move(available.center() - rect().center());
if (const QScreen *screen = QGuiApplication::primaryScreen())
{
const QRect available = screen->availableGeometry();
move(available.center() - rect().center());
}
}
}
+10 -1
View File
@@ -2,8 +2,12 @@
#include <QLabel>
#include <QPoint>
#include <QStringList>
#include <QTimer>
#include <QWidget>
struct CharacterState;
class PetWindow : public QWidget
{
public:
@@ -17,11 +21,16 @@ protected:
private:
void loadInitialImage();
void setDisplayImage(const QString &imagePath);
void startIdleAnimation(const CharacterState &idleState);
void advanceIdleFrame();
void setDisplayImage(const QString &imagePath, bool centerWindow);
void setAlwaysOnTop(bool enabled);
QLabel *m_imageLabel;
QTimer m_animationTimer;
QStringList m_idleFrames;
QPoint m_dragOffset;
int m_currentFrameIndex;
bool m_dragging;
bool m_alwaysOnTop;
};