diff --git a/backgroundselector.cpp b/backgroundselector.cpp index 0b1004b..2d252fb 100644 --- a/backgroundselector.cpp +++ b/backgroundselector.cpp @@ -1,126 +1,125 @@ /* * Copyright (C) 2010 Andreas Scherf * * This file is part of the KDE project "KBounce" * * KBounce 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. * * KBounce 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 KBounce; if not, write to the Free * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. */ #include "backgroundselector.h" #include "ui_backgroundselector.h" -#include #include #include #include "renderer.h" #include BackgroundSelector::BackgroundSelector(QWidget* parent, KConfigSkeleton* config) : QWidget(parent), ui(new Ui::KBounceBackgroundSelector),m_config(config) { ui->setupUi(this); setupData(); } BackgroundSelector::~BackgroundSelector() { delete ui; } void BackgroundSelector::changeEvent(QEvent *e) { QWidget::changeEvent(e); switch (e->type()) { case QEvent::LanguageChange: ui->retranslateUi(this); break; default: break; } } void BackgroundSelector::setupData() { if (m_config) { //The lineEdit widget holds our bg path, but the user does not manipulate it directly ui->kcfg_BackgroundPicturePath->hide(); connect(ui->kurlrequester, &KUrlRequester::textChanged, this, &BackgroundSelector::imagePathChanged); connect(ui->kcfg_UseRandomBackgroundPictures, &QCheckBox::toggled, this, &BackgroundSelector::useRandomBackgroundPicturesChanged); //Get our currently configured Tileset entry KConfig * config = m_config->config(); KConfigGroup group = config->group("General"); QString picturePath = group.readPathEntry("BackgroundPicturePath",QDir::homePath() ); ui->kurlrequester->setUrl(QUrl(picturePath)); ui->kurlrequester->setStartDir(QUrl(picturePath)); } } void BackgroundSelector::useRandomBackgroundPicturesChanged(bool toggled) { if (toggled) { enableSettings(true); previewBackgroundPicture(); } else { enableSettings(false); } } void BackgroundSelector::enableSettings(bool enable) { ui->kurlrequester->setEnabled(enable); ui->backgroundPicturePreview->setEnabled(enable); } void BackgroundSelector::imagePathChanged(const QString& path) { ui->kcfg_BackgroundPicturePath->setText(path); previewBackgroundPicture(); } void BackgroundSelector::previewBackgroundPicture() { KBounceRenderer render; QSize previewSize = ui->backgroundPicturePreview->size(); QPixmap previewPixmap = render.getRandomBackgroundPixmap(ui->kcfg_BackgroundPicturePath->text()); if (previewPixmap.isNull()) { previewPixmap = QPixmap(previewSize); previewPixmap.fill( Qt::transparent ); QPainter p( &previewPixmap ); QString text=i18n("No background pictures found."); QFont font; font.setPointSize( 11 ); p.setFont( font ); KColorScheme kcs(QPalette::Normal,KColorScheme::Window); p.setPen(kcs.foreground(KColorScheme::NeutralText).color()); p.drawText( p.viewport(), Qt::AlignCenter | Qt::AlignTop | Qt::TextWordWrap, text ); p.end(); } ui->backgroundPicturePreview->setPixmap(previewPixmap.scaled(previewSize,Qt::KeepAspectRatio,Qt::SmoothTransformation)); } diff --git a/board.h b/board.h index 752400a..f96f294 100644 --- a/board.h +++ b/board.h @@ -1,98 +1,97 @@ /* * Copyright (C) 2000-2005 Stefan Schimanski <1Stein@gmx.de> * * 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 -#include #include #include #include #include "gameobject.h" #include "renderer.h" #define TILE_NUM_H 20 #define TILE_NUM_W 32 class KBounceBall; class KBounceWall; class KBounceBoard: public QGraphicsObject { Q_OBJECT public: enum TileType{ Empty, Free, Border, Wall, Temp }; explicit KBounceBoard( KBounceRenderer *renderer ); ~KBounceBoard(); QPixmap applyWallsOn(const QPixmap &background) const; void resize( QSize& size ); void paint(QPainter *, const QStyleOptionGraphicsItem *, QWidget *) Q_DECL_OVERRIDE {} void newLevel( int level ); void setPaused( bool ); void buildWall( const QPointF& pos, bool vertical ); int balls(); int filled(); KBounceCollision checkCollision( void* object, const QRectF& rect, int type ); KBounceCollision checkCollisionTiles( const QRectF& rect ); void checkCollisions(); QPoint mapPosition( const QPointF& pos ) const; QRectF boundingRect() const Q_DECL_OVERRIDE; void setBallVelocity(qreal velocity); void setWallVelocity(qreal velocity); signals: void ballsChanged( int balls ); void fillChanged( int fill ); void wallDied(); protected slots: void tick(); void wallFinished( int x1, int y1, int x2, int y2 ); private: void clear(); void fill( int x, int y ); KBounceRenderer* m_renderer; TileType m_tiles[TILE_NUM_W][TILE_NUM_H]; QSize m_tileSize; int m_filled; QList m_balls; QList m_walls; QTimer* m_clock; qreal m_ballVelocity; qreal m_wallVelocity; }; #endif // BOARD_H diff --git a/mainwindow.cpp b/mainwindow.cpp index 6ee4818..ad88412 100644 --- a/mainwindow.cpp +++ b/mainwindow.cpp @@ -1,277 +1,276 @@ /* * Copyright (C) 2000-2005 Stefan Schimanski <1Stein@gmx.de> * * 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,Life 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. */ #include "mainwindow.h" #include "gamewidget.h" #include "settings.h" #include "backgroundselector.h" #include "debug.h" -#include #include #include #include #include #include #include #include #include #include #include #include KBounceMainWindow::KBounceMainWindow() { //setComponentName(QStringLiteral("kbounce"), i18n("KBounce")); m_statusBar = statusBar(); levelLabel->setText(i18n("Level: %1", QStringLiteral( "XX" ))); scoreLabel->setText(i18n("Score: %1", QStringLiteral( "XXXXXX" ))); filledLabel->setText(i18n( "Filled: %1%", QStringLiteral( "XX" ))); livesLabel->setText(i18n( "Lives: %1", QStringLiteral( "XX" ))); timeLabel->setText(i18n( "Time: %1", QStringLiteral( "XXX" ))); m_statusBar->insertPermanentWidget(0, levelLabel, 1); m_statusBar->insertPermanentWidget(1, scoreLabel, 1); m_statusBar->insertPermanentWidget(2, filledLabel, 1); m_statusBar->insertPermanentWidget(3, livesLabel, 1); m_statusBar->insertPermanentWidget(4, timeLabel, 1); m_gameWidget = new KBounceGameWidget( this ); connect( m_gameWidget, SIGNAL(levelChanged(int)), this, SLOT(displayLevel(int)) ); connect( m_gameWidget, &KBounceGameWidget::scoreChanged, this, &KBounceMainWindow::displayScore ); connect( m_gameWidget, &KBounceGameWidget::livesChanged, this, &KBounceMainWindow::displayLives ); connect( m_gameWidget, &KBounceGameWidget::filledChanged, this, &KBounceMainWindow::displayFilled ); connect( m_gameWidget, &KBounceGameWidget::timeChanged, this, &KBounceMainWindow::displayTime ); connect( m_gameWidget, &KBounceGameWidget::stateChanged, this, &KBounceMainWindow::gameStateChanged ); //connect( m_gameWidget, SIGNAL(gameOver()), this, SLOT(gameOverNow()) ); setCentralWidget( m_gameWidget ); initXMLUI(); setFocusPolicy(Qt::StrongFocus); setFocus(); setupGUI(); readSettings(); } KBounceMainWindow::~KBounceMainWindow() { } /** * create the action events create the gui. */ void KBounceMainWindow::initXMLUI() { // Game m_newAction = KStandardGameAction::gameNew(this, SLOT(newGame()), actionCollection()); KStandardGameAction::end(this, SLOT(closeGame()), actionCollection()); m_pauseAction = KStandardGameAction::pause(this, SLOT(pauseGame()), actionCollection()); KStandardGameAction::highscores(this, SLOT(showHighscore()), actionCollection()); KStandardGameAction::quit(this, SLOT(close()), actionCollection()); // Difficulty Kg::difficulty()->addStandardLevelRange( KgDifficultyLevel::Easy, KgDifficultyLevel::Hard ); KgDifficultyGUI::init(this); connect(Kg::difficulty(), SIGNAL(currentLevelChanged(const KgDifficultyLevel*)), m_gameWidget, SLOT(levelChanged())); // Settings KStandardAction::preferences( this, SLOT(configureSettings()), actionCollection() ); m_soundAction = new KToggleAction( i18n("&Play Sounds"), this ); actionCollection()->addAction( QStringLiteral( "toggle_sound" ), m_soundAction ); connect( m_soundAction, &QAction::triggered, this, &KBounceMainWindow::setSounds ); } void KBounceMainWindow::newGame() { // Check for running game closeGame(); if ( m_gameWidget->state() == KBounceGameWidget::BeforeFirstGame || m_gameWidget->state() == KBounceGameWidget::GameOver ) { m_gameWidget->newGame(); } } void KBounceMainWindow::pauseGame() { if ( m_gameWidget->state() == KBounceGameWidget::Paused ) { m_gameWidget->setPaused( false ); } else { m_gameWidget->setPaused( true ); } } void KBounceMainWindow::closeGame() { if ( m_gameWidget->state() == KBounceGameWidget::BeforeFirstGame || m_gameWidget->state() == KBounceGameWidget::GameOver ) { return; } KBounceGameWidget::State old_state = m_gameWidget->state(); if ( old_state == KBounceGameWidget::Running ) m_gameWidget->setPaused( true ); int ret = KMessageBox::questionYesNo( this, i18n( "Do you really want to close the running game?" ), QString(), KStandardGuiItem::yes(), KStandardGuiItem::cancel() ); if ( ret == KMessageBox::Yes ) { m_gameWidget->closeGame(); } else if ( old_state == KBounceGameWidget::Running ) { m_gameWidget->setPaused( false ); } } void KBounceMainWindow::gameOverNow() { statusBar()->showMessage( i18n("Game over. Click to start a game") ); highscore(); } /** * Bring up the standard kde high score dialog. */ void KBounceMainWindow::showHighscore() { KScoreDialog ksdialog( KScoreDialog::Name | KScoreDialog::Score, this ); ksdialog.initFromDifficulty(Kg::difficulty()); ksdialog.exec(); } void KBounceMainWindow::highscore() { if ( m_gameWidget->score() == 0 ) { return; } qCDebug(KBOUNCE_LOG); KScoreDialog ksdialog( KScoreDialog::Name | KScoreDialog::Score | KScoreDialog::Level, this ); ksdialog.initFromDifficulty(Kg::difficulty()); KScoreDialog::FieldInfo info; info[KScoreDialog::Score].setNum( m_gameWidget->score() ); info[KScoreDialog::Level].setNum( m_gameWidget->level() ); if ( ksdialog.addScore( info ) ) ksdialog.exec(); } void KBounceMainWindow::configureSettings() { if ( KConfigDialog::showDialog( QStringLiteral("settings") ) ) return; KConfigDialog* dialog = new KConfigDialog( this, QStringLiteral("settings"), KBounceSettings::self()); dialog->addPage( new KgThemeSelector(m_gameWidget->renderer()->themeProvider(), 0, dialog), i18n( "Theme" ), QStringLiteral("games-config-theme") ); dialog->addPage( new BackgroundSelector(dialog,KBounceSettings::self() ),i18n("Background"),QStringLiteral("games-config-background")); dialog->show(); connect( dialog, &KConfigDialog::settingsChanged, this, &KBounceMainWindow::settingsChanged ); } void KBounceMainWindow::readSettings() { m_soundAction->setChecked( KBounceSettings::playSounds() ); m_gameWidget->settingsChanged(); } void KBounceMainWindow::settingsChanged() { m_gameWidget->settingsChanged(); KBounceSettings::self()->save(); // Bug 184606 } void KBounceMainWindow::setSounds( bool val ) { KBounceSettings::setPlaySounds( val ); settingsChanged(); } void KBounceMainWindow::displayLevel( int level ) { levelLabel->setText(i18n("Level: %1", level)); } void KBounceMainWindow::displayScore( int score ) { scoreLabel->setText(i18n("Score: %1", score)); } void KBounceMainWindow::displayFilled( int filled ) { filledLabel->setText(i18n("Filled: %1%", filled)); } void KBounceMainWindow::displayLives( int lives ) { livesLabel->setText(i18n("Lives: %1", lives - 1)); } void KBounceMainWindow::displayTime( int time ) { timeLabel->setText(i18n("Time: %1", time)); } void KBounceMainWindow::gameStateChanged( KBounceGameWidget::State state ) { switch ( state ) { case KBounceGameWidget::BeforeFirstGame : break; case KBounceGameWidget::BetweenLevels : break; case KBounceGameWidget::Suspended : break; case KBounceGameWidget::Paused : m_pauseAction->setChecked( true ); m_statusBar->clearMessage(); break; case KBounceGameWidget::Running : m_pauseAction->setChecked( false ); m_statusBar->clearMessage(); break; case KBounceGameWidget::GameOver : statusBar()->showMessage( i18n("Game over. Click to start a game") ); highscore(); break; } } void KBounceMainWindow::focusOutEvent( QFocusEvent *ev ) { if ( m_gameWidget->state() == KBounceGameWidget::Running && focusWidget() != m_gameWidget ) { m_gameWidget->setPaused( true ); } KXmlGuiWindow::focusOutEvent( ev ); } void KBounceMainWindow::focusInEvent ( QFocusEvent *ev ) { //m_board->setSuspended( true ); KXmlGuiWindow::focusInEvent( ev ); } diff --git a/renderer.cpp b/renderer.cpp index 5403486..908d290 100644 --- a/renderer.cpp +++ b/renderer.cpp @@ -1,138 +1,136 @@ /* * Copyright (C) 2006 Dmitry Suzdalev * Copyright (C) 2007 Tomasz Boczkowski * * This file is part of the KDE project "KBounce" * * KBounce 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. * * KBounce 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 KBounce; if not, write to the Free * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. */ #include "renderer.h" #include "settings.h" #include "debug.h" -#include -#include #include #include #include static KgThemeProvider* provider() { KgThemeProvider* prov = new KgThemeProvider; prov->discoverThemes( "appdata", QStringLiteral("themes"), //theme file location QStringLiteral("default") //default theme file name ); return prov; } KBounceRenderer::KBounceRenderer() : KGameRenderer(provider()), m_backgroundSize( QSize( 0, 0 ) ), m_useRandomBackgrounds(false) { } KBounceRenderer::~KBounceRenderer() { } void KBounceRenderer::setCustomBackgroundPath(const QString& path) { m_useRandomBackgrounds = !path.isEmpty(); m_customBackgroundPath = path; m_cachedBackground = QPixmap(); } void KBounceRenderer::setBackgroundSize( const QSize& size ) { if (size != m_backgroundSize ) { m_backgroundSize = size; if ( m_useRandomBackgrounds && !m_cachedBackground.isNull() ) { m_cachedBackground = m_randomBackground.scaled(m_backgroundSize,Qt::IgnoreAspectRatio); } else { m_cachedBackground = QPixmap(); } } } bool KBounceRenderer::loadNewBackgroundPixmap() { bool backgroundFound = false; if ( !m_customBackgroundPath.isEmpty() ) { m_randomBackground = getRandomBackgroundPixmap(m_customBackgroundPath); if ( !m_randomBackground.isNull() ) { m_cachedBackground = m_randomBackground.scaled(m_backgroundSize,Qt::IgnoreAspectRatio); backgroundFound = true; } } return backgroundFound; } QPixmap KBounceRenderer::renderBackground() { if (m_cachedBackground.isNull() && !m_backgroundSize.isNull()) { //This is a dirty fix to the qt's m_svgRenderer.render() method that //leaves an garbage-filled border of a pixmap qCDebug(KBOUNCE_LOG) << "Rendering the background. Size:" << m_backgroundSize; if ( m_useRandomBackgrounds && loadNewBackgroundPixmap() ) { return m_cachedBackground; } // If no valid backgound pixmap found use the original from theme ... m_cachedBackground = spritePixmap( QStringLiteral("background"), m_backgroundSize ); } return m_cachedBackground; } QPixmap KBounceRenderer::getRandomBackgroundPixmap(const QString& path) { // list directory QDir dir( path, QStringLiteral("*.png *.jpg"), QDir::Name|QDir::IgnoreCase, QDir::Files ); if ( !dir.exists() ) { qCDebug(KBOUNCE_LOG) << "CustomBackground Directory not found" << endl; return QPixmap(); } if ( dir.count() > 1 ) { QString filename; // return random pixmap uint pos = KRandom::random() % dir.count(); if ( pos < dir.count() ) { filename = dir.absoluteFilePath( dir[pos] ); } if (!filename.isEmpty() && QFile(filename).exists()) { return QPixmap(filename); } else return QPixmap(); } else if ( dir.count() == 1 ) { return QPixmap( dir.absoluteFilePath(dir[0]) ); } else return QPixmap(); } diff --git a/wall.cpp b/wall.cpp index ff44151..8cedb51 100644 --- a/wall.cpp +++ b/wall.cpp @@ -1,322 +1,321 @@ /* * Copyright (C) 2000-2005 Stefan Schimanski <1Stein@gmx.de> * * 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. */ #include "wall.h" #include -#include #include #include #include "board.h" #include "renderer.h" #include "settings.h" QSize KBounceWall::s_tileSize; KBounceRenderer * KBounceWall::m_renderer = NULL; KBounceWall::Sprites * KBounceWall::s_sprites = NULL; KBounceWall::KBounceWall( Direction dir, KBounceRenderer* renderer, KBounceBoard* board ) : KGameRenderedItem( renderer,QLatin1String(""),board ) , m_board( board ) , m_dir( dir ) , m_soundWallstart( QStandardPaths::locate( QStandardPaths::AppDataLocation, QStringLiteral("sounds/wallstart.wav") ) ) , m_soundReflect( QStandardPaths::locate( QStandardPaths::AppDataLocation, QStringLiteral("sounds/reflect.wav") ) ) { // The wall velocity would initialised on every new level. m_wallVelocity = 0.0; if (!s_sprites) { s_sprites = new Sprites; } if (!m_renderer) { m_renderer = renderer; } } KBounceWall::~KBounceWall() { } void KBounceWall::collide( KBounceCollision collision ) { if ( !isVisible() ) return; foreach( const KBounceHit &hit, collision ) { switch (hit.type) { case ALL: break; case TILE: finish(); break; case BALL: if (safeEdgeHit(hit.boundingRect)) { KBounceVector normal = hit.normal; if (qAbs(normal.x) < qAbs(normal.y)) { // vertical if (m_dir == Up || m_dir == Down) { finish( true, m_dir ); } } else if (m_dir == Left || m_dir == Right) { finish( true, m_dir ); } } else { emit died(); hide(); } break; case WALL: if (safeEdgeHit(hit.boundingRect)) { finish(); } break; } } } void KBounceWall::goForward() { if (!isVisible()) { return; } switch( m_dir ) { case Up: m_boundingRect.setTop( m_boundingRect.top() - m_wallVelocity ); m_nextBoundingRect.setTop( m_boundingRect.top() - m_wallVelocity ); break; case Left: m_boundingRect.setLeft( m_boundingRect.left() - m_wallVelocity ); m_nextBoundingRect.setLeft( m_boundingRect.left() - m_wallVelocity ); break; case Down: m_boundingRect.setBottom( m_boundingRect.bottom() + m_wallVelocity ); m_nextBoundingRect.setBottom( m_boundingRect.bottom() + m_wallVelocity ); break; case Right: m_boundingRect.setRight( m_boundingRect.right() + m_wallVelocity ); m_nextBoundingRect.setRight( m_boundingRect.right() + m_wallVelocity ); break; } } void KBounceWall::update() { if (!isVisible()) return; int boundingRectWidth = static_cast(std::ceil(m_boundingRect.width() * s_tileSize.width())); int boundingRectHeight = static_cast(std::ceil(m_boundingRect.height() * s_tileSize.height())); if (!(boundingRectWidth && boundingRectHeight)) return; int tileWidth = s_tileSize.width(); int tileHeight = s_tileSize.height(); QSize pixSize; if (m_dir == Left || m_dir == Right) { pixSize = QSize(boundingRectWidth + 64 - (boundingRectWidth%64), boundingRectHeight); } else { pixSize = QSize(boundingRectWidth, boundingRectHeight + 64 - (boundingRectHeight%64)); } QPixmap px; if (pixmap().width() < pixSize.width() || pixmap().height() < pixSize.height()) { px = QPixmap(pixSize); } else { px = pixmap(); // already ARGB } px.fill(Qt::transparent); QPainter p(&px); QPointF offset = m_board->mapPosition(m_boundingRect.topLeft()); switch ( m_dir ) { case Up: { const int split = qMin(tileHeight, boundingRectHeight); p.drawPixmap(0, 0, s_sprites->wallEndUp, 0, 0, tileWidth, split); p.drawTiledPixmap(0, split, tileWidth, boundingRectHeight - split, s_sprites->wallV, 0, offset.y()); break; } case Right: { const int split = qMin(tileWidth, boundingRectWidth); p.drawPixmap(boundingRectWidth - tileWidth, 0, split, tileHeight, s_sprites->wallEndRight); p.drawTiledPixmap(0, 0, boundingRectWidth - split, tileHeight, s_sprites->wallH); break; } case Down: { const int split = qMin(tileHeight, boundingRectHeight); p.drawPixmap(0, boundingRectHeight - tileHeight, tileWidth, split, s_sprites->wallEndDown); p.drawTiledPixmap(0, 0, tileWidth, boundingRectHeight - split, s_sprites->wallV); break; } case Left: const int split = qMin(boundingRectWidth, tileWidth); p.drawPixmap(0, 0, split, tileHeight, s_sprites->wallEndLeft); p.drawTiledPixmap(split, 0, boundingRectWidth - split, tileHeight, s_sprites->wallH, offset.x()); } setPos(offset); p.end(); setPixmap(px); } void KBounceWall::loadSprites() { s_sprites->wallEndLeft = m_renderer->spritePixmap(QStringLiteral("wallEndLeft"), s_tileSize); s_sprites->wallEndUp = m_renderer->spritePixmap(QStringLiteral("wallEndUp"), s_tileSize); s_sprites->wallEndRight = m_renderer->spritePixmap(QStringLiteral("wallEndRight"), s_tileSize); s_sprites->wallEndDown = m_renderer->spritePixmap(QStringLiteral("wallEndDown"), s_tileSize); s_sprites->wallH = m_renderer->spritePixmap(QStringLiteral("wallH"), QSize(32 * s_tileSize.width(), s_tileSize.height())); s_sprites->wallV = m_renderer->spritePixmap(QStringLiteral("wallV"), QSize(s_tileSize.width(), 18*s_tileSize.height())); } void KBounceWall::resize( const QSize& tileSize ) { if ( tileSize != s_tileSize ) { s_tileSize = tileSize; loadSprites(); update(); } } void KBounceWall::build( int x, int y ) { if (isVisible()) return; if ( m_dir == Up || m_dir == Down ) { m_boundingRect.setTop( y ); if (m_dir == Down) { m_boundingRect.setBottom(y + 1); } else { m_boundingRect.setBottom( y ); } m_boundingRect.setLeft( x ); m_boundingRect.setRight( x + 1 ); } else if ( m_dir == Left || m_dir == Right ) { m_boundingRect.setTop( y ); m_boundingRect.setBottom( y + 1 ); m_boundingRect.setLeft( x ); if (m_dir == Right) { m_boundingRect.setRight(x + 1); } else { m_boundingRect.setRight( x ); } } m_nextBoundingRect = m_boundingRect; setPixmap(QPixmap()); setPos(m_board->mapPosition(QPointF( x, y ))); show(); if ( KBounceSettings::playSounds() ) m_soundWallstart.start(); } QRectF KBounceWall::nextBoundingRect() const { return m_nextBoundingRect; } bool KBounceWall::safeEdgeHit( const QRectF& rect2 ) const { bool safeEdgeHit = false; QPointF p1, p2, p3; switch ( m_dir ) { case Up: p1 = m_nextBoundingRect.topLeft(); p2 = m_nextBoundingRect.topRight(); break; case Right: p1 = m_nextBoundingRect.topRight(); p2 = m_nextBoundingRect.bottomRight(); break; case Down: p1 = m_nextBoundingRect.bottomRight(); p2 = m_nextBoundingRect.bottomLeft(); break; case Left: p1 = m_nextBoundingRect.bottomLeft(); p2 = m_nextBoundingRect.topLeft(); break; default: Q_ASSERT(false); break; } p3.setX( ( p1.x() + p2.x() ) / 2.0 ); p3.setY( ( p1.y() + p2.y() ) / 2.0 ); if ( rect2.contains( p1 ) ) safeEdgeHit = true; else if ( rect2.contains( p2 ) ) safeEdgeHit = true; else if ( rect2.contains( p3 ) ) safeEdgeHit = true; return safeEdgeHit; } void KBounceWall::finish( bool shorten, Direction dir ) { int left = static_cast( m_boundingRect.left() ); int top = static_cast( m_boundingRect.top() ); int right = static_cast( m_boundingRect.right() ); int bottom = static_cast( m_boundingRect.bottom() ); if ( shorten ) { switch ( dir ) { case Left: left++; break; case Up: top++; break; case Right: right--; break; case Down: bottom--; break; } } emit finished( left, top, right, bottom ); hide(); if (KBounceSettings::playSounds()) m_soundReflect.start(); } void KBounceWall::setWallVelocity(qreal velocity) { m_wallVelocity = velocity; }