Add basic character state switching

This commit is contained in:
2026-05-28 10:55:22 +08:00
parent 69c3d34ae8
commit ece41bafc9
2 changed files with 61 additions and 18 deletions
+54 -13
View File
@@ -45,7 +45,7 @@ PetWindow::PetWindow(QWidget *parent)
layout->addWidget(m_imageLabel); layout->addWidget(m_imageLabel);
connect(&m_animationTimer, &QTimer::timeout, this, [this]() { connect(&m_animationTimer, &QTimer::timeout, this, [this]() {
advanceIdleFrame(); advanceStateFrame();
}); });
loadInitialImage(); loadInitialImage();
@@ -91,6 +91,7 @@ void PetWindow::mousePressEvent(QMouseEvent *event)
{ {
m_dragging = true; m_dragging = true;
m_dragOffset = event->globalPosition().toPoint() - frameGeometry().topLeft(); m_dragOffset = event->globalPosition().toPoint() - frameGeometry().topLeft();
playState(QStringLiteral("drag"), false);
event->accept(); event->accept();
return; return;
} }
@@ -103,6 +104,7 @@ void PetWindow::mouseReleaseEvent(QMouseEvent *event)
if (event->button() == Qt::LeftButton) if (event->button() == Qt::LeftButton)
{ {
m_dragging = false; m_dragging = false;
playState(QStringLiteral("idle"), false);
event->accept(); event->accept();
return; return;
} }
@@ -113,39 +115,78 @@ void PetWindow::mouseReleaseEvent(QMouseEvent *event)
void PetWindow::loadInitialImage() void PetWindow::loadInitialImage()
{ {
QString loadError; QString loadError;
const CharacterPackage package = CharacterPackageLoader::load(characterPackagePath(), &loadError); m_characterPackage = CharacterPackageLoader::load(characterPackagePath(), &loadError);
const CharacterState *idleState = package.state(QStringLiteral("idle")); if (m_characterPackage.hasState(QStringLiteral("idle")))
if (idleState != nullptr && !idleState->framePaths.isEmpty())
{ {
startIdleAnimation(*idleState); playState(QStringLiteral("idle"), true);
return; return;
} }
setDisplayImage(previewImagePath(), true); setDisplayImage(previewImagePath(), true);
} }
void PetWindow::startIdleAnimation(const CharacterState &idleState) void PetWindow::playState(const QString &stateName, bool centerWindow)
{ {
if (m_currentStateName == stateName && !m_currentFrames.isEmpty())
{
return;
}
const CharacterState *state = m_characterPackage.state(stateName);
if (state == nullptr || state->framePaths.isEmpty() || state->fps <= 0)
{
return;
}
m_animationTimer.stop(); m_animationTimer.stop();
m_idleFrames = idleState.framePaths; m_currentStateName = stateName;
m_currentFrames = state->framePaths;
m_currentFrameIndex = 0; m_currentFrameIndex = 0;
setDisplayImage(m_idleFrames.at(m_currentFrameIndex), true); setDisplayImage(m_currentFrames.at(m_currentFrameIndex), centerWindow);
const int intervalMs = qMax(1, 1000 / idleState.fps); const int intervalMs = qMax(1, 1000 / state->fps);
m_animationTimer.start(intervalMs); m_animationTimer.start(intervalMs);
} }
void PetWindow::advanceIdleFrame() void PetWindow::advanceStateFrame()
{ {
if (m_idleFrames.isEmpty()) if (m_currentFrames.isEmpty())
{ {
m_animationTimer.stop(); m_animationTimer.stop();
return; return;
} }
m_currentFrameIndex = (m_currentFrameIndex + 1) % m_idleFrames.size(); const CharacterState *state = m_characterPackage.state(m_currentStateName);
setDisplayImage(m_idleFrames.at(m_currentFrameIndex), false); if (state == nullptr)
{
m_animationTimer.stop();
return;
}
if (m_currentFrameIndex + 1 >= m_currentFrames.size())
{
if (state->loop)
{
m_currentFrameIndex = 0;
}
else if (!state->nextState.isEmpty())
{
playState(state->nextState, false);
return;
}
else
{
m_animationTimer.stop();
return;
}
}
else
{
++m_currentFrameIndex;
}
setDisplayImage(m_currentFrames.at(m_currentFrameIndex), false);
} }
void PetWindow::setDisplayImage(const QString &imagePath, bool centerWindow) void PetWindow::setDisplayImage(const QString &imagePath, bool centerWindow)
+7 -5
View File
@@ -1,13 +1,13 @@
#pragma once #pragma once
#include "../character/CharacterPackage.h"
#include <QLabel> #include <QLabel>
#include <QPoint> #include <QPoint>
#include <QStringList> #include <QStringList>
#include <QTimer> #include <QTimer>
#include <QWidget> #include <QWidget>
struct CharacterState;
class PetWindow : public QWidget class PetWindow : public QWidget
{ {
public: public:
@@ -21,14 +21,16 @@ protected:
private: private:
void loadInitialImage(); void loadInitialImage();
void startIdleAnimation(const CharacterState &idleState); void playState(const QString &stateName, bool centerWindow);
void advanceIdleFrame(); void advanceStateFrame();
void setDisplayImage(const QString &imagePath, bool centerWindow); void setDisplayImage(const QString &imagePath, bool centerWindow);
void setAlwaysOnTop(bool enabled); void setAlwaysOnTop(bool enabled);
QLabel *m_imageLabel; QLabel *m_imageLabel;
QTimer m_animationTimer; QTimer m_animationTimer;
QStringList m_idleFrames; CharacterPackage m_characterPackage;
QString m_currentStateName;
QStringList m_currentFrames;
QPoint m_dragOffset; QPoint m_dragOffset;
int m_currentFrameIndex; int m_currentFrameIndex;
bool m_dragging; bool m_dragging;