2
* Copyright 2007-2008 Thomas Gallinari <tg8187@yahoo.fr>
3
* Copyright 2007-2008 Alexandre Galinier <alex.galinier@hotmail.com>
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.
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.
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/>.
22
#include <KgDifficulty>
23
#include <QRandomGenerator>
27
const qreal Ghost::MAX_SPEED_RATIO = 2.0;
28
const int Ghost::POINTS = 200;
30
Ghost::Ghost(qreal p_x, qreal p_y, const QString &p_imageId, Maze *p_maze) : Character(p_x, p_y, p_maze)
32
// Initialize the ghost attributes
33
m_imageId = p_imageId;
34
m_points = Ghost::POINTS;
35
m_type = Element::GHOST;
36
m_state = Ghost::HUNTER;
37
m_maxSpeed = m_normalSpeed * MAX_SPEED_RATIO;
38
// Makes the ghost move as soon as the game is created
71
void Ghost::updateMove()
73
// Get the current cell coordinates from the character coordinates
74
int curCellRow = m_maze->getRowFromY(m_y);
75
int curCellCol = m_maze->getColFromX(m_x);
76
// Contains the different directions a ghost can choose when on a cell center
77
QList<QPointF> directionsList;
80
// If the ghost is not "eaten"
81
if (m_state != Ghost::EATEN) {
82
// If the ghost gets on a Cell center
84
// We retrieve all the directions the ghost can choose (save the turning back)
85
if (m_maze->getCell(curCellRow, curCellCol + 1).getType() == Cell::CORRIDOR ||
86
(m_maze->getCell(curCellRow, curCellCol).getType() == Cell::GHOSTCAMP &&
87
m_maze->getCell(curCellRow, curCellCol + 1).getType() == Cell::GHOSTCAMP)) {
89
directionsList.append(QPointF(m_speed, 0.0));
92
if (m_maze->getCell(curCellRow + 1, curCellCol).getType() == Cell::CORRIDOR ||
93
(m_maze->getCell(curCellRow, curCellCol).getType() == Cell::GHOSTCAMP &&
94
m_maze->getCell(curCellRow + 1, curCellCol).getType() == Cell::GHOSTCAMP)) {
96
directionsList.append(QPointF(0.0, m_speed));
99
if (m_maze->getCell(curCellRow - 1, curCellCol).getType() == Cell::CORRIDOR ||
100
(m_maze->getCell(curCellRow, curCellCol).getType() == Cell::GHOSTCAMP &&
101
m_maze->getCell(curCellRow - 1, curCellCol).getType() == Cell::GHOSTCAMP)) {
103
directionsList.append(QPointF(0.0, -m_speed));
106
if (m_maze->getCell(curCellRow, curCellCol - 1).getType() == Cell::CORRIDOR ||
107
(m_maze->getCell(curCellRow, curCellCol).getType() == Cell::GHOSTCAMP &&
108
m_maze->getCell(curCellRow, curCellCol - 1).getType() == Cell::GHOSTCAMP)) {
110
directionsList.append(QPointF(-m_speed, 0.0));
113
// Random number generation to choose one of the directions
114
nb = int(double(QRandomGenerator::global()->bounded(RAND_MAX)) / (double(RAND_MAX) + 1) * directionsList.size());
115
// If there is no directions in the list, the character goes backward
116
if (directionsList.size() == 0) {
117
m_xSpeed = -m_xSpeed;
118
m_ySpeed = -m_ySpeed;
119
} else if ((m_xSpeed != 0 && m_xSpeed != directionsList[nb].x()) ||
120
(m_ySpeed != 0 && m_ySpeed != directionsList[nb].y())) { // If the chosen direction isn't forward
121
// We move the ghost on the center of the cell and update the directions
123
m_xSpeed = directionsList[nb].x();
124
m_ySpeed = directionsList[nb].y();
129
} else { // If the ghost has been eaten
131
// If the ghost has not reached the camp yet
132
if (m_pathToCamp.size() != 0) {
133
// Go to the next cell to the camp
134
updateMove(m_pathToCamp.first().y(), m_pathToCamp.first().x());
135
// Remove the cell the ghost has reached from the path
136
m_pathToCamp.removeFirst();
138
// If the ghost is not at home (that means it has just been eaten)
139
if (curCellRow != m_maze->getResurrectionCell().y() || curCellCol != m_maze->getResurrectionCell().x()) {
140
// Compute the path to go back to the camp
141
m_pathToCamp = m_maze->getPathToGhostCamp(curCellRow, curCellCol);
142
if (!m_pathToCamp.isEmpty()) {
143
updateMove(m_pathToCamp.first().y(), m_pathToCamp.first().x());
145
// Set the ghost at home
146
m_x = m_maze->getResurrectionCell().x() * Cell::SIZE + Cell::SIZE / 2;
147
m_y = m_maze->getResurrectionCell().y() * Cell::SIZE + Cell::SIZE / 2;
148
setState(Ghost::HUNTER);
150
} else { // The ghost has reached the ghost camp
151
setState(Ghost::HUNTER);
159
void Ghost::updateMove(int p_row, int p_col)
161
// Get the current cell coordinates from the ghost coordinates
162
int curGhostRow = m_maze->getRowFromY(m_y);
163
int curGhostCol = m_maze->getColFromX(m_x);
166
if (curGhostRow == p_row) {
167
if (p_col > curGhostCol) {
175
if (p_row > curGhostRow) {
188
QString Ghost::getImageId() const
193
Ghost::State Ghost::getState() const
198
void Ghost::setState(Ghost::State p_state)
204
m_speed = m_normalSpeed / 2;
208
m_speed = m_normalSpeed;
211
Q_EMIT stateChanged();
214
void Ghost::doActionOnCollision(Kapman *)
221
Q_EMIT ghostEaten(this);
229
void Ghost::initSpeedInc()
231
// Ghosts speed increase when level up
232
switch ((int) Kg::difficultyLevel()) {
233
case KgDifficultyLevel::Easy:
234
m_speedIncrease = Character::LOW_SPEED_INC;
236
case KgDifficultyLevel::Medium:
237
m_speedIncrease = Character::MEDIUM_SPEED_INC;
239
case KgDifficultyLevel::Hard:
240
m_speedIncrease = Character::HIGH_SPEED_INC;