diff options
Diffstat (limited to 'kbounce')
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 Binary files differnew file mode 100644 index 00000000..3afe8f0e --- /dev/null +++ b/kbounce/pics/ball0000.png diff --git a/kbounce/pics/ball0001.png b/kbounce/pics/ball0001.png Binary files differnew file mode 100644 index 00000000..845c833b --- /dev/null +++ b/kbounce/pics/ball0001.png diff --git a/kbounce/pics/ball0002.png b/kbounce/pics/ball0002.png Binary files differnew file mode 100644 index 00000000..e561860c --- /dev/null +++ b/kbounce/pics/ball0002.png diff --git a/kbounce/pics/ball0003.png b/kbounce/pics/ball0003.png Binary files differnew file mode 100644 index 00000000..ee1bfad0 --- /dev/null +++ b/kbounce/pics/ball0003.png diff --git a/kbounce/pics/ball0004.png b/kbounce/pics/ball0004.png Binary files differnew file mode 100644 index 00000000..cc39da5b --- /dev/null +++ b/kbounce/pics/ball0004.png diff --git a/kbounce/pics/ball0005.png b/kbounce/pics/ball0005.png Binary files differnew file mode 100644 index 00000000..a316f11a --- /dev/null +++ b/kbounce/pics/ball0005.png diff --git a/kbounce/pics/ball0006.png b/kbounce/pics/ball0006.png Binary files differnew file mode 100644 index 00000000..c3f024ae --- /dev/null +++ b/kbounce/pics/ball0006.png diff --git a/kbounce/pics/ball0007.png b/kbounce/pics/ball0007.png Binary files differnew file mode 100644 index 00000000..c2d4f803 --- /dev/null +++ b/kbounce/pics/ball0007.png diff --git a/kbounce/pics/ball0008.png b/kbounce/pics/ball0008.png Binary files differnew file mode 100644 index 00000000..c0b9a075 --- /dev/null +++ b/kbounce/pics/ball0008.png diff --git a/kbounce/pics/ball0009.png b/kbounce/pics/ball0009.png Binary files differnew file mode 100644 index 00000000..aedbd608 --- /dev/null +++ b/kbounce/pics/ball0009.png diff --git a/kbounce/pics/ball0010.png b/kbounce/pics/ball0010.png Binary files differnew file mode 100644 index 00000000..133527df --- /dev/null +++ b/kbounce/pics/ball0010.png diff --git a/kbounce/pics/ball0011.png b/kbounce/pics/ball0011.png Binary files differnew file mode 100644 index 00000000..4db6a483 --- /dev/null +++ b/kbounce/pics/ball0011.png diff --git a/kbounce/pics/ball0012.png b/kbounce/pics/ball0012.png Binary files differnew file mode 100644 index 00000000..8b2f758f --- /dev/null +++ b/kbounce/pics/ball0012.png diff --git a/kbounce/pics/ball0013.png b/kbounce/pics/ball0013.png Binary files differnew file mode 100644 index 00000000..6d551dc0 --- /dev/null +++ b/kbounce/pics/ball0013.png diff --git a/kbounce/pics/ball0014.png b/kbounce/pics/ball0014.png Binary files differnew file mode 100644 index 00000000..851cd6cb --- /dev/null +++ b/kbounce/pics/ball0014.png diff --git a/kbounce/pics/ball0015.png b/kbounce/pics/ball0015.png Binary files differnew file mode 100644 index 00000000..f706d722 --- /dev/null +++ b/kbounce/pics/ball0015.png diff --git a/kbounce/pics/ball0016.png b/kbounce/pics/ball0016.png Binary files differnew file mode 100644 index 00000000..cd762eb9 --- /dev/null +++ b/kbounce/pics/ball0016.png diff --git a/kbounce/pics/ball0017.png b/kbounce/pics/ball0017.png Binary files differnew file mode 100644 index 00000000..fba03084 --- /dev/null +++ b/kbounce/pics/ball0017.png diff --git a/kbounce/pics/ball0018.png b/kbounce/pics/ball0018.png Binary files differnew file mode 100644 index 00000000..e500118e --- /dev/null +++ b/kbounce/pics/ball0018.png diff --git a/kbounce/pics/ball0019.png b/kbounce/pics/ball0019.png Binary files differnew file mode 100644 index 00000000..46952614 --- /dev/null +++ b/kbounce/pics/ball0019.png diff --git a/kbounce/pics/ball0020.png b/kbounce/pics/ball0020.png Binary files differnew file mode 100644 index 00000000..70d1d658 --- /dev/null +++ b/kbounce/pics/ball0020.png diff --git a/kbounce/pics/ball0021.png b/kbounce/pics/ball0021.png Binary files differnew file mode 100644 index 00000000..f219ffcf --- /dev/null +++ b/kbounce/pics/ball0021.png diff --git a/kbounce/pics/ball0022.png b/kbounce/pics/ball0022.png Binary files differnew file mode 100644 index 00000000..bb4bb0a8 --- /dev/null +++ b/kbounce/pics/ball0022.png diff --git a/kbounce/pics/ball0023.png b/kbounce/pics/ball0023.png Binary files differnew file mode 100644 index 00000000..80f8d792 --- /dev/null +++ b/kbounce/pics/ball0023.png diff --git a/kbounce/pics/ball0024.png b/kbounce/pics/ball0024.png Binary files differnew file mode 100644 index 00000000..7a6db2bd --- /dev/null +++ b/kbounce/pics/ball0024.png diff --git a/kbounce/pics/hi128-app-kbounce.png b/kbounce/pics/hi128-app-kbounce.png Binary files differnew file mode 100644 index 00000000..d9c49bbe --- /dev/null +++ b/kbounce/pics/hi128-app-kbounce.png diff --git a/kbounce/pics/hi16-app-kbounce.png b/kbounce/pics/hi16-app-kbounce.png Binary files differnew file mode 100644 index 00000000..916fe18d --- /dev/null +++ b/kbounce/pics/hi16-app-kbounce.png diff --git a/kbounce/pics/hi22-app-kbounce.png b/kbounce/pics/hi22-app-kbounce.png Binary files differnew file mode 100644 index 00000000..51b7b1c8 --- /dev/null +++ b/kbounce/pics/hi22-app-kbounce.png diff --git a/kbounce/pics/hi32-app-kbounce.png b/kbounce/pics/hi32-app-kbounce.png Binary files differnew file mode 100644 index 00000000..652824f7 --- /dev/null +++ b/kbounce/pics/hi32-app-kbounce.png diff --git a/kbounce/pics/hi48-app-kbounce.png b/kbounce/pics/hi48-app-kbounce.png Binary files differnew file mode 100644 index 00000000..4b91913c --- /dev/null +++ b/kbounce/pics/hi48-app-kbounce.png diff --git a/kbounce/pics/hi64-app-kbounce.png b/kbounce/pics/hi64-app-kbounce.png Binary files differnew file mode 100644 index 00000000..98ec084a --- /dev/null +++ b/kbounce/pics/hi64-app-kbounce.png diff --git a/kbounce/pics/tiles.png b/kbounce/pics/tiles.png Binary files differnew file mode 100644 index 00000000..13461e3d --- /dev/null +++ b/kbounce/pics/tiles.png 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 Binary files differnew file mode 100644 index 00000000..7d628632 --- /dev/null +++ b/kbounce/sounds/death.au diff --git a/kbounce/sounds/reflect.au b/kbounce/sounds/reflect.au Binary files differnew file mode 100644 index 00000000..5975c174 --- /dev/null +++ b/kbounce/sounds/reflect.au diff --git a/kbounce/sounds/seconds.au b/kbounce/sounds/seconds.au Binary files differnew file mode 100644 index 00000000..c6d4f6c1 --- /dev/null +++ b/kbounce/sounds/seconds.au diff --git a/kbounce/sounds/timeout.au b/kbounce/sounds/timeout.au Binary files differnew file mode 100644 index 00000000..515fb728 --- /dev/null +++ b/kbounce/sounds/timeout.au diff --git a/kbounce/sounds/wallend.au b/kbounce/sounds/wallend.au Binary files differnew file mode 100644 index 00000000..5093e916 --- /dev/null +++ b/kbounce/sounds/wallend.au diff --git a/kbounce/sounds/wallstart.au b/kbounce/sounds/wallstart.au Binary files differnew file mode 100644 index 00000000..d4377742 --- /dev/null +++ b/kbounce/sounds/wallstart.au |