diff --git a/src/blockitem.cpp b/src/blockitem.cpp index 6da3cb7..d5ad165 100644 --- a/src/blockitem.cpp +++ b/src/blockitem.cpp @@ -1,60 +1,60 @@ /* * Copyright 2009 Mathias Kraus * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include "blockitem.h" #include "block.h" #include #include BlockItem::BlockItem(Block* p_model, KGameRenderer* renderer) : ElementItem (p_model, renderer) { setSpriteKey(p_model->getImageId()); m_destructionTimer = nullptr; - connect(p_model, SIGNAL(startDestructionAnimation()), this, SLOT(startDestructionAnimation())); + connect(p_model, &Block::startDestructionAnimation, this, &BlockItem::startDestructionAnimation); } BlockItem::~BlockItem() { delete m_destructionTimer; } void BlockItem::startDestructionAnimation() { m_destructionCounter = 0; m_destructionTimer = new QTimer(this); m_destructionTimer->setInterval(300); m_destructionTimer->start(); connect(m_destructionTimer, &QTimer::timeout, this, &BlockItem::destructionAnimation); setSpriteKey(QStringLiteral("arena_block_highlight")); } void BlockItem::destructionAnimation() { m_destructionCounter++; m_destructionTimer->setInterval(50); setOpacity((5-m_destructionCounter)/5.0); if(m_destructionCounter >= 5) { m_destructionTimer->stop(); delete m_destructionTimer; m_destructionTimer = nullptr; emit blockItemDestroyed(this); } } diff --git a/src/bombitem.cpp b/src/bombitem.cpp index 2b5191b..a6b3510 100644 --- a/src/bombitem.cpp +++ b/src/bombitem.cpp @@ -1,319 +1,319 @@ /* * Copyright 2009 Mathias Kraus * Copyright 2007-2008 Thomas Gallinari * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include "bombitem.h" #include "bomb.h" #include "settings.h" #include #include #include const int nBombPulseTime = 100; BombItem::BombItem(Bomb* p_model, KGameRenderer* renderer) : ElementItem (p_model, renderer) { setSpriteKey(QStringLiteral("bomb")); setZValue(210); - connect(p_model, SIGNAL(bombDetonated(Bomb*)), this, SLOT(startDetonation())); - connect(p_model, SIGNAL(falling()), this, SLOT(fallingAnimation())); - connect(this, SIGNAL(bombItemFinished(BombItem*)), p_model, SLOT(slot_detonationCompleted())); + connect(p_model, &Bomb::bombDetonated, this, &BombItem::startDetonation); + connect(p_model, &Bomb::falling, this, &BombItem::fallingAnimation); + connect(this, &BombItem::bombItemFinished, p_model, &Bomb::slot_detonationCompleted); int width = static_cast(Granatier::CellSize * 0.9); int height = static_cast(Granatier::CellSize * 0.9); if((static_cast(Granatier::CellSize) - width) % 2 != 0) { width--; } if((static_cast(Granatier::CellSize) - height) % 2 != 0) { height--; } m_itemSizeSet = QSize(width, height); m_itemSizeReal = m_itemSizeSet; m_animationCounter = 0; // Define the timer which sets the puls frequency m_pulseTimer = new QTimer(this); m_pulseTimer->setInterval(nBombPulseTime); m_pulseTimer->start(); connect(m_pulseTimer, &QTimer::timeout, this, &BombItem::pulse); m_explosionTimer = nullptr; m_listExplosionTiming.append(Settings::self()->blastTime1()); m_listExplosionTiming.append(Settings::self()->blastTime2()); m_listExplosionTiming.append(Settings::self()->blastTime3()); m_listExplosionTiming.append(Settings::self()->blastTime4()); m_listExplosionTiming.append(Settings::self()->blastTime5()); m_fallingAnimationCounter = 0; m_dudBomb = false; } BombItem::~BombItem() { delete m_pulseTimer; delete m_explosionTimer; } QPainterPath BombItem::shape() const { QPainterPath path; // Temporary variable to keep the boundingRect available QRectF rect = boundingRect(); // Calculation of the shape QRectF shapeRect = QRectF( rect.x()+rect.width()/8, rect.y()+rect.height()/8, rect.width()*3.0/4.0, rect.height()*3.0/4.0 ); path.addEllipse(shapeRect); return path; } void BombItem::pauseAnim() { dynamic_cast (m_model)->pause(); if(m_pulseTimer) { m_pulseTimer->stop(); } if(m_explosionTimer) { m_explosionTimer->stop(); } } void BombItem::resumeAnim() { if(m_pulseTimer && !m_dudBomb) { m_pulseTimer->start(); } if(m_explosionTimer) { m_explosionTimer->start(); } dynamic_cast (m_model)->resume(); } void BombItem::update(qreal p_x, qreal p_y) { // Compute the top-right coordinates of the item qreal x = p_x - m_itemSizeSet.width() / 2; qreal y = p_y - m_itemSizeSet.height() / 2; // Updates the view coordinates setPos(x, y); m_x = static_cast(p_x); m_y = static_cast(p_y); } void BombItem::startDetonation() { if(m_pulseTimer) { m_pulseTimer->stop(); delete m_pulseTimer; m_pulseTimer = nullptr; } m_animationCounter = 0; QTransform transform; transform.translate(m_itemSizeSet.width() / 2.0, m_itemSizeSet.height() / 2.0); setRenderSize(m_renderSize); transform.translate(-m_itemSizeReal.width() / 2.0, -m_itemSizeReal.height() / 2.0); setTransform(transform); dynamic_cast (m_model)->setXSpeed(0); dynamic_cast (m_model)->setYSpeed(0); // Define the timer which sets the explosion frequency m_explosionTimer = new QTimer(this); m_explosionTimer->setInterval(m_listExplosionTiming.at(0)); m_explosionTimer->setSingleShot(true); m_explosionTimer->start(); connect(m_explosionTimer, &QTimer::timeout, this, &BombItem::updateAnimation); int width = static_cast(Granatier::CellSize * 1.1); int height = static_cast(Granatier::CellSize * 1.1); if((static_cast(Granatier::CellSize) - width) % 2 != 0) { width--; } if((static_cast(Granatier::CellSize) - height) % 2 != 0) { height--; } m_itemSizeSet = QSize(width, height); m_itemSizeReal = m_itemSizeSet; setSpriteKey(QStringLiteral("bomb_blast_core_0")); setZValue(300+15); //300+maxBombPower+5 updateGraphics(scale()); update(m_x, m_y); } void BombItem::pulse() { if(m_fallingAnimationCounter == 0) { m_animationCounter++; if (m_animationCounter % 2 == 0) { m_animationCounter = 0; int viewWidth = static_cast(m_renderSize.width() * 0.98); int viewHeight = static_cast(m_renderSize.height() * 0.98); if((m_renderSize.width() - viewWidth) % 2 != 0) { viewWidth--; } if((m_renderSize.height() - viewHeight) % 2 != 0) { viewHeight--; } //calculate the real item size after change of the render size QPointF sceneTopLeft = scene()->views().first()->mapToScene(QPoint(0, 0)); QPointF sceneBottomRight = scene()->views().first()->mapToScene(QPoint(viewWidth, viewHeight)); qreal sceneWidth = sceneBottomRight.x() - sceneTopLeft.x(); qreal sceneHeight = sceneBottomRight.y() - sceneTopLeft.y(); // shrink the item QTransform transform; transform.translate(m_itemSizeSet.width() / 2.0, m_itemSizeSet.height() / 2.0); setRenderSize(QSize(viewWidth, viewHeight)); transform.translate(-sceneWidth / 2.0, -sceneHeight / 2.0); setTransform(transform); } else { QTransform transform; transform.translate(m_itemSizeSet.width() / 2.0, m_itemSizeSet.height() / 2.0); setRenderSize(m_renderSize); transform.translate(-m_itemSizeReal.width() / 2.0, -m_itemSizeReal.height() / 2.0); setTransform(transform); } } else { // shrink the item QTransform transform; transform.translate(m_itemSizeSet.width() / 2.0, m_itemSizeSet.height() / 2.0); setRenderSize(m_renderSize * (1-m_fallingAnimationCounter*0.02)); transform.translate(-m_itemSizeReal.width() * (1-m_fallingAnimationCounter*0.02) / 2.0, -m_itemSizeReal.height() * (1-m_fallingAnimationCounter*0.02) / 2.0); setTransform(transform); m_fallingAnimationCounter++; if(m_fallingAnimationCounter > 50) { m_pulseTimer->stop(); m_dudBomb = true; emit bombItemFinished(this); } } } void BombItem::updateAnimation() { m_animationCounter++; if (m_animationCounter > 4) { emit bombItemFinished(this); m_animationCounter = 0; return; } QString strElemetId = QStringLiteral("bomb_blast_core_%1").arg(m_animationCounter); setSpriteKey(strElemetId); updateGraphics(scale()); update(m_x, m_y); emit animationFrameChanged(this, m_animationCounter); m_explosionTimer->setInterval(m_listExplosionTiming.at(m_animationCounter)); m_explosionTimer->start(); } void BombItem::updateMortar(int nMortarState, int nMortarRampEnd, int nMortarPeak, int nMortarGround) { if(m_pulseTimer) { m_pulseTimer->stop(); delete m_pulseTimer; m_pulseTimer = nullptr; } if(nMortarState <= 0) { setVisible(false); setZValue(-1); } else if(nMortarState <= nMortarGround) { updateMortarAnimation(nMortarState, nMortarRampEnd, nMortarPeak); } else { if(!m_pulseTimer) { m_pulseTimer = new QTimer(this); m_pulseTimer->setInterval(nBombPulseTime); m_animationCounter = 1; // set to one, to start pulsing with a small bomb m_pulseTimer->start(); connect(m_pulseTimer, &QTimer::timeout, this, &BombItem::pulse); } QTransform transform; transform.translate(m_itemSizeSet.width() / 2.0, m_itemSizeSet.height() / 2.0); setRenderSize(m_renderSize); transform.translate(-m_itemSizeReal.width() / 2.0, -m_itemSizeReal.height() / 2.0); setTransform(transform); setVisible(true); setZValue(210); } } void BombItem::updateMortarAnimation(int animationCounter, int nMortarRampEnd, int nMortarPeak) { qreal mortarScale = 1; int mortarZValue = 210; QTransform transform; if(animationCounter < nMortarRampEnd) { mortarZValue = 210; } else { mortarZValue = 800; } int frame = animationCounter - nMortarRampEnd; int peak = nMortarPeak - nMortarRampEnd; mortarScale = 1.5 - (frame-peak) * (frame-peak) / static_cast(peak*peak) * 0.5; transform.translate(m_itemSizeSet.width() / 2.0, m_itemSizeSet.height() / 2.0); setRenderSize(m_renderSize * mortarScale); transform.translate(-m_itemSizeReal.width() * mortarScale / 2.0, -m_itemSizeReal.height() * mortarScale / 2.0); setTransform(transform); setVisible(true); setZValue(mortarZValue); } void BombItem::fallingAnimation() { m_fallingAnimationCounter = 1; // set z-value below the ground setZValue(-2); m_pulseTimer->setInterval(1000 / Granatier::FPS); } diff --git a/src/characteritem.cpp b/src/characteritem.cpp index d44c1c1..b615866 100644 --- a/src/characteritem.cpp +++ b/src/characteritem.cpp @@ -1,58 +1,58 @@ /* * Copyright 2009 Mathias Kraus * Copyright 2007-2008 Thomas Gallinari * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include "characteritem.h" #include "character.h" #include CharacterItem::CharacterItem(Character* p_model, KGameRenderer* renderer) : ElementItem (p_model, renderer) { m_renderer = renderer; - connect(p_model, SIGNAL(dead()), this, SLOT(setDead())); + connect(p_model, &Character::dead, this, &CharacterItem::setDead); } CharacterItem::~CharacterItem() { } QPainterPath CharacterItem::shape() const { QPainterPath path; // Temporary variable to keep the boundingRect available QRectF rect = boundingRect(); // Calculation of the shape QRectF shapeRect = QRectF( rect.x()+rect.width()/8, rect.y()+rect.height()/8, rect.width()*3.0/4.0, rect.height()*3.0/4.0 ); path.addEllipse(shapeRect); return path; } void CharacterItem::update(qreal p_x, qreal p_y) { // Compute the top-right coordinates of the item qreal x = p_x - m_itemSizeSet.width() / 2; qreal y = p_y - m_itemSizeSet.height() / 2; // Updates the view coordinates setPos(x, y); } void CharacterItem::setDead() { } diff --git a/src/config/arenasettings.h b/src/config/arenasettings.h index c88c707..565ef4e 100644 --- a/src/config/arenasettings.h +++ b/src/config/arenasettings.h @@ -1,86 +1,86 @@ /* Copyright (C) 2009 Mathias Kraus Copyright (C) 2007 Mauricio Piacentini Copyright (C) 2007 Matt Williams This library is free software; you can redistribute it and/or modify it under the terms of the GNU 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 General Public License for more details. You should have received a copy of the GNU 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 ARENASETTINGS_H #define ARENASETTINGS_H #include class ArenaSettingsPrivate; /** * \class ArenaSettings arenasettings.h * * @short Class for loading arena files * * Essentially just a wrapper around a .desktop arena file. Load a file with * load() and then access its properties. * * For more advanced feaures like dynamic arenas or custom game rules, it * will likely be necessary to derive from this class * * @author Mauricio Piacentini **/ class ArenaSettings { public: - explicit ArenaSettings(const QString &arenaGroup = QLatin1String("Arena")); + explicit ArenaSettings(const QString &arenaGroup = QStringLiteral("Arena")); virtual ~ArenaSettings(); /** * Load the default arena file. Called "granatier.desktop" * @return true if the arena files and properties could be loaded */ virtual bool loadDefault(); /** * Load a specific arena file. * Note that although arena could be successfully loaded, * no check on the validity of arena's XML file contents is done. * Application writers will need to perform this check manually * @param file the name of the arena file relative to the share/apps/appname * directory. e.g. "arena/granatier.desktop" * @return true if the arena files and properties could be loaded */ virtual bool load(const QString &file); /// @return the full path of the .desktop file QString path() const; /// @return just the "*.desktop" part QString fileName() const; /// @return the full path of the svg file which is specified in "FileName" key virtual QString graphics() const; /// @return a property directly from the .desktop file QString property(const QString &key) const; /** * Possible keys: * - Name * - Author * - Description * - AuthorEmail * @param key the key of the wanted property * @return the data related to 'key' */ virtual QString arenaProperty(const QString &key) const; private: friend class ArenaSettingsPrivate; ArenaSettingsPrivate *const d; }; #endif diff --git a/src/gamescene.cpp b/src/gamescene.cpp index efaa27f..67ee3aa 100644 --- a/src/gamescene.cpp +++ b/src/gamescene.cpp @@ -1,1086 +1,1086 @@ /* * Copyright 2009 Mathias Kraus * Copyright 2007-2008 Thomas Gallinari * Copyright 2007-2008 Alexandre Galinier * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include "gamescene.h" #include "cell.h" #include "bonus.h" #include "bonusitem.h" #include "settings.h" #include "game.h" #include "player.h" #include "block.h" #include "blockitem.h" #include "bomb.h" #include "arena.h" #include "arenaitem.h" #include "playeritem.h" #include "bombitem.h" #include "bombexplosionitem.h" #include "infooverlay.h" #include "infosidebar.h" #include "granatier_random.h" #include #include #include #include #include #include #include #include #include #include GameScene::GameScene(Game* p_game, KgThemeProvider* p_themeProvider) : m_game(p_game), m_themeProvider(p_themeProvider) { - connect(p_game, SIGNAL(gameStarted()), this, SLOT(start())); - connect(p_game, SIGNAL(pauseChanged(bool,bool)), this, SLOT(setPaused(bool,bool))); - connect(p_game, SIGNAL(bombCreated(Bomb*)), this, SLOT(createBombItem(Bomb*))); - connect(p_game, SIGNAL(infoChanged(Granatier::Info::Type)), this, SLOT(updateInfo(Granatier::Info::Type))); + connect(p_game, &Game::gameStarted, this, &GameScene::start); + connect(p_game, &Game::pauseChanged, this, &GameScene::setPaused); + connect(p_game, &Game::bombCreated, this, &GameScene::createBombItem); + connect(p_game, &Game::infoChanged, this, &GameScene::updateInfo); m_SvgScaleFactor = 1; m_backgroundResizeTimer = new QTimer(); m_backgroundResizeTimer->setSingleShot(true); connect(m_backgroundResizeTimer, &QTimer::timeout, this, &GameScene::resizeBackground); // Create the PlayerItems and the points labels QList players = p_game->getPlayers(); PlayerItem* playerItem; for(auto & player : players) { const QString desktopPath = player->getDesktopFilePath(); KgTheme* theme = new KgTheme(desktopPath.toUtf8()); theme->readFromDesktopFile(desktopPath); auto playerRenderer = new KGameRenderer(theme); m_mapRendererPlayerItems.insert(player, playerRenderer); playerItem = new PlayerItem(player, playerRenderer); // Corrects the position of the player playerItem->update(player->getX(), player->getY()); // Stops the player animation playerItem->stopAnim(); m_playerItems.append(playerItem); connect(this, &GameScene::resizeGraphics, playerItem, &PlayerItem::updateGraphics); connect(playerItem, &PlayerItem::bonusItemTaken, this, &GameScene::removeBonusItem); } // The remaining time m_remainingTimeLabel = new QGraphicsTextItem(i18n("0:00")); m_remainingTimeLabel->setFont(QFont(QStringLiteral("Helvetica"), static_cast(Granatier::CellSize * 0.35), QFont::Bold, false)); m_remainingTimeLabel->setDefaultTextColor(QColor("#FFFF00")); m_remainingTimeLabel->setZValue(1000); m_arenaNameLabel = new QGraphicsTextItem(i18n("Arena Name")); m_arenaNameLabel->setFont(QFont(QStringLiteral("Helvetica"), static_cast(Granatier::CellSize * 0.35), QFont::Bold, false)); m_arenaNameLabel->setDefaultTextColor(QColor("#FFFF00")); m_arenaNameLabel->setZValue(1000); // setup the theme renderer m_rendererSelectedTheme = new KGameRenderer(m_themeProvider); m_rendererDefaultTheme = nullptr; setupThemeRenderer(); connect(m_themeProvider, &KgThemeProvider::currentThemeChanged, this, &GameScene::themeChanged); // create the info overlay m_infoOverlay = new InfoOverlay(m_game, this); connect(this, &GameScene::resizeGraphics, m_infoOverlay, &InfoOverlay::updateGraphics); init(); } void GameScene::setupThemeRenderer() { bool selectedThemeIsDefault = true; if(m_themeProvider->currentTheme() != m_themeProvider->defaultTheme()) { // Load the default SVG file as fallback selectedThemeIsDefault = false; if(m_rendererDefaultTheme == nullptr) { KgTheme* theme = new KgTheme(m_themeProvider->defaultTheme()->identifier()); theme->setGraphicsPath(m_themeProvider->defaultTheme()->graphicsPath()); m_rendererDefaultTheme = new KGameRenderer(theme); } } if(selectedThemeIsDefault || m_rendererSelectedTheme->spriteExists(QStringLiteral("background"))) { m_rendererBackground = m_rendererSelectedTheme; } else { m_rendererBackground = m_rendererDefaultTheme; } // set the renderer for the arena items TODO: add all the arena items if(selectedThemeIsDefault || (m_rendererSelectedTheme->spriteExists(QStringLiteral("arena_ground")) && m_rendererSelectedTheme->spriteExists(QStringLiteral("arena_wall")) && m_rendererSelectedTheme->spriteExists(QStringLiteral("arena_block")) && m_rendererSelectedTheme->spriteExists(QStringLiteral("arena_block_highlight")) && m_rendererSelectedTheme->spriteExists(QStringLiteral("arena_ice")) && m_rendererSelectedTheme->spriteExists(QStringLiteral("arena_bomb_mortar")) && m_rendererSelectedTheme->spriteExists(QStringLiteral("arena_arrow_up")) && m_rendererSelectedTheme->spriteExists(QStringLiteral("arena_arrow_right")) && m_rendererSelectedTheme->spriteExists(QStringLiteral("arena_arrow_down")) && m_rendererSelectedTheme->spriteExists(QStringLiteral("arena_arrow_left")))) { m_rendererArenaItems = m_rendererSelectedTheme; } else { m_rendererArenaItems = m_rendererDefaultTheme; } // set the renderer for the bonus items TODO: add all the bonus items if(selectedThemeIsDefault || (m_rendererSelectedTheme->spriteExists(QStringLiteral("bonus_speed")) && m_rendererSelectedTheme->spriteExists(QStringLiteral("bonus_bomb")) && m_rendererSelectedTheme->spriteExists(QStringLiteral("bonus_power")) && m_rendererSelectedTheme->spriteExists(QStringLiteral("bonus_shield")) && m_rendererSelectedTheme->spriteExists(QStringLiteral("bonus_throw")) && m_rendererSelectedTheme->spriteExists(QStringLiteral("bonus_kick")) && m_rendererSelectedTheme->spriteExists(QStringLiteral("bonus_bad_slow")) && m_rendererSelectedTheme->spriteExists(QStringLiteral("bonus_bad_hyperactive")) && m_rendererSelectedTheme->spriteExists(QStringLiteral("bonus_bad_mirror")) && m_rendererSelectedTheme->spriteExists(QStringLiteral("bonus_bad_scatty")) && m_rendererSelectedTheme->spriteExists(QStringLiteral("bonus_bad_restrain")) && m_rendererSelectedTheme->spriteExists(QStringLiteral("bonus_neutral_pandora")) && m_rendererSelectedTheme->spriteExists(QStringLiteral("bonus_neutral_resurrect")))) { m_rendererBonusItems = m_rendererSelectedTheme; } else { m_rendererBonusItems = m_rendererDefaultTheme; } // set the renderer for the bomb items if(selectedThemeIsDefault || (m_rendererSelectedTheme->spriteExists(QStringLiteral("bomb")) && m_rendererSelectedTheme->spriteExists(QStringLiteral("bomb_blast_core_0")) && m_rendererSelectedTheme->spriteExists(QStringLiteral("bomb_blast_north_0")) && m_rendererSelectedTheme->spriteExists(QStringLiteral("bomb_blast_east_0")) && m_rendererSelectedTheme->spriteExists(QStringLiteral("bomb_blast_south_0")) && m_rendererSelectedTheme->spriteExists(QStringLiteral("bomb_blast_west_0")))) { m_rendererBombItems = m_rendererSelectedTheme; } else { m_rendererBombItems = m_rendererDefaultTheme; } // set the renderer for the score items if(selectedThemeIsDefault || (m_rendererSelectedTheme->spriteExists(QStringLiteral("score_star_enabled")) && m_rendererSelectedTheme->spriteExists(QStringLiteral("score_star_disabled")))) { m_rendererScoreItems = m_rendererSelectedTheme; } else { m_rendererScoreItems = m_rendererDefaultTheme; } } void GameScene::init() { initItemsWithGraphicsFromTheme(); // Display each PlayerItem for (auto & playerItem : m_playerItems) { if(!items().contains(playerItem)) { addItem(playerItem); } playerItem->resurrect(); } if (!items().contains(m_remainingTimeLabel)) { addItem(m_remainingTimeLabel); } m_remainingTimeLabel->setDefaultTextColor(QColor("#FFFF00")); int nTime = m_game->getRemainingTime(); m_remainingTimeLabel->setPlainText(QStringLiteral("%1:%2").arg(nTime/60).arg(nTime%60, 2, 10, QLatin1Char('0'))); m_remainingTimeLabel->setPos(Granatier::CellSize * m_game->getArena()->getNbColumns() - m_remainingTimeLabel->boundingRect().width(), - m_remainingTimeLabel->boundingRect().height()); if (!items().contains(m_arenaNameLabel)) { addItem(m_arenaNameLabel); } m_arenaNameLabel->setPlainText(m_game->getArena()->getName()); m_arenaNameLabel->setPos(0, - m_arenaNameLabel->boundingRect().height()); //this is needed for info sidebar setSceneRect(0, -m_remainingTimeLabel->boundingRect().height(), m_game->getArena()->getNbColumns()*Granatier::CellSize, m_game->getArena()->getNbRows()*Granatier::CellSize + m_remainingTimeLabel->boundingRect().height()); // create the info sidebar m_infoSidebar = new InfoSidebar(m_game, this); connect(this, &GameScene::resizeGraphics, m_infoSidebar, &InfoSidebar::updateGraphics); //update the sceneRect QRectF oldSceneRect = sceneRect(); QRectF sidebarRect = m_infoSidebar->rect(); QRectF newSceneRect; newSceneRect.setLeft(oldSceneRect.left() < sidebarRect.left() ? oldSceneRect.left() : sidebarRect.left()); newSceneRect.setRight(oldSceneRect.right() > sidebarRect.right() ? oldSceneRect.right() : sidebarRect.right()); newSceneRect.setTop(oldSceneRect.top() < sidebarRect.top() ? oldSceneRect.top() : sidebarRect.top()); newSceneRect.setBottom(oldSceneRect.bottom() > sidebarRect.bottom() ? oldSceneRect.bottom() : sidebarRect.bottom()); newSceneRect.adjust(-5, -5, 5, 5); setSceneRect(newSceneRect); m_infoSidebar->reset(); m_infoOverlay->showGetReady(); //set the minimum size for the scene m_minSize = sceneRect(); int minWidth = static_cast((m_minSize.width() / Granatier::CellSize + 1.1) * Granatier::CellSize); int minHeight = static_cast((m_minSize.height() / Granatier::CellSize + 1.1) * Granatier::CellSize); m_minSize.setX(m_minSize.x() + (m_minSize.width() - minWidth) / 10); m_minSize.setY(m_minSize.y() + (m_minSize.height() - minHeight) / 4); m_minSize.setWidth(minWidth); m_minSize.setHeight(minHeight); setSceneRect(m_minSize); resizeSprites(); } void GameScene::initItemsWithGraphicsFromTheme() { // Create the ArenaItems m_arenaItem = new ArenaItem**[m_game->getArena()->getNbRows()]; for (int i = 0; i < m_game->getArena()->getNbRows(); ++i) { m_arenaItem[i] = new ArenaItem*[m_game->getArena()->getNbColumns()]; for (int j = 0; j < m_game->getArena()->getNbColumns(); ++j) { // Create the ArenaItem and set the image ArenaItem* arenaItem = new ArenaItem(j * Granatier::CellSize, i * Granatier::CellSize, m_rendererArenaItems, QStringLiteral("")); connect(this, &GameScene::resizeGraphics, arenaItem, &ArenaItem::updateGraphics); //TODO: use this function call //arenaItem->setElementId(m_game->getArena()->getCell(i,j).getElement()->getImageId()); switch(m_game->getArena()->getCell(i,j).getType()) { case Granatier::Cell::WALL: arenaItem->setSpriteKey(QStringLiteral("arena_wall")); arenaItem->setZValue(-2); break; case Granatier::Cell::HOLE: delete arenaItem; arenaItem = nullptr; break; case Granatier::Cell::ICE: arenaItem->setSpriteKey(QStringLiteral("arena_ice")); arenaItem->setZValue(0); break; case Granatier::Cell::BOMBMORTAR: arenaItem->setSpriteKey(QStringLiteral("arena_bomb_mortar")); arenaItem->setZValue(0); break; case Granatier::Cell::ARROWUP: arenaItem->setSpriteKey(QStringLiteral("arena_arrow_up")); arenaItem->setZValue(0); break; case Granatier::Cell::ARROWRIGHT: arenaItem->setSpriteKey(QStringLiteral("arena_arrow_right")); arenaItem->setZValue(0); break; case Granatier::Cell::ARROWDOWN: arenaItem->setSpriteKey(QStringLiteral("arena_arrow_down")); arenaItem->setZValue(0); break; case Granatier::Cell::ARROWLEFT: arenaItem->setSpriteKey(QStringLiteral("arena_arrow_left")); arenaItem->setZValue(0); break; case Granatier::Cell::GROUND: case Granatier::Cell::BLOCK: default: arenaItem->setSpriteKey(QStringLiteral("arena_ground")); arenaItem->setZValue(-1); } m_arenaItem[i][j] = arenaItem; } } // Create the Block and Bonus items m_blockItems = new BlockItem**[m_game->getArena()->getNbRows()]; m_bonusItems = new BonusItem**[m_game->getArena()->getNbRows()]; QList blockElements; for (int i = 0; i < m_game->getArena()->getNbRows(); ++i) { m_blockItems[i] = new BlockItem*[m_game->getArena()->getNbColumns()]; m_bonusItems[i] = new BonusItem*[m_game->getArena()->getNbColumns()]; for (int j = 0; j < m_game->getArena()->getNbColumns(); ++j) { blockElements = m_game->getArena()->getCell(i, j).getElements(Granatier::Element::BLOCK); if (!blockElements.isEmpty()) { // Create the element item and set the image for(const auto& element: blockElements) { Block* block = dynamic_cast (element); BlockItem* blockItem = new BlockItem(block, m_rendererArenaItems); connect(this, &GameScene::resizeGraphics, blockItem, &BlockItem::updateGraphics); blockItem->setSpriteKey(block->getImageId()); blockItem->update(block->getX(), block->getY()); blockItem->setZValue(200); if(Settings::self()->showAllTiles() == 1) { blockItem->setZValue(99); } connect(this, &GameScene::resizeGraphics, blockItem, &BlockItem::updateGraphics); connect(blockItem, &BlockItem::blockItemDestroyed, this, &GameScene::removeBlockItem); m_blockItems[i][j] = blockItem; // if the block contains a hidden bonus, create the bonus item Bonus* bonus = block->getBonus(); if(bonus) { BonusItem* bonusItem = new BonusItem(bonus, m_rendererBonusItems); switch(bonus->getBonusType()) { case Granatier::Bonus::SPEED: bonusItem->setSpriteKey(QStringLiteral("bonus_speed")); break; case Granatier::Bonus::BOMB: bonusItem->setSpriteKey(QStringLiteral("bonus_bomb")); break; case Granatier::Bonus::POWER: bonusItem->setSpriteKey(QStringLiteral("bonus_power")); break; case Granatier::Bonus::SHIELD: bonusItem->setSpriteKey(QStringLiteral("bonus_shield")); break; case Granatier::Bonus::THROW: bonusItem->setSpriteKey(QStringLiteral("bonus_throw")); break; case Granatier::Bonus::KICK: bonusItem->setSpriteKey(QStringLiteral("bonus_kick")); break; case Granatier::Bonus::HYPERACTIVE: bonusItem->setSpriteKey(QStringLiteral("bonus_bad_hyperactive")); break; case Granatier::Bonus::SLOW: bonusItem->setSpriteKey(QStringLiteral("bonus_bad_slow")); break; case Granatier::Bonus::MIRROR: bonusItem->setSpriteKey(QStringLiteral("bonus_bad_mirror")); break; case Granatier::Bonus::SCATTY: bonusItem->setSpriteKey(QStringLiteral("bonus_bad_scatty")); break; case Granatier::Bonus::RESTRAIN: bonusItem->setSpriteKey(QStringLiteral("bonus_bad_restrain")); break; case Granatier::Bonus::RESURRECT: bonusItem->setSpriteKey(QStringLiteral("bonus_neutral_resurrect")); break; default: bonusItem->setSpriteKey(QStringLiteral("bonus_neutral_pandora")); } if(granatier::RNG::fromRange(0, 10) > 9 && bonusItem->spriteKey() != QStringLiteral("bonus_neutral_resurrect")) { bonusItem->setSpriteKey(QStringLiteral("bonus_neutral_pandora")); } bonusItem->update(bonus->getX(), bonus->getY()); bonusItem->setZValue(100); m_bonusItems[i][j] = bonusItem; connect(this, &GameScene::resizeGraphics, bonusItem, &BonusItem::updateGraphics); connect(bonusItem, &BonusItem::bonusItemDestroyed, this, &GameScene::removeBonusItem); addItem(bonusItem); if(Settings::self()->showAllTiles() == 0) { bonusItem->hide(); } } else { m_bonusItems[i][j] = nullptr; } } } else { m_blockItems[i][j] = nullptr; m_bonusItems[i][j] = nullptr; } } } // Create the Bomb items for(auto& bomb: m_tempBombList) { createBombItem(bomb); } if(!m_tempBombList.isEmpty()) { QHash >::iterator i = m_bombItems.begin(); while (i != m_bombItems.end()) { i.key()->pauseAnim(); i++; } } // Display the ArenaItem for (int i = 0; i < m_game->getArena()->getNbRows();++i) { for (int j = 0; j < m_game->getArena()->getNbColumns(); ++j) { if(m_arenaItem[i][j] != nullptr) { addItem(m_arenaItem[i][j]); } } } // Display the Block Items for (int i = 0; i < m_game->getArena()->getNbRows(); ++i) { for (int j = 0; j < m_game->getArena()->getNbColumns(); ++j) { if (m_blockItems[i][j] != nullptr) { if (!items().contains(m_blockItems[i][j])) { addItem(m_blockItems[i][j]); } } } } //create the background m_arenaBackground = new KGameRenderedItem(m_rendererBackground, QStringLiteral("background")); m_arenaBackground->setZValue(-5); m_arenaBackground->setPos(0, 0); m_arenaBackground->setCacheMode(QGraphicsItem::NoCache); // if cache is set, there are some artifacts; pay attention, that the KGameRenderer cache is used nevertheless m_arenaBackground->setRenderSize(QSize(100, 100)); //just to get something in the background, until the right size is rendered addItem(m_arenaBackground); resizeSprites(); } GameScene::~GameScene() { delete m_backgroundResizeTimer; cleanUp(); delete m_infoOverlay; for (auto & playerItem : m_playerItems) { if(items().contains(playerItem)) { removeItem(playerItem); } playerItem->stopAnim(); delete playerItem; } QMap ::iterator iteratorRendererPlayer = m_mapRendererPlayerItems.begin(); while (iteratorRendererPlayer != m_mapRendererPlayerItems.end()) { delete iteratorRendererPlayer.value(); iteratorRendererPlayer++; } delete m_rendererSelectedTheme; delete m_rendererDefaultTheme; } void GameScene::cleanUp() { cleanUpItemsWithGraphicsFromTheme(); delete m_infoSidebar; if(items().contains(m_remainingTimeLabel)) { removeItem(m_remainingTimeLabel); } if(items().contains(m_arenaNameLabel)) { removeItem(m_arenaNameLabel); } } void GameScene::cleanUpItemsWithGraphicsFromTheme() { // remove the arena items for (int i = 0; i < m_game->getArena()->getNbRows();++i) { for (int j = 0; j < m_game->getArena()->getNbColumns(); ++j) { if (m_arenaItem[i][j] != nullptr) { if (items().contains(m_arenaItem[i][j])) { removeItem(m_arenaItem[i][j]); } delete m_arenaItem[i][j]; } } delete[] m_arenaItem[i]; } delete[] m_arenaItem; // Find the BombItem and remove it BombExplosionItem* bombExplosionItem; QHash >::iterator i = m_bombItems.begin(); while (i != m_bombItems.end()) { while(!i.value().isEmpty()) { bombExplosionItem = i.value().takeFirst(); if(items().contains(bombExplosionItem)) { removeItem(bombExplosionItem); } delete bombExplosionItem; } if(items().contains(i.key())) { removeItem(i.key()); } if(dynamic_cast (i.key()->getModel())->isDetonated()) { dynamic_cast (i.key()->getModel())->slot_detonationCompleted(); } delete i.key(); i = m_bombItems.erase(i); } // Find the BlockItems and BonusItems and remove it for (int i = 0; i < m_game->getArena()->getNbRows();++i) { for (int j = 0; j < m_game->getArena()->getNbColumns(); ++j) { if (m_blockItems[i][j] != nullptr) { if (items().contains(m_blockItems[i][j])) { removeItem(m_blockItems[i][j]); } delete m_blockItems[i][j]; } if (m_bonusItems[i][j] != nullptr) { if (items().contains(m_bonusItems[i][j])) { removeItem(m_bonusItems[i][j]); } delete m_bonusItems[i][j]; } } delete[] m_blockItems[i]; delete[] m_bonusItems[i]; } delete[] m_blockItems; delete[] m_bonusItems; removeItem(m_arenaBackground); delete m_arenaBackground; } void GameScene::themeChanged() { m_tempBombList.clear(); QHash >::iterator i = m_bombItems.begin(); while (i != m_bombItems.end()) { if(!(dynamic_cast (i.key()->getModel())->isDetonated())) { m_tempBombList.append(dynamic_cast (i.key()->getModel())); } i++; } cleanUpItemsWithGraphicsFromTheme(); setupThemeRenderer(); initItemsWithGraphicsFromTheme(); m_infoSidebar->themeChanged(); m_infoOverlay->themeChanged(); m_tempBombList.clear(); } KGameRenderer* GameScene::renderer(Granatier::Element::Type type, Player* player) { switch(type) { case Granatier::Element::BLOCK: return m_rendererArenaItems; case Granatier::Element::BONUS: return m_rendererBonusItems; case Granatier::Element::BOMB: return m_rendererBombItems; case Granatier::Element::PLAYER: return m_mapRendererPlayerItems.value(player); case Granatier::Element::SCORE: return m_rendererScoreItems; default: return nullptr; } } void GameScene::showScore() { m_infoOverlay->showScore(); } void GameScene::resizeSprites(int delayForBackground) { if(views().isEmpty()) { return; } //calculate the scaling factor for the SVGs int horizontalPixelsPerCell = static_cast(views().first()->size().width() / (m_minSize.width()/Granatier::CellSize)); int verticalPixelsPerCell = static_cast(views().first()->size().height() / (m_minSize.height()/Granatier::CellSize)); if(horizontalPixelsPerCell < verticalPixelsPerCell) { m_SvgScaleFactor = Granatier::CellSize / horizontalPixelsPerCell; } else { m_SvgScaleFactor = Granatier::CellSize / verticalPixelsPerCell; } QTransform transform; transform.scale(1/m_SvgScaleFactor, 1/m_SvgScaleFactor); views().first()->setTransform(transform); views().first()->centerOn(sceneRect().center()); views().first()->updateSceneRect(m_minSize);; //update pixmaps emit resizeGraphics(m_SvgScaleFactor); //update overlay QRect viewRect = views().first()->rect(); QRectF viewRectToScene = QRectF(views().first()->mapToScene(viewRect.topLeft()), views().first()->mapToScene(viewRect.bottomRight())); m_infoOverlay->resizeDimmOverlay(viewRectToScene.x(), viewRectToScene.y(), viewRectToScene.width(), viewRectToScene.height()); //update background pixmap m_arenaBackground->setPos(views().first()->mapToScene(viewRect.topLeft())); m_arenaBackground->setScale(m_SvgScaleFactor); m_arenaBackground->setPixmap(m_arenaBackground->pixmap().scaled(viewRect.size())); m_backgroundResizeTimer->stop(); m_backgroundResizeTimer->start(delayForBackground); } void GameScene::resizeBackground() { if(views().isEmpty()) { return; } QRect viewRect = views().first()->rect(); m_arenaBackground->setRenderSize(viewRect.size()); } Game* GameScene::getGame() const { return m_game; } void GameScene::start() { // hide the info items m_infoOverlay->hideItems(); } void GameScene::setPaused(const bool p_pause, const bool p_fromUser) { // If the game has paused if (p_pause) { // If the pause is due to an action from the user if (p_fromUser) { m_infoOverlay->showPause(); } // Stop player animation for (auto & playerItem : m_playerItems) { playerItem->pauseAnim(); } // Stop bomb animation QHash >::iterator i = m_bombItems.begin(); while (i != m_bombItems.end()) { i.key()->pauseAnim(); ++i; } } else { // If the game has resumed, hide the info items m_infoOverlay->hideItems(); // Resume player animation for (auto & playerItem : m_playerItems) { playerItem->resumeAnim(); } // Resume bomb animation QHash >::iterator i = m_bombItems.begin(); while (i != m_bombItems.end()) { i.key()->resumeAnim(); ++i; } } } void GameScene::removeBlockItem(BlockItem* blockItem) { // remove the Bonus Items for (int i = 0; i < m_game->getArena()->getNbRows(); ++i) { for (int j = 0; j < m_game->getArena()->getNbColumns(); ++j) { if (m_blockItems[i][j] != nullptr && m_blockItems[i][j] == blockItem) { if (items().contains(m_blockItems[i][j])) { removeItem(m_blockItems[i][j]); m_blockItems[i][j] = nullptr; m_game->blockDestroyed(i, j, dynamic_cast (blockItem->getModel())); delete blockItem; } } } } } void GameScene::removeBonusItem(BonusItem* bonusItem) { // remove the Bonus Items for (int i = 0; i < m_game->getArena()->getNbRows(); ++i) { for (int j = 0; j < m_game->getArena()->getNbColumns(); ++j) { if (m_bonusItems[i][j] != nullptr && m_bonusItems[i][j] == bonusItem) { if (items().contains(m_bonusItems[i][j])) { removeItem(m_bonusItems[i][j]); m_bonusItems[i][j] = nullptr; m_game->removeBonus(dynamic_cast (bonusItem->getModel())); delete bonusItem; } } } } } void GameScene::updateInfo(const Granatier::Info::Type p_info) { if(p_info == Granatier::Info::TimeInfo) { int nTime = m_game->getRemainingTime(); if(nTime > 0) { m_remainingTimeLabel->setPlainText(QStringLiteral("%1:%2").arg(nTime/60).arg(nTime%60, 2, 10, QLatin1Char('0'))); } else { m_remainingTimeLabel->setPlainText(i18n("Sudden Death")); m_remainingTimeLabel->setDefaultTextColor(QColor("#FF0000")); m_remainingTimeLabel->setPos(Granatier::CellSize * m_game->getArena()->getNbColumns() - m_remainingTimeLabel->boundingRect().width(), - m_remainingTimeLabel->boundingRect().height()); } } } void GameScene::createBombItem(Bomb* bomb) { // Create the Bombs BombItem* bombItem = new BombItem(bomb, m_rendererBombItems); // Corrects the position of the BombItem bombItem->update(bomb->getX(), bomb->getY()); addItem(bombItem); m_bombItems[bombItem].append(nullptr); bombItem->updateGraphics(m_SvgScaleFactor); //TODO: use a Renderer class and get the scale factor from a static function during initialization connect(this, &GameScene::resizeGraphics, bombItem, &BombItem::updateGraphics); connect(bomb, SIGNAL(mortar(int,int,int,int)), bombItem, SLOT(updateMortar(int,int,int,int))); - connect(bomb, SIGNAL(bombDetonated(Bomb*)), this, SLOT(bombDetonated(Bomb*))); + connect(bomb, &Bomb::bombDetonated, this, &GameScene::bombDetonated); connect(bombItem, &BombItem::bombItemFinished, this, &GameScene::removeBombItem); connect(bombItem, &BombItem::animationFrameChanged, this, &GameScene::updateBombExplosionItemAnimation); } void GameScene::removeBombItem(BombItem* bombItem) { m_game->removeBomb(dynamic_cast (bombItem->getModel())); // Find the BombItem and remove it BombExplosionItem* bombExplosionItem; QHash >::iterator i = m_bombItems.begin(); while (i != m_bombItems.end()) { if(i.key() == bombItem) { while(!i.value().isEmpty()) { bombExplosionItem = i.value().takeFirst(); if(items().contains(bombExplosionItem)) { removeItem(bombExplosionItem); } delete bombExplosionItem; } if(items().contains(i.key())) { removeItem(i.key()); } delete i.key(); i = m_bombItems.erase(i); break; } else { ++i; } } } void GameScene::bombDetonated(Bomb* bomb) { BombItem* bombItem = nullptr; BombExplosionItem* bombExplosionItem = nullptr; QList blockElements; QList bombElements; int nBombPower = bomb->bombPower(); int nNumberOfColums = m_game->getArena()->getNbColumns(); int nNumberOfRows = m_game->getArena()->getNbRows(); int nColumn; int nRow; qreal xPos = 0; qreal yPos = 0; bool abDirectionsDone[] = {false, false, false, false}; int nDetonationCountdown = 75; int anDirectionDetonationCountdown[] = {nDetonationCountdown, nDetonationCountdown, nDetonationCountdown, nDetonationCountdown}; // Find the BombItem from the Bomb QHash >::iterator i = m_bombItems.begin(); while (i != m_bombItems.end()) { if(i.key()->getModel() == bomb) { bombItem = i.key(); break; } ++i; } if(!bombItem) { return; } //check if there is a bomb or block at the position where the bomb exploded (possible when thrown) nColumn = m_game->getArena()->getColFromX(bomb->getX()); nRow = m_game->getArena()->getRowFromY(bomb->getY()); if(nColumn >= 0 && nColumn < nNumberOfColums && nRow >= 0 && nRow < nNumberOfRows) { bombElements = m_game->getArena()->getCell(nRow, nColumn).getElements(Granatier::Element::BOMB); int tempBombDetonationCountdown = nDetonationCountdown; for(const auto& element: bombElements) { if(dynamic_cast (element) != bomb && !(dynamic_cast (element)->isDetonated())) { dynamic_cast (element)->initDetonation(bomb->explosionID(), tempBombDetonationCountdown); tempBombDetonationCountdown += 10; } } blockElements = m_game->getArena()->getCell(nRow, nColumn).getElements(Granatier::Element::BLOCK); if(!blockElements.isEmpty()) { for(const auto& element: blockElements) { dynamic_cast (element)->startDestruction(); if (m_blockItems[nRow][nColumn] != nullptr) { //display bonus if available if (m_bonusItems[nRow][nColumn] != nullptr) { m_bonusItems[nRow][nColumn]->setUndestroyable(bomb->explosionID()); m_bonusItems[nRow][nColumn]->show(); } } } } else if(m_bonusItems[nRow][nColumn] != nullptr) { m_bonusItems[nRow][nColumn]->initDestruction(bomb->explosionID()); } } for(int i = 0; i < nBombPower; i++) { Granatier::Direction::Type direction = Granatier::Direction::NORTH; do { switch(direction) { case Granatier::Direction::NORTH: xPos = bomb->getX(); yPos = bomb->getY() - (i+1)*Granatier::CellSize; break; case Granatier::Direction::EAST: xPos = bomb->getX() + (i+1)*Granatier::CellSize; yPos = bomb->getY(); break; case Granatier::Direction::SOUTH: xPos = bomb->getX(); yPos = bomb->getY() + (i+1)*Granatier::CellSize; break; case Granatier::Direction::WEST: xPos = bomb->getX() - (i+1)*Granatier::CellSize; yPos = bomb->getY(); break; } nColumn = m_game->getArena()->getColFromX(xPos); nRow = m_game->getArena()->getRowFromY(yPos); if(!abDirectionsDone[direction] && nColumn >= 0 && nColumn < nNumberOfColums && nRow >= 0 && nRow < nNumberOfRows) { bombElements = m_game->getArena()->getCell(nRow, nColumn).getElements(Granatier::Element::BOMB); blockElements = m_game->getArena()->getCell(nRow, nColumn).getElements(Granatier::Element::BLOCK); if(m_game->getArena()->getCell(nRow, nColumn).getType() != Granatier::Cell::WALL) { int tempBombDetonationCountdown = anDirectionDetonationCountdown[direction]; bool increaseDetonationTimeout = false; for(const auto& element: bombElements) { if(dynamic_cast (element) != bomb && !(dynamic_cast (element)->isDetonated())) { dynamic_cast (element)->initDetonation(bomb->explosionID(), tempBombDetonationCountdown); tempBombDetonationCountdown += 10; increaseDetonationTimeout = true; } } if(increaseDetonationTimeout) { anDirectionDetonationCountdown[direction] += nDetonationCountdown; } if(!blockElements.isEmpty()) { abDirectionsDone[direction] = true; for(const auto& element: blockElements) { dynamic_cast (element)->startDestruction(); if (m_blockItems[nRow][nColumn] != nullptr) { //display bonus if available if (m_bonusItems[nRow][nColumn] != nullptr) { m_bonusItems[nRow][nColumn]->setUndestroyable(bomb->explosionID()); m_bonusItems[nRow][nColumn]->show(); } } } } else if(m_bonusItems[nRow][nColumn] != nullptr) { m_bonusItems[nRow][nColumn]->initDestruction(bomb->explosionID()); } bombExplosionItem = new BombExplosionItem (bomb, direction, nBombPower - i, m_rendererBombItems, m_SvgScaleFactor); bombExplosionItem->setPosition(xPos, yPos); connect(this, &GameScene::resizeGraphics, bombExplosionItem, &BombExplosionItem::updateGraphics); addItem(bombExplosionItem); m_bombItems[bombItem].append(bombExplosionItem); } else { abDirectionsDone[direction] = true; } } else { abDirectionsDone[direction] = true; } switch(direction) { case Granatier::Direction::NORTH: direction = Granatier::Direction::EAST; break; case Granatier::Direction::EAST: direction = Granatier::Direction::SOUTH; break; case Granatier::Direction::SOUTH: direction = Granatier::Direction::WEST; break; case Granatier::Direction::WEST: direction = Granatier::Direction::NORTH; break; } } while(direction != Granatier::Direction::NORTH); } } void GameScene::updateBombExplosionItemAnimation(BombItem* bombItem, int nFrame) { // Find the BombItems and update the frame BombExplosionItem* bombExplosionItem; QHash >::iterator i = m_bombItems.begin(); while (i != m_bombItems.end()) { if(i.key() == bombItem) { for(int nIndex = 0; nIndex < i.value().count(); nIndex++) { bombExplosionItem = i.value().at(nIndex); if(bombExplosionItem) { bombExplosionItem->updateAnimationn(nFrame); } } break; } else { ++i; } } } diff --git a/src/gameview.cpp b/src/gameview.cpp index c1fd4d1..dea093c 100644 --- a/src/gameview.cpp +++ b/src/gameview.cpp @@ -1,73 +1,73 @@ /* * Copyright 2009 Mathias Kraus * Copyright 2007-2008 Thomas Gallinari * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include "gameview.h" #include "gamescene.h" #include "game.h" #include #include GameView::GameView(GameScene* p_scene, Game * p_game) : QGraphicsView(p_scene) { setFrameStyle(QFrame::NoFrame); setFocusPolicy(Qt::StrongFocus); setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff); // Forward the key press events to the Game instance - connect(this, SIGNAL(keyPressed(QKeyEvent*)), p_game, SLOT(keyPressEvent(QKeyEvent*))); - connect(this, SIGNAL(keyReleased(QKeyEvent*)), p_game, SLOT(keyReleaseEvent(QKeyEvent*))); + connect(this, &GameView::keyPressed, p_game, &Game::keyPressEvent); + connect(this, &GameView::keyReleased, p_game, &Game::keyReleaseEvent); } GameView::~GameView() { } void GameView::resizeEvent(QResizeEvent*) { dynamic_cast (scene())->resizeSprites(250); } void GameView::focusOutEvent(QFocusEvent*) { // Pause the game if it is not already paused if (((GameScene*)scene())->getGame()->getTimer()->isActive()) { ((GameScene*)scene())->getGame()->switchPause(); } } void GameView::keyPressEvent(QKeyEvent* p_event) { if(p_event->isAutoRepeat()) { return; } emit(keyPressed(p_event)); } void GameView::keyReleaseEvent(QKeyEvent* p_event) { if(p_event->isAutoRepeat()) { return; } emit(keyReleased(p_event)); } diff --git a/src/infosidebar.cpp b/src/infosidebar.cpp index 65b9cb5..8905f3e 100644 --- a/src/infosidebar.cpp +++ b/src/infosidebar.cpp @@ -1,497 +1,497 @@ /* * Copyright 2009 Mathias Kraus * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include "infosidebar.h" #include "game.h" #include "gamescene.h" #include "player.h" #include "settings.h" #include #include #include #include #include #include InfoSidebar::InfoSidebar (Game* p_game, GameScene* p_scene) : QObject() { m_game = p_game; m_gameScene = p_scene; m_svgScaleFactor = 1; m_badBonusSpriteKey = QStringLiteral("bonus_bad_restrain"); QList playerList = m_game->getPlayers(); int nMaxPlayerNameLength = 0; int nTop = 0; int nLeft = 0; int nWidth = 0; int nHeight = 0; //calculate max player name length and top-left position for(int i = 0; i < playerList.count(); i++) { QGraphicsTextItem playerName (playerList[i]->getPlayerName()); playerName.setFont(QFont(QStringLiteral("Helvetica"), static_cast(Granatier::CellSize * 0.25), QFont::Bold, false)); if(nMaxPlayerNameLength < playerName.boundingRect().width()) { nMaxPlayerNameLength = static_cast(playerName.boundingRect().width()); } if(i == playerList.count() - 1) { int nAllItemsWidth = static_cast(4 * (Granatier::CellSize / 2 + 4)); if(nAllItemsWidth > nMaxPlayerNameLength + Granatier::CellSize / 2 + 4) { nWidth = nAllItemsWidth; } else { nWidth = static_cast(nMaxPlayerNameLength + Granatier::CellSize / 2 + 4); } nLeft = -(nWidth + 20); nHeight = static_cast(playerName.boundingRect().height() + Granatier::CellSize / 2); nTop = static_cast(m_gameScene->sceneRect().y() + m_gameScene->height()/2 - playerList.count()/2 * (nHeight + 4)); } } //create the labels PlayerInfo* playerInfo; KGameRenderer* renderer; for(int i = 0; i < playerList.count(); i++) { QPen dimmRectPen; dimmRectPen.setWidth(0); dimmRectPen.setColor(QColor(0,0,0,200)); QBrush dimmRectBrush(QColor(0,0,0,200)); playerInfo = new PlayerInfo; playerInfo->name = nullptr; playerInfo->icon = nullptr; playerInfo->bonusShield = nullptr; playerInfo->bonusShieldDimm = nullptr; playerInfo->bonusThrow = nullptr; playerInfo->bonusThrowDimm = nullptr; playerInfo->bonusKick = nullptr; playerInfo->bonusKickDimm = nullptr; playerInfo->badBonus = nullptr; playerInfo->badBonusDimm = nullptr; //create the player icons renderer = m_gameScene->renderer(Granatier::Element::PLAYER, playerList[i]); if(renderer) { playerInfo->icon = new KGameRenderedItem(renderer, QStringLiteral("player_0")); playerInfo->icon->setZValue(1001); playerInfo->icon->setPos(nLeft, nTop + i * (nHeight + 4)); m_gameScene->addItem(playerInfo->icon); } //create the player names playerInfo->name = new QGraphicsTextItem(playerList[i]->getPlayerName()); playerInfo->name->setFont(QFont(QStringLiteral("Helvetica"), static_cast(Granatier::CellSize * 0.25), QFont::Bold, false)); playerInfo->name->setDefaultTextColor(QColor("#FFFF00")); playerInfo->name->setZValue(1001); playerInfo->name->setPos(nLeft + Granatier::CellSize / 2 + 2, nTop + i * (nHeight+4) - 4); m_gameScene->addItem(playerInfo->name); renderer = m_gameScene->renderer(Granatier::Element::BONUS); if(renderer) { //create the bonus shield icons playerInfo->bonusShield = new KGameRenderedItem(renderer, QStringLiteral("bonus_shield")); playerInfo->bonusShield->setZValue(1001); playerInfo->bonusShield->setPos(nLeft, nTop + Granatier::CellSize / 2 + 1 + i * (nHeight + 4)); m_gameScene->addItem(playerInfo->bonusShield); playerInfo->bonusShieldDimm = new QGraphicsRectItem(); playerInfo->bonusShieldDimm->setBrush(dimmRectBrush); playerInfo->bonusShieldDimm->setPen(dimmRectPen); playerInfo->bonusShieldDimm->setZValue(1002); playerInfo->bonusShieldDimm->setPos(playerInfo->bonusShield->pos().x()-0.5, playerInfo->bonusShield->pos().y()-0.5); m_gameScene->addItem(playerInfo->bonusShieldDimm); //create the bonus throw icons playerInfo->bonusThrow = new KGameRenderedItem(renderer, QStringLiteral("bonus_throw")); playerInfo->bonusThrow->setZValue(1001); playerInfo->bonusThrow->setPos(nLeft + Granatier::CellSize / 2 + 4, nTop + Granatier::CellSize / 2 + 1 + i * (nHeight + 4)); m_gameScene->addItem(playerInfo->bonusThrow); playerInfo->bonusThrowDimm = new QGraphicsRectItem(); playerInfo->bonusThrowDimm->setBrush(dimmRectBrush); playerInfo->bonusThrowDimm->setPen(dimmRectPen); playerInfo->bonusThrowDimm->setZValue(1002); playerInfo->bonusThrowDimm->setPos(playerInfo->bonusThrow->pos().x()-0.5, playerInfo->bonusThrow->pos().y()-0.5); m_gameScene->addItem(playerInfo->bonusThrowDimm); //create the bonus kick icons playerInfo->bonusKick = new KGameRenderedItem(renderer, QStringLiteral("bonus_kick")); playerInfo->bonusKick->setZValue(1001); playerInfo->bonusKick->setPos(nLeft + 2 * (Granatier::CellSize / 2 + 4), nTop + Granatier::CellSize / 2 + 1 + i * (nHeight + 4)); m_gameScene->addItem(playerInfo->bonusKick); playerInfo->bonusKickDimm = new QGraphicsRectItem(); playerInfo->bonusKickDimm->setBrush(dimmRectBrush); playerInfo->bonusKickDimm->setPen(dimmRectPen); playerInfo->bonusKickDimm->setZValue(1002); playerInfo->bonusKickDimm->setPos(playerInfo->bonusKick->pos().x()-0.5, playerInfo->bonusKick->pos().y()-0.5); m_gameScene->addItem(playerInfo->bonusKickDimm); //create the bad bonus icons playerInfo->badBonus = new KGameRenderedItem(renderer, m_badBonusSpriteKey); playerInfo->badBonus->setZValue(1001); playerInfo->badBonus->setPos(nLeft + 3 * (Granatier::CellSize / 2 + 4), nTop + Granatier::CellSize / 2 + 1 + i * (nHeight + 4)); m_gameScene->addItem(playerInfo->badBonus); playerInfo->badBonusDimm = new QGraphicsRectItem(); playerInfo->badBonusDimm->setBrush(dimmRectBrush); playerInfo->badBonusDimm->setPen(dimmRectPen); playerInfo->badBonusDimm->setZValue(1002); playerInfo->badBonusDimm->setPos(playerInfo->badBonus->pos().x()-0.5, playerInfo->badBonus->pos().y()-0.5); m_gameScene->addItem(playerInfo->badBonusDimm); } m_mapPlayerInfo.insert(playerList[i], playerInfo); //connect player - connect(playerList[i], SIGNAL(bonusUpdated(Player*,Granatier::Bonus::Type,int)), this, SLOT(bonusInfoChanged(Player*,Granatier::Bonus::Type,int))); + connect(playerList[i], &Player::bonusUpdated, this, &InfoSidebar::bonusInfoChanged); } m_background = new QGraphicsRectItem(); m_background->setBrush(QBrush(QColor(0,0,0,175))); m_background->setZValue(1000); m_background->setRect(nLeft - 10 , nTop - 10, nWidth + 16, playerList.count() * (nHeight + 4) + 16); m_gameScene->addItem(m_background); } InfoSidebar::~InfoSidebar() { //Remove the player infosidebar QMap ::iterator iteratorPlayerInfo = m_mapPlayerInfo.begin(); while (iteratorPlayerInfo != m_mapPlayerInfo.end()) { if(iteratorPlayerInfo.value()) { //remove the icon if(m_gameScene->items().contains(iteratorPlayerInfo.value()->icon)) { m_gameScene->removeItem(iteratorPlayerInfo.value()->icon); } delete iteratorPlayerInfo.value()->icon; //remove the name if(m_gameScene->items().contains(iteratorPlayerInfo.value()->name)) { m_gameScene->removeItem(iteratorPlayerInfo.value()->name); } delete iteratorPlayerInfo.value()->name; //remove shield bonus if(m_gameScene->items().contains(iteratorPlayerInfo.value()->bonusShield)) { m_gameScene->removeItem(iteratorPlayerInfo.value()->bonusShield); } delete iteratorPlayerInfo.value()->bonusShield; //remove shield bonus dimm if(m_gameScene->items().contains(iteratorPlayerInfo.value()->bonusShieldDimm)) { m_gameScene->removeItem(iteratorPlayerInfo.value()->bonusShieldDimm); } delete iteratorPlayerInfo.value()->bonusShieldDimm; //remove throw bonus if(m_gameScene->items().contains(iteratorPlayerInfo.value()->bonusThrow)) { m_gameScene->removeItem(iteratorPlayerInfo.value()->bonusThrow); } delete iteratorPlayerInfo.value()->bonusThrow; //remove throw bonus dimm if(m_gameScene->items().contains(iteratorPlayerInfo.value()->bonusThrowDimm)) { m_gameScene->removeItem(iteratorPlayerInfo.value()->bonusThrowDimm); } delete iteratorPlayerInfo.value()->bonusThrowDimm; //remove kick bonus if(m_gameScene->items().contains(iteratorPlayerInfo.value()->bonusKick)) { m_gameScene->removeItem(iteratorPlayerInfo.value()->bonusKick); } delete iteratorPlayerInfo.value()->bonusKick; //remove kick bonus dimm if(m_gameScene->items().contains(iteratorPlayerInfo.value()->bonusKickDimm)) { m_gameScene->removeItem(iteratorPlayerInfo.value()->bonusKickDimm); } delete iteratorPlayerInfo.value()->bonusKickDimm; //remove bad bonus if(m_gameScene->items().contains(iteratorPlayerInfo.value()->badBonus)) { m_gameScene->removeItem(iteratorPlayerInfo.value()->badBonus); } delete iteratorPlayerInfo.value()->badBonus; //remove bad bonus dimm if(m_gameScene->items().contains(iteratorPlayerInfo.value()->badBonusDimm)) { m_gameScene->removeItem(iteratorPlayerInfo.value()->badBonusDimm); } delete iteratorPlayerInfo.value()->badBonusDimm; delete iteratorPlayerInfo.value(); } iteratorPlayerInfo = m_mapPlayerInfo.erase(iteratorPlayerInfo); } //remove the background if(m_gameScene->items().contains(m_background)) { m_gameScene->removeItem(m_background); } delete m_background; m_gameScene = nullptr; m_game = nullptr; } void InfoSidebar::reset() { QList playerList = m_game->getPlayers(); for(int i = 0; i < playerList.count(); i++) { m_mapPlayerInfo.value(playerList[i])->bonusShieldDimm->setVisible(true); m_mapPlayerInfo.value(playerList[i])->bonusThrowDimm->setVisible(true); m_mapPlayerInfo.value(playerList[i])->bonusKickDimm->setVisible(true); m_mapPlayerInfo.value(playerList[i])->badBonusDimm->setVisible(true); } } QRectF InfoSidebar::rect() { return m_background->rect(); } void InfoSidebar::themeChanged() { KGameRenderer* renderer = m_gameScene->renderer(Granatier::Element::BONUS); KGameRenderedItem* tempItem; //update player infosidebar QMap ::iterator iteratorPlayerInfo = m_mapPlayerInfo.begin(); while (iteratorPlayerInfo != m_mapPlayerInfo.end()) { tempItem = iteratorPlayerInfo.value()->bonusShield; if(m_gameScene->items().contains(tempItem)) { m_gameScene->removeItem(tempItem); } //create the bonus shield iteratorPlayerInfo.value()->bonusShield = new KGameRenderedItem(renderer, QStringLiteral("bonus_shield")); iteratorPlayerInfo.value()->bonusShield->setZValue(1001); iteratorPlayerInfo.value()->bonusShield->setPos(tempItem->pos()); m_gameScene->addItem(iteratorPlayerInfo.value()->bonusShield); delete tempItem; tempItem = iteratorPlayerInfo.value()->bonusThrow; if(m_gameScene->items().contains(tempItem)) { m_gameScene->removeItem(tempItem); } //create the bonus throw iteratorPlayerInfo.value()->bonusThrow = new KGameRenderedItem(renderer, QStringLiteral("bonus_throw")); iteratorPlayerInfo.value()->bonusThrow->setZValue(1001); iteratorPlayerInfo.value()->bonusThrow->setPos(tempItem->pos()); m_gameScene->addItem(iteratorPlayerInfo.value()->bonusThrow); delete tempItem; tempItem = iteratorPlayerInfo.value()->bonusKick; if(m_gameScene->items().contains(tempItem)) { m_gameScene->removeItem(tempItem); } //create the bonus kick iteratorPlayerInfo.value()->bonusKick = new KGameRenderedItem(renderer, QStringLiteral("bonus_kick")); iteratorPlayerInfo.value()->bonusKick->setZValue(1001); iteratorPlayerInfo.value()->bonusKick->setPos(tempItem->pos()); m_gameScene->addItem(iteratorPlayerInfo.value()->bonusKick); delete tempItem; tempItem = iteratorPlayerInfo.value()->badBonus; if(m_gameScene->items().contains(tempItem)) { m_gameScene->removeItem(tempItem); } //create the bad bonus iteratorPlayerInfo.value()->badBonus = new KGameRenderedItem(renderer, m_badBonusSpriteKey); iteratorPlayerInfo.value()->badBonus->setZValue(1001); iteratorPlayerInfo.value()->badBonus->setPos(tempItem->pos()); m_gameScene->addItem(iteratorPlayerInfo.value()->badBonus); delete tempItem; iteratorPlayerInfo++; } updateGraphics(m_svgScaleFactor); } void InfoSidebar::bonusInfoChanged(Player* player, Granatier::Bonus::Type bonusType, int percentageElapsed) { if(m_gameScene->views().isEmpty()) { return; } switch(static_cast(bonusType)) { case Granatier::Bonus::SHIELD: m_mapPlayerInfo.value(player)->bonusShieldDimm->setVisible(percentageElapsed); break; case Granatier::Bonus::THROW: m_mapPlayerInfo.value(player)->bonusThrowDimm->setVisible(percentageElapsed); break; case Granatier::Bonus::KICK: m_mapPlayerInfo.value(player)->bonusKickDimm->setVisible(percentageElapsed); break; case Granatier::Bonus::HYPERACTIVE: case Granatier::Bonus::SLOW: case Granatier::Bonus::MIRROR: case Granatier::Bonus::SCATTY: case Granatier::Bonus::RESTRAIN: if(percentageElapsed == 0) { //set the new bad bonus icon KGameRenderer* renderer = m_gameScene->renderer(Granatier::Element::BONUS); if(renderer) { switch(static_cast(bonusType)) { case Granatier::Bonus::HYPERACTIVE: m_badBonusSpriteKey = QStringLiteral("bonus_bad_hyperactive"); break; case Granatier::Bonus::SLOW: m_badBonusSpriteKey = QStringLiteral("bonus_bad_slow"); break; case Granatier::Bonus::MIRROR: m_badBonusSpriteKey = QStringLiteral("bonus_bad_mirror"); break; case Granatier::Bonus::SCATTY: m_badBonusSpriteKey = QStringLiteral("bonus_bad_scatty"); break; case Granatier::Bonus::RESTRAIN: m_badBonusSpriteKey = QStringLiteral("bonus_bad_restrain"); break; } if(renderer->spriteExists(m_badBonusSpriteKey)) { m_mapPlayerInfo.value(player)->badBonus->setSpriteKey(m_badBonusSpriteKey); } //hide the dimm overlay m_mapPlayerInfo.value(player)->badBonusDimm->setVisible(false); //calculate graphics size QSize renderSize; QPoint topLeft(0, 0); topLeft = m_gameScene->views().first()->mapFromScene(topLeft); QRectF rect; QPoint bottomRight(static_cast(Granatier::CellSize * 0.5), static_cast(Granatier::CellSize * 0.5)); bottomRight = m_gameScene->views().first()->mapFromScene(bottomRight); renderSize.setHeight(bottomRight.y() - topLeft.y()); renderSize.setWidth(bottomRight.x() - topLeft.x()); m_mapPlayerInfo.value(player)->badBonus->setRenderSize(renderSize); m_mapPlayerInfo.value(player)->badBonus->setScale(m_svgScaleFactor); rect = m_mapPlayerInfo.value(player)->badBonusDimm->rect(); rect.setWidth(renderSize.width() * m_svgScaleFactor); rect.setHeight(renderSize.height() * m_svgScaleFactor); m_mapPlayerInfo.value(player)->badBonusDimm->setRect(rect); } } else { m_mapPlayerInfo.value(player)->badBonusDimm->setVisible(true); QRectF rect = m_mapPlayerInfo.value(player)->badBonusDimm->rect(); rect.setHeight(rect.width() * percentageElapsed/100.0); m_mapPlayerInfo.value(player)->badBonusDimm->setRect(rect); } break; } } void InfoSidebar::updateGraphics(qreal svgScaleFactor) { if(m_gameScene->views().isEmpty()) { return; } QSize renderSize; QPoint topLeft(0, 0); topLeft = m_gameScene->views().first()->mapFromScene(topLeft); QPoint bottomRight; QRectF rect; m_svgScaleFactor = svgScaleFactor; //update player infosidebar QMap ::iterator iteratorPlayerInfo = m_mapPlayerInfo.begin(); while (iteratorPlayerInfo != m_mapPlayerInfo.end()) { bottomRight.setX(static_cast(Granatier::CellSize * 0.45)); bottomRight.setY(static_cast(Granatier::CellSize * 0.45)); bottomRight = m_gameScene->views().first()->mapFromScene(bottomRight); renderSize.setHeight(bottomRight.y() - topLeft.y()); renderSize.setWidth(bottomRight.x() - topLeft.x()); iteratorPlayerInfo.value()->icon->setRenderSize(renderSize); iteratorPlayerInfo.value()->icon->setScale(m_svgScaleFactor); bottomRight.setX(static_cast(Granatier::CellSize * 0.5)); bottomRight.setY(static_cast(Granatier::CellSize * 0.5)); bottomRight = m_gameScene->views().first()->mapFromScene(bottomRight); renderSize.setHeight(bottomRight.y() - topLeft.y()); renderSize.setWidth(bottomRight.x() - topLeft.x()); iteratorPlayerInfo.value()->bonusShield->setRenderSize(renderSize); iteratorPlayerInfo.value()->bonusShield->setScale(m_svgScaleFactor); rect = iteratorPlayerInfo.value()->bonusShieldDimm->rect(); rect.setWidth(renderSize.width() * m_svgScaleFactor); rect.setHeight(renderSize.height() * m_svgScaleFactor); iteratorPlayerInfo.value()->bonusShieldDimm->setRect(rect); iteratorPlayerInfo.value()->bonusThrow->setRenderSize(renderSize); iteratorPlayerInfo.value()->bonusThrow->setScale(m_svgScaleFactor); rect = iteratorPlayerInfo.value()->bonusThrowDimm->rect(); rect.setWidth(renderSize.width() * m_svgScaleFactor); rect.setHeight(renderSize.height() * m_svgScaleFactor); iteratorPlayerInfo.value()->bonusThrowDimm->setRect(rect); iteratorPlayerInfo.value()->bonusKick->setRenderSize(renderSize); iteratorPlayerInfo.value()->bonusKick->setScale(m_svgScaleFactor); rect = iteratorPlayerInfo.value()->bonusKickDimm->rect(); rect.setWidth(renderSize.width() * m_svgScaleFactor); rect.setHeight(renderSize.height() * m_svgScaleFactor); iteratorPlayerInfo.value()->bonusKickDimm->setRect(rect); iteratorPlayerInfo.value()->badBonus->setRenderSize(renderSize); iteratorPlayerInfo.value()->badBonus->setScale(m_svgScaleFactor); rect = iteratorPlayerInfo.value()->badBonusDimm->rect(); rect.setWidth(renderSize.width() * m_svgScaleFactor); rect.setHeight(renderSize.height() * m_svgScaleFactor); iteratorPlayerInfo.value()->badBonusDimm->setRect(rect); iteratorPlayerInfo++; } } diff --git a/src/playeritem.cpp b/src/playeritem.cpp index 84bf941..4a99e55 100644 --- a/src/playeritem.cpp +++ b/src/playeritem.cpp @@ -1,390 +1,390 @@ /* * Copyright 2009 Mathias Kraus * Copyright 2007-2008 Thomas Gallinari * Copyright 2007-2008 Nathalie Liesse * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include "playeritem.h" #include "player.h" #include "bonus.h" #include "bonusitem.h" #include "bomb.h" #include "bombitem.h" #include "bombexplosionitem.h" #include #include const int PlayerItem::NB_FRAMES = 13; const int PlayerItem::ANIM_SPEED = 240; PlayerItem::PlayerItem(Player* p_model, KGameRenderer* renderer) : CharacterItem(p_model, renderer) { - connect(p_model, SIGNAL(directionChanged()), this, SLOT(updateDirection())); - connect(p_model, SIGNAL(gameUpdated()), this, SLOT(manageCollision())); - connect(p_model, SIGNAL(stopped()), this, SLOT(stopAnim())); - connect(p_model, SIGNAL(falling()), this, SLOT(fallingAnimation())); - connect(p_model, SIGNAL(resurrected()), this, SLOT(resurrect())); + connect(p_model, &Player::directionChanged, this, &PlayerItem::updateDirection); + connect(p_model, &Player::gameUpdated, this, &PlayerItem::manageCollision); + connect(p_model, &Player::stopped, this, &PlayerItem::stopAnim); + connect(p_model, &Player::falling, this, &PlayerItem::fallingAnimation); + connect(p_model, &Player::resurrected, this, &PlayerItem::resurrect); // A timeLine for the Player animation m_animationTimer = new QTimeLine(); m_animationTimer->setCurveShape(QTimeLine::LinearCurve); m_animationTimer->setLoopCount(0); m_animationTimer->setFrameRange(0, NB_FRAMES - 1); // Animation speed m_animationTimer->setDuration(PlayerItem::ANIM_SPEED); connect(m_animationTimer, &QTimeLine::frameChanged, this, &PlayerItem::setFrame); int width = static_cast(Granatier::CellSize * 0.9); int height = static_cast(Granatier::CellSize * 0.9); if((static_cast(Granatier::CellSize) - width) % 2 != 0) { width--; } if((static_cast(Granatier::CellSize) - height) % 2 != 0) { height--; } m_itemSizeSet = QSize(width, height); m_itemSizeReal = m_itemSizeSet; if(m_renderer->spriteExists(QStringLiteral("player_0"))) { setSpriteKey(QStringLiteral("player_0")); } setZValue(250); m_fallingAnimationCounter = 0; m_resurrectionAnimationCounter = 0; } PlayerItem::~PlayerItem() { delete m_animationTimer; } void PlayerItem::resurrect() { int nDirection = dynamic_cast (m_model)->direction(); setZValue(250); m_fallingAnimationCounter = 0; m_resurrectionAnimationCounter = 10; setRenderSize(m_renderSize); if(m_renderer->spriteExists(QStringLiteral("player_0"))) { setSpriteKey(QStringLiteral("player_0")); } QTransform transform; transform.translate(m_itemSizeSet.width() / 2.0, m_itemSizeSet.height() / 2.0); // get the angle switch(nDirection) { case Granatier::Direction::EAST: transform.rotate(0); break; case Granatier::Direction::SOUTH: transform.rotate(90); break; case Granatier::Direction::NORTH: transform.rotate(-90); break; case Granatier::Direction::WEST: transform.rotate(180); break; default: transform.rotate(0); break; } transform.translate(-m_itemSizeReal.width() / 2.0, -m_itemSizeReal.height() / 2.0); setTransform(transform); startAnim(); setVisible(true); } void PlayerItem::updateDirection() { int nDirection = dynamic_cast (m_model)->direction(); // Rotate the item QTransform transform; transform.translate(m_itemSizeSet.width() / 2.0, m_itemSizeSet.height() / 2.0); // get the angle switch(nDirection) { case Granatier::Direction::EAST: transform.rotate(0); break; case Granatier::Direction::SOUTH: transform.rotate(90); break; case Granatier::Direction::NORTH: transform.rotate(-90); break; case Granatier::Direction::WEST: transform.rotate(180); break; default: transform.rotate(0); break; } transform.translate(-m_itemSizeReal.width() / 2.0, -m_itemSizeReal.height() / 2.0); setTransform(transform); } void PlayerItem::updateGraphics(qreal svgScaleFactor) { updateGraphicsInternal(svgScaleFactor); updateDirection(); } void PlayerItem::manageCollision() { QList collidingList = collidingItems(); BonusItem* bonusItem; // The signal is emitted only if the list contains more than 1 items (to exclude the case // when the player only collides with the arena) if (collidingList.size() > 1) { for (auto & i : collidingList) { // The arena and the points labels have a negative zValue which allows to exclude them from the treatment of collisions if (i->zValue() >= 300 && i->zValue() < 400) { //((ElementItem*)collidingList[i])->getModel()->doActionOnCollision((Player*)getModel()); int nExplosionID; if(i->zValue() == 315) { BombItem* bombItem = dynamic_cast (i); nExplosionID = dynamic_cast (bombItem->getModel())->explosionID(); } else { nExplosionID = dynamic_cast (i)->explosionID(); } if(dynamic_cast (m_model)->shield(nExplosionID) == false) { setDead(); dynamic_cast (m_model)->die(); } } else if (i->zValue() == 100) { bonusItem = dynamic_cast (i); if(dynamic_cast (bonusItem->getModel())->isTaken() == false) { dynamic_cast (bonusItem->getModel())->setTaken(); bonusItem->getModel()->doActionOnCollision(dynamic_cast (this->getModel())); emit bonusItemTaken(bonusItem); } } } } } void PlayerItem::update(qreal p_x, qreal p_y) { ElementItem::update(p_x, p_y); // If the player is moving if (((Player*)getModel())->getXSpeed() != 0 || ((Player*)getModel())->getYSpeed() != 0) { startAnim(); } } void PlayerItem::startAnim() { // Start the animation timer if it is not active if (m_animationTimer->state() != QTimeLine::Running) { m_animationTimer->start(); } } void PlayerItem::pauseAnim() { dynamic_cast (m_model)->pause(); if (m_animationTimer->state() == QTimeLine::Running) { m_animationTimer->setPaused(true); } } void PlayerItem::resumeAnim() { dynamic_cast (m_model)->resume(); if (m_animationTimer->state() == QTimeLine::Paused) { m_animationTimer->setPaused(false); } } void PlayerItem::stopAnim() { if(m_renderer->spriteExists(QStringLiteral("player_0"))) { setSpriteKey(QStringLiteral("player_0")); } if (m_animationTimer->state() != QTimeLine::NotRunning && m_resurrectionAnimationCounter == 0) { m_animationTimer->stop(); } } void PlayerItem::fallingAnimation() { m_fallingAnimationCounter = 1; } void PlayerItem::setFrame(const int p_frame) { if(m_renderer->spriteExists(QStringLiteral("player_%1").arg(p_frame))) { setSpriteKey(QStringLiteral("player_%1").arg(p_frame)); if(m_fallingAnimationCounter > 0 || m_resurrectionAnimationCounter > 0) { int angle = 0; int nDirection = dynamic_cast (m_model)->direction(); // get the angle switch(nDirection) { case Granatier::Direction::EAST: angle = 0; break; case Granatier::Direction::SOUTH: angle = 90; break; case Granatier::Direction::NORTH: angle = -90; break; case Granatier::Direction::WEST: angle = 180; break; default: angle = 0; break; } if(m_fallingAnimationCounter > 0) { // set z-value below the ground setZValue(-2); // shrink the item QTransform transform; transform.translate(m_itemSizeSet.width() / 2.0, m_itemSizeSet.width() / 2.0); transform.rotate(angle); setRenderSize(m_renderSize * (1-m_fallingAnimationCounter*0.02)); transform.translate(-m_itemSizeReal.width() * (1-m_fallingAnimationCounter*0.02) / 2.0, -m_itemSizeReal.width() * (1-m_fallingAnimationCounter*0.02) / 2.0); setTransform(transform); m_fallingAnimationCounter++; if(m_fallingAnimationCounter > 50) { setDead(); dynamic_cast (m_model)->die(); setVisible(false); } } if(m_resurrectionAnimationCounter > 0) { qreal resurrectionScale = 1; QTransform transform; transform.translate(m_itemSizeSet.width() / 2.0, m_itemSizeSet.width() / 2.0); transform.rotate(angle); if(m_resurrectionAnimationCounter > 9) { resurrectionScale = 1.1; } else if(m_resurrectionAnimationCounter > 8) { resurrectionScale = 0.9; } else if(m_resurrectionAnimationCounter > 7) { resurrectionScale = 0.6; } else if(m_resurrectionAnimationCounter > 6) { resurrectionScale = 0.7; } else if(m_resurrectionAnimationCounter > 5) { resurrectionScale = 0.85; } else if(m_resurrectionAnimationCounter > 4) { resurrectionScale = 1; } else if(m_resurrectionAnimationCounter > 3) { resurrectionScale = 1.05; } else if(m_resurrectionAnimationCounter > 2) { resurrectionScale = 1.1; } else if(m_resurrectionAnimationCounter > 1) { resurrectionScale = 1.05; } else if(m_resurrectionAnimationCounter > 0) { resurrectionScale = 1; } m_resurrectionAnimationCounter--; if(m_resurrectionAnimationCounter == 0) { resurrectionScale = 1; stopAnim(); } setRenderSize(m_renderSize * resurrectionScale); transform.translate(-m_itemSizeReal.width() * resurrectionScale / 2.0, -m_itemSizeReal.width() * resurrectionScale / 2.0); setTransform(transform); } } } } void PlayerItem::setDead() { stopAnim(); setZValue(1); if(m_resurrectionAnimationCounter != 0) { QTransform transform; transform.translate(m_itemSizeSet.width() / 2.0, m_itemSizeSet.height() / 2.0); setRenderSize(m_renderSize); transform.translate(-m_itemSizeReal.width() / 2.0, -m_itemSizeReal.height() / 2.0); setTransform(transform); } if(m_renderer->spriteExists(QStringLiteral("player_death"))) { setSpriteKey(QStringLiteral("player_death")); } }