1/*
2 * Copyright 2007-2008 Thomas Gallinari <tg8187@yahoo.fr>
3 * Copyright 2007-2008 Pierre-BenoƮt Besse <besse.pb@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#include "character.h"
20
21#include <KgDifficulty>
22
23const qreal Character::LOW_SPEED = 3.75;
24const qreal Character::MEDIUM_SPEED = 4.5;
25const qreal Character::HIGH_SPEED = 5.25;
26const qreal Character::LOW_SPEED_INC = 0.005;
27const qreal Character::MEDIUM_SPEED_INC = 0.01;
28const qreal Character::HIGH_SPEED_INC = 0.02;
29
30Character::Character(qreal p_x, qreal p_y, Maze* p_maze) : Element(p_x, p_y, p_maze), m_xSpeed(0), m_ySpeed(0) {
31 initSpeed();
32 m_maxSpeed = m_normalSpeed; // To avoid bugs, but will be overridden in the Ghost and Kapman constructors
33}
34
35Character::~Character() {
36}
37
38void Character::move() {
39 // Take care of the Maze borders
40 if (m_maze->getColFromX(m_x + m_xSpeed) == 0) { // First column
41 m_x = (m_maze->getNbColumns() - 1.5) * Cell::SIZE;
42 } else if (m_maze->getColFromX(m_x + m_xSpeed) == m_maze->getNbColumns() - 1) { // Last column
43 m_x = 1.5 * Cell::SIZE;
44 } else if (m_maze->getRowFromY(m_y + m_ySpeed) == 0) { // First row
45 m_y = (m_maze->getNbRows() - 1.5) * Cell::SIZE;
46 } else if (m_maze->getRowFromY(m_y + m_ySpeed) == m_maze->getNbRows() - 1) { // Last row
47 m_y = 1.5 * Cell::SIZE;
48 }
49 // Move the Character
50 m_x += m_xSpeed;
51 m_y += m_ySpeed;
52 emit(moved(m_x, m_y));
53}
54
55void Character::die() {
56 emit(eaten());
57}
58
59qreal Character::getXSpeed() const {
60 return m_xSpeed;
61}
62
63qreal Character::getYSpeed() const {
64 return m_ySpeed;
65}
66
67qreal Character::getSpeed() const {
68 return m_speed;
69}
70
71qreal Character::getNormalSpeed() const {
72 return m_normalSpeed;
73}
74
75void Character::setXSpeed(qreal p_xSpeed) {
76 m_xSpeed = p_xSpeed;
77}
78
79void Character::setYSpeed(qreal p_ySpeed) {
80 m_ySpeed = p_ySpeed;
81}
82
83void Character::initSpeed() {
84 // Kapman speed increase when level up
85 switch ((int) Kg::difficultyLevel())
86 {
87 case KgDifficultyLevel::Easy:
88 m_normalSpeed = Character::LOW_SPEED;
89 break;
90 case KgDifficultyLevel::Medium:
91 m_normalSpeed = Character::MEDIUM_SPEED;
92 break;
93 case KgDifficultyLevel::Hard:
94 m_normalSpeed = Character::HIGH_SPEED;
95 break;
96 }
97 m_speed = m_normalSpeed;
98}
99
100void Character::increaseCharactersSpeed() {
101 m_normalSpeed += m_normalSpeed * m_speedIncrease;
102 // Do not have a speed over the max allowed speed
103 if (m_normalSpeed > m_maxSpeed) {
104 m_normalSpeed = m_maxSpeed;
105 }
106 m_speed = m_normalSpeed;
107}
108
109bool Character::isInLineSight(Character* p_character) {
110 int curCallerRow; // The current row of the Character
111 int curCallerCol; // The current column of the Character
112 int curCharacterRow; // The current row of the other Character
113 int curCharacterCol; // The current column of the other Character
114
115 curCallerRow = m_maze->getRowFromY(m_y);
116 curCallerCol = m_maze->getColFromX(m_x);
117 curCharacterRow = m_maze->getRowFromY(p_character->getY());
118 curCharacterCol = m_maze->getColFromX(p_character->getX());
119
120 // If the two Characters are on the same row
121 if (curCallerRow == curCharacterRow ) {
122 // If The Character is on the right of the other one and goes to the left
123 if (curCallerCol > curCharacterCol && m_xSpeed < 0) {
124 // Check there is a wall between them
125 for (int i = curCharacterCol; i < curCallerCol; ++i) {
126 if (m_maze->getCell(curCallerRow, i).getType() != Cell::CORRIDOR) {
127 return false;
128 }
129 }
130 // If not, the other Character is in the line sight
131 return true;
132 // If the Character is on the left of the other one and goes to the right
133 } else if (curCallerCol < curCharacterCol && m_xSpeed > 0) {
134 // Check there is a wall between them
135 for (int i = curCallerCol; i < curCharacterCol; ++i) {
136 if (m_maze->getCell(curCallerRow, i).getType() != Cell::CORRIDOR) {
137 return false;
138 }
139 }
140 // If not, the other Character is in the line sight
141 return true;
142 }
143 // If the two Characters are on the same column
144 } else if (curCallerCol == curCharacterCol) {
145 // If The Character is on the bottom of the other one and goes up
146 if (curCallerRow > curCharacterRow && m_ySpeed < 0) {
147 // Check there is a wall between them
148 for (int i = curCharacterRow; i < curCallerRow; ++i) {
149 if (m_maze->getCell(i, curCallerCol).getType() != Cell::CORRIDOR) {
150 return false;
151 }
152 }
153 // If not, the other Character is in the line sight
154 return true;
155 // If the Character is on the top of the other one and goes down
156 } else if (curCallerRow < curCharacterRow && m_ySpeed > 0) {
157 // Check there is a wall between them
158 for (int i = curCallerRow; i < curCharacterRow; ++i) {
159 if (m_maze->getCell(i, curCallerCol).getType() != Cell::CORRIDOR) {
160 return false;
161 }
162 }
163 // If not, the other Character is in the line sight
164 return true;
165 }
166 }
167 // If the two Characters are not on the same row or column, they are not in the line of sight
168 return false;
169}
170
171Cell Character::getNextCell() {
172 Cell nextCell;
173 // Get the current cell coordinates from the character coordinates
174 int curCellRow = m_maze->getRowFromY(m_y);
175 int curCellCol = m_maze->getColFromX(m_x);
176
177 // Get the next cell function of the character direction
178 if (m_xSpeed > 0) {
179 nextCell = m_maze->getCell(curCellRow, curCellCol + 1);
180 } else if (m_xSpeed < 0) {
181 nextCell = m_maze->getCell(curCellRow, curCellCol - 1);
182 } else if (m_ySpeed > 0) {
183 nextCell = m_maze->getCell(curCellRow + 1, curCellCol);
184 } else if (m_ySpeed < 0) {
185 nextCell = m_maze->getCell(curCellRow - 1, curCellCol);
186 }
187
188 return nextCell;
189}
190
191bool Character::onCenter() {
192 // Get the current cell center coordinates
193 qreal centerX = (m_maze->getColFromX(m_x) + 0.5) * Cell::SIZE;
194 qreal centerY = (m_maze->getRowFromY(m_y) + 0.5) * Cell::SIZE;
195 bool willGoPast = false;
196
197 // Will the character go past the center of the cell it's on ?
198 // If goes right
199 if (m_xSpeed > 0) {
200 willGoPast = (m_x <= centerX && m_x + m_xSpeed >= centerX);
201 }
202 // If goes left
203 else if (m_xSpeed < 0) {
204 willGoPast = (m_x >= centerX && m_x + m_xSpeed <= centerX);
205 }
206 // If goes down
207 else if (m_ySpeed > 0) {
208 willGoPast = (m_y <= centerY && m_y + m_ySpeed >= centerY);
209 }
210 // If goes up
211 else if (m_ySpeed < 0) {
212 willGoPast = (m_y >= centerY && m_y + m_ySpeed <= centerY);
213 }
214 // If does not moe
215 else {
216 willGoPast = (m_x == centerX && m_y == centerY);
217 }
218
219 return willGoPast;
220}
221
222void Character::moveOnCenter() {
223 setX((m_maze->getColFromX(m_x) + 0.5) * Cell::SIZE);
224 setY((m_maze->getRowFromY(m_y) + 0.5) * Cell::SIZE);
225}
226