Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Namespace Members | Class Members | File Members | Related Pages

view.cpp

Go to the documentation of this file.
00001 /**********************************************************************
00002 ** Copyright (C) 2000 Trolltech AS.  All rights reserved.
00003 **
00004 ** This file is part of Qtopia Environment.
00005 **
00006 ** This file may be distributed and/or modified under the terms of the
00007 ** GNU General Public License version 2 as published by the Free Software
00008 ** Foundation and appearing in the file LICENSE.GPL included in the
00009 ** packaging of this file.
00010 **
00011 ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
00012 ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
00013 **
00014 ** See http://www.trolltech.com/gpl/ for GPL licensing information.
00015 **
00016 ** Contact info@trolltech.com if any conditions of this licensing are
00017 ** not clear to you.
00018 **
00019 **********************************************************************//*
00020  * KAsteroids - Copyright (c) Martin R. Jones 1997
00021  *
00022  * Part of the KDE project
00023  */
00024 
00025 #include "view.h"
00026 
00027 #include <opie2/oresource.h>
00028 #include <qpe/qpeapplication.h>
00029 
00030 #include <stdlib.h>
00031 #include <math.h>
00032 
00033 #define IMG_BACKGROUND "qasteroids/bg"
00034 
00035 #define REFRESH_DELAY           33
00036 #define SHIP_SPEED              0.3
00037 #define MISSILE_SPEED           10.0
00038 #define SHIP_STEPS              64
00039 #define ROTATE_RATE             2
00040 #define SHIELD_ON_COST          1
00041 #define SHIELD_HIT_COST         30
00042 #define BRAKE_ON_COST           4
00043 
00044 #define MAX_ROCK_SPEED          2.5
00045 #define MAX_POWERUP_SPEED       1.5
00046 #define MAX_SHIP_SPEED          8
00047 #define MAX_BRAKES              5
00048 #define MAX_SHIELDS             5
00049 #define MAX_FIREPOWER           5
00050 
00051 #define TEXT_SPEED              4
00052 
00053 #define PI_X_2                  6.283185307
00054 #ifndef M_PI
00055 #define M_PI 3.141592654
00056 #endif
00057 
00058 struct kas_animations_t
00059 {
00060     int id;
00061     const char *path;
00062     int frames;
00063 };
00064 
00065 static const kas_animations_t kas_animations [] =
00066 {
00067 //    { ID_ROCK_LARGE,       "rock1/rock1\%1.png",       32 },
00068     { ID_ROCK_MEDIUM,      "rock2/rock2\%1.png",       32 },
00069     { ID_ROCK_SMALL,       "rock3/rock3\%1.png",       32 },
00070     { ID_SHIP,             "ship/ship\%1.png",         32 },
00071     { ID_MISSILE,          "missile/missile.png",      0 },
00072     { ID_BIT,              "bits/bits\%1.png",         16 },
00073     { ID_EXHAUST,          "exhaust/exhaust.png",      0 },
00074     { ID_ENERGY_POWERUP,   "powerups/energy.png",      0 },
00075 //    { ID_TELEPORT_POWERUP, "powerups/teleport%1.png", 12 },
00076     { ID_BRAKE_POWERUP,    "powerups/brake.png",       0 },
00077     { ID_SHIELD_POWERUP,   "powerups/shield.png",      0 },
00078     { ID_SHOOT_POWERUP,    "powerups/shoot.png",       0 },
00079     { ID_SHIELD,           "shield/shield\%1.png",      6 },
00080     { 0,                   0,                          0 }
00081 };
00082 
00083 
00084 
00085 KAsteroidsView::KAsteroidsView( QWidget *parent, const char *name )
00086     : QWidget( parent, name ),
00087       field(200, 200),
00088       view(&field,this)
00089 {
00090     view.setVScrollBarMode( QScrollView::AlwaysOff );
00091     view.setHScrollBarMode( QScrollView::AlwaysOff );
00092     rocks.setAutoDelete( TRUE );
00093     missiles.setAutoDelete( TRUE );
00094     bits.setAutoDelete( TRUE );
00095     powerups.setAutoDelete( TRUE );
00096     exhaust.setAutoDelete( TRUE );
00097 
00098     field.setBackgroundPixmap( Opie::Core::OResource::loadPixmap(IMG_BACKGROUND) );
00099 
00100     textSprite = new QCanvasText( &field );
00101     QFont font( "helvetica", 14 );
00102     textSprite->setFont( font );
00103 
00104     shield = 0;
00105     shieldOn = FALSE;
00106     refreshRate = REFRESH_DELAY;
00107 
00108     readSprites();
00109 
00110     shieldTimer = new QTimer( this );
00111     connect( shieldTimer, SIGNAL(timeout()), this, SLOT(hideShield()) );
00112     mTimerId = -1;
00113 
00114     shipPower = MAX_POWER_LEVEL;
00115     vitalsChanged = TRUE;
00116     can_destroy_powerups = FALSE;
00117 
00118     mPaused = TRUE;
00119 }
00120 
00121 // - - -
00122 
00123 KAsteroidsView::~KAsteroidsView()
00124 {
00125 }
00126 
00127 // - - -
00128 
00129 void KAsteroidsView::reset()
00130 {
00131     rocks.clear();
00132     missiles.clear();
00133     bits.clear();
00134     powerups.clear();
00135     exhaust.clear();
00136 
00137     shotsFired = 0;
00138     shotsHit = 0;
00139 
00140     rockSpeed = 1.0;
00141     powerupSpeed = 1.0;
00142     mFrameNum = 0;
00143     mPaused = FALSE;
00144 
00145     ship->hide();
00146     shield->hide();
00147 /*
00148     if ( mTimerId >= 0 ) {
00149         killTimer( mTimerId );
00150         mTimerId = -1;
00151     }
00152 */
00153 }
00154 
00155 // - --
00156 
00157 void KAsteroidsView::newGame()
00158 {
00159     if ( shieldOn )
00160     {
00161       shield->hide();
00162       shieldOn = FALSE;
00163     }
00164     reset();
00165     if ( mTimerId < 0 )
00166         mTimerId = startTimer( REFRESH_DELAY );
00167     emit updateVitals();
00168 }
00169 
00170 // - - -
00171 
00172 void KAsteroidsView::endGame()
00173 {
00174 }
00175 
00176 void KAsteroidsView::pause( bool p )
00177 {
00178     if ( !mPaused && p ) {
00179         if ( mTimerId >= 0 ) {
00180             killTimer( mTimerId );
00181             mTimerId = -1;
00182         }
00183     } else if ( mPaused && !p )
00184         mTimerId = startTimer( REFRESH_DELAY );
00185     mPaused = p;
00186 }
00187 
00188 // - - -
00189 
00190 void KAsteroidsView::newShip()
00191 {
00192     ship->move( field.width()/2, field.height()/2, 0 );
00193     shield->move( field.width()/2, field.height()/2, 0 );
00194     ship->setVelocity( 0.0, 0.0 );
00195     shipDx = 0;
00196     shipDy = 0;
00197     shipAngle = 0;
00198     rotateL = FALSE;
00199     rotateR = FALSE;
00200     thrustShip = FALSE;
00201     shootShip = FALSE;
00202     brakeShip = FALSE;
00203     teleportShip = FALSE;
00204     shieldOn = TRUE;
00205     shootDelay = 0;
00206     shipPower = MAX_POWER_LEVEL;
00207     rotateRate = ROTATE_RATE;
00208     rotateSlow = 0;
00209 
00210     mBrakeCount = 0;
00211     mTeleportCount = 0;
00212     mShootCount = 0;
00213 
00214     ship->show();
00215     shield->show();
00216     mShieldCount = 1;   // just in case the ship appears on a rock.
00217     shieldTimer->start( 1000, TRUE );
00218 }
00219 
00220 void KAsteroidsView::setShield( bool s )
00221 {
00222     if ( shieldTimer->isActive() && !s ) {
00223         shieldTimer->stop();
00224         hideShield();
00225     } else {
00226         shieldOn = s && mShieldCount;
00227     }
00228 }
00229 
00230 void KAsteroidsView::brake( bool b )
00231 {
00232     if ( mBrakeCount )
00233     {
00234         if ( brakeShip && !b )
00235         {
00236             rotateL = FALSE;
00237             rotateR = FALSE;
00238             thrustShip = FALSE;
00239             rotateRate = ROTATE_RATE;
00240         }
00241 
00242         brakeShip = b;
00243     }
00244 }
00245 
00246 // - - -
00247 
00248 void KAsteroidsView::readSprites()
00249 {
00250     QString sprites_prefix = QPEApplication::qpeDir() + "pics/qasteroids";
00251 
00252     int i = 0;
00253     while ( kas_animations[i].id )
00254     {
00255         animation.insert( kas_animations[i].id,
00256             new QCanvasPixmapArray( sprites_prefix + "/" + kas_animations[i].path,
00257                                     kas_animations[i].frames ) );
00258         i++;
00259     }
00260 
00261     ship = new QCanvasSprite( animation[ID_SHIP], &field );
00262     ship->hide();
00263 
00264     shield = new KShield( animation[ID_SHIELD], &field );
00265     shield->hide();
00266 }
00267 
00268 // - - -
00269 
00270 void KAsteroidsView::addRocks( int num )
00271 {
00272     for ( int i = 0; i < num; i++ )
00273     {
00274         KRock *rock = new KRock( animation[ID_ROCK_MEDIUM], &field,
00275                              ID_ROCK_MEDIUM, randInt(2), randInt(2) ? -1 : 1 );
00276         double dx = (2.0 - randDouble()*4.0) * rockSpeed;
00277         double dy = (2.0 - randDouble()*4.0) * rockSpeed;
00278         rock->setVelocity( dx, dy );
00279         rock->setFrame( randInt( rock->frameCount() ) );
00280         if ( dx > 0 )
00281         {
00282             if ( dy > 0 )
00283                 rock->move( 5, 5, 0 );
00284             else
00285                 rock->move( 5, field.height() - 25, 0 );
00286         }
00287         else
00288         {
00289             if ( dy > 0 )
00290                 rock->move( field.width() - 25, 5, 0 );
00291             else
00292                 rock->move( field.width() - 25, field.height() - 25, 0 );
00293         }
00294         rock->show( );
00295         rocks.append( rock );
00296     }
00297 }
00298 
00299 // - - -
00300 
00301 void KAsteroidsView::showText( const QString &text, const QColor &color, bool scroll )
00302 {
00303     textSprite->setTextFlags( AlignLeft | AlignVCenter );
00304     textSprite->setText( text );
00305     textSprite->setColor( color );
00306 
00307     if ( scroll ) {
00308         textSprite->move( (field.width()-textSprite->boundingRect().width()) / 2,
00309                             -textSprite->boundingRect().height() );
00310         textDy = TEXT_SPEED;
00311     } else {
00312         textSprite->move( (field.width()-textSprite->boundingRect().width()) / 2,
00313                           (field.height()-textSprite->boundingRect().height()) / 2 );
00314         textDy = 0;
00315     }
00316     textSprite->show();
00317 }
00318 
00319 // - - -
00320 
00321 void KAsteroidsView::hideText()
00322 {
00323     textDy = -TEXT_SPEED;
00324 }
00325 
00326 // - - -
00327 
00328 void KAsteroidsView::resizeEvent(QResizeEvent* event)
00329 {
00330     QWidget::resizeEvent(event);
00331     field.resize(width()-4, height()-4);
00332     view.resize(width(),height());
00333 }
00334 
00335 // - - -
00336 
00337 void KAsteroidsView::timerEvent( QTimerEvent * )
00338 {
00339     field.advance();
00340 
00341     QCanvasSprite *rock;
00342 
00343     // move rocks forward
00344     for ( rock = rocks.first(); rock; rock = rocks.next() ) {
00345         ((KRock *)rock)->nextFrame();
00346         wrapSprite( rock );
00347     }
00348 
00349     wrapSprite( ship );
00350 
00351     // check for missile collision with rocks.
00352     processMissiles();
00353 
00354     // these are generated when a ship explodes
00355     for ( KBit *bit = bits.first(); bit; bit = bits.next() )
00356     {
00357         if ( bit->expired() )
00358         {
00359             bits.removeRef( bit );
00360         }
00361         else
00362         {
00363             bit->growOlder();
00364             bit->setFrame( ( bit->frame()+1 ) % bit->frameCount() );
00365         }
00366     }
00367 
00368     for ( KExhaust *e = exhaust.first(); e; e = exhaust.next() )
00369         exhaust.removeRef( e );
00370 
00371     // move / rotate ship.
00372     // check for collision with a rock.
00373     processShip();
00374 
00375     // move powerups and check for collision with player and missiles
00376     processPowerups();
00377 
00378     if ( textSprite->visible() )
00379     {
00380         if ( textDy < 0 &&
00381              textSprite->boundingRect().y() <= -textSprite->boundingRect().height() ) {
00382             textSprite->hide();
00383         } else {
00384             textSprite->moveBy( 0, textDy );
00385         }
00386         if ( textSprite->boundingRect().y() > (field.height()-textSprite->boundingRect().height())/2 )
00387             textDy = 0;
00388     }
00389 
00390     if ( vitalsChanged && !(mFrameNum % 10) ) {
00391         emit updateVitals();
00392         vitalsChanged = FALSE;
00393     }
00394 
00395     mFrameNum++;
00396 }
00397 
00398 void KAsteroidsView::wrapSprite( QCanvasItem *s )
00399 {
00400     int x = int(s->x() + s->boundingRect().width() / 2);
00401     int y = int(s->y() + s->boundingRect().height() / 2);
00402 
00403     if ( x > field.width() )
00404         s->move( s->x() - field.width(), s->y() );
00405     else if ( x < 0 )
00406         s->move( field.width() + s->x(), s->y() );
00407 
00408     if ( y > field.height() )
00409         s->move( s->x(), s->y() - field.height() );
00410     else if ( y < 0 )
00411         s->move( s->x(), field.height() + s->y() );
00412 }
00413 
00414 // - - -
00415 
00416 void KAsteroidsView::rockHit( QCanvasItem *hit )
00417 {
00418     KPowerup *nPup = 0;
00419     int rnd = static_cast<int>(randDouble()*30.0) % 30;
00420     switch( rnd )
00421     {
00422       case 4:
00423       case 5:
00424         nPup = new KPowerup( animation[ID_ENERGY_POWERUP], &field,
00425                              ID_ENERGY_POWERUP );
00426         break;
00427       case 10:
00428 //        nPup = new KPowerup( animation[ID_TELEPORT_POWERUP], &field,
00429 //                             ID_TELEPORT_POWERUP );
00430         break;
00431       case 15:
00432         nPup = new KPowerup( animation[ID_BRAKE_POWERUP], &field,
00433                                   ID_BRAKE_POWERUP );
00434         break;
00435       case 20:
00436         nPup = new KPowerup( animation[ID_SHIELD_POWERUP], &field,
00437                                   ID_SHIELD_POWERUP );
00438         break;
00439       case 24:
00440       case 25:
00441         nPup = new KPowerup( animation[ID_SHOOT_POWERUP], &field,
00442                                   ID_SHOOT_POWERUP );
00443         break;
00444     }
00445     if ( nPup )
00446     {
00447         double r = 0.5 - randDouble();
00448         nPup->move( hit->x(), hit->y(), 0 );
00449         nPup->setVelocity( hit->xVelocity() + r, hit->yVelocity() + r );
00450         nPup->show( );
00451         powerups.append( nPup );
00452     }
00453 
00454     if ( hit->rtti() == ID_ROCK_LARGE || hit->rtti() == ID_ROCK_MEDIUM )
00455     {
00456         // break into smaller rocks
00457         double addx[4] = { 1.0, 1.0, -1.0, -1.0 };
00458         double addy[4] = { -1.0, 1.0, -1.0, 1.0 };
00459 
00460         double dx = hit->xVelocity();
00461         double dy = hit->yVelocity();
00462 
00463         double maxRockSpeed = MAX_ROCK_SPEED * rockSpeed;
00464         if ( dx > maxRockSpeed )
00465             dx = maxRockSpeed;
00466         else if ( dx < -maxRockSpeed )
00467             dx = -maxRockSpeed;
00468         if ( dy > maxRockSpeed )
00469             dy = maxRockSpeed;
00470         else if ( dy < -maxRockSpeed )
00471             dy = -maxRockSpeed;
00472 
00473         QCanvasSprite *nrock;
00474 
00475         for ( int i = 0; i < 4; i++ )
00476         {
00477             double r = rockSpeed/2 - randDouble()*rockSpeed;
00478             if ( hit->rtti() == ID_ROCK_LARGE )
00479             {
00480                 nrock = new KRock( animation[ID_ROCK_MEDIUM], &field,
00481                                ID_ROCK_MEDIUM, randInt(2), randInt(2) ? -1 : 1 );
00482                 emit rockHit( 0 );
00483             }
00484             else
00485             {
00486                 nrock = new KRock( animation[ID_ROCK_SMALL], &field,
00487                                ID_ROCK_SMALL, randInt(2), randInt(2) ? -1 : 1 );
00488                 emit rockHit( 1 );
00489             }
00490 
00491             nrock->move( hit->x(), hit->y(), 0 );
00492             nrock->setVelocity( dx+addx[i]*rockSpeed+r, dy+addy[i]*rockSpeed+r );
00493             nrock->setFrame( randInt( nrock->frameCount() ) );
00494             nrock->show( );
00495             rocks.append( nrock );
00496         }
00497     }
00498     else if ( hit->rtti() == ID_ROCK_SMALL )
00499         emit rockHit( 2 );
00500     rocks.removeRef( (QCanvasSprite *)hit );
00501     if ( rocks.count() == 0 )
00502         emit rocksRemoved();
00503 }
00504 
00505 void KAsteroidsView::reducePower( int val )
00506 {
00507     shipPower -= val;
00508     if ( shipPower <= 0 )
00509     {
00510         shipPower = 0;
00511         thrustShip = FALSE;
00512         if ( shieldOn )
00513         {
00514             shieldOn = FALSE;
00515             shield->hide();
00516         }
00517     }
00518     vitalsChanged = TRUE;
00519 }
00520 
00521 void KAsteroidsView::addExhaust( double x, double y, double dx,
00522                                  double dy, int count )
00523 {
00524     for ( int i = 0; i < count; i++ )
00525     {
00526         KExhaust *e = new KExhaust( animation[ID_EXHAUST], &field );
00527         e->move( x + 2 - randDouble()*4, y + 2 - randDouble()*4 );
00528         e->setVelocity( dx, dy );
00529         e->show( );
00530         exhaust.append( e );
00531     }
00532 }
00533 
00534 void KAsteroidsView::processMissiles()
00535 {
00536     KMissile *missile;
00537 
00538     // if a missile has hit a rock, remove missile and break rock into smaller
00539     // rocks or remove completely.
00540     QPtrListIterator<KMissile> it(missiles);
00541 
00542     for ( ; it.current(); ++it )
00543     {
00544         missile = it.current();
00545         missile->growOlder();
00546 
00547         if ( missile->expired() )
00548         {
00549             missiles.removeRef( missile );
00550             continue;
00551         }
00552 
00553         wrapSprite( missile );
00554 
00555         QCanvasItemList hits = missile->collisions( TRUE );
00556         QCanvasItemList::Iterator hit;
00557         for ( hit = hits.begin(); hit != hits.end(); ++hit )
00558         {
00559             if ( (*hit)->rtti() >= ID_ROCK_LARGE &&
00560                  (*hit)->rtti() <= ID_ROCK_SMALL )
00561             {
00562                 shotsHit++;
00563                 rockHit( *hit );
00564                 missiles.removeRef( missile );
00565                 break;
00566             }
00567         }
00568     }
00569 }
00570 
00571 // - - -
00572 
00573 void KAsteroidsView::processShip()
00574 {
00575     if ( ship->visible() )
00576     {
00577         if ( shieldOn )
00578         {
00579             shield->show();
00580             reducePower( SHIELD_ON_COST );
00581             static int sf = 0;
00582             sf++;
00583 
00584             if ( sf % 2 )
00585                 shield->setFrame( (shield->frame()+1) % shield->frameCount() );
00586             shield->move( ship->x() - 5, ship->y() - 5 );
00587 
00588             QCanvasItemList hits = shield->collisions( TRUE );
00589             QCanvasItemList::Iterator it;
00590             for ( it = hits.begin(); it != hits.end(); ++it )
00591             {
00592                 if ( (*it)->rtti() >= ID_ROCK_LARGE &&
00593                      (*it)->rtti() <= ID_ROCK_SMALL )
00594                 {
00595                     int factor;
00596                     switch ( (*it)->rtti() )
00597                     {
00598                         case ID_ROCK_LARGE:
00599                             factor = 3;
00600                             break;
00601 
00602                         case ID_ROCK_MEDIUM:
00603                             factor = 2;
00604                             break;
00605 
00606                         default:
00607                             factor = 1;
00608                     }
00609 
00610                     if ( factor > mShieldCount )
00611                     {
00612                         // shield not strong enough
00613                         shieldOn = FALSE;
00614                         break;
00615                     }
00616                     rockHit( *it );
00617                     // the more shields we have the less costly
00618                     reducePower( factor * (SHIELD_HIT_COST - mShieldCount*2) );
00619                 }
00620             }
00621         }
00622 
00623         if ( !shieldOn )
00624         {
00625             shield->hide();
00626             QCanvasItemList hits = ship->collisions( TRUE );
00627             QCanvasItemList::Iterator it;
00628             for ( it = hits.begin(); it != hits.end(); ++it )
00629             {
00630                 if ( (*it)->rtti() >= ID_ROCK_LARGE &&
00631                      (*it)->rtti() <= ID_ROCK_SMALL )
00632                 {
00633                     KBit *bit;
00634                     for ( int i = 0; i < 8; i++ )
00635                     {
00636                       bit = new KBit( animation[ID_BIT], &field );
00637                       bit->move( ship->x() + 5 - randDouble() * 10,
00638                                  ship->y() + 5 - randDouble() * 10,
00639                                  randInt(bit->frameCount()) );
00640                       bit->setVelocity( 1-randDouble()*2,
00641                                         1-randDouble()*2 );
00642                       bit->setDeath( 60 + randInt(60) );
00643                       bit->show( );
00644                       bits.append( bit );
00645                     }
00646                     ship->hide();
00647                     shield->hide();
00648                     emit shipKilled();
00649                     break;
00650                 }
00651             }
00652         }
00653 
00654 
00655         if ( rotateSlow )
00656             rotateSlow--;
00657 
00658         if ( rotateL )
00659         {
00660             shipAngle -= rotateSlow ? 1 : rotateRate;
00661             if ( shipAngle < 0 )
00662                 shipAngle += SHIP_STEPS;
00663         }
00664 
00665         if ( rotateR )
00666         {
00667             shipAngle += rotateSlow ? 1 : rotateRate;
00668             if ( shipAngle >= SHIP_STEPS )
00669                 shipAngle -= SHIP_STEPS;
00670         }
00671 
00672         double angle = shipAngle * PI_X_2 / SHIP_STEPS;
00673         double cosangle = cos( angle );
00674         double sinangle = sin( angle );
00675 
00676         if ( brakeShip )
00677         {
00678             thrustShip = FALSE;
00679             rotateL = FALSE;
00680             rotateR = FALSE;
00681             rotateRate = ROTATE_RATE;
00682             if ( fabs(shipDx) < 2.5 && fabs(shipDy) < 2.5 )
00683             {
00684                 shipDx = 0.0;
00685                 shipDy = 0.0;
00686                 ship->setVelocity( shipDx, shipDy );
00687                 brakeShip = FALSE;
00688             }
00689             else
00690             {
00691                 double motionAngle = atan2( -shipDy, -shipDx );
00692                 if ( angle > M_PI )
00693                     angle -= PI_X_2;
00694                 double angleDiff = angle - motionAngle;
00695                 if ( angleDiff > M_PI )
00696                     angleDiff = PI_X_2 - angleDiff;
00697                 else if ( angleDiff < -M_PI )
00698                     angleDiff = PI_X_2 + angleDiff;
00699                 double fdiff = fabs( angleDiff );
00700                 if ( fdiff > 0.08 )
00701                 {
00702                     if ( angleDiff > 0 )
00703                         rotateL = TRUE;
00704                     else if ( angleDiff < 0 )
00705                         rotateR = TRUE;
00706                     if ( fdiff > 0.6 )
00707                         rotateRate = mBrakeCount + 1;
00708                     else if ( fdiff > 0.4 )
00709                         rotateRate = 2;
00710                     else
00711                         rotateRate = 1;
00712 
00713                     if ( rotateRate > 5 )
00714                         rotateRate = 5;
00715                 }
00716                 else if ( fabs(shipDx) > 1 || fabs(shipDy) > 1 )
00717                 {
00718                     thrustShip = TRUE;
00719                     // we'll make braking a bit faster
00720                     shipDx += cosangle/6 * (mBrakeCount - 1);
00721                     shipDy += sinangle/6 * (mBrakeCount - 1);
00722                     reducePower( BRAKE_ON_COST );
00723                     addExhaust( ship->x() + 10 - cosangle*11,
00724                                 ship->y() + 10 - sinangle*11,
00725                                 shipDx-cosangle, shipDy-sinangle,
00726                                 mBrakeCount+1 );
00727                 }
00728             }
00729         }
00730 
00731         if ( thrustShip )
00732         {
00733             // The ship has a terminal velocity, but trying to go faster
00734             // still uses fuel (can go faster diagonally - don't care).
00735             double thrustx = cosangle/8;
00736             double thrusty = sinangle/8;
00737             if ( fabs(shipDx + thrustx) < MAX_SHIP_SPEED )
00738                 shipDx += thrustx;
00739             if ( fabs(shipDy + thrusty) < MAX_SHIP_SPEED )
00740                 shipDy += thrusty;
00741             ship->setVelocity( shipDx, shipDy );
00742             reducePower( 1 );
00743             addExhaust( ship->x() + 10 - cosangle*10,
00744                         ship->y() + 10 - sinangle*10,
00745                         shipDx-cosangle, shipDy-sinangle, 3 );
00746         }
00747 
00748         ship->setFrame( shipAngle >> 1 );
00749 
00750         if ( shootShip )
00751         {
00752             if ( !shootDelay && (int)missiles.count() < mShootCount + 2 )
00753             {
00754               KMissile *missile = new KMissile( animation[ID_MISSILE], &field );
00755               missile->move( 11+ship->x()+cosangle*11,
00756                              11+ship->y()+sinangle*11, 0 );
00757               missile->setVelocity( shipDx + cosangle*MISSILE_SPEED,
00758                                     shipDy + sinangle*MISSILE_SPEED );
00759               missile->show( );
00760               missiles.append( missile );
00761               shotsFired++;
00762               reducePower( 1 );
00763 
00764               shootDelay = 5;
00765             }
00766 
00767             if ( shootDelay )
00768               shootDelay--;
00769         }
00770 
00771         if ( teleportShip )
00772         {
00773             int ra = rand() % 10;
00774             if( ra == 0 )
00775             ra += rand() % 20;
00776             int xra = ra * 60 + ( (rand() % 20) * (rand() % 20) );
00777             int yra = ra * 50 - ( (rand() % 20) * (rand() % 20) );
00778             ship->move( xra, yra );
00779         }
00780 
00781         vitalsChanged = TRUE;
00782     }
00783 }
00784 
00785 // - - -
00786 
00787 void KAsteroidsView::processPowerups()
00788 {
00789     if ( !powerups.isEmpty() )
00790     {
00791         // if player gets the powerup remove it from the screen, if option
00792         // "Can destroy powerups" is enabled and a missile hits the powerup
00793         // destroy it
00794 
00795         KPowerup *pup;
00796         QPtrListIterator<KPowerup> it( powerups );
00797 
00798         for( ; it.current(); ++it )
00799         {
00800             pup = it.current();
00801             pup->growOlder();
00802 
00803             if( pup->expired() )
00804             {
00805                 powerups.removeRef( pup );
00806                 continue;
00807             }
00808 
00809             wrapSprite( pup );
00810 
00811             QCanvasItemList hits = pup->collisions( TRUE );
00812             QCanvasItemList::Iterator it;
00813             for ( it = hits.begin(); it != hits.end(); ++it )
00814             {
00815                 if ( (*it) == ship )
00816                 {
00817                     switch( pup->rtti() )
00818                     {
00819                       case ID_ENERGY_POWERUP:
00820                         shipPower += 150;
00821                         if ( shipPower > MAX_POWER_LEVEL )
00822                             shipPower = MAX_POWER_LEVEL;
00823                         break;
00824                       case ID_TELEPORT_POWERUP:
00825                         mTeleportCount++;
00826                         break;
00827                       case ID_BRAKE_POWERUP:
00828                         if ( mBrakeCount < MAX_BRAKES )
00829                             mBrakeCount++;
00830                         break;
00831                       case ID_SHIELD_POWERUP:
00832                         if ( mShieldCount < MAX_SHIELDS )
00833                             mShieldCount++;
00834                         break;
00835                       case ID_SHOOT_POWERUP:
00836                         if ( mShootCount < MAX_FIREPOWER )
00837                             mShootCount++;
00838                         break;
00839                     }
00840 
00841                     powerups.removeRef( pup );
00842                     vitalsChanged = TRUE;
00843                 }
00844                 else if ( (*it) == shield )
00845                 {
00846                     powerups.removeRef( pup );
00847                 }
00848                 else if ( (*it)->rtti() == ID_MISSILE )
00849                 {
00850                     if ( can_destroy_powerups )
00851                     {
00852                       powerups.removeRef( pup );
00853                     }
00854                 }
00855             }
00856         }
00857     }         // -- if( powerups.isEmpty() )
00858 }
00859 
00860 // - - -
00861 
00862 void KAsteroidsView::hideShield()
00863 {
00864     shield->hide();
00865     mShieldCount = 0;
00866     shieldOn = FALSE;
00867 }
00868 
00869 double KAsteroidsView::randDouble()
00870 {
00871     int v = rand();
00872     return (double)v / (double)RAND_MAX;
00873 }
00874 
00875 int KAsteroidsView::randInt( int range )
00876 {
00877     return rand() % range;
00878 }

Generated on Sat Nov 5 16:15:53 2005 for OPIE by  doxygen 1.4.2