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 | |
28 | const int KapmanItem::NB_FRAMES = 32; |
29 | const int KapmanItem::ANIM_LOW_SPEED = 500; |
30 | const int KapmanItem::ANIM_MEDIUM_SPEED = 400; |
31 | const int KapmanItem::ANIM_HIGH_SPEED = 300; |
32 | |
33 | KapmanItem::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 | |
64 | KapmanItem::~KapmanItem() { |
65 | delete m_animationTimer; |
66 | } |
67 | |
68 | void 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 | |
95 | void 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 | |
113 | void 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 | |
122 | void 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 | |
129 | void KapmanItem::pauseAnim() { |
130 | if (m_animationTimer->state() == QTimeLine::Running) |
131 | m_animationTimer->setPaused(true); |
132 | } |
133 | |
134 | void KapmanItem::resumeAnim() { |
135 | if (m_animationTimer->state() == QTimeLine::Running) |
136 | m_animationTimer->setPaused(false); |
137 | } |
138 | |
139 | void KapmanItem::stopAnim() { |
140 | setElementId("kapman_0" ); |
141 | if (m_animationTimer->state() == QTimeLine::Running) |
142 | m_animationTimer->stop(); |
143 | } |
144 | |
145 | void KapmanItem::setFrame(const int p_frame) { |
146 | setElementId(QString("kapman_%1" ).arg(p_frame)); |
147 | } |
148 | |
149 | void KapmanItem::startBlinking() { |
150 | stopAnim(); |
151 | setElementId("kapman_0" ); |
152 | CharacterItem::startBlinking(); |
153 | } |
154 | |
155 | void 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 | |