#pragma once #include #include #include #include #include class AppSettings; // Drives the cat: wanders along its ground line, sits, grooms, stretches and // naps, chases the odd metal chip, and reacts to petting and dragging. class CatController : public QObject { Q_OBJECT QML_ELEMENT QML_UNCREATABLE("Provided by C++") Q_PROPERTY(qreal x READ x WRITE setX NOTIFY xChanged) Q_PROPERTY(qreal stageWidth READ stageWidth WRITE setStageWidth NOTIFY stageWidthChanged) Q_PROPERTY(qreal catWidth READ catWidth WRITE setCatWidth NOTIFY catWidthChanged) Q_PROPERTY(QPointF catCenter READ catCenter WRITE setCatCenter NOTIFY catCenterChanged) Q_PROPERTY(bool facingRight READ facingRight NOTIFY facingRightChanged) Q_PROPERTY(Mood mood READ mood NOTIFY moodChanged) Q_PROPERTY(bool paused READ paused WRITE setPaused NOTIFY pausedChanged) Q_PROPERTY(bool dragging READ dragging WRITE setDragging NOTIFY draggingChanged) Q_PROPERTY(bool hovered READ hovered WRITE setHovered NOTIFY hoveredChanged) Q_PROPERTY(QPointF look READ look NOTIFY lookChanged) Q_PROPERTY(bool chipVisible READ chipVisible NOTIFY chipVisibleChanged) Q_PROPERTY(qreal chipX READ chipX NOTIFY chipXChanged) Q_PROPERTY(int chipKick READ chipKick NOTIFY chipKickChanged) Q_PROPERTY(bool cupVisible READ cupVisible NOTIFY cupVisibleChanged) Q_PROPERTY(qreal cupX READ cupX NOTIFY cupXChanged) public: enum class Mood { Walking, Running, Sitting, Grooming, Stretching, Sleeping, Loving, Alert, Chasing, Batting, Drinking }; Q_ENUM(Mood) explicit CatController(AppSettings *settings, QObject *parent = nullptr); qreal x() const { return m_x; } void setX(qreal x); qreal stageWidth() const { return m_stageWidth; } void setStageWidth(qreal width); qreal catWidth() const { return m_catWidth; } void setCatWidth(qreal width); // Where the cat's face is on the desktop, so the eyes can find the cursor. QPointF catCenter() const { return m_catCenter; } void setCatCenter(const QPointF ¢er); bool facingRight() const { return m_facingRight; } Mood mood() const { return m_mood; } bool paused() const { return m_paused; } void setPaused(bool paused); bool dragging() const { return m_dragging; } void setDragging(bool dragging); bool hovered() const { return m_hovered; } void setHovered(bool hovered); QPointF look() const { return m_look; } bool chipVisible() const { return m_chipVisible; } qreal chipX() const { return m_chipX; } int chipKick() const { return m_chipKick; } bool cupVisible() const { return m_cupVisible; } qreal cupX() const { return m_cupX; } Q_INVOKABLE void pet(); Q_INVOKABLE void doTrick(Mood mood); Q_INVOKABLE void tossChip(); Q_INVOKABLE void coffeeBreak(); signals: void xChanged(); void stageWidthChanged(); void catWidthChanged(); void catCenterChanged(); void facingRightChanged(); void moodChanged(); void pausedChanged(); void draggingChanged(); void hoveredChanged(); void lookChanged(); void chipVisibleChanged(); void chipXChanged(); void chipKickChanged(); void cupVisibleChanged(); void cupXChanged(); private: void tick(); void trackCursor(); void setMood(Mood mood); void setFacingRight(bool right); void setChipX(qreal x); void pickNextMood(); void holdMood(Mood mood, int ms); void batChip(); void endChase(); void endCoffee(); void scheduleChip(); qreal catNose() const; AppSettings *m_settings; QTimer m_tickTimer; QTimer m_moodTimer; QTimer m_cursorTimer; QTimer m_chipTimer; QElapsedTimer m_clock; qint64 m_lastTickMs = 0; qreal m_x = 120; qreal m_stageWidth = 1440; qreal m_catWidth = 120; QPointF m_catCenter; bool m_facingRight = true; Mood m_mood = Mood::Walking; bool m_paused = false; bool m_dragging = false; bool m_hovered = false; bool m_frozen = false; QPointF m_look; bool m_chipVisible = false; qreal m_chipX = 0; int m_chipKick = 0; int m_batsLeft = 0; bool m_cupVisible = false; qreal m_cupX = 0; };