File indexing completed on 2024-04-21 04:01:58

0001 /*
0002     SPDX-FileCopyrightText: 2007-2008 Thomas Gallinari <tg8187@yahoo.fr>
0003     SPDX-FileCopyrightText: 2007-2008 Nathalie Liesse <nathalie.liesse@gmail.com>
0004 
0005     SPDX-License-Identifier: GPL-2.0-or-later
0006 */
0007 
0008 #include "kapmanitem.h"
0009 #include "ghost.h"
0010 #include "settings.h"
0011 
0012 #include <KGameDifficulty>
0013 #include <QGraphicsScene>
0014 
0015 const int KapmanItem::NB_FRAMES = 32;
0016 const int KapmanItem::ANIM_LOW_SPEED = 500;
0017 const int KapmanItem::ANIM_MEDIUM_SPEED = 400;
0018 const int KapmanItem::ANIM_HIGH_SPEED = 300;
0019 
0020 KapmanItem::KapmanItem(Kapman *p_model)
0021     : CharacterItem(p_model)
0022 {
0023     connect(p_model, &Kapman::directionChanged, this, &KapmanItem::updateDirection);
0024     connect(p_model, &Kapman::gameUpdated, this, &KapmanItem::manageCollision);
0025     connect(p_model, &Kapman::stopped, this, &KapmanItem::stopAnim);
0026 
0027     // A timeLine for the Kapman animation
0028     m_animationTimer = new QTimeLine();
0029     m_animationTimer->setEasingCurve(QEasingCurve::SineCurve);
0030     m_animationTimer->setLoopCount(0);
0031     m_animationTimer->setFrameRange(0, NB_FRAMES - 1);
0032     // Animation speed
0033     switch ((int)KGameDifficulty::globalLevel()) {
0034     case KGameDifficultyLevel::Easy:
0035         m_animationTimer->setDuration(KapmanItem::ANIM_LOW_SPEED);
0036         break;
0037     case KGameDifficultyLevel::Medium:
0038         m_animationTimer->setDuration(KapmanItem::ANIM_MEDIUM_SPEED);
0039         break;
0040     case KGameDifficultyLevel::Hard:
0041         m_animationTimer->setDuration(KapmanItem::ANIM_HIGH_SPEED);
0042         break;
0043     }
0044     connect(m_animationTimer, &QTimeLine::frameChanged, this, &KapmanItem::setFrame);
0045 
0046     // Define the timer which sets the blinking frequency
0047     m_blinkTimer = new QTimer(this);
0048     m_blinkTimer->setInterval(400);
0049     connect(m_blinkTimer, &QTimer::timeout, this, &KapmanItem::blink);
0050 }
0051 
0052 KapmanItem::~KapmanItem()
0053 {
0054     delete m_animationTimer;
0055 }
0056 
0057 void KapmanItem::updateDirection()
0058 {
0059     QTransform transform;
0060     int angle = 0;
0061     auto model = (Kapman *)getModel();
0062 
0063     // Compute the angle
0064     if (model->getXSpeed() > 0) {
0065         angle = 0;
0066     } else if (model->getXSpeed() < 0) {
0067         angle = 180; // The default image is right oriented
0068     }
0069     if (model->getYSpeed() > 0) {
0070         angle = 90;
0071     } else if (model->getYSpeed() < 0) {
0072         angle = -90;
0073     }
0074 
0075     if (m_rotationFlag == 0) {
0076         angle = 0;
0077     }
0078     // Rotate the item
0079     transform.translate(boundingRect().width() / 2, boundingRect().height() / 2);
0080     transform.rotate(angle);
0081     transform.translate(-boundingRect().width() / 2, -boundingRect().height() / 2);
0082     setTransform(transform);
0083 }
0084 
0085 void KapmanItem::manageCollision()
0086 {
0087     QList<QGraphicsItem *> collidingList = collidingItems();
0088 
0089     // The signal is emitted only if the list contains more than 1 item (to exclude the case
0090     // when the kapman only collides with the maze)
0091     if (collidingList.size() > 1) {
0092         for (int i = 0; i < collidingList.size(); ++i) {
0093             // The maze and the points labels have a negative zValue which allows to exclude them from the treatment of collisions
0094             if (collidingList[i]->zValue() >= 0) {
0095                 auto item = dynamic_cast<ElementItem *>(collidingList[i]);
0096                 if (item) {
0097                     item->getModel()->doActionOnCollision((Kapman *)getModel());
0098                 }
0099             }
0100         }
0101     }
0102 }
0103 
0104 void KapmanItem::update(qreal p_x, qreal p_y)
0105 {
0106     ElementItem::update(p_x, p_y);
0107 
0108     // If the kapman is moving
0109     if (((Kapman *)getModel())->getXSpeed() != 0 || ((Kapman *)getModel())->getYSpeed() != 0) {
0110         startAnim();
0111     }
0112 }
0113 
0114 void KapmanItem::startAnim()
0115 {
0116     // Start the animation timer if it is not active
0117     if (m_animationTimer->state() != QTimeLine::Running) {
0118         m_animationTimer->start();
0119     }
0120 }
0121 
0122 void KapmanItem::pauseAnim()
0123 {
0124     if (m_animationTimer->state() == QTimeLine::Running) {
0125         m_animationTimer->setPaused(true);
0126     }
0127 }
0128 
0129 void KapmanItem::resumeAnim()
0130 {
0131     if (m_animationTimer->state() == QTimeLine::Running) {
0132         m_animationTimer->setPaused(false);
0133     }
0134 }
0135 
0136 void KapmanItem::stopAnim()
0137 {
0138     setElementId(QStringLiteral("kapman_0"));
0139     if (m_animationTimer->state() == QTimeLine::Running) {
0140         m_animationTimer->stop();
0141     }
0142 }
0143 
0144 void KapmanItem::setFrame(const int p_frame)
0145 {
0146     setElementId(QStringLiteral("kapman_%1").arg(p_frame));
0147 }
0148 
0149 void KapmanItem::startBlinking()
0150 {
0151     stopAnim();
0152     setElementId(QStringLiteral("kapman_0"));
0153     CharacterItem::startBlinking();
0154 }
0155 
0156 void KapmanItem::blink()
0157 {
0158     CharacterItem::blink();
0159     if (m_nbBlinks % 2 == 0) {
0160         setElementId(QStringLiteral("kapman_0"));
0161     } else {
0162         setElementId(QStringLiteral("kapman_blink"));
0163     }
0164     // Make the kapman blink 2 times (4 ticks)
0165     if (m_nbBlinks == 4) {
0166         m_blinkTimer->stop();
0167     }
0168 }
0169 
0170 #include "moc_kapmanitem.cpp"