File indexing completed on 2024-04-21 04:01:56

0001 /*
0002     SPDX-FileCopyrightText: 2007-2008 Thomas Gallinari <tg8187@yahoo.fr>
0003     SPDX-FileCopyrightText: 2007-2008 Pierre-BenoƮt Besse <besse.pb@gmail.com>
0004 
0005     SPDX-License-Identifier: GPL-2.0-or-later
0006 */
0007 
0008 #include "character.h"
0009 
0010 #include <KGameDifficulty>
0011 
0012 const qreal Character::LOW_SPEED = 3.75;
0013 const qreal Character::MEDIUM_SPEED = 4.5;
0014 const qreal Character::HIGH_SPEED = 5.25;
0015 const qreal Character::LOW_SPEED_INC = 0.005;
0016 const qreal Character::MEDIUM_SPEED_INC = 0.01;
0017 const qreal Character::HIGH_SPEED_INC = 0.02;
0018 
0019 Character::Character(qreal p_x, qreal p_y, Maze *p_maze)
0020     : Element(p_x, p_y, p_maze)
0021     , m_xSpeed(0)
0022     , m_ySpeed(0)
0023 {
0024     initSpeed();
0025     m_maxSpeed = m_normalSpeed; // To avoid bugs, but will be overridden in the Ghost and Kapman constructors
0026 }
0027 
0028 Character::~Character() = default;
0029 
0030 void Character::move()
0031 {
0032     // Take care of the Maze borders
0033     if (m_maze->getColFromX(m_x + m_xSpeed) == 0) { // First column
0034         m_x = (m_maze->getNbColumns() - 1.5) * Cell::SIZE;
0035     } else if (m_maze->getColFromX(m_x + m_xSpeed) == m_maze->getNbColumns() - 1) { // Last column
0036         m_x = 1.5 * Cell::SIZE;
0037     } else if (m_maze->getRowFromY(m_y + m_ySpeed) == 0) { // First row
0038         m_y = (m_maze->getNbRows() - 1.5) * Cell::SIZE;
0039     } else if (m_maze->getRowFromY(m_y + m_ySpeed) == m_maze->getNbRows() - 1) { // Last row
0040         m_y = 1.5 * Cell::SIZE;
0041     }
0042     // Move the Character
0043     m_x += m_xSpeed;
0044     m_y += m_ySpeed;
0045     Q_EMIT moved(m_x, m_y);
0046 }
0047 
0048 void Character::die()
0049 {
0050     Q_EMIT eaten();
0051 }
0052 
0053 qreal Character::getXSpeed() const
0054 {
0055     return m_xSpeed;
0056 }
0057 
0058 qreal Character::getYSpeed() const
0059 {
0060     return m_ySpeed;
0061 }
0062 
0063 qreal Character::getSpeed() const
0064 {
0065     return m_speed;
0066 }
0067 
0068 qreal Character::getNormalSpeed() const
0069 {
0070     return m_normalSpeed;
0071 }
0072 
0073 void Character::setXSpeed(qreal p_xSpeed)
0074 {
0075     m_xSpeed = p_xSpeed;
0076 }
0077 
0078 void Character::setYSpeed(qreal p_ySpeed)
0079 {
0080     m_ySpeed = p_ySpeed;
0081 }
0082 
0083 void Character::initSpeed()
0084 {
0085     // Kapman speed increase when level up
0086     switch ((int)KGameDifficulty::globalLevel()) {
0087     case KGameDifficultyLevel::Easy:
0088         m_normalSpeed = Character::LOW_SPEED;
0089         break;
0090     case KGameDifficultyLevel::Medium:
0091         m_normalSpeed = Character::MEDIUM_SPEED;
0092         break;
0093     case KGameDifficultyLevel::Hard:
0094         m_normalSpeed = Character::HIGH_SPEED;
0095         break;
0096     }
0097     m_speed = m_normalSpeed;
0098 }
0099 
0100 void Character::increaseCharactersSpeed()
0101 {
0102     m_normalSpeed += m_normalSpeed * m_speedIncrease;
0103     // Do not have a speed over the max allowed speed
0104     if (m_normalSpeed > m_maxSpeed) {
0105         m_normalSpeed = m_maxSpeed;
0106     }
0107     m_speed = m_normalSpeed;
0108 }
0109 
0110 bool Character::isInLineSight(Character *p_character)
0111 {
0112     int curCallerRow; // The current row of the Character
0113     int curCallerCol; // The current column of the Character
0114     int curCharacterRow; // The current row of the other Character
0115     int curCharacterCol; // The current column of the other Character
0116 
0117     curCallerRow = m_maze->getRowFromY(m_y);
0118     curCallerCol = m_maze->getColFromX(m_x);
0119     curCharacterRow = m_maze->getRowFromY(p_character->getY());
0120     curCharacterCol = m_maze->getColFromX(p_character->getX());
0121 
0122     // If the two Characters are on the same row
0123     if (curCallerRow == curCharacterRow) {
0124         // If The Character is on the right of the other one and goes to the left
0125         if (curCallerCol > curCharacterCol && m_xSpeed < 0) {
0126             // Check there is a wall between them
0127             for (int i = curCharacterCol; i < curCallerCol; ++i) {
0128                 if (m_maze->getCell(curCallerRow, i).getType() != Cell::CORRIDOR) {
0129                     return false;
0130                 }
0131             }
0132             // If not, the other Character is in the line sight
0133             return true;
0134             // If the Character is on the left of the other one and goes to the right
0135         } else if (curCallerCol < curCharacterCol && m_xSpeed > 0) {
0136             // Check there is a wall between them
0137             for (int i = curCallerCol; i < curCharacterCol; ++i) {
0138                 if (m_maze->getCell(curCallerRow, i).getType() != Cell::CORRIDOR) {
0139                     return false;
0140                 }
0141             }
0142             // If not, the other Character is in the line sight
0143             return true;
0144         }
0145         // If the two Characters are on the same column
0146     } else if (curCallerCol == curCharacterCol) {
0147         // If The Character is on the bottom of the other one and goes up
0148         if (curCallerRow > curCharacterRow && m_ySpeed < 0) {
0149             // Check there is a wall between them
0150             for (int i = curCharacterRow; i < curCallerRow; ++i) {
0151                 if (m_maze->getCell(i, curCallerCol).getType() != Cell::CORRIDOR) {
0152                     return false;
0153                 }
0154             }
0155             // If not, the other Character is in the line sight
0156             return true;
0157             // If the Character is on the top of the other one and goes down
0158         } else if (curCallerRow < curCharacterRow && m_ySpeed > 0) {
0159             // Check there is a wall between them
0160             for (int i = curCallerRow; i < curCharacterRow; ++i) {
0161                 if (m_maze->getCell(i, curCallerCol).getType() != Cell::CORRIDOR) {
0162                     return false;
0163                 }
0164             }
0165             // If not, the other Character is in the line sight
0166             return true;
0167         }
0168     }
0169     // If the two Characters are not on the same row or column, they are not in the line of sight
0170     return false;
0171 }
0172 
0173 Cell Character::getNextCell()
0174 {
0175     Cell nextCell;
0176     // Get the current cell coordinates from the character coordinates
0177     int curCellRow = m_maze->getRowFromY(m_y);
0178     int curCellCol = m_maze->getColFromX(m_x);
0179 
0180     // Get the next cell function of the character direction
0181     if (m_xSpeed > 0) {
0182         nextCell = m_maze->getCell(curCellRow, curCellCol + 1);
0183     } else if (m_xSpeed < 0) {
0184         nextCell = m_maze->getCell(curCellRow, curCellCol - 1);
0185     } else if (m_ySpeed > 0) {
0186         nextCell = m_maze->getCell(curCellRow + 1, curCellCol);
0187     } else if (m_ySpeed < 0) {
0188         nextCell = m_maze->getCell(curCellRow - 1, curCellCol);
0189     }
0190 
0191     return nextCell;
0192 }
0193 
0194 bool Character::onCenter()
0195 {
0196     // Get the current cell center coordinates
0197     qreal centerX = (m_maze->getColFromX(m_x) + 0.5) * Cell::SIZE;
0198     qreal centerY = (m_maze->getRowFromY(m_y) + 0.5) * Cell::SIZE;
0199     bool willGoPast = false;
0200 
0201     // Will the character go past the center of the cell it's on ?
0202     // If it goes right
0203     if (m_xSpeed > 0) {
0204         willGoPast = (m_x <= centerX && m_x + m_xSpeed >= centerX);
0205     }
0206     // If it goes left
0207     else if (m_xSpeed < 0) {
0208         willGoPast = (m_x >= centerX && m_x + m_xSpeed <= centerX);
0209     }
0210     // If it goes down
0211     else if (m_ySpeed > 0) {
0212         willGoPast = (m_y <= centerY && m_y + m_ySpeed >= centerY);
0213     }
0214     // If it goes up
0215     else if (m_ySpeed < 0) {
0216         willGoPast = (m_y >= centerY && m_y + m_ySpeed <= centerY);
0217     }
0218     // If it does not move
0219     else {
0220         willGoPast = (m_x == centerX && m_y == centerY);
0221     }
0222 
0223     return willGoPast;
0224 }
0225 
0226 bool Character::isOnCenter()
0227 {
0228     // Get the current cell center coordinates
0229     qreal centerX = (m_maze->getColFromX(m_x) + 0.5) * Cell::SIZE;
0230     qreal centerY = (m_maze->getRowFromY(m_y) + 0.5) * Cell::SIZE;
0231 
0232     return m_x == centerX && m_y == centerY;
0233 }
0234 
0235 void Character::moveOnCenter()
0236 {
0237     setX((m_maze->getColFromX(m_x) + 0.5) * Cell::SIZE);
0238     setY((m_maze->getRowFromY(m_y) + 0.5) * Cell::SIZE);
0239 }
0240 
0241 #include "moc_character.cpp"