1/*
2 * Copyright 2007-2008 Thomas Gallinari <tg8187@yahoo.fr>
3 * Copyright 2007-2008 Nathalie Liesse <nathalie.liesse@gmail.com>
4 *
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License as
7 * published by the Free Software Foundation; either version 2 of
8 * the License, or (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 */
18
19
20#include "kapmanitem.h"
21#include "characteritem.h"
22#include "ghost.h"
23#include "settings.h"
24
25#include <QGraphicsScene>
26#include <KgDifficulty>
27
28const int KapmanItem::NB_FRAMES = 32;
29const int KapmanItem::ANIM_LOW_SPEED = 500;
30const int KapmanItem::ANIM_MEDIUM_SPEED = 400;
31const int KapmanItem::ANIM_HIGH_SPEED = 300;
32
33KapmanItem::KapmanItem(Kapman* p_model) : CharacterItem(p_model) {
34 connect(p_model, SIGNAL(directionChanged()), this, SLOT(updateDirection()));
35 connect(p_model, SIGNAL(gameUpdated()), this, SLOT(manageCollision()));
36 connect(p_model, SIGNAL(stopped()), this, SLOT(stopAnim()));
37
38 // A timeLine for the Kapman animation
39 m_animationTimer = new QTimeLine();
40 m_animationTimer->setCurveShape(QTimeLine::SineCurve);
41 m_animationTimer->setLoopCount(0);
42 m_animationTimer->setFrameRange(0, NB_FRAMES - 1);
43 // Animation speed
44 switch ((int) Kg::difficultyLevel())
45 {
46 case KgDifficultyLevel::Easy:
47 m_animationTimer->setDuration(KapmanItem::ANIM_LOW_SPEED);
48 break;
49 case KgDifficultyLevel::Medium:
50 m_animationTimer->setDuration(KapmanItem::ANIM_MEDIUM_SPEED);
51 break;
52 case KgDifficultyLevel::Hard:
53 m_animationTimer->setDuration(KapmanItem::ANIM_HIGH_SPEED);
54 break;
55 }
56 connect(m_animationTimer, SIGNAL(frameChanged(int)), this, SLOT(setFrame(int)));
57
58 // Define the timer which sets the blinking frequency
59 m_blinkTimer = new QTimer(this);
60 m_blinkTimer->setInterval(400);
61 connect(m_blinkTimer, SIGNAL(timeout()), this, SLOT(blink()));
62}
63
64KapmanItem::~KapmanItem() {
65 delete m_animationTimer;
66}
67
68void KapmanItem::updateDirection() {
69 QTransform transform;
70 int angle = 0;
71 Kapman* model = (Kapman*)getModel();
72
73 // Compute the angle
74 if (model->getXSpeed() > 0) {
75 angle = 0;
76 } else if (model->getXSpeed() < 0) {
77 angle = 180; // The default image is right oriented
78 }
79 if (model->getYSpeed() > 0) {
80 angle = 90;
81 } else if (model->getYSpeed() < 0) {
82 angle = -90;
83 }
84
85 if (m_rotationFlag==0) {
86 angle=0;
87 }
88 // Rotate the item
89 transform.translate(boundingRect().width() / 2, boundingRect().height() / 2);
90 transform.rotate(angle);
91 transform.translate(-boundingRect().width() / 2, -boundingRect().height() / 2);
92 setTransform(transform);
93}
94
95void KapmanItem::manageCollision() {
96 QList<QGraphicsItem*> collidingList = collidingItems();
97
98 // The signal is emitted only if the list contains more than 1 items (to exclude the case
99 // when the kapman only collides with the maze)
100 if (collidingList.size() > 1) {
101 for (int i = 0; i < collidingList.size(); ++i) {
102 // The maze and the points labels have a negative zValue which allows to exclude them from the treatment of collisions
103 if (collidingList[i]->zValue() >= 0) {
104 ElementItem* item = dynamic_cast<ElementItem*>(collidingList[i]);
105 if (item) {
106 item->getModel()->doActionOnCollision((Kapman*)getModel());
107 }
108 }
109 }
110 }
111}
112
113void KapmanItem::update(qreal p_x, qreal p_y) {
114 ElementItem::update(p_x, p_y);
115
116 // If the kapman is moving
117 if (((Kapman*)getModel())->getXSpeed() != 0 || ((Kapman*)getModel())->getYSpeed() != 0) {
118 startAnim();
119 }
120}
121
122void KapmanItem::startAnim() {
123 // Start the animation timer if it is not active
124 if (m_animationTimer->state() != QTimeLine::Running) {
125 m_animationTimer->start();
126 }
127}
128
129void KapmanItem::pauseAnim() {
130 if (m_animationTimer->state() == QTimeLine::Running)
131 m_animationTimer->setPaused(true);
132}
133
134void KapmanItem::resumeAnim() {
135 if (m_animationTimer->state() == QTimeLine::Running)
136 m_animationTimer->setPaused(false);
137}
138
139void KapmanItem::stopAnim() {
140 setElementId("kapman_0");
141 if (m_animationTimer->state() == QTimeLine::Running)
142 m_animationTimer->stop();
143}
144
145void KapmanItem::setFrame(const int p_frame) {
146 setElementId(QString("kapman_%1").arg(p_frame));
147}
148
149void KapmanItem::startBlinking() {
150 stopAnim();
151 setElementId("kapman_0");
152 CharacterItem::startBlinking();
153}
154
155void KapmanItem::blink() {
156 CharacterItem::blink();
157 if (m_nbBlinks % 2 == 0) {
158 setElementId("kapman_0");
159 } else {
160 setElementId("kapman_blink");
161 }
162 // Make the kapman blink 2 times (4 ticks)
163 if (m_nbBlinks == 4) {
164 m_blinkTimer->stop();
165 }
166}
167
168