~neon/kapman/master

« back to all changes in this revision

Viewing changes to ghost.cpp

  • Committer: Friedrich W. H. Kossebau
  • Date: 2020-12-30 12:55:56 UTC
  • Revision ID: git-v1:5864d1ce6462952ea2fc8a6a263976a5c97142e8
Move source files into own subfolder src/

GIT_SILENT

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*
2
 
 * Copyright 2007-2008 Thomas Gallinari <tg8187@yahoo.fr>
3
 
 * Copyright 2007-2008 Alexandre Galinier <alex.galinier@hotmail.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 "ghost.h"
20
 
 
21
 
#include <QPointF>
22
 
#include <KgDifficulty>
23
 
#include <QRandomGenerator>
24
 
#include <cstdlib>
25
 
#include <ctime>
26
 
 
27
 
const qreal Ghost::MAX_SPEED_RATIO = 2.0;
28
 
const int Ghost::POINTS = 200;
29
 
 
30
 
Ghost::Ghost(qreal p_x, qreal p_y, const QString &p_imageId, Maze *p_maze) : Character(p_x, p_y, p_maze)
31
 
{
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
39
 
    goLeft();
40
 
}
41
 
 
42
 
Ghost::~Ghost()
43
 
{
44
 
 
45
 
}
46
 
 
47
 
void Ghost::goUp()
48
 
{
49
 
    m_xSpeed = 0;
50
 
    m_ySpeed = -m_speed;
51
 
}
52
 
 
53
 
void Ghost::goDown()
54
 
{
55
 
    m_xSpeed = 0;
56
 
    m_ySpeed = m_speed;
57
 
}
58
 
 
59
 
void Ghost::goRight()
60
 
{
61
 
    m_xSpeed = m_speed;
62
 
    m_ySpeed = 0;
63
 
}
64
 
 
65
 
void Ghost::goLeft()
66
 
{
67
 
    m_xSpeed = -m_speed;
68
 
    m_ySpeed = 0;
69
 
}
70
 
 
71
 
void Ghost::updateMove()
72
 
{
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;
78
 
    int nb = 0;
79
 
 
80
 
    // If the ghost is not "eaten"
81
 
    if (m_state != Ghost::EATEN) {
82
 
        // If the ghost gets on a Cell center
83
 
        if (onCenter()) {
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)) {
88
 
                if (m_xSpeed >= 0) {
89
 
                    directionsList.append(QPointF(m_speed, 0.0));
90
 
                }
91
 
            }
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)) {
95
 
                if (m_ySpeed >= 0) {
96
 
                    directionsList.append(QPointF(0.0, m_speed));
97
 
                }
98
 
            }
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)) {
102
 
                if (m_ySpeed <= 0) {
103
 
                    directionsList.append(QPointF(0.0, -m_speed));
104
 
                }
105
 
            }
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)) {
109
 
                if (m_xSpeed <= 0) {
110
 
                    directionsList.append(QPointF(-m_speed, 0.0));
111
 
                }
112
 
            }
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
122
 
                moveOnCenter();
123
 
                m_xSpeed = directionsList[nb].x();
124
 
                m_ySpeed = directionsList[nb].y();
125
 
            }
126
 
        }
127
 
        // We move the ghost
128
 
        move();
129
 
    } else {    // If the ghost has been eaten
130
 
        if (onCenter()) {
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();
137
 
            } else {
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());
144
 
                    } else {
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);
149
 
                    }
150
 
                } else {    // The ghost has reached the ghost camp
151
 
                    setState(Ghost::HUNTER);
152
 
                }
153
 
            }
154
 
        }
155
 
        move();
156
 
    }
157
 
}
158
 
 
159
 
void Ghost::updateMove(int p_row, int p_col)
160
 
{
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);
164
 
 
165
 
    if (onCenter()) {
166
 
        if (curGhostRow == p_row) {
167
 
            if (p_col > curGhostCol) {
168
 
                m_xSpeed = m_speed;
169
 
                m_ySpeed = 0;
170
 
            } else {
171
 
                m_xSpeed = -m_speed;
172
 
                m_ySpeed = 0;
173
 
            }
174
 
        } else {
175
 
            if (p_row > curGhostRow) {
176
 
                m_xSpeed = 0;
177
 
                m_ySpeed = m_speed;
178
 
            } else {
179
 
                m_xSpeed = 0;
180
 
                m_ySpeed = -m_speed;
181
 
            }
182
 
        }
183
 
    }
184
 
    // We move the ghost
185
 
    move();
186
 
}
187
 
 
188
 
QString Ghost::getImageId() const
189
 
{
190
 
    return m_imageId;
191
 
}
192
 
 
193
 
Ghost::State Ghost::getState() const
194
 
{
195
 
    return m_state;
196
 
}
197
 
 
198
 
void Ghost::setState(Ghost::State p_state)
199
 
{
200
 
    // Change the state
201
 
    m_state = p_state;
202
 
    switch (m_state) {
203
 
    case Ghost::PREY:
204
 
        m_speed = m_normalSpeed / 2;
205
 
        break;
206
 
    case HUNTER:
207
 
    case EATEN:
208
 
        m_speed = m_normalSpeed;
209
 
        break;
210
 
    }
211
 
    Q_EMIT stateChanged();
212
 
}
213
 
 
214
 
void Ghost::doActionOnCollision(Kapman *)
215
 
{
216
 
    switch (m_state) {
217
 
    case Ghost::HUNTER:
218
 
        Q_EMIT lifeLost();
219
 
        break;
220
 
    case Ghost::PREY:
221
 
        Q_EMIT ghostEaten(this);
222
 
        break;
223
 
    case Ghost::EATEN:
224
 
        // Do nothing
225
 
        break;
226
 
    }
227
 
}
228
 
 
229
 
void Ghost::initSpeedInc()
230
 
{
231
 
    // Ghosts speed increase when level up
232
 
    switch ((int) Kg::difficultyLevel()) {
233
 
    case KgDifficultyLevel::Easy:
234
 
        m_speedIncrease = Character::LOW_SPEED_INC;
235
 
        break;
236
 
    case KgDifficultyLevel::Medium:
237
 
        m_speedIncrease = Character::MEDIUM_SPEED_INC;
238
 
        break;
239
 
    case KgDifficultyLevel::Hard:
240
 
        m_speedIncrease = Character::HIGH_SPEED_INC;
241
 
        break;
242
 
    }
243
 
}
244