summaryrefslogtreecommitdiffstats
path: root/kbounce
diff options
context:
space:
mode:
Diffstat (limited to 'kbounce')
-rw-r--r--kbounce/Makefile.am76
-rw-r--r--kbounce/RULES25
-rw-r--r--kbounce/configure.in.in4
-rw-r--r--kbounce/game.cpp699
-rw-r--r--kbounce/game.h183
-rw-r--r--kbounce/highscores.cpp18
-rw-r--r--kbounce/highscores.h17
-rw-r--r--kbounce/kbounce.cpp491
-rw-r--r--kbounce/kbounce.desktop67
-rw-r--r--kbounce/kbounce.h104
-rw-r--r--kbounce/kbounceui.rc17
-rw-r--r--kbounce/main.cpp75
-rw-r--r--kbounce/pics/Makefile.am34
-rw-r--r--kbounce/pics/ball0000.pngbin0 -> 641 bytes
-rw-r--r--kbounce/pics/ball0001.pngbin0 -> 622 bytes
-rw-r--r--kbounce/pics/ball0002.pngbin0 -> 616 bytes
-rw-r--r--kbounce/pics/ball0003.pngbin0 -> 598 bytes
-rw-r--r--kbounce/pics/ball0004.pngbin0 -> 593 bytes
-rw-r--r--kbounce/pics/ball0005.pngbin0 -> 595 bytes
-rw-r--r--kbounce/pics/ball0006.pngbin0 -> 589 bytes
-rw-r--r--kbounce/pics/ball0007.pngbin0 -> 591 bytes
-rw-r--r--kbounce/pics/ball0008.pngbin0 -> 596 bytes
-rw-r--r--kbounce/pics/ball0009.pngbin0 -> 592 bytes
-rw-r--r--kbounce/pics/ball0010.pngbin0 -> 603 bytes
-rw-r--r--kbounce/pics/ball0011.pngbin0 -> 613 bytes
-rw-r--r--kbounce/pics/ball0012.pngbin0 -> 623 bytes
-rw-r--r--kbounce/pics/ball0013.pngbin0 -> 627 bytes
-rw-r--r--kbounce/pics/ball0014.pngbin0 -> 635 bytes
-rw-r--r--kbounce/pics/ball0015.pngbin0 -> 624 bytes
-rw-r--r--kbounce/pics/ball0016.pngbin0 -> 608 bytes
-rw-r--r--kbounce/pics/ball0017.pngbin0 -> 614 bytes
-rw-r--r--kbounce/pics/ball0018.pngbin0 -> 609 bytes
-rw-r--r--kbounce/pics/ball0019.pngbin0 -> 610 bytes
-rw-r--r--kbounce/pics/ball0020.pngbin0 -> 604 bytes
-rw-r--r--kbounce/pics/ball0021.pngbin0 -> 609 bytes
-rw-r--r--kbounce/pics/ball0022.pngbin0 -> 629 bytes
-rw-r--r--kbounce/pics/ball0023.pngbin0 -> 638 bytes
-rw-r--r--kbounce/pics/ball0024.pngbin0 -> 645 bytes
-rw-r--r--kbounce/pics/hi128-app-kbounce.pngbin0 -> 12438 bytes
-rw-r--r--kbounce/pics/hi16-app-kbounce.pngbin0 -> 822 bytes
-rw-r--r--kbounce/pics/hi22-app-kbounce.pngbin0 -> 1298 bytes
-rw-r--r--kbounce/pics/hi32-app-kbounce.pngbin0 -> 2175 bytes
-rw-r--r--kbounce/pics/hi48-app-kbounce.pngbin0 -> 3697 bytes
-rw-r--r--kbounce/pics/hi64-app-kbounce.pngbin0 -> 5157 bytes
-rw-r--r--kbounce/pics/tiles.pngbin0 -> 753 bytes
-rw-r--r--kbounce/sounds/Makefile.am7
-rw-r--r--kbounce/sounds/death.aubin0 -> 1407 bytes
-rw-r--r--kbounce/sounds/reflect.aubin0 -> 716 bytes
-rw-r--r--kbounce/sounds/seconds.aubin0 -> 362 bytes
-rw-r--r--kbounce/sounds/timeout.aubin0 -> 23239 bytes
-rw-r--r--kbounce/sounds/wallend.aubin0 -> 759 bytes
-rw-r--r--kbounce/sounds/wallstart.aubin0 -> 1271 bytes
52 files changed, 1817 insertions, 0 deletions
diff --git a/kbounce/Makefile.am b/kbounce/Makefile.am
new file mode 100644
index 00000000..25d0909b
--- /dev/null
+++ b/kbounce/Makefile.am
@@ -0,0 +1,76 @@
+if include_ARTS
+artslib = -lartskde
+else
+artslib =
+endif
+
+SUBDIRS = pics sounds
+
+INCLUDES = -I$(top_srcdir)/libkdegames -I$(top_srcdir)/libkdegames/highscore $(all_includes)
+METASOURCES = AUTO
+KDE_CXXFLAGS = $(KDE_USE_FPIE)
+
+bin_PROGRAMS = kbounce
+kbounce_SOURCES = main.cpp kbounce.cpp game.cpp highscores.cpp
+kbounce_LDFLAGS = $(all_libraries) $(KDE_RPATH) $(KDE_USE_PIE)
+kbounce_LDADD = $(LIB_KDEGAMES) $(LIB_KFILE) $(LIB_ARTS) $(artslib)
+kbounce_DEPENDENCIES = $(LIB_KDEGAMES_DEP)
+
+xdg_apps_DATA = kbounce.desktop
+
+EXTRA_DIST = RULES $(xdg_apps_DATA)
+
+rcdir = $(kde_datadir)/kbounce
+rc_DATA = kbounceui.rc
+
+messages: rc.cpp
+ $(XGETTEXT) *.cpp -o $(podir)/kbounce.pot
+
+# for system-wide highscore file
+DESTBIN = $(DESTDIR)$(bindir)/$(bin_PROGRAMS)
+DESTHIGHSCORES = $(DESTDIR)$(HIGHSCORE_DIRECTORY)
+DESTSCORES = $(DESTDIR)$(HIGHSCORE_DIRECTORY)/$(bin_PROGRAMS).scores
+
+install-data-local:
+ @if test x$(HIGHSCORE_DIRECTORY) != x; then \
+ echo "********************************************************" ;\
+ echo "" ;\
+ echo "This game is installed sgid \"games\" to use the" ;\
+ echo "system-wide highscore file (in "$(HIGHSCORE_DIRECTORY)")." ;\
+ echo "" ;\
+ echo "If the system-wide highscore file does not exist, it is" ;\
+ echo "created with the correct ownership and permissions. See the" ;\
+ echo "INSTALL file in \"kdegames/libkdegames/highscore\" for details." ;\
+ echo "" ;\
+ echo "********************************************************" ;\
+ fi
+
+install-exec-hook:
+ @if test x$(HIGHSCORE_DIRECTORY) != x; then \
+ chown $(highscore_user):$(highscore_group) $(DESTBIN) \
+ || echo "Error: Could not install the game with correct permissions !!" ;\
+ fi
+
+ @if test x$(HIGHSCORE_DIRECTORY) != x; then \
+ mkdir -p $(DESTHIGHSCORES) && \
+ chown $(highscore_user):$(highscore_group) $(DESTHIGHSCORES) \
+ && chmod 750 $(DESTHIGHSCORES) \
+ || echo "Error: Could not create the highscore directory with correct permissions !!" ;\
+ fi
+
+ @if test x$(HIGHSCORE_DIRECTORY) != x; then \
+ chown $(highscore_user):$(highscore_group) $(DESTBIN) \
+ || echo "Error: Could not install the game with correct permissions !!" ;\
+ fi
+
+ @if test ${setgid} = true; then \
+ chmod 2755 $(DESTBIN) \
+ || echo "Error: Could not install the game with correct permissions !!" ;\
+ fi
+
+ @if test x$(HIGHSCORE_DIRECTORY) != x; then \
+ touch $(DESTSCORES) && chown $(highscore_user):$(highscore_group) $(DESTSCORES) \
+ && chmod 0660 $(DESTSCORES) \
+ || echo "Error: Could not create system-wide highscore file with correct permissions !!" ;\
+ fi
+
diff --git a/kbounce/RULES b/kbounce/RULES
new file mode 100644
index 00000000..1636814b
--- /dev/null
+++ b/kbounce/RULES
@@ -0,0 +1,25 @@
+======================
+= Rules of Jezz Ball =
+======================
+
+Game/Level Length
+1. The game will be over if
+ a) your number of lifes is zero or
+ b) your time is over.
+2. When at least 75% of the field is filled. a level is completed.
+
+Lifes
+3. A level is started with one life per ball on the field.
+4. You will lose a life if a ball hits the inner of a wall.
+
+Balls
+5. Each level include one more ball.
+6. A ball is reflected by blue and black blocks.
+
+Walls
+7. You build a wall with the left mouse buttoyn and change the direction with the right.
+8. You can _always_ build _two_ "half" walls concurrently. If one half is already finished,
+ you can build another "half" wall.
+9. A wall is finished if it is hit by a ball at its end or it hits a black block.
+10. A wall is removed if it is hit by a ball at the wall's inner or two "half" walls hit each
+ other with their blue ends. \ No newline at end of file
diff --git a/kbounce/configure.in.in b/kbounce/configure.in.in
new file mode 100644
index 00000000..d34f1b32
--- /dev/null
+++ b/kbounce/configure.in.in
@@ -0,0 +1,4 @@
+if test "x$build_arts" != "xno"; then
+ AC_DEFINE_UNQUOTED(HAVE_ARTS, 1, [Define if aRts is available])
+ LIB_ARTS="-lsoundserver_idl"
+fi
diff --git a/kbounce/game.cpp b/kbounce/game.cpp
new file mode 100644
index 00000000..853a645d
--- /dev/null
+++ b/kbounce/game.cpp
@@ -0,0 +1,699 @@
+/*
+ * Copyright (C) 2000 Stefan Schimanski <[email protected]>
+ *
+ * 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 <stdlib.h>
+#include <qtimer.h>
+#include <kstandarddirs.h>
+#include <kapplication.h>
+#include <kdebug.h>
+#include <qimage.h>
+#include <kglobalsettings.h>
+
+#include "game.h"
+
+
+#define TILE_SIZE 16
+
+#define TILE_FIRST ((FIELD_WIDTH-2)*(FIELD_HEIGHT-2))
+#define TILE_FREE (TILE_FIRST + 0)
+#define TILE_BORDER (TILE_FIRST + 1)
+#define TILE_WALLEND (TILE_FIRST + 2)
+#define TILE_WALLUP (TILE_FIRST + 3)
+#define TILE_WALLDOWN (TILE_FIRST + 4)
+#define TILE_WALLLEFT (TILE_FIRST + 5)
+#define TILE_WALLRIGHT (TILE_FIRST + 6)
+
+#define GAME_DELAY 15
+#define BALL_ANIM_DELAY 60
+#define WALL_DELAY 100
+
+
+#if HAVE_ARTS
+SimpleSoundServer *JezzGame::m_artsServer = 0;
+#endif
+QString JezzGame::m_soundPath;
+bool JezzGame::m_sound = true;
+
+#define MS2TICKS( ms ) ((ms)/GAME_DELAY)
+
+Ball::Ball(QCanvasPixmapArray* array, QCanvas* canvas)
+ : QCanvasSprite( array, canvas ), m_animDelay( 0 ), m_soundDelay( MS2TICKS(BALL_ANIM_DELAY)/2 )
+{
+}
+
+void Ball::update()
+{
+ // set pixmap frame
+ m_animDelay--;
+ if ( m_animDelay<=0 )
+ {
+ m_animDelay = MS2TICKS(BALL_ANIM_DELAY);
+ int frameNum = frame();
+ frameNum++;
+ if ( frameNum>=frameCount() )
+ frameNum = 0;
+ setFrame( frameNum );
+ }
+}
+
+void Ball::advance(int stage)
+{
+ bool reflectX = false;
+ bool reflectY = false;
+
+ m_soundDelay++;
+
+ // ball already on a wall? (should normally never happen)
+ // commented out to stop bug which causes balls to
+ // sometimes stop when clicked on
+ // if ( collide(0, 0) ) setVelocity( 0, 0 );
+
+ // check for collisions
+ if ( collide(xVelocity(), 0) ) reflectX = true;
+ if ( collide(0, yVelocity()) ) reflectY = true;
+ if ( !reflectX && !reflectY && collide(xVelocity(), yVelocity()) ) reflectX = reflectY = true;
+
+ // emit collision
+ QRect r = boundingRect();
+ r.moveBy( xVelocity(), yVelocity() );
+ JezzField* field = (JezzField *)canvas();
+
+ int ul = field->tile( r.left() / TILE_SIZE, r.top() / TILE_SIZE );
+ int ur = field->tile( r.right() / TILE_SIZE, r.top() / TILE_SIZE );
+ int bl = field->tile( r.left() / TILE_SIZE, r.bottom() / TILE_SIZE );
+ int br = field->tile( r.right() / TILE_SIZE, r.bottom() / TILE_SIZE );
+
+ if ( ul!=TILE_FREE ) field->emitBallCollisiton( this, r.left() / TILE_SIZE, r.top() / TILE_SIZE, ul ); else
+ if ( ur!=TILE_FREE ) field->emitBallCollisiton( this, r.right() / TILE_SIZE, r.top() / TILE_SIZE, ur ); else
+ if ( bl!=TILE_FREE ) field->emitBallCollisiton( this, r.left() / TILE_SIZE, r.bottom() / TILE_SIZE, bl ); else
+ if ( br!=TILE_FREE ) field->emitBallCollisiton( this, r.right() / TILE_SIZE, r.bottom() / TILE_SIZE, br );
+
+ // apply reflection
+ if ( reflectX ) setXVelocity( -xVelocity() );
+ if ( reflectY ) setYVelocity( -yVelocity() );
+
+ // play collision sound
+ if ( reflectX || reflectY )
+ {
+ if ( m_soundDelay>50 ) JezzGame::playSound( "reflect.au" );
+ m_soundDelay = 0;
+ }
+
+ // update field
+ update();
+ QCanvasSprite::advance( stage );
+}
+
+bool Ball::collide( double dx, double dy )
+{
+ QRect r = boundingRect();
+ r.moveBy( dx, dy );
+ JezzField* field = (JezzField *)canvas();
+
+ int ul = field->tile( r.left() / TILE_SIZE, r.top() / TILE_SIZE );
+ int ur = field->tile( r.right() / TILE_SIZE, r.top() / TILE_SIZE );
+ int bl = field->tile( r.left() / TILE_SIZE, r.bottom() / TILE_SIZE );
+ int br = field->tile( r.right() / TILE_SIZE, r.bottom() / TILE_SIZE );
+
+ return ( ul!=TILE_FREE || ur!=TILE_FREE || bl!=TILE_FREE || br!=TILE_FREE );
+}
+
+/*************************************************************************/
+
+Wall::Wall( JezzField *field, int x, int y, Direction dir, int tile, QObject *parent, const char *name )
+ : QObject( parent, name ), m_dir( dir ), m_field( field ), m_startX( x ), m_startY( y ),
+ m_tile( tile ), m_delay( MS2TICKS(WALL_DELAY)/2 ), m_active( true )
+{
+ //kdDebug(12008) << "Wall::Wall" << endl;
+
+ // setup position and direction
+ m_dx = 0;
+ m_dy = 0;
+ switch ( m_dir )
+ {
+ case Up: m_dy = -1; break;
+ case Down: m_dy = 1; break;
+ case Left: m_dx = -1; break;
+ case Right: m_dx = 1; break;
+ }
+
+ m_x = m_startX;
+ m_y = m_startY;
+
+ m_field->setTile( m_x, m_y, m_tile );
+}
+
+void Wall::finish()
+{
+ m_active = false;
+}
+
+bool Wall::isFree( int x, int y )
+{
+ if ( m_field->tile(x, y)==TILE_FREE )
+ {
+ // check whether there is a ball at the moment
+ QCanvasItemList cols = m_field->collisions( QRect(x*TILE_SIZE, y*TILE_SIZE,
+ TILE_SIZE, TILE_SIZE) );
+ if ( cols.count()==0 )
+ return true;
+ }
+
+ return false;
+}
+
+void Wall::update()
+{
+}
+
+void Wall::advance()
+{
+ update();
+
+ // move wall
+ if ( m_active )
+ {
+ m_delay--;
+ if ( m_delay<=0 )
+ {
+ m_delay = MS2TICKS(WALL_DELAY);
+
+ // set previous tile
+ m_field->setTile( m_x, m_y, m_tile );
+
+ // check whether next place is still free
+ if ( isFree(m_x+m_dx, m_y+m_dy) )
+ {
+ // move ball
+ m_x += m_dx;
+ m_y += m_dy;
+
+ // set tile
+ m_field->setTile( m_x, m_y, TILE_WALLEND );
+ } else
+ {
+ finish();
+ emit finished( this, m_field->tile( m_x+m_dx, m_y+m_dy ) );
+ }
+ }
+ }
+}
+
+void Wall::fill( bool black )
+{
+ if ( m_dx )
+ {
+ for ( int x=m_startX ; x!=m_x; x+=m_dx )
+ if ( m_field->tile(x, m_startY)==m_tile )
+ m_field->setGameTile( x, m_startY, black );
+
+ m_field->setGameTile( m_x, m_startY, black );
+ } else
+ {
+ for ( int y=m_startY ; y!=m_y; y+=m_dy )
+ if ( m_field->tile(m_startX, y)==m_tile )
+ m_field->setGameTile( m_startX, y, black );
+
+ m_field->setGameTile( m_startX, m_y, black );
+ }
+}
+
+/*************************************************************************/
+
+JezzField::JezzField( const QPixmap &tiles, const QPixmap &background, QObject* parent, const char* name )
+ : QCanvas( parent, name ), m_tiles( tiles )
+{
+ setPixmaps( tiles, background );
+}
+
+void JezzField::setGameTile( int x, int y, bool black )
+{
+ if ( m_background )
+ setTile( x, y, black ? ((x-1)+(y-1)*(FIELD_WIDTH-2)) : TILE_FREE );
+ else
+ setTile( x, y, black ? TILE_BORDER : TILE_FREE );
+}
+
+void JezzField::setBackground( const QPixmap &background )
+{
+ // copy current field into buffer
+ int backup[FIELD_WIDTH][FIELD_HEIGHT];
+ for ( int y=0; y<FIELD_HEIGHT; y++ )
+ for ( int x=0; x<FIELD_WIDTH; x++ )
+ backup[x][y] = tile( x, y );
+
+ setPixmaps( m_tiles, background );
+
+ // restore tiles
+ for ( int x=0; x<FIELD_WIDTH; x++ )
+ setTile( x, 0, TILE_BORDER );
+ for ( int y=1; y<FIELD_HEIGHT-1; y++ ) {
+
+ setTile( 0, y, TILE_BORDER );
+
+ for ( int x=1; x<FIELD_WIDTH-1; x++ ) {
+ int tile = backup[x][y];
+
+ if ( m_background ) {
+ if ( tile==TILE_BORDER || tile<TILE_FIRST )
+ tile = (x-1)+(y-1)*(FIELD_WIDTH-2);
+ } else {
+ if ( tile<TILE_FIRST )
+ tile = TILE_BORDER;
+ }
+
+ setTile( x, y, tile );
+ }
+
+ setTile( FIELD_WIDTH-1, y, TILE_BORDER );
+ }
+ for ( int x=0; x<FIELD_WIDTH; x++ )
+ setTile( x, FIELD_HEIGHT-1, TILE_BORDER );
+}
+
+void JezzField::setPixmaps( const QPixmap &tiles, const QPixmap &background )
+{
+ // create new tiles
+ QPixmap allTiles( TILE_SIZE*(FIELD_WIDTH-2), TILE_SIZE*(FIELD_HEIGHT-1) );
+
+ if ( background.width()==0 || background.height()==0 ) {
+ m_background = false;
+ } else {
+ // handle background
+ m_background = true;
+ QImage img = background.convertToImage();
+ QPixmap scalledBackground( img.smoothScale( TILE_SIZE*(FIELD_WIDTH-2),
+ TILE_SIZE*(FIELD_HEIGHT-2) ) );
+ bitBlt( &allTiles, 0, 0, &scalledBackground, 0, 0, scalledBackground.width(), scalledBackground.height() );
+ }
+
+ // handle default tiles
+ bitBlt( &allTiles, 0, TILE_SIZE*(FIELD_HEIGHT-2),
+ &tiles, 0, 0, tiles.width(), tiles.height() );
+
+ // load tiles into canvas
+ setTiles( allTiles, FIELD_WIDTH, FIELD_HEIGHT, TILE_SIZE, TILE_SIZE );
+}
+
+
+/*************************************************************************/
+
+JezzView::JezzView(QCanvas* viewing, QWidget* parent, const char* name, WFlags f)
+ : QCanvasView( viewing, parent, name, f ), m_vertical( false )
+{
+ setResizePolicy( AutoOne );
+ setHScrollBarMode( AlwaysOff );
+ setVScrollBarMode( AlwaysOff );
+
+ setCursor( sizeHorCursor );
+}
+
+void JezzView::viewportMouseReleaseEvent( QMouseEvent *ev )
+{
+ if ( ev->button() & RightButton )
+ {
+ m_vertical = !m_vertical;
+ if ( m_vertical ) setCursor( sizeVerCursor ); else setCursor( sizeHorCursor );
+ }
+
+ if ( ev->button() & LeftButton )
+ {
+ emit buildWall( ev->x()/TILE_SIZE, ev->y()/TILE_SIZE, m_vertical );
+ }
+}
+
+/*************************************************************************/
+
+JezzGame::JezzGame( const QPixmap &background, int ballNum, QWidget *parent, const char *name )
+ : QWidget( parent, name ), m_wall1( 0 ), m_wall2( 0 ),
+ m_text( 0 ), m_running( false ), m_percent( 0 ), m_pictured( false )
+{
+ QString path = kapp->dirs()->findResourceDir( "data", "kbounce/pics/ball0000.png" ) + "kbounce/pics/";
+
+ // load gfx
+ m_ballPixmaps = new QCanvasPixmapArray( path + "ball%1.png", 25 );
+ for ( unsigned n=0; n<m_ballPixmaps->count(); n++ )
+ m_ballPixmaps->image(n)->setOffset( 0, 0 );
+ QPixmap tiles( path + "tiles.png" );
+
+ // setup arts
+#if HAVE_ARTS
+ m_artsServer = new SimpleSoundServer;
+ *m_artsServer = Arts::Reference("global:Arts_SimpleSoundServer");
+ if ( m_artsServer->isNull() )
+ kdDebug(12008) << "Can't connect to aRts sound server" << endl;
+#endif
+ m_soundPath = kapp->dirs()->findResourceDir( "data", "kbounce/sounds/death.au" ) +
+ "kbounce/sounds/";
+
+ // create field
+ m_field = new JezzField( tiles, background, this, "m_field" );
+ m_field->resize( TILE_SIZE*FIELD_WIDTH, TILE_SIZE*FIELD_HEIGHT );
+
+ for ( int x=0; x<FIELD_WIDTH; x++ )
+ m_field->setTile( x, 0, TILE_BORDER );
+ for ( int y=1; y<FIELD_HEIGHT-1; y++ )
+ {
+ m_field->setTile( 0, y, TILE_BORDER );
+ for ( int x=1; x<FIELD_WIDTH-1; x++ )
+ m_field->setTile( x, y, TILE_FREE );
+ m_field->setTile( FIELD_WIDTH-1, y, TILE_BORDER );
+ }
+ for ( int x=0; x<FIELD_WIDTH; x++ )
+ m_field->setTile( x, FIELD_HEIGHT-1, TILE_BORDER );
+
+ connect( m_field, SIGNAL(ballCollision(Ball *, int, int, int)), this, SLOT(ballCollision(Ball *, int, int, int)) );
+
+ // create view
+ m_view = new JezzView( m_field, this, "m_view" );
+ m_view->move( 0, 0 );
+ m_view->adjustSize();
+ connect( m_view, SIGNAL(buildWall(int, int, bool)), this, SLOT(buildWall(int, int, bool)) );
+
+ // create balls
+ for ( int n=0; n<ballNum; n++ )
+ {
+ Ball *ball = new Ball( m_ballPixmaps, m_field );
+ m_balls.append( ball );
+ ball->setVelocity( ((kapp->random() & 1)*2-1)*2, ((kapp->random() & 1)*2-1)*2 );
+ ball->setFrame( kapp->random() % 25 );
+ ball->move( 4*TILE_SIZE + kapp->random() % ( (FIELD_WIDTH-8)*TILE_SIZE ),
+ 4*TILE_SIZE + kapp->random() % ( (FIELD_HEIGHT-8)*TILE_SIZE ) );
+ ball->show();
+ }
+
+ // create text label
+ m_text = new QCanvasText( m_field );
+
+ // create game clock
+ m_clock = new QTimer( this );
+ connect( m_clock, SIGNAL(timeout()), this, SLOT(tick()) );
+ m_clock->start( GAME_DELAY );
+
+ // setup geometry
+ setFixedSize( m_view->size() );
+}
+
+JezzGame::~JezzGame()
+{
+ m_balls.clear();
+ delete m_view;
+ delete m_field;
+ delete m_ballPixmaps;
+#if HAVE_ARTS
+ delete m_artsServer;
+#endif
+}
+
+
+void JezzGame::display( const QString &text, int size )
+{
+ qDebug("This function \"display\" shouldn't be called!!!");
+ if ( !text.isEmpty() )
+ {
+ //kdDebug(12008) << "text = " << text << endl;
+
+ QFont font = KGlobalSettings::generalFont();
+ font.setBold(true);
+ font.setPointSize(size);
+ m_text->setFont( font );
+ m_text->setText( text );
+
+ QRect size = m_text->boundingRect();
+ m_text->move( ( FIELD_WIDTH*TILE_SIZE - size.width() ) / 2,
+ ( FIELD_HEIGHT*TILE_SIZE - size.height() ) / 2 );
+
+ m_text->show();
+ } else
+ {
+ m_text->hide();
+ }
+}
+
+void JezzGame::playSound( const QString &name )
+{
+#if HAVE_ARTS
+ if( !m_artsServer->isNull() && m_sound)
+ {
+ QString path = m_soundPath + name;
+ m_artsServer->play( path.latin1() );
+ }
+#else
+ return;
+#endif
+}
+
+void JezzGame::setBackground( const QPixmap &background )
+{
+ m_field->setBackground( background );
+}
+
+void JezzGame::setSound( bool sound )
+{
+ m_sound = sound;
+}
+
+void JezzGame::start()
+{
+ m_running = true;
+}
+
+void JezzGame::stop()
+{
+ m_running = false;
+}
+
+
+void JezzGame::makeBlack()
+{
+ // copy current field into buffer
+ for ( int y=0; y<FIELD_HEIGHT; y++ )
+ for ( int x=0; x<FIELD_WIDTH; x++ )
+ m_buf[x][y] = m_field->tile( x, y );
+
+ // fill areas that contains a ball
+ for ( Ball *ball=m_balls.first(); ball!=0; ball=m_balls.next() )
+ fill( ball->x()/TILE_SIZE, ball->y()/TILE_SIZE );
+
+ // areas still free can be blacked now
+ for ( int y=0; y<FIELD_HEIGHT; y++ )
+ for ( int x=0; x<FIELD_WIDTH; x++ )
+ {
+ if ( m_buf[x][y]==TILE_FREE )
+ m_field->setGameTile( x, y, true );
+ }
+
+ m_field->update();
+ m_view->repaint();
+
+ // count percent value of occupied area
+ int p = percent();
+ if ( p!=m_percent )
+ {
+ m_percent = p;
+ emit newPercent( m_percent );
+ }
+}
+
+int JezzGame::percent()
+{
+ int notFree = 0;
+ for ( int y=1; y<FIELD_HEIGHT-1; y++ )
+ for ( int x=1; x<FIELD_WIDTH-1; x++ )
+ {
+ if ( m_field->tile(x,y)!=TILE_FREE )
+ notFree++;
+ }
+
+ return 100 * notFree / ( (FIELD_WIDTH-2) * (FIELD_HEIGHT-2) );
+}
+
+void JezzGame::fill( int x, int y )
+{
+ if ( m_buf[x][y]!=TILE_FREE) return;
+
+ // go left
+ int _x=x;
+ for ( ; m_buf[_x][y]==TILE_FREE; _x-- )
+ m_buf[_x][y] = TILE_BORDER;
+ int stopx = _x;
+
+ // fill above
+ for ( _x=x; _x>stopx; _x-- )
+ if ( m_buf[_x][y-1]==TILE_FREE ) fill( _x, y-1 );
+
+ // fill below
+ for ( _x=x; _x>stopx; _x-- )
+ if ( m_buf[_x][y+1]==TILE_FREE ) fill( _x, y+1 );
+
+ // go right
+ for ( _x=x+1; m_buf[_x][y]==TILE_FREE; _x++ )
+ m_buf[_x][y] = TILE_BORDER;
+ stopx = _x;
+
+ // fill above
+ for ( _x=x+1; _x<stopx; _x++ )
+ if ( m_buf[_x][y-1]==TILE_FREE ) fill( _x, y-1 );
+
+ // fill below;
+ for ( _x=x+1; _x<stopx; _x++ )
+ if ( m_buf[_x][y+1]==TILE_FREE ) fill( _x, y+1 );
+}
+
+void JezzGame::ballCollision( Ball */*ball*/, int /*x*/, int /*y*/, int tile )
+{
+ if ( tile!=TILE_BORDER && tile>TILE_FREE && tile!=TILE_WALLEND )
+ {
+ kdDebug(12008) << "Collision" << endl;
+
+ // play explosion sound
+ playSound( "death.au" );
+
+ // stop walls
+ if ( (tile==TILE_WALLUP || tile==TILE_WALLLEFT) && m_wall1 )
+ {
+ kdDebug(12008) << "up or left" << endl;
+ m_wall1->finish();
+ m_wall1->fill( false );
+ delete m_wall1;
+ m_wall1 = 0;
+ }
+
+ if ( (tile==TILE_WALLDOWN || tile==TILE_WALLRIGHT) && m_wall2 )
+ {
+ kdDebug(12008) << "down or right" << endl;
+ m_wall2->finish();
+ m_wall2->fill( false );
+ delete m_wall2;
+ m_wall2 = 0;
+ }
+
+ // update view
+ m_field->update();
+ m_view->repaint();
+
+ // send death msg
+ emit died();
+ }
+}
+
+void JezzGame::buildWall( int x, int y, bool vertical )
+{
+ if ( !m_running ) return;
+
+ kdDebug(12008) << "JezzGame::buildWall( x=" << x << " y=" << y << " vertical=" << vertical << " )" << endl;
+ if ( m_field->tile(x, y)==TILE_FREE )
+ {
+ playSound( "wallstart.au" );
+
+ // check whether there is a ball at the moment
+ QCanvasItemList cols = m_field->collisions( QRect(x*TILE_SIZE, y*TILE_SIZE, TILE_SIZE, TILE_SIZE) );
+ if ( cols.count()>0 )
+ {
+ kdDebug(12008) << "Direct collision" << endl;
+ emit ballCollision( (Ball*)cols.first(), x, y, TILE_WALLUP );
+ return;
+ }
+
+ // start walls
+ if ( !m_wall1 )
+ {
+ m_wall1 = new Wall( m_field, x, y,
+ vertical? Wall::Up : Wall::Left,
+ vertical? TILE_WALLUP : TILE_WALLLEFT,
+ this, "m_wall1" );
+ connect( m_wall1, SIGNAL(finished(Wall *, int)),
+ this, SLOT(wallFinished(Wall *, int)) ); }
+
+ if ( !m_wall2 )
+ {
+ m_wall2 = new Wall( m_field, x, y,
+ vertical? Wall::Down: Wall::Right,
+ vertical? TILE_WALLDOWN : TILE_WALLRIGHT,
+ this, "m_wall2" );
+ connect( m_wall2, SIGNAL(finished(Wall *, int)),
+ this, SLOT(wallFinished(Wall *, int)) );
+ }
+ }
+}
+
+void JezzGame::wallFinished( Wall *wall, int tile )
+{
+ //kdDebug(12008) << "wallFinished" << endl;
+ playSound( "wallend.au" );
+
+ if ( tile==TILE_WALLEND )
+ {
+ if ( m_wall1 )
+ {
+ m_wall1->fill( false );
+ delete m_wall1;
+ m_wall1 = 0;
+ }
+
+ if ( m_wall2 )
+ {
+ m_wall2->fill( false );
+ delete m_wall2;
+ m_wall2 = 0;
+ }
+ } else
+ {
+ if ( m_wall1==wall && m_wall1 )
+ {
+ m_wall1->fill( true );
+ delete m_wall1;
+ m_wall1 = 0;
+ }
+
+ if ( m_wall2==wall && m_wall2 )
+ {
+ m_wall2->fill( true );
+ delete m_wall2;
+ m_wall2 = 0;
+ }
+ }
+
+ m_field->update();
+ m_view->repaint();
+
+ makeBlack();
+}
+
+void JezzGame::tick()
+{
+ if ( m_running )
+ {
+ if ( m_field ) m_field->advance();
+ if ( m_wall1 ) m_wall1->advance();
+ if ( m_wall2 ) m_wall2->advance();
+ } else
+ {
+ for ( Ball *ball=m_balls.first(); ball!=0; ball=m_balls.next() )
+ ball->update();
+
+ if ( m_field ) m_field->update();
+ if ( m_wall1 ) m_wall1->update();
+ if ( m_wall2 ) m_wall2->update();
+ }
+
+ //kapp->syncX();
+}
+
+#include "game.moc"
diff --git a/kbounce/game.h b/kbounce/game.h
new file mode 100644
index 00000000..eb5208cd
--- /dev/null
+++ b/kbounce/game.h
@@ -0,0 +1,183 @@
+/*
+ * Copyright (C) 2000 Stefan Schimanski <[email protected]>
+ *
+ * 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 GAME_H_INCLUDED
+#define GAME_H_INCLUDED
+
+#include <qwidget.h>
+#include <qcanvas.h>
+#include <qmemarray.h>
+
+#if HAVE_ARTS
+#include <arts/soundserver.h>
+
+using namespace Arts;
+#endif
+
+class QTimer;
+class JezzField;
+
+#define FIELD_WIDTH 32
+#define FIELD_HEIGHT 20
+
+class Ball : public QCanvasSprite
+{
+ public:
+ Ball(QCanvasPixmapArray* array, QCanvas* canvas);
+
+ void update();
+ void advance(int stage);
+ bool collide( double dx=0, double dy=0 );
+
+ protected:
+ int m_animDelay;
+ int m_soundDelay;
+};
+
+
+class Wall : public QObject
+{
+ Q_OBJECT
+public:
+ enum Direction { Up, Down, Left, Right };
+
+ Wall( JezzField *field, int x, int y, Direction dir, int tile,
+ QObject *parent=0, const char *name=0 );
+
+ void finish();
+ void fill( bool black );
+
+signals:
+ void finished( Wall *wall, int tile );
+
+public slots:
+ void advance();
+ void update();
+
+private:
+ bool isFree( int x, int y );
+
+ Direction m_dir;
+ JezzField *m_field;
+ int m_dx, m_dy;
+ int m_x, m_y;
+ int m_startX, m_startY;
+ int m_tile;
+ int m_delay;
+ bool m_active;
+};
+
+
+class JezzField : public QCanvas
+{
+ Q_OBJECT
+public:
+ JezzField( const QPixmap &tiles, const QPixmap &background, QObject* parent = 0, const char* name = 0 );
+
+ void setGameTile( int x, int y, bool black );
+ void setBackground( const QPixmap &background );
+
+signals:
+ void ballCollision( Ball *ball, int x, int y, int tile );
+
+private:
+ friend class Ball;
+ bool m_background;
+ QPixmap m_tiles;
+ QMemArray<QPixmap> m_backTiles;
+
+ void setPixmaps( const QPixmap &tiles, const QPixmap &background );
+ void emitBallCollisiton( Ball *ball, int x, int y, int tile )
+ { emit ballCollision( ball, x, y, tile ); }
+
+};
+
+
+class JezzView : public QCanvasView
+{
+ Q_OBJECT
+public:
+ JezzView(QCanvas* viewing=0, QWidget* parent=0, const char* name=0, WFlags f=0);
+
+signals:
+ void buildWall( int x, int y, bool vertical );
+
+protected:
+ void viewportMouseReleaseEvent( QMouseEvent * );
+
+private:
+ bool m_vertical;
+};
+
+
+class JezzGame : public QWidget
+{
+ Q_OBJECT
+
+public:
+ JezzGame( const QPixmap &background, int ballNum, QWidget *parent=0, const char *name=0 );
+ ~JezzGame();
+
+ int percent();
+ static void playSound( const QString &name );
+ void display( const QString &text, int size=20 );
+ void setBackground( const QPixmap &background );
+
+signals:
+ void died();
+ void newPercent( int percent );
+
+public slots:
+ void start();
+ void stop();
+ void setSound( bool sound );
+
+protected slots:
+ void tick();
+ void buildWall( int x, int y, bool vertical );
+ void wallFinished( Wall *wall, int tile );
+ void ballCollision( Ball *ball, int x, int y, int tile );
+
+protected:
+ void makeBlack();
+ void fill( int x, int y );
+ void fillLeft( int x, int y );
+ int m_buf[FIELD_WIDTH][FIELD_HEIGHT];
+
+ JezzField *m_field;
+ JezzView *m_view;
+
+ Wall *m_wall1, *m_wall2;
+
+ QPtrList<Ball> m_balls;
+ QCanvasPixmapArray *m_ballPixmaps;
+ QCanvasText *m_text;
+
+ QTimer *m_clock;
+ bool m_running;
+ int m_percent;
+ bool m_pictured;
+
+#if HAVE_ARTS
+ static SimpleSoundServer *m_artsServer;
+#endif
+ static QString m_soundPath;
+ static bool m_sound;
+};
+
+#endif
diff --git a/kbounce/highscores.cpp b/kbounce/highscores.cpp
new file mode 100644
index 00000000..fec2d1e6
--- /dev/null
+++ b/kbounce/highscores.cpp
@@ -0,0 +1,18 @@
+#include "highscores.h"
+
+#include <klocale.h>
+
+using namespace KExtHighscore;
+
+ExtManager::ExtManager()
+{
+ Item *item = new Item((uint)0, i18n("Level"), Qt::AlignRight);
+ addScoreItem("level", item);
+}
+
+bool ExtManager::isStrictlyLess(const Score &s1, const Score &s2) const
+{
+ if ( s1.score()==s2.score() )
+ return s1.data("level").toUInt()>s2.data("level").toUInt();
+ return Manager::isStrictlyLess(s1, s2);
+}
diff --git a/kbounce/highscores.h b/kbounce/highscores.h
new file mode 100644
index 00000000..59372ed6
--- /dev/null
+++ b/kbounce/highscores.h
@@ -0,0 +1,17 @@
+#ifndef HIGHSCORES_H
+#define HIGHSCORES_H
+
+#include <kexthighscore.h>
+
+using namespace KExtHighscore;
+
+class ExtManager : public Manager
+{
+ public:
+ ExtManager();
+
+ private:
+ bool isStrictlyLess(const Score &s1, const Score &s2) const;
+};
+
+#endif
diff --git a/kbounce/kbounce.cpp b/kbounce/kbounce.cpp
new file mode 100644
index 00000000..eab691b8
--- /dev/null
+++ b/kbounce/kbounce.cpp
@@ -0,0 +1,491 @@
+/*
+ * Copyright (C) 2000 Stefan Schimanski <[email protected]>
+ *
+ * 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 <qlayout.h>
+#include <klocale.h>
+#include <kapplication.h>
+#include <kaction.h>
+#include <kstdgameaction.h>
+#include <qtimer.h>
+#include <qlcdnumber.h>
+#include <kmessagebox.h>
+#include <kdebug.h>
+#include <kfiledialog.h>
+#include <kstatusbar.h>
+#include <khighscore.h>
+#include <kexthighscore.h>
+
+#include "kbounce.h"
+#include "game.h"
+
+KJezzball::KJezzball()
+ : m_gameWidget( 0 )
+{
+ // setup variables
+ m_game.level = 1;
+ m_game.score = 0;
+ m_state = Idle;
+
+ KConfig *config = kapp->config();
+ m_backgroundDir = config->readPathEntry( "BackgroundDir" );
+ m_showBackground = config->readBoolEntry( "ShowBackground", false );
+
+ statusBar();
+ initXMLUI();
+
+ m_soundAction -> setChecked((config->readBoolEntry( "PlaySounds", true )));
+
+ // create widgets
+ m_view = new QWidget( this, "m_view" );
+ setCentralWidget( m_view );
+
+ m_layout = new QGridLayout( m_view, 1, 3 );
+ m_layout->setColStretch( 2, 1 );
+
+ QVBoxLayout *infoLayout = new QVBoxLayout;
+ m_layout->addLayout( infoLayout, 0, 1 );
+
+ QLabel *label = new QLabel( i18n("Level:"), m_view );
+ infoLayout->addWidget( label );
+ m_levelLCD = new QLCDNumber( 5, m_view );
+ infoLayout->addWidget( m_levelLCD );
+
+ label = new QLabel( i18n("Score:"), m_view );
+ infoLayout->addWidget( label );
+ m_scoreLCD = new QLCDNumber( 5, m_view );
+ infoLayout->addWidget( m_scoreLCD );
+
+ infoLayout->addSpacing( 20 );
+
+ label = new QLabel( i18n("Filled area:"), m_view );
+ infoLayout->addWidget( label );
+ m_percentLCD = new QLCDNumber( 5, m_view );
+ infoLayout->addWidget( m_percentLCD );
+
+ label = new QLabel( i18n("Lives:"), m_view );
+ infoLayout->addWidget( label );
+ m_lifesLCD = new QLCDNumber( 5, m_view );
+ infoLayout->addWidget( m_lifesLCD );
+
+ label = new QLabel( i18n("Time:"), m_view );
+ infoLayout->addWidget( label );
+ m_timeLCD = new QLCDNumber( 5, m_view );
+ infoLayout->addWidget( m_timeLCD );
+
+ // create timers
+ m_nextLevelTimer = new QTimer( this, "m_nextLevelTimer" );
+ connect( m_nextLevelTimer, SIGNAL(timeout()), this, SLOT(switchLevel()) );
+
+ m_gameOverTimer = new QTimer( this, "m_gameOverTimer" );
+ connect( m_gameOverTimer, SIGNAL(timeout()), this, SLOT(gameOverNow()) );
+
+ m_timer = new QTimer( this, "m_timer" );
+ connect( m_timer, SIGNAL(timeout()), this, SLOT(second()) );
+
+ // create demo game
+ createLevel( 1 );
+ statusBar()->message( i18n("Press %1 to start a game!")
+ .arg(m_newAction->shortcut().toString()) );
+ //m_gameWidget->display( i18n("Press <Space> to start a game!") );
+
+ setFocusPolicy(QWidget::StrongFocus);
+ setFocus();
+ setupGUI();
+}
+
+KJezzball::~KJezzball()
+{
+ KConfig *config = kapp->config();
+ config->writeEntry( "PlaySounds", m_soundAction->isChecked() );
+}
+
+/**
+ * create the action events create the gui.
+ */
+void KJezzball::initXMLUI()
+{
+ m_newAction = KStdGameAction::gameNew( this, SLOT(newGame()), actionCollection() );
+ // AB: originally KBounce/KJezzball used Space for new game - but Ctrl+N is
+ // default. We solve this by providing space as an alternative key
+ KShortcut s = m_newAction->shortcut();
+ s.append(KKeySequence(QKeySequence(Key_Space)));
+ m_newAction->setShortcut(s);
+
+ KStdGameAction::quit(this, SLOT(close()), actionCollection() );
+ KStdGameAction::highscores(this, SLOT(showHighscore()), actionCollection() );
+ m_pauseButton = KStdGameAction::pause(this, SLOT(pauseGame()), actionCollection());
+ KStdGameAction::end(this, SLOT(closeGame()), actionCollection());
+ KStdGameAction::configureHighscores(this, SLOT(configureHighscores()),actionCollection());
+
+ new KAction( i18n("&Select Background Folder..."), 0, this, SLOT(selectBackground()),
+ actionCollection(), "background_select" );
+ m_backgroundShowAction =
+ new KToggleAction( i18n("Show &Backgrounds"), 0, this, SLOT(showBackground()),
+ actionCollection(), "background_show" );
+ m_backgroundShowAction->setCheckedState(i18n("Hide &Backgrounds"));
+ m_backgroundShowAction->setEnabled( !m_backgroundDir.isEmpty() );
+ m_backgroundShowAction->setChecked( m_showBackground );
+
+ m_soundAction = new KToggleAction( i18n("&Play Sounds"), 0, 0, 0, actionCollection(), "toggle_sound");
+}
+
+void KJezzball::newGame()
+{
+ // Check for running game
+ closeGame();
+ if ( m_state==Idle )
+ {
+ // untoggles the pause button in case it was toggled
+ m_pauseButton->setChecked(false);
+
+ // update displays
+ m_game.level = 1;
+ m_game.score = 0;
+
+ m_levelLCD->display( m_game.level );
+ m_scoreLCD->display( m_game.score );
+
+ statusBar()->clear();
+
+ // start new game
+ m_state = Running;
+
+ createLevel( m_game.level );
+ startLevel();
+ }
+}
+
+void KJezzball::closeGame()
+{
+ if ( m_state!=Idle )
+ {
+ int old_state = m_state;
+ if (old_state == Running)
+ pauseGame();
+ int ret = KMessageBox::questionYesNo( this, i18n("Do you really want to close the running game?"), QString::null, KStdGuiItem::close(), KStdGuiItem::cancel() );
+ if ( ret==KMessageBox::Yes )
+ {
+ stopLevel();
+ m_state = Idle;
+ highscore();
+ }
+ else if (old_state == Running)
+ {
+ pauseGame(); // Unpause
+ }
+ }
+}
+
+void KJezzball::pauseGame()
+{
+ switch ( m_state )
+ {
+ case Running:
+ m_state = Paused;
+ statusBar()->message(i18n("Game paused.") );
+ //m_gameWidget->display( i18n("Game paused. Press P to continue!") );
+ stopLevel();
+ break;
+
+ case Paused:
+ case Suspend:
+ m_state = Running;
+ statusBar()->clear();
+ //m_gameWidget->display( QString::null );
+ startLevel();
+ break;
+
+ case Idle:
+ break;
+ }
+}
+
+void KJezzball::gameOver()
+{
+ stopLevel();
+ m_gameOverTimer->start( 100, TRUE );
+}
+
+
+void KJezzball::gameOverNow()
+{
+ m_state = Idle;
+
+ QString score;
+ score.setNum( m_game.score );
+ KMessageBox::information( this, i18n("Game Over! Score: %1").arg(score) );
+ statusBar()->message( i18n("Game over. Press <Space> for a new game") );
+ //m_gameWidget->display( i18n("Game over. Press <Space> for a new game!") );
+ highscore();
+}
+
+/**
+ * Bring up the standard kde high score configure dialog.
+ */
+void KJezzball::configureHighscores()
+{
+ KExtHighscore::configure(this);
+}
+
+/**
+ * Bring up the standard kde high score dialog.
+ */
+void KJezzball::showHighscore()
+{
+ KExtHighscore::show(this);
+}
+
+/**
+ * Select a background image.
+ */
+void KJezzball::selectBackground()
+{
+ QString path = KFileDialog::getExistingDirectory( m_backgroundDir, this,
+ i18n("Select Background Image Folder") );
+ if ( !path.isEmpty() && path!=m_backgroundDir ) {
+ m_backgroundDir = path;
+
+ // enable action
+ m_backgroundShowAction->setEnabled(true);
+
+ // save settings
+ KConfig *config = kapp->config();
+ config->writePathEntry( "BackgroundDir", m_backgroundDir );
+ config->sync();
+
+ // apply background setting
+ if ( m_showBackground ) {
+ if ( m_background.width()==0 )
+ m_background = getBackgroundPixmap();
+
+ m_gameWidget->setBackground( m_background );
+ }
+ else{
+ KMessageBox::information( this, i18n("You may now turn on background images."));
+ }
+ }
+}
+
+void KJezzball::showBackground()
+{
+ bool show = m_backgroundShowAction->isChecked();
+ if ( show!=m_showBackground ) {
+
+ m_showBackground = show;
+
+ // save setting
+ KConfig *config = kapp->config();
+ config->writeEntry( "ShowBackground", m_showBackground );
+ config->sync();
+
+ // update field
+ if ( m_showBackground ) {
+ if ( m_background.width()==0 )
+ m_background = getBackgroundPixmap();
+ }
+
+ m_gameWidget->setBackground( m_showBackground ? m_background : QPixmap() );
+ }
+}
+
+QPixmap KJezzball::getBackgroundPixmap()
+{
+ // list directory
+ QDir dir( m_backgroundDir, "*.png *.jpg", QDir::Name|QDir::IgnoreCase, QDir::Files );
+ if ( !dir.exists() ) {
+ kdDebug(12008) << "Directory not found" << endl;
+ return QPixmap();
+ }
+
+ if (dir.count() > 1)
+ {
+ // return random pixmap
+ int num = kapp->random() % dir.count();
+ return QPixmap( dir.absFilePath( dir[num] ) );
+ }
+ else if (dir.count()==1)
+ {
+ return QPixmap( dir.absFilePath(dir[0]) );
+ }
+ else return QPixmap();
+}
+
+void KJezzball::focusOutEvent( QFocusEvent *ev )
+{
+ if ( m_state==Running )
+ {
+ stopLevel();
+ m_state = Suspend;
+ m_pauseButton->setChecked(true);
+ statusBar()->message( i18n("Game suspended") );
+ // m_gameWidget->display( i18n("Game suspended") );
+ }
+
+ KMainWindow::focusOutEvent( ev );
+}
+
+void KJezzball::focusInEvent ( QFocusEvent *ev )
+{
+ if ( m_state==Suspend )
+ {
+ startLevel();
+ m_state = Running;
+ statusBar()->clear();
+ m_pauseButton->setChecked(false);
+ //m_gameWidget->display( QString::null );
+ }
+
+ KMainWindow::focusInEvent( ev );
+}
+
+void KJezzball::second()
+{
+ m_level.time--;
+ m_timeLCD->display( m_level.time );
+ if ( m_level.time<=0 )
+ {
+ JezzGame::playSound( "timeout.au" );
+ gameOver();
+ } else
+ if ( m_level.time<=30 )
+ JezzGame::playSound( "seconds.au" );
+}
+
+void KJezzball::died()
+{
+ kdDebug(12008) << "died" << endl;
+ m_level.lifes--;
+ m_lifesLCD->display( m_level.lifes );
+ if ( m_level.lifes==0 ) gameOver();
+}
+
+void KJezzball::newPercent( int percent )
+{
+ m_percentLCD->display( percent );
+ if ( percent>=75 )
+ {
+ m_level.score = m_level.lifes*15 + (percent-75)*2*(m_game.level+5);
+ nextLevel();
+ }
+}
+
+void KJezzball::createLevel( int level )
+{
+ // destroy old game
+ if ( m_gameWidget ) delete m_gameWidget;
+
+ // create new game widget
+ if ( m_showBackground )
+ m_background = getBackgroundPixmap();
+ else
+ m_background = QPixmap();
+
+ m_gameWidget = new JezzGame( m_background, level+1, m_view, "m_gameWidget" );
+ m_gameWidget->setSound(m_soundAction->isChecked());
+
+ m_gameWidget->show();
+ m_layout->addWidget( m_gameWidget, 0, 0 );
+ connect( m_gameWidget, SIGNAL(died()), this, SLOT(died()) );
+ connect( m_gameWidget, SIGNAL(newPercent(int)), this, SLOT(newPercent(int)) );
+ connect( m_soundAction, SIGNAL(toggled(bool)), m_gameWidget, SLOT(setSound(bool)) );
+
+ // update displays
+ m_level.lifes = level+1;
+ m_lifesLCD->display( m_level.lifes );
+ m_percentLCD->display( 0 );
+
+ m_level.time = (level+2)*30;
+ m_timeLCD->display( m_level.time );
+
+ m_level.score = 0;
+}
+
+void KJezzball::startLevel()
+{
+ if ( m_gameWidget )
+ {
+ m_timer->start( 1000 );
+ m_gameWidget->start();
+ }
+}
+
+void KJezzball::stopLevel()
+{
+ if ( m_gameWidget )
+ {
+ m_gameWidget->stop();
+ m_timer->stop();
+ }
+}
+
+void KJezzball::nextLevel()
+{
+ stopLevel();
+ m_nextLevelTimer->start( 100, TRUE );
+}
+
+void KJezzball::switchLevel()
+{
+ m_game.score += m_level.score;
+
+ // make sure the LCD provides enough digits for the score
+ // (fixes #96841)
+ int numDigits=0;
+ int temp_score = m_game.score;
+ for ( ; temp_score > 0; ++numDigits ) temp_score /= 10;
+ if ( numDigits < 5 ) numDigits = 5; // set numDigits to at least 5, otherwise it does not look well
+
+ m_scoreLCD->setNumDigits( numDigits );
+ m_scoreLCD->display( m_game.score );
+
+ QString score;
+ score.setNum( m_level.score );
+
+ QString level;
+ level.setNum( m_game.level );
+
+QString foo = QString(
+i18n("You have successfully cleared more than 75% of the board.\n") +
+i18n("%1 points: 15 points per remaining life\n").arg(m_level.lifes*15) +
+i18n("%1 points: Bonus\n").arg((m_gameWidget->percent()-75)*2*(m_game.level+5)) +
+i18n("%1 points: Total score for this level\n").arg(score) +
+i18n("On to level %1. Remember you get %2 lives this time!")).arg(m_game.level+1).arg(m_game.level+2);
+
+ KMessageBox::information( this,foo );
+
+
+ // KMessageBox::information( this, i18n("You've completed level %1 with "
+ // "a score of %2.\nGet ready for the next one!").arg(level).arg(score));
+
+ m_game.level++;
+ m_levelLCD->display( m_game.level );
+
+ createLevel( m_game.level );
+ startLevel();
+}
+
+
+void KJezzball::highscore()
+{
+ KExtHighscore::Score score(KExtHighscore::Won);
+ score.setScore(m_game.score);
+ score.setData("level", m_game.level);
+ KExtHighscore::submitScore(score, this);
+}
+
+#include "kbounce.moc"
diff --git a/kbounce/kbounce.desktop b/kbounce/kbounce.desktop
new file mode 100644
index 00000000..0f629644
--- /dev/null
+++ b/kbounce/kbounce.desktop
@@ -0,0 +1,67 @@
+[Desktop Entry]
+Name=KBounce
+Name[af]=K-hop
+Name[ar]=لعبة الإرتداد (KBounce)
+Name[be]=Несуцішныя шарыкі
+Name[bn]=কে-বাউন্স
+Name[hi]=के-बाउंस
+Name[ne]=केडीई उफ्रिने
+Name[pa]=ਕੇ-ਬਾਊਂਸ
+Name[sv]=Kbounce
+Name[ta]=கேபவுன்ஸ்
+Name[tg]=KТӯби ҷаҳанда
+Name[tr]=Zıplayan toplar
+Name[zh_TW]=KBounce 彈力球
+
+Type=Application
+Exec=kbounce %i %m -caption "%c"
+DocPath=kbounce/index.html
+Icon=kbounce
+
+GenericName=Bounce Ball Game
+GenericName[be]=Гульня ў шарыкі
+GenericName[bg]=Подскачащи топки
+GenericName[bn]=বাউন্স বল খেলা
+GenericName[bs]=Igra odbijajuće loptice
+GenericName[ca]=Joc de boles rebotadores
+GenericName[cs]=Hra s poskakujícími míčky
+GenericName[cy]=Gêm Bêl Sboncio
+GenericName[da]=Spil med springende bolde
+GenericName[de]=Ballspiel
+GenericName[el]=Παιχνίδι αναπηδούμενης μπάλας
+GenericName[eo]=Saltpilka ludo
+GenericName[es]=Juego de pelotas que rebotan
+GenericName[et]=Põrkava palli mäng
+GenericName[eu]=Pilota errebotatzeko jokoa
+GenericName[fa]=بازی Bounce Ball
+GenericName[fi]=Lautapeli
+GenericName[fr]=Jeu de balles rebondissantes
+GenericName[he]=משחק כדורים קופצים
+GenericName[hr]=Igra s poskakujućom loptom
+GenericName[hu]=Labdás
+GenericName[is]=Skoppandi boltaleikur
+GenericName[it]=Gioco del BounceBall
+GenericName[ja]=跳ねるボールのゲーム
+GenericName[km]=ល្បែង​បាល់​លោត
+GenericName[lt]=Bounce Ball žaidimas
+GenericName[lv]=Lēkājošo bumbu spēle
+GenericName[mk]=Игра со топки што скокаат
+GenericName[nb]=Sprettballspill
+GenericName[nds]=Ballspeel
+GenericName[ne]=बल हिर्काउने खेल
+GenericName[nl]=Bal-stuiter spel
+GenericName[nn]=Sprettballspel
+GenericName[pl]=Piłki
+GenericName[pt]=Jogo de Bola Saltitante
+GenericName[pt_BR]=Jogo de bolas que pulam
+GenericName[ru]=Неуёмные шарики
+GenericName[sk]=Bounce loptová hra
+GenericName[sl]=Igra odbijajoče žoge
+GenericName[sr]=Игра одбијања лопте
+GenericName[sr@Latn]=Igra odbijanja lopte
+GenericName[sv]=Studsande boll spel
+GenericName[ta]=திரும்பும் பந்து விளையாட்டு
+GenericName[uk]=Кульки-стрибунці
+GenericName[zh_TW]=彈跳球遊戲
+X-DCOP-ServiceType=Multi
+Categories=Qt;KDE;Game;ArcadeGame;
diff --git a/kbounce/kbounce.h b/kbounce/kbounce.h
new file mode 100644
index 00000000..a4e0a95f
--- /dev/null
+++ b/kbounce/kbounce.h
@@ -0,0 +1,104 @@
+/*
+ * Copyright (C) 2000 Stefan Schimanski <[email protected]>
+ *
+ * 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 KBOUNCE_H
+#define KBOUNCE_H
+
+#include <kmainwindow.h>
+
+class JezzGame;
+class QLCDNumber;
+class QGridLayout;
+class KToggleAction;
+class KAction;
+
+class KJezzball : public KMainWindow
+{
+ Q_OBJECT
+
+public:
+ KJezzball();
+ ~KJezzball();
+
+public slots:
+ void newGame();
+ void pauseGame();
+ void closeGame();
+ void showHighscore();
+ void selectBackground();
+ void showBackground();
+
+protected slots:
+ void died();
+ void newPercent( int percent );
+ void second();
+ void switchLevel();
+ void gameOverNow();
+ void configureHighscores();
+
+protected:
+ void createLevel( int level );
+ void startLevel();
+ void stopLevel();
+ void nextLevel();
+ void highscore();
+ void gameOver();
+ void initXMLUI();
+
+ void focusOutEvent( QFocusEvent * );
+ void focusInEvent ( QFocusEvent * );
+
+ QPixmap getBackgroundPixmap();
+
+ JezzGame *m_gameWidget;
+ QWidget *m_view;
+ QGridLayout *m_layout;
+ QLCDNumber *m_levelLCD;
+ QLCDNumber *m_lifesLCD;
+ QLCDNumber *m_scoreLCD;
+ QLCDNumber *m_percentLCD;
+ QLCDNumber *m_timeLCD;
+ KToggleAction *m_pauseButton, *m_backgroundShowAction, *m_soundAction;
+ KAction *m_newAction;
+
+ QTimer *m_timer;
+ QTimer *m_nextLevelTimer;
+ QTimer *m_gameOverTimer;
+
+ QString m_backgroundDir;
+ bool m_showBackground;
+ QPixmap m_background;
+
+ enum { Idle, Running, Paused, Suspend } m_state;
+
+ struct
+ {
+ int lifes;
+ int time;
+ int score;
+ } m_level;
+
+ struct
+ {
+ int level;
+ int score;
+ } m_game;
+};
+
+#endif // KBOUNCE_h
+
diff --git a/kbounce/kbounceui.rc b/kbounce/kbounceui.rc
new file mode 100644
index 00000000..058ab702
--- /dev/null
+++ b/kbounce/kbounceui.rc
@@ -0,0 +1,17 @@
+<!DOCTYPE kpartgui SYSTEM "kpartgui.dtd">
+<kpartgui name="kbounce" version="6">
+
+<MenuBar>
+ <Menu name="settings">
+ <Action name="background_select"/>
+ <Action name="background_show"/>
+ <Action name="toggle_sound" append="save_merge"/>
+ </Menu>
+</MenuBar>
+
+<ToolBar noMerge="1" name="mainToolBar"><text>Main Toolbar</text>
+ <Action name="game_new"/>
+ <Action name="game_pause"/>
+</ToolBar>
+
+</kpartgui>
diff --git a/kbounce/main.cpp b/kbounce/main.cpp
new file mode 100644
index 00000000..390b7c62
--- /dev/null
+++ b/kbounce/main.cpp
@@ -0,0 +1,75 @@
+/*
+ * Copyright (C) 2000 Stefan Schimanski <[email protected]>
+ *
+ * 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 <kapplication.h>
+#include <kcmdlineargs.h>
+#include <kaboutdata.h>
+
+#if HAVE_ARTS
+#include <arts/dispatcher.h>
+#endif
+
+#include "kbounce.h"
+
+#include <khighscore.h>
+#include <highscores.h>
+
+using namespace std;
+
+#if HAVE_ARTS
+using namespace Arts;
+#endif
+
+static const char description[] = I18N_NOOP("KDE Bounce Ball Game");
+static const char version[] = "0.5";
+
+int main(int argc, char **argv)
+{
+ KHighscore::init("kbounce");
+
+ KAboutData aboutData( "kbounce", I18N_NOOP("KBounce"),
+ version, description, KAboutData::License_GPL,
+ "(c) 2000, Stefan Schimanski");
+
+ aboutData.addAuthor("Stefan Schimanski", I18N_NOOP("Original author"), "[email protected]");
+ aboutData.addAuthor("Sandro Sigala", I18N_NOOP("Highscore"), "[email protected]");
+ aboutData.addAuthor("Benjamin Meyer", I18N_NOOP("Contributions"), "[email protected]");
+
+ KCmdLineArgs::init( argc, argv, &aboutData );
+
+ QApplication::setColorSpec(QApplication::ManyColor);
+ KApplication a;
+ KGlobal::locale()->insertCatalogue("libkdegames");
+
+ ExtManager manager;
+
+ // setup MCOP
+#if HAVE_ARTS
+ Dispatcher dispatcher;
+#endif
+
+ if (a.isRestored())
+ RESTORE(KJezzball)
+ else {
+ KJezzball *w = new KJezzball;
+ a.setMainWidget(w);
+ w->show();
+ }
+ return a.exec();
+}
+
diff --git a/kbounce/pics/Makefile.am b/kbounce/pics/Makefile.am
new file mode 100644
index 00000000..e7ad910e
--- /dev/null
+++ b/kbounce/pics/Makefile.am
@@ -0,0 +1,34 @@
+pics_DATA = \
+ ball0000.png \
+ ball0001.png \
+ ball0002.png \
+ ball0003.png \
+ ball0004.png \
+ ball0005.png \
+ ball0006.png \
+ ball0007.png \
+ ball0008.png \
+ ball0009.png \
+ ball0010.png \
+ ball0011.png \
+ ball0012.png \
+ ball0013.png \
+ ball0014.png \
+ ball0015.png \
+ ball0016.png \
+ ball0017.png \
+ ball0018.png \
+ ball0019.png \
+ ball0020.png \
+ ball0021.png \
+ ball0022.png \
+ ball0023.png \
+ ball0024.png \
+ tiles.png
+
+picsdir = $(kde_datadir)/kbounce/pics
+
+KDE_ICON = kbounce
+
+EXTRA_DIST = $(pics_DATA)
+
diff --git a/kbounce/pics/ball0000.png b/kbounce/pics/ball0000.png
new file mode 100644
index 00000000..3afe8f0e
--- /dev/null
+++ b/kbounce/pics/ball0000.png
Binary files differ
diff --git a/kbounce/pics/ball0001.png b/kbounce/pics/ball0001.png
new file mode 100644
index 00000000..845c833b
--- /dev/null
+++ b/kbounce/pics/ball0001.png
Binary files differ
diff --git a/kbounce/pics/ball0002.png b/kbounce/pics/ball0002.png
new file mode 100644
index 00000000..e561860c
--- /dev/null
+++ b/kbounce/pics/ball0002.png
Binary files differ
diff --git a/kbounce/pics/ball0003.png b/kbounce/pics/ball0003.png
new file mode 100644
index 00000000..ee1bfad0
--- /dev/null
+++ b/kbounce/pics/ball0003.png
Binary files differ
diff --git a/kbounce/pics/ball0004.png b/kbounce/pics/ball0004.png
new file mode 100644
index 00000000..cc39da5b
--- /dev/null
+++ b/kbounce/pics/ball0004.png
Binary files differ
diff --git a/kbounce/pics/ball0005.png b/kbounce/pics/ball0005.png
new file mode 100644
index 00000000..a316f11a
--- /dev/null
+++ b/kbounce/pics/ball0005.png
Binary files differ
diff --git a/kbounce/pics/ball0006.png b/kbounce/pics/ball0006.png
new file mode 100644
index 00000000..c3f024ae
--- /dev/null
+++ b/kbounce/pics/ball0006.png
Binary files differ
diff --git a/kbounce/pics/ball0007.png b/kbounce/pics/ball0007.png
new file mode 100644
index 00000000..c2d4f803
--- /dev/null
+++ b/kbounce/pics/ball0007.png
Binary files differ
diff --git a/kbounce/pics/ball0008.png b/kbounce/pics/ball0008.png
new file mode 100644
index 00000000..c0b9a075
--- /dev/null
+++ b/kbounce/pics/ball0008.png
Binary files differ
diff --git a/kbounce/pics/ball0009.png b/kbounce/pics/ball0009.png
new file mode 100644
index 00000000..aedbd608
--- /dev/null
+++ b/kbounce/pics/ball0009.png
Binary files differ
diff --git a/kbounce/pics/ball0010.png b/kbounce/pics/ball0010.png
new file mode 100644
index 00000000..133527df
--- /dev/null
+++ b/kbounce/pics/ball0010.png
Binary files differ
diff --git a/kbounce/pics/ball0011.png b/kbounce/pics/ball0011.png
new file mode 100644
index 00000000..4db6a483
--- /dev/null
+++ b/kbounce/pics/ball0011.png
Binary files differ
diff --git a/kbounce/pics/ball0012.png b/kbounce/pics/ball0012.png
new file mode 100644
index 00000000..8b2f758f
--- /dev/null
+++ b/kbounce/pics/ball0012.png
Binary files differ
diff --git a/kbounce/pics/ball0013.png b/kbounce/pics/ball0013.png
new file mode 100644
index 00000000..6d551dc0
--- /dev/null
+++ b/kbounce/pics/ball0013.png
Binary files differ
diff --git a/kbounce/pics/ball0014.png b/kbounce/pics/ball0014.png
new file mode 100644
index 00000000..851cd6cb
--- /dev/null
+++ b/kbounce/pics/ball0014.png
Binary files differ
diff --git a/kbounce/pics/ball0015.png b/kbounce/pics/ball0015.png
new file mode 100644
index 00000000..f706d722
--- /dev/null
+++ b/kbounce/pics/ball0015.png
Binary files differ
diff --git a/kbounce/pics/ball0016.png b/kbounce/pics/ball0016.png
new file mode 100644
index 00000000..cd762eb9
--- /dev/null
+++ b/kbounce/pics/ball0016.png
Binary files differ
diff --git a/kbounce/pics/ball0017.png b/kbounce/pics/ball0017.png
new file mode 100644
index 00000000..fba03084
--- /dev/null
+++ b/kbounce/pics/ball0017.png
Binary files differ
diff --git a/kbounce/pics/ball0018.png b/kbounce/pics/ball0018.png
new file mode 100644
index 00000000..e500118e
--- /dev/null
+++ b/kbounce/pics/ball0018.png
Binary files differ
diff --git a/kbounce/pics/ball0019.png b/kbounce/pics/ball0019.png
new file mode 100644
index 00000000..46952614
--- /dev/null
+++ b/kbounce/pics/ball0019.png
Binary files differ
diff --git a/kbounce/pics/ball0020.png b/kbounce/pics/ball0020.png
new file mode 100644
index 00000000..70d1d658
--- /dev/null
+++ b/kbounce/pics/ball0020.png
Binary files differ
diff --git a/kbounce/pics/ball0021.png b/kbounce/pics/ball0021.png
new file mode 100644
index 00000000..f219ffcf
--- /dev/null
+++ b/kbounce/pics/ball0021.png
Binary files differ
diff --git a/kbounce/pics/ball0022.png b/kbounce/pics/ball0022.png
new file mode 100644
index 00000000..bb4bb0a8
--- /dev/null
+++ b/kbounce/pics/ball0022.png
Binary files differ
diff --git a/kbounce/pics/ball0023.png b/kbounce/pics/ball0023.png
new file mode 100644
index 00000000..80f8d792
--- /dev/null
+++ b/kbounce/pics/ball0023.png
Binary files differ
diff --git a/kbounce/pics/ball0024.png b/kbounce/pics/ball0024.png
new file mode 100644
index 00000000..7a6db2bd
--- /dev/null
+++ b/kbounce/pics/ball0024.png
Binary files differ
diff --git a/kbounce/pics/hi128-app-kbounce.png b/kbounce/pics/hi128-app-kbounce.png
new file mode 100644
index 00000000..d9c49bbe
--- /dev/null
+++ b/kbounce/pics/hi128-app-kbounce.png
Binary files differ
diff --git a/kbounce/pics/hi16-app-kbounce.png b/kbounce/pics/hi16-app-kbounce.png
new file mode 100644
index 00000000..916fe18d
--- /dev/null
+++ b/kbounce/pics/hi16-app-kbounce.png
Binary files differ
diff --git a/kbounce/pics/hi22-app-kbounce.png b/kbounce/pics/hi22-app-kbounce.png
new file mode 100644
index 00000000..51b7b1c8
--- /dev/null
+++ b/kbounce/pics/hi22-app-kbounce.png
Binary files differ
diff --git a/kbounce/pics/hi32-app-kbounce.png b/kbounce/pics/hi32-app-kbounce.png
new file mode 100644
index 00000000..652824f7
--- /dev/null
+++ b/kbounce/pics/hi32-app-kbounce.png
Binary files differ
diff --git a/kbounce/pics/hi48-app-kbounce.png b/kbounce/pics/hi48-app-kbounce.png
new file mode 100644
index 00000000..4b91913c
--- /dev/null
+++ b/kbounce/pics/hi48-app-kbounce.png
Binary files differ
diff --git a/kbounce/pics/hi64-app-kbounce.png b/kbounce/pics/hi64-app-kbounce.png
new file mode 100644
index 00000000..98ec084a
--- /dev/null
+++ b/kbounce/pics/hi64-app-kbounce.png
Binary files differ
diff --git a/kbounce/pics/tiles.png b/kbounce/pics/tiles.png
new file mode 100644
index 00000000..13461e3d
--- /dev/null
+++ b/kbounce/pics/tiles.png
Binary files differ
diff --git a/kbounce/sounds/Makefile.am b/kbounce/sounds/Makefile.am
new file mode 100644
index 00000000..6b779bda
--- /dev/null
+++ b/kbounce/sounds/Makefile.am
@@ -0,0 +1,7 @@
+AUTOMAKE_OPTIONS = foreign
+
+sound_DATA = death.au reflect.au wallstart.au wallend.au seconds.au timeout.au
+sounddir = $(kde_datadir)/kbounce/sounds
+
+EXTRA_DIST = $(sound_DATA)
+
diff --git a/kbounce/sounds/death.au b/kbounce/sounds/death.au
new file mode 100644
index 00000000..7d628632
--- /dev/null
+++ b/kbounce/sounds/death.au
Binary files differ
diff --git a/kbounce/sounds/reflect.au b/kbounce/sounds/reflect.au
new file mode 100644
index 00000000..5975c174
--- /dev/null
+++ b/kbounce/sounds/reflect.au
Binary files differ
diff --git a/kbounce/sounds/seconds.au b/kbounce/sounds/seconds.au
new file mode 100644
index 00000000..c6d4f6c1
--- /dev/null
+++ b/kbounce/sounds/seconds.au
Binary files differ
diff --git a/kbounce/sounds/timeout.au b/kbounce/sounds/timeout.au
new file mode 100644
index 00000000..515fb728
--- /dev/null
+++ b/kbounce/sounds/timeout.au
Binary files differ
diff --git a/kbounce/sounds/wallend.au b/kbounce/sounds/wallend.au
new file mode 100644
index 00000000..5093e916
--- /dev/null
+++ b/kbounce/sounds/wallend.au
Binary files differ
diff --git a/kbounce/sounds/wallstart.au b/kbounce/sounds/wallstart.au
new file mode 100644
index 00000000..d4377742
--- /dev/null
+++ b/kbounce/sounds/wallstart.au
Binary files differ