diff --git a/CMakeLists.txt b/CMakeLists.txt index 6def868..f1f97ca 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,51 +1,48 @@ # KDE Application Version, managed by release script set (KDE_APPLICATIONS_VERSION_MAJOR "19") set (KDE_APPLICATIONS_VERSION_MINOR "07") set (KDE_APPLICATIONS_VERSION_MICRO "70") set (KDE_APPLICATIONS_VERSION "${KDE_APPLICATIONS_VERSION_MAJOR}.${KDE_APPLICATIONS_VERSION_MINOR}.${KDE_APPLICATIONS_VERSION_MICRO}") cmake_minimum_required (VERSION 3.0 FATAL_ERROR) project(bomber VERSION ${KDE_APPLICATIONS_VERSION}) -set (QT_MIN_VERSION "5.7.0") -set (KF5_MIN_VERSION "5.30.0") +set (QT_MIN_VERSION "5.10.0") +set (KF5_MIN_VERSION "5.46.0") find_package(ECM ${KF5_MIN_VERSION} REQUIRED CONFIG) set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${ECM_MODULE_PATH} ${ECM_KDE_MODULE_DIR}) find_package(Qt5 ${QT_MIN_VERSION} REQUIRED NO_MODULE COMPONENTS Widgets) find_package(KF5 ${KF5_MIN_VERSION} REQUIRED COMPONENTS Config CoreAddons Crash DBusAddons DocTools I18n XmlGui ) find_package(KF5KDEGames 4.9.0 REQUIRED) include(FeatureSummary) include(ECMInstallIcons) include(KDEInstallDirs) -include(KDECompilerSettings NO_POLICY_SCOPE) +include(KDEFrameworkCompilerSettings NO_POLICY_SCOPE) include(KDECMakeSettings) include(ECMAddAppIcon) -add_definitions( - -DQT_USE_FAST_CONCATENATION - -DQT_USE_FAST_OPERATOR_PLUS - -DQT_NO_CAST_FROM_ASCII - -DQT_NO_CAST_TO_ASCII - -DQT_NO_CAST_FROM_BYTEARRAY - -DQT_NO_URL_CAST_FROM_STRING -) - +# workaround for https://bugreports.qt.io/browse/QTBUG-74665 (bug in qt5.13 reevaluate it) +if (${Qt5Widgets_VERSION} STREQUAL "5.13.0") + MESSAGE(STATUS "Qt version: ${Qt5Widgets_VERSION} DISABLE compile without deprecated methods. bug QTBUG-74665") +else() + add_definitions(-DQT_DISABLE_DEPRECATED_BEFORE=0x060000) +endif() add_subdirectory(themes) add_subdirectory(sounds) add_subdirectory(icons) add_subdirectory(src) add_subdirectory(doc) feature_summary(WHAT ALL INCLUDE_QUIET_PACKAGES FATAL_ON_MISSING_REQUIRED_PACKAGES) diff --git a/src/board.h b/src/board.h index 97c9444..09e9f40 100644 --- a/src/board.h +++ b/src/board.h @@ -1,210 +1,210 @@ /* * Copyright (C) 2007-2008 John-Paul Stanford * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public * License along with this program; if not, write to the Free * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef BOARD_H #define BOARD_H // Qt #include #include #include #include #include // KDE #include class Plane; class Building; class Bomb; /** * This class used to represent the game board. This makes sure all the game objects * get moved and redrawn every second. It also checks for any collisions */ class BomberBoard : public QGraphicsScene { Q_OBJECT public: /** * The constructor used to create the board. * \param renderer The renderer used to render game objects * \param view The graphics view object which this board is bound to * \param parent The widget which the board is inserted into */ explicit BomberBoard(KGameRenderer * renderer, QGraphicsView * view, QObject * parent = nullptr); ~BomberBoard(); /** * This is called when the game board is resized * \param size The new tile size used on the game board */ void resize(QSize & size); /** * This will redraw the game board */ void redraw(); /** * This is called to start a new level * \param level The level number been started */ void newLevel(unsigned int level); /** * This is called to pause the game. * \param val True if paused, otherwise false */ void setPaused(bool val); /** * This will convert the tile location to actual cords on the board * \param pos The cords relative to the tile * \return The cords relative to the widget */ QPoint mapPosition(const QPointF & pos) const; /** * This will convert the widget location to tile locations * \param pos The cords relative to the widget * \return The cords relative to the tile */ QPointF unmapPosition(const QPoint & pos) const; /** * Used to set the plane state to flying and move it to the start position */ void resetPlane(); /** * This will attempt to drop a bomb if their is not already a bomb dropping */ void dropBomb(); -signals: +Q_SIGNALS: /** * This is emitted when a plane crashes into a building */ void onPlaneCrash(); void playBombSound(); void playCrashSound(); /** * This signal is emitted when a bomb hits a building and before it's exploding * animation starts */ void onBombHit(); /** * This is emitted when the level has been cleared of all buildings */ void levelCleared(); -public slots: +public Q_SLOTS: /** * This is called when the settings change to save the settings */ void settingsChanged(); -private slots: +private Q_SLOTS: /** * This is called once a second to update and draw all the game objects */ void tick(); /** * This is called when a plane has finished exploding */ void planeExploded(); /** * This is called when a bomb has finished exploding */ void bombExploded(); private: /** * This is called when a bomb hits a building * \param bomb The bomb that hit * \param moveBombToX The x position to move the explosion too * \param moveBombToY The y position to move the explosion too */ void bombHit(Bomb * bomb, qreal moveBombToX, qreal moveBombToY); /** * This is used to remove all the current game objects, usually called before * stating a new level */ void clear(); /** * This is used to check for any collisions of the plane or bombs */ void checkCollisions(); /** * This is called when a plane crashes into a building */ void crashed(); /** * This is the renderer used to render game objects */ KGameRenderer * m_renderer; /** * This is the size of a tiling block */ QSize m_tileSize; QTimer * m_clock; /** * If their is a bomb currently dropping then it is pointed to by this */ Bomb * m_bomb; /** * This points to the plane object used in the level */ Plane * m_plane; /** * This contains all the buildings in the current level */ QList m_buildings; /** * This contains all the bombs that are currently exploding */ QQueue m_explodingBombs; /** * This is the number of blocks that make up the buildings */ unsigned int m_buildingBlocks; /** * This is the graphics view object which this board is bound. */ QGraphicsView * m_view; }; #endif diff --git a/src/bomber.h b/src/bomber.h index deb5825..a871aa1 100644 --- a/src/bomber.h +++ b/src/bomber.h @@ -1,76 +1,76 @@ /* * Copyright (C) 2007-2008 John-Paul Stanford * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public * License along with this program; if not, write to the Free * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef BOMBER_H #define BOMBER_H // KDE #include #include // Bomber #include "bomberwidget.h" class QAction; class QStatusBar; class KToggleAction; class KgThemeSelector; class QLabel; /** * This class serves as the main window for Bomber. It handles the * menus, toolbars, and status bars. * * @short Main window class */ class Bomber : public KXmlGuiWindow { Q_OBJECT public: Bomber(); virtual ~Bomber(); void readSettings(); -private slots: +private Q_SLOTS: void closeGame(); void newGame(); void pauseGame(); void showHighscore(); void displayLevel(unsigned int level); void displayScore(unsigned int score); void displayLives(unsigned int lives); void gameStateChanged(BomberGameWidget::State state); private: void highscore(); void initXMLUI(); void setupActions(); KgThemeProvider m_provider; KgThemeSelector * m_selector; BomberGameWidget * m_gameWidget; QStatusBar * m_statusBar; KToggleAction *m_pauseAction, *m_backgroundShowAction, *m_soundAction; QAction * m_newAction; QLabel *m_level, *m_score, *m_lives; }; #endif diff --git a/src/bomberwidget.cpp b/src/bomberwidget.cpp index 83b08fe..49080b2 100644 --- a/src/bomberwidget.cpp +++ b/src/bomberwidget.cpp @@ -1,370 +1,370 @@ /* * Copyright (C) 2007-2008 John-Paul Stanford * Copyright 2010 Stefan Majewsky * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public * License along with this program; if not, write to the Free * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ // own #include "bomberwidget.h" // Qt #include #include #include // KDE #include // Bomber #include "settings.h" #define NEW_LIVE_AT_SCORE 10000; /** The amount the score increases when a bomb hits something */ static const unsigned int SCORE_INCREMENT = 5; static const unsigned int GAME_TIME_DELAY = 1000; static const unsigned int TICKS_PER_SECOND = 1000 / GAME_TIME_DELAY; /** The z-value for overlays */ static const unsigned int OVERLAY_Z_VALUE = 1000; BomberGameWidget::BomberGameWidget(KgThemeProvider * provider, QWidget * parent) : QGraphicsView(parent) , m_state(State::BeforeFirstGame) , m_level(0) , m_lives(0) , m_time(0) , m_renderer(provider) , m_soundBomb(QStandardPaths::locate(QStandardPaths::GenericDataLocation, QStringLiteral("bomber/sounds/bomb.ogg"))) , m_soundCrash(QStandardPaths::locate(QStandardPaths::GenericDataLocation, QStringLiteral("bomber/sounds/crash.ogg"))) { // Gameboard m_board = new BomberBoard(&m_renderer, this, this); connect(m_board, &BomberBoard::playBombSound, this, &BomberGameWidget::playBombSound); connect(m_board, &BomberBoard::playCrashSound, this, &BomberGameWidget::playCrashSound); connect(m_board, &BomberBoard::onPlaneCrash, this, &BomberGameWidget::onPlaneCrashed); connect(m_board, &BomberBoard::onBombHit, this, &BomberGameWidget::onBombHit); connect(m_board, &BomberBoard::levelCleared, this, &BomberGameWidget::onLevelCleared); setScene(m_board); setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff); setFrameStyle(QFrame::NoFrame); setCacheMode(QGraphicsView::CacheBackground); // Optimize caching setFocusPolicy(Qt::StrongFocus); setAlignment(Qt::AlignLeft | Qt::AlignTop); // Overlay m_overlay = new QGraphicsPixmapItem(); m_board->addItem(m_overlay); m_clock = new QTimer(this); m_clock->setInterval(GAME_TIME_DELAY); connect(m_clock, &QTimer::timeout, this, &BomberGameWidget::tick); setMouseTracking(true); generateOverlay(); } BomberGameWidget::~BomberGameWidget() { delete m_board; } unsigned int BomberGameWidget::level() const { return m_level; } unsigned int BomberGameWidget::score() const { return m_score; } void BomberGameWidget::closeGame() { if (m_state != State::BeforeFirstGame && m_state != State::GameOver) { closeLevel(); m_state = State::GameOver; emit stateChanged(m_state); emit gameOver(); redraw(); } } void BomberGameWidget::newGame() { closeGame(); m_level = 1; m_score = 0; m_lives = 3; m_scoreLeftBeforeNewLife = NEW_LIVE_AT_SCORE; emit levelChanged(m_level); emit scoreChanged(m_score); emit livesChanged(m_lives); newLevel(); } void BomberGameWidget::setPaused(bool val) { if (m_state == State::Paused && val == false) { m_clock->start(); m_board->setPaused(false); m_state = State::Running; } else if (m_state == State::Running && val == true) { m_clock->stop(); m_board->setPaused(true); m_state = State::Paused; } emit stateChanged(m_state); redraw(); } void BomberGameWidget::setSuspended(bool val) { if (m_state == State::Suspended && val == false) { m_clock->start(); m_board->setPaused(false); m_state = State::Running; } else if (m_state == State::Running && val == true) { m_clock->stop(); m_board->setPaused(true); m_state = State::Suspended; } emit stateChanged(m_state); redraw(); } void BomberGameWidget::settingsChanged() { m_board->settingsChanged(); } void BomberGameWidget::setSoundsEnabled(bool enable) { BomberSettings::setPlaySounds(enable); BomberSettings::self()->save(); m_board->settingsChanged(); } void BomberGameWidget::onPlaneCrashed() { --m_lives; emit livesChanged(m_lives); if (m_lives == 0) { closeGame(); } else { m_board->resetPlane(); } if (BomberSettings::playSounds() == true) { m_soundCrash.stop(); } } void BomberGameWidget::onBombHit() { unsigned int bonus = SCORE_INCREMENT * m_level; m_score += bonus; emit scoreChanged(m_score); m_scoreLeftBeforeNewLife -= bonus; if (m_scoreLeftBeforeNewLife <= 0) { m_scoreLeftBeforeNewLife = NEW_LIVE_AT_SCORE; ++m_lives; emit livesChanged(m_lives); } if (BomberSettings::playSounds() == true) { m_soundBomb.stop(); } } void BomberGameWidget::playBombSound() { if (BomberSettings::playSounds() == true) { m_soundBomb.start(); } } void BomberGameWidget::playCrashSound() { if (BomberSettings::playSounds() == true) { m_soundCrash.start(); } } void BomberGameWidget::tick() { static signed int ticks = TICKS_PER_SECOND; --ticks; if (ticks <= 0) { ++m_time; emit timeChanged(m_time); ticks = TICKS_PER_SECOND; } } void BomberGameWidget::resizeEvent(QResizeEvent * ev) { QSize boardSize = ev->size(); m_board->resize(boardSize); redraw(); } void BomberGameWidget::closeLevel() { m_clock->stop(); m_board->setPaused(true); } void BomberGameWidget::newLevel() { m_state = State::Running; emit stateChanged(m_state); m_clock->start(); m_board->newLevel(m_level); m_board->setPaused(false); emit livesChanged(m_lives); emit timeChanged(m_time); redraw(); } void BomberGameWidget::mouseReleaseEvent(QMouseEvent * event) { if (event->button() & Qt::LeftButton) { onDropBomb(); } } void BomberGameWidget::onDropBomb() { if (m_state == State::Running) { m_board->dropBomb(); } else if (m_state == State::BetweenLevels) { newLevel(); } else if (m_state == State::BeforeFirstGame) { newGame(); } } void BomberGameWidget::redraw() { if (size().isEmpty()) { return; } QGraphicsItem * item; switch (m_state) { case State::BeforeFirstGame: foreach (item, m_board->items()) { item->hide(); } generateOverlay(); m_overlay->show(); break; case State::Running: foreach (item, m_board->items()) { item->show(); } m_overlay->hide(); break; default: foreach (item, m_board->items()) { item->show(); } generateOverlay(); m_overlay->show(); break; } m_board->redraw(); update(); } void BomberGameWidget::generateOverlay() { unsigned int itemWidth = qRound(0.8 * size().width()); unsigned int itemHeight = qRound(0.6 * size().height()); QPixmap px(itemWidth, itemHeight); px.fill(QColor(0, 0, 0, 0)); QPainter p(&px); p.setPen(QColor(0, 0, 0, 0)); p.setBrush(QBrush(QColor(188, 202, 222, 155))); p.setRenderHint(QPainter::Antialiasing); - p.drawRoundRect(0, 0, itemWidth, itemHeight, 25); + p.drawRoundedRect(0, 0, itemWidth, itemHeight, 25, Qt::RelativeSize); QString text; switch (m_state) { case State::BeforeFirstGame: text = i18nc("Message show to the user when the game is loaded", "Welcome to Bomber.\nClick to start a game"); break; case State::Paused: text = i18nc("Message show to the user while the game is paused", "Paused"); break; case State::BetweenLevels: text = i18nc("Message telling user which level they just completed", "You have successfully cleared level %1\n", m_level - 1) + i18nc("Message telling user which level they are about to start", "On to level %1.", m_level); break; case State::GameOver: text = i18nc("Used to tell the user that the game is over", "Game over."); break; default: text.clear(); } QFont font; font.setPointSize(28); p.setFont(font); unsigned int textWidth = p.boundingRect(p.viewport(), Qt::AlignCenter | Qt::AlignVCenter, text).width(); unsigned int fontSize = 28; while (textWidth > itemWidth * 0.95) { --fontSize; font.setPointSize(fontSize); p.setFont(font); textWidth = p.boundingRect(p.viewport(), Qt::AlignCenter | Qt::AlignVCenter, text).width(); } p.setPen(QColor(0, 0, 0, 255)); p.drawText(p.viewport(), Qt::AlignCenter | Qt::AlignVCenter, text); p.end(); m_overlay->setPixmap(px); m_overlay->setPos((size().width() - itemWidth) / 2, (size().height() - itemHeight) / 2); m_overlay->setZValue(OVERLAY_Z_VALUE); } void BomberGameWidget::onLevelCleared() { if (m_state == State::Running) { m_state = State::BetweenLevels; closeLevel(); ++m_level; emit levelChanged(m_level); emit stateChanged(m_state); redraw(); } } BomberGameWidget::State BomberGameWidget::state() const { return m_state; } diff --git a/src/bomberwidget.h b/src/bomberwidget.h index 2a5b4bc..ffc755f 100644 --- a/src/bomberwidget.h +++ b/src/bomberwidget.h @@ -1,209 +1,209 @@ /* * Copyright (C) 2007-2008 John-Paul Stanford * Copyright 2010 Stefan Majewsky * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public * License along with this program; if not, write to the Free * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef BOMBER_WIDGET_H #define BOMBER_WIDGET_H // Qt #include #include // KDE #include // Bomber #include "board.h" class KgThemeProvider; /** * This is the main game widget class. It manages things like the lives, source counts and game states. */ class BomberGameWidget : public QGraphicsView { Q_OBJECT public: /** * The different states that the game can be in */ enum class State { BeforeFirstGame, Running, BetweenLevels, Paused, Suspended, GameOver }; explicit BomberGameWidget(KgThemeProvider * provider, QWidget * parent = nullptr); ~BomberGameWidget(); /** * Used to find out the current level * \return The current level */ unsigned int level() const; /** * Used to find the current score * \return the current score */ unsigned int score() const; /** * Used to return the game sate * \return The game state */ BomberGameWidget::State state() const; -public slots: +public Q_SLOTS: /** * Used to end the game */ void closeGame(); /** * Used to start a new game */ void newGame(); /** * Used to pause the game * \param paused True to pause the game, False to resume the game */ void setPaused(bool paused); /** * This is called when the settings change to save the settings */ void settingsChanged(); /** * Enabled or disabled the sounds * \param enable True to enable the sounds, false to disable */ void setSoundsEnabled(bool enable); /** * Used to toggle the suspended game state. If val is true and the state is currently running, * them set the sate to suspended. If value is false and the state is suspended, set the sate to running. * \param value True to set state to suspended, False to set state to running. */ void setSuspended(bool value); /** * This is called when the drop bomb key is press or the mouse in the game area. * If the game state is running, If it is between levels, then a new level is created and * if it's BeforeFirstGame then a new game is started. */ void onDropBomb(); -signals: +Q_SIGNALS: /** * This is emitted when the game is over */ void gameOver(); /** * This is emitted when the level changes. * \param level The new level */ void levelChanged(unsigned int level); /** * This is emitted when the source changes * \param score The new score */ void scoreChanged(unsigned int score); /** * This is emitted when the lives change * \param lives The new lives */ void livesChanged(unsigned int lives); /** * This is emitted when the time changes * \param time The new time value */ void timeChanged(unsigned int time); /** * This is emitted when the game state changes * \param state The new game state */ void stateChanged(BomberGameWidget::State state); -private slots: +private Q_SLOTS: void tick(); /** * This is called when a bomb hits a building */ void onBombHit(); /** * This slot is called when a level has been cleared to change the state and get * ready for the next level. */ void onLevelCleared(); /** * This slot is called when the plane crashes */ void onPlaneCrashed(); private: virtual void resizeEvent(QResizeEvent * event) Q_DECL_OVERRIDE; virtual void mouseReleaseEvent(QMouseEvent * event) Q_DECL_OVERRIDE; /** * Create the overlay used to display info to the user. The info will * change depending on the game state. */ void generateOverlay(); void redraw(); void closeLevel(); void newLevel(); void playBombSound(); void playCrashSound(); State m_state; unsigned int m_level; unsigned int m_score; unsigned int m_lives; unsigned int m_time; /** * Used to store the remaining score before a new life is given */ int m_scoreLeftBeforeNewLife; KGameRenderer m_renderer; QTimer * m_clock; BomberBoard * m_board; QGraphicsPixmapItem * m_overlay; KgSound m_soundBomb; KgSound m_soundCrash; }; #endif