-rw-r--r-- | noncore/games/zbounce/game.cpp | 606 | ||||
-rw-r--r-- | noncore/games/zbounce/game.h | 183 | ||||
-rw-r--r-- | noncore/games/zbounce/kbounce.cpp | 302 | ||||
-rw-r--r-- | noncore/games/zbounce/kbounce.h | 99 | ||||
-rw-r--r-- | noncore/games/zbounce/main.cpp | 29 | ||||
-rw-r--r-- | noncore/games/zbounce/opie-zbounce.control | 20 | ||||
-rw-r--r-- | noncore/games/zbounce/zbounce.pro | 10 |
7 files changed, 1249 insertions, 0 deletions
diff --git a/noncore/games/zbounce/game.cpp b/noncore/games/zbounce/game.cpp new file mode 100644 index 0000000..7a1a3cd --- a/dev/null +++ b/noncore/games/zbounce/game.cpp @@ -0,0 +1,606 @@ +/* + * Copyright (C) 2000 Stefan Schimanski <1Stein@gmx.de> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this program; if not, write to the Free + * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + + +#include <stdlib.h> +#include <qtimer.h> +#include <qpe/qpeapplication.h> +#include <qimage.h> + +#include "game.h" + +#define TILE_SIZE 9 + +#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 + +#define MS2TICKS( ms ) ((ms)/GAME_DELAY) + +Arrow::Arrow(QCanvasPixmapArray* array, QCanvas* canvas) + : QCanvasSprite( array, canvas ) +{ + m_vertical = true; + move(3,3); +} + +void Arrow::update() +{ + if ( m_vertical ) + setFrame( 0 ); + else + setFrame( 1 ); +} + +void Arrow::changeDirection() +{ + m_vertical = ! m_vertical; + update(); +} + + +Ball::Ball(QCanvasPixmapArray* array, QCanvas* canvas) + : QCanvasSprite( array, canvas ), m_animDelay( 0 ), m_soundDelay( MS2TICKS(BALL_ANIM_DELAY)/2 ) +{ +} + +void Ball::update() +{ + 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; + + // 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() ); + + // 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 ) +{ + // 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( QPixmap tiles, QObject* parent, const char* name ) + : QCanvas( parent, name ), m_tiles( tiles ) +{ + setPixmaps( tiles ); +} + +void JezzField::setGameTile( int x, int y, bool black ) +{ + setTile( x, y, black ? TILE_BORDER : TILE_FREE ); +} + +void JezzField::setPixmaps( QPixmap tiles ) +{ + // create new tiles + QPixmap allTiles( TILE_SIZE*(FIELD_WIDTH-2), TILE_SIZE*(FIELD_HEIGHT-1) ); + + // 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() & LeftButton ) + { + emit buildWall( ev->x()/TILE_SIZE, ev->y()/TILE_SIZE, m_vertical ); + } +} + +void JezzView::changeCursor() +{ + m_vertical = !m_vertical; + if ( m_vertical ) + { + setCursor( sizeVerCursor ); + } + else + { + setCursor( sizeHorCursor ); + } +} + +/*************************************************************************/ + +JezzGame::JezzGame( 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 = QPEApplication::qpeDir()+"pics/zbounce/"; + + // 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 ); + + m_arrowPixmaps = new QCanvasPixmapArray( path + "arrow%1.png", 2 ); + for ( unsigned n=0; n < m_arrowPixmaps->count(); n++ ) + m_arrowPixmaps->image(n)->setOffset( 0, 0 ); + + QPixmap tiles( path + "tiles.png" ); + + // create field + m_field = new JezzField( tiles, 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( ((rand() & 1)*2-1)*2, ((rand() & 1)*2-1)*2 ); + ball->setFrame( rand() % 25 ); + ball->move( 4*TILE_SIZE + ( rand() - 50 ) % ( (FIELD_WIDTH-8)*TILE_SIZE ), + 4*TILE_SIZE + rand() % ( (FIELD_HEIGHT-8)*TILE_SIZE ) ); + ball->show(); + } + + // create arrow + arrow = new Arrow( m_arrowPixmaps, m_field ); + arrow->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; +} + +void JezzGame::display( QString text, int size ) +{ + qDebug("This function \"display\" shouldn't be called!!!"); + if ( !text.isEmpty() ) + { + QFont font( "Helvetica", size, QFont::Bold ); + font.setStyleHint( QFont::Helvetica ); + 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::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-1) * (FIELD_HEIGHT-1) ); +} + +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*, int, int, int tile ) +{ + if ( tile!=TILE_BORDER && tile>TILE_FREE && tile!=TILE_WALLEND ) + { + // stop walls + if ( (tile==TILE_WALLUP || tile==TILE_WALLLEFT) && m_wall1 ) + { + m_wall1->finish(); + m_wall1->fill( false ); + delete m_wall1; + m_wall1 = 0; + } + + if ( (tile==TILE_WALLDOWN || tile==TILE_WALLRIGHT) && m_wall2 ) + { + 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; + + 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 ) + { + //kdDebug() << "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 ) +{ + 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(); + } +} + +void JezzGame::changeCursor() +{ + arrow->changeDirection(); + m_view->changeCursor(); +} diff --git a/noncore/games/zbounce/game.h b/noncore/games/zbounce/game.h new file mode 100644 index 0000000..ae0d4fa --- a/dev/null +++ b/noncore/games/zbounce/game.h @@ -0,0 +1,183 @@ +/* + * Copyright (C) 2000 Stefan Schimanski <1Stein@gmx.de> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this program; if not, write to the Free + * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef GAME_H_INCLUDED +#define GAME_H_INCLUDED + +#include <qwidget.h> +#include <qcanvas.h> +#include <qmemarray.h> + +class QTimer; +class JezzField; + +#define FIELD_WIDTH 26 +#define FIELD_HEIGHT 26 + +class Arrow : public QCanvasSprite +{ + public: + Arrow(QCanvasPixmapArray* array, QCanvas* canvas); + + void update(); + void changeDirection(); + + protected: + bool m_vertical; +}; + +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( QPixmap tiles, QObject* parent = 0, const char* name = 0 ); + + void setGameTile( int x, int y, bool black ); + +signals: + void ballCollision( Ball *ball, int x, int y, int tile ); + +private: + friend class Ball; + QPixmap m_tiles; + QMemArray<QPixmap> m_backTiles; + + void setPixmaps( QPixmap tiles ); + 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); + void changeCursor(); + +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( int ballNum, QWidget *parent=0, const char *name=0 ); + ~JezzGame(); + + int percent(); + void display( QString text, int size=20 ); + void changeCursor(); + +signals: + void died(); + void newPercent( int percent ); + +public slots: + void start(); + void stop(); + +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; + + QList<Ball> m_balls; + QCanvasPixmapArray *m_ballPixmaps; + QCanvasPixmapArray *m_arrowPixmaps; + QCanvasText *m_text; + Arrow *arrow; + + QTimer *m_clock; + bool m_running; + int m_percent; + bool m_pictured; + +}; + +#endif diff --git a/noncore/games/zbounce/kbounce.cpp b/noncore/games/zbounce/kbounce.cpp new file mode 100644 index 0000000..c1c0f70 --- a/dev/null +++ b/noncore/games/zbounce/kbounce.cpp @@ -0,0 +1,302 @@ +/* + * Copyright (C) 2000 Stefan Schimanski <1Stein@gmx.de> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License,Life or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this program; if not, write to the Free + * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include <qlayout.h> +#include <qtimer.h> +#include <qlcdnumber.h> +#include <qmessagebox.h> +#include <qmainwindow.h> +#include <qpe/qpeapplication.h> + +#include "kbounce.h" +#include "game.h" +#include <qlabel.h> + +KJezzball::KJezzball() : QMainWindow(0), m_gameWidget( 0 ) +{ + setCaption(tr("ZBounce")); + // setup variables + m_game.level = 1; + m_game.score = 0; + m_state = Idle; + + + menu = menuBar(); + game = new QPopupMenu; + game->insertItem(tr("&New game"), this, SLOT(newGame()), Key_N ); + game->insertItem(tr("&Pause game"), this, SLOT(pauseGame()), Key_P ); + game->insertSeparator(); + game->insertItem(tr("&About"), this, SLOT(about())); + menu->insertItem( tr("&Game"), game ); + + // create widgets + m_view = new QWidget( this, "m_view" ); + setCentralWidget( m_view ); + + m_layout = new QGridLayout( m_view ); + m_layout->setSpacing( 0 ); + m_layout->setMargin( 0 ); + + ScoreLabel = new QLabel( m_view, "ScoreLabel" ); + ScoreLabel->setText( tr( "Score: 00" ) ); + ScoreLabel->setAlignment( int( QLabel::AlignCenter ) ); + + m_layout->addWidget( ScoreLabel, 1, 0 ); + + LivesLabel = new QLabel( m_view, "LivesLabel" ); + LivesLabel->setText( tr( "Lives: 0%" ) ); + LivesLabel->setAlignment( int( QLabel::AlignCenter ) ); + + m_layout->addWidget( LivesLabel, 1, 2 ); + + FilledLabel = new QLabel( m_view, "FilledLabel" ); + FilledLabel->setText( tr( "Filled: 00%" ) ); + FilledLabel->setAlignment( int( QLabel::AlignCenter ) ); + + m_layout->addWidget( FilledLabel, 1, 1 ); + + TimeLabel = new QLabel( m_view, "TimeLabel" ); + TimeLabel->setText( tr( "Time: 00" ) ); + TimeLabel->setAlignment( int( QLabel::AlignCenter ) ); + + m_layout->addWidget( TimeLabel, 1, 3 ); + + // 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 ); +} + +void KJezzball::newGame() +{ + // Check for running game + closeGame(); + if ( m_state==Idle ) + { + // update displays + m_game.level = 1; + m_game.score = 0; + + setCaption(tr("ZBounce Level %1").arg(m_game.level)); + ScoreLabel->setText( tr( "Score: %1" ).arg(m_game.score) ); + + // start new game + m_state = Running; + + createLevel( m_game.level ); + startLevel(); + } +} + +void KJezzball::about() +{ + QMessageBox::information( this, "About", "Written by: Stefan Schimanski\nPorted by: Martin Imobersteg\n\nThis program is distributed under\nthe terms of the GPL v2." ); +} + +void KJezzball::closeGame() +{ + if ( m_state!=Idle ) + { + stopLevel(); + m_state = Idle; + } +} + +void KJezzball::pauseGame() +{ + switch ( m_state ) + { + case Running: + m_state = Paused; + m_gameWidget->display( tr("Game paused.\nPress P to continue!") ); + stopLevel(); + break; + + case Paused: + case Suspend: + m_state = Running; + 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 ); + QMessageBox::information( this, "Game Over", tr("Game Over!\nScore: %1").arg(score) ); +} + +void KJezzball::focusOutEvent( QFocusEvent *ev ) +{ + if ( m_state==Running ) + { + stopLevel(); + m_state = Suspend; + } + + QMainWindow::focusOutEvent( ev ); +} + +void KJezzball::focusInEvent ( QFocusEvent *ev ) +{ + if ( m_state==Suspend ) + { + startLevel(); + m_state = Running; + } + + QMainWindow::focusInEvent( ev ); +} + +void KJezzball::second() +{ + m_level.time--; + TimeLabel->setText( tr( "Time: %1" ).arg(m_level.time) ); + if ( m_level.time<=0 ) + { + gameOver(); + } +} + +void KJezzball::died() +{ + m_level.lifes--; + LivesLabel->setText( tr( "Lives: %1" ).arg(m_level.lifes) ); + if ( m_level.lifes==0 ) gameOver(); +} + +void KJezzball::newPercent( int percent ) +{ + FilledLabel->setText( tr( "Filled: %1%" ).arg(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; + + m_gameWidget = new JezzGame( level+1, m_view, "m_gameWidget" ); + + m_gameWidget->show(); + m_layout->addMultiCellWidget( m_gameWidget, 0, 0, 0, 3 ); + connect( m_gameWidget, SIGNAL(died()), this, SLOT(died()) ); + connect( m_gameWidget, SIGNAL(newPercent(int)), this, SLOT(newPercent(int)) ); + + // update displays + m_level.lifes = level+1; + LivesLabel->setText( tr( "Lives: %1" ).arg(m_level.lifes) ); + FilledLabel->setText( tr( "Filled: 0%" ) ); + + m_level.time = (level+2)*30; + TimeLabel->setText( tr( "Time: %1" ).arg(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; + ScoreLabel->setText( tr( "Score: %1" ).arg(m_game.score) ); + + QString score; + score.setNum( m_level.score ); + + QString level; + level.setNum( m_game.level ); + + QString foo = QString( + tr("Successfully cleared more than 75%.\n") + + tr("%1 points: 15 points per life\n").arg(m_level.lifes*15) + + tr("%1 points: Bonus\n").arg((m_gameWidget->percent()-75)*2*(m_game.level+5)) + + tr("%1 points: Total score\n").arg(score) + + tr("On to level %1.\nYou get %2 lives this time!")).arg(m_game.level+1).arg(m_game.level+2); + + QMessageBox::information( this, "Success", foo ); + + m_game.level++; + + createLevel( m_game.level ); + startLevel(); +} + +void KJezzball::keyPressEvent( QKeyEvent *ev ) +{ + if ( ev->key() == Key_Space || + ev->key() == Key_Up || + ev->key() == Key_Down || + ev->key() == Key_Right || + ev->key() == Key_Left ) + { + m_gameWidget->changeCursor(); + } + else + { + ev->ignore(); + } +} diff --git a/noncore/games/zbounce/kbounce.h b/noncore/games/zbounce/kbounce.h new file mode 100644 index 0000000..de41710 --- a/dev/null +++ b/noncore/games/zbounce/kbounce.h @@ -0,0 +1,99 @@ +/* + * Copyright (C) 2000 Stefan Schimanski <1Stein@gmx.de> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this program; if not, write to the Free + * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef KJEZZBALL_H_INCLUDED +#define KJEZZBALL_H_INCLUDED + +#include <qmainwindow.h> +#include <qmenubar.h> +#include <qlabel.h> + +class JezzGame; +class QLCDNumber; +class QGridLayout; + +class KJezzball : public QMainWindow +{ + Q_OBJECT + +public: + KJezzball(); + +public slots: + void newGame(); + void pauseGame(); + void closeGame(); + void about(); + +protected slots: + void died(); + void newPercent( int percent ); + void second(); + void switchLevel(); + void gameOverNow(); + +protected: + void createLevel( int level ); + void startLevel(); + void stopLevel(); + void nextLevel(); + void gameOver(); + void initXMLUI(); + + void focusOutEvent( QFocusEvent * ); + void focusInEvent ( QFocusEvent * ); + void keyPressEvent( QKeyEvent *ev ); + + JezzGame *m_gameWidget; + QWidget *m_view; + QGridLayout *m_layout; + QLCDNumber *m_levelLCD; + QLCDNumber *m_lifesLCD; + QLCDNumber *m_scoreLCD; + QLCDNumber *m_percentLCD; + QLCDNumber *m_timeLCD; + + QTimer *m_timer; + QTimer *m_nextLevelTimer; + QTimer *m_gameOverTimer; + + enum { Idle, Running, Paused, Suspend } m_state; + + struct + { + int lifes; + int time; + int score; + } m_level; + + struct + { + int level; + int score; + } m_game; +private: + QMenuBar *menu; + QPopupMenu *game; + QLabel* ScoreLabel; + QLabel* LivesLabel; + QLabel* FilledLabel; + QLabel* TimeLabel; + +}; + +#endif diff --git a/noncore/games/zbounce/main.cpp b/noncore/games/zbounce/main.cpp new file mode 100644 index 0000000..a6b7c1a --- a/dev/null +++ b/noncore/games/zbounce/main.cpp @@ -0,0 +1,29 @@ +/* + * Copyright (C) 2000 Stefan Schimanski <schimmi@kde.org> + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include <qpe/qpeapplication.h> +#include "kbounce.h" + +int main(int argc, char **argv) +{ + QPEApplication a( argc, argv ); + KJezzball *top = new KJezzball; + a.showMainWidget(top); + + return a.exec(); +} diff --git a/noncore/games/zbounce/opie-zbounce.control b/noncore/games/zbounce/opie-zbounce.control new file mode 100644 index 0000000..d419eaf --- a/dev/null +++ b/noncore/games/zbounce/opie-zbounce.control @@ -0,0 +1,20 @@ +Files: bin/zbounce apps/Games/zbounce.desktop pics/zbounce/zbounce.png \ +pics/zbounce/arrow0000.png pics/zbounce/ball0008.png pics/zbounce/ball0018.png \ +pics/zbounce/arrow0001.png pics/zbounce/ball0009.png pics/zbounce/ball0019.png \ +pics/zbounce/ball0000.png pics/zbounce/ball0010.png pics/zbounce/ball0020.png \ +pics/zbounce/ball0001.png pics/zbounce/ball0011.png pics/zbounce/ball0021.png \ +pics/zbounce/ball0002.png pics/zbounce/ball0012.png pics/zbounce/ball0022.png \ +pics/zbounce/ball0003.png pics/zbounce/ball0013.png pics/zbounce/ball0023.png \ +pics/zbounce/ball0004.png pics/zbounce/ball0014.png pics/zbounce/ball0024.png \ +pics/zbounce/ball0005.png pics/zbounce/ball0015.png pics/zbounce/tiles.png \ +pics/zbounce/ball0006.png pics/zbounce/ball0016.png \ +pics/zbounce/ball0007.png pics/zbounce/ball0017.png \ +Version: 0.6 +Depends: opie-base ($QPE_VERSION) +Priority: optional +Section: opie/games +Maintainer: Martin Imobersteg <imm@gmx.ch> +Architecture: arm +License: GPL +Description: ZBounce + A JezzGame like game for Qtopia. diff --git a/noncore/games/zbounce/zbounce.pro b/noncore/games/zbounce/zbounce.pro new file mode 100644 index 0000000..4bf2058 --- a/dev/null +++ b/noncore/games/zbounce/zbounce.pro @@ -0,0 +1,10 @@ +TEMPLATE = app +#CONFIG = qt warn_on debug +CONFIG = qt warn_on release +HEADERS = game.h kbounce.h +SOURCES = game.cpp kbounce.cpp main.cpp +INCLUDEPATH += $(QPEDIR)/include +DEPENDPATH += $(QPEDIR)/include +LIBS += -lqpe +DESTDIR = $(OPIEDIR)/bin +TARGET = zbounce |