source: trunk/examples/graphicsview/portedasteroids/view.cpp@ 342

Last change on this file since 342 was 2, checked in by Dmitry A. Kuminov, 16 years ago

Initially imported qt-all-opensource-src-4.5.1 from Trolltech.

File size: 23.8 KB
Line 
1/****************************************************************************
2**
3** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
4** Contact: Qt Software Information ([email protected])
5**
6** This file is part of the examples of the Qt Toolkit.
7**
8** $QT_BEGIN_LICENSE:LGPL$
9** Commercial Usage
10** Licensees holding valid Qt Commercial licenses may use this file in
11** accordance with the Qt Commercial License Agreement provided with the
12** Software or, alternatively, in accordance with the terms contained in
13** a written agreement between you and Nokia.
14**
15** GNU Lesser General Public License Usage
16** Alternatively, this file may be used under the terms of the GNU Lesser
17** General Public License version 2.1 as published by the Free Software
18** Foundation and appearing in the file LICENSE.LGPL included in the
19** packaging of this file. Please review the following information to
20** ensure the GNU Lesser General Public License version 2.1 requirements
21** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
22**
23** In addition, as a special exception, Nokia gives you certain
24** additional rights. These rights are described in the Nokia Qt LGPL
25** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
26** package.
27**
28** GNU General Public License Usage
29** Alternatively, this file may be used under the terms of the GNU
30** General Public License version 3.0 as published by the Free Software
31** Foundation and appearing in the file LICENSE.GPL included in the
32** packaging of this file. Please review the following information to
33** ensure the GNU General Public License version 3.0 requirements will be
34** met: http://www.gnu.org/copyleft/gpl.html.
35**
36** If you are unsure which license is appropriate for your use, please
37** contact the sales department at [email protected].
38** $QT_END_LICENSE$
39**
40****************************************************************************/
41
42/*
43 * KAsteroids - Copyright (c) Martin R. Jones 1997
44 *
45 * Part of the KDE project
46 */
47
48#include <stdlib.h>
49#include <math.h>
50#include <qapplication.h>
51#include <qnamespace.h>
52#include <q3accel.h>
53#include <qmessagebox.h>
54#include <q3scrollview.h>
55#include <qdir.h>
56#include <QGraphicsItem>
57//Added by qt3to4:
58#include <QTimerEvent>
59#include <QPixmap>
60#include <QResizeEvent>
61#include <QShowEvent>
62
63#include "view.h"
64
65#define IMG_BACKGROUND ":/trolltech/examples/graphicsview/portedasteroids/bg.png"
66
67#define REFRESH_DELAY 33
68#define SHIP_SPEED 0.3
69#define MISSILE_SPEED 10.0
70#define SHIP_STEPS 64
71#define ROTATE_RATE 2
72#define SHIELD_ON_COST 1
73#define SHIELD_HIT_COST 30
74#define BRAKE_ON_COST 4
75
76#define MAX_ROCK_SPEED 2.5
77#define MAX_POWERUP_SPEED 1.5
78#define MAX_SHIP_SPEED 12
79#define MAX_BRAKES 5
80#define MAX_SHIELDS 5
81#define MAX_FIREPOWER 5
82
83#define TEXT_SPEED 4
84
85#define PI_X_2 6.283185307
86#ifndef M_PI
87#define M_PI 3.141592654
88#endif
89
90static struct
91{
92 int id;
93 const char *path;
94 int frames;
95}
96kas_animations [] =
97{
98 { ID_ROCK_LARGE, "rock1/rock1%1.png", 32 },
99 { ID_ROCK_MEDIUM, "rock2/rock2%1.png", 32 },
100 { ID_ROCK_SMALL, "rock3/rock3%1.png", 32 },
101 { ID_SHIP, "ship/ship%1.png", 32 },
102 { ID_MISSILE, "missile/missile.png", 1 },
103 { ID_BIT, "bits/bits%1.png", 16 },
104 { ID_EXHAUST, "exhaust/exhaust.png", 1 },
105 { ID_ENERGY_POWERUP, "powerups/energy.png", 1 },
106// { ID_TELEPORT_POWERUP, "powerups/teleport%1.png", 12 },
107 { ID_BRAKE_POWERUP, "powerups/brake.png", 1 },
108 { ID_SHIELD_POWERUP, "powerups/shield.png", 1 },
109 { ID_SHOOT_POWERUP, "powerups/shoot.png", 1 },
110 { ID_SHIELD, "shield/shield%1.png", 6 },
111 { 0, 0, 0 }
112};
113
114KAsteroidsView::KAsteroidsView( QWidget *parent, const char *name )
115 : QWidget( parent, name ),
116 field(0, 0, 640, 440),
117 view(&field,this)
118{
119 view.setVerticalScrollBarPolicy( Qt::ScrollBarAlwaysOff );
120 view.setHorizontalScrollBarPolicy( Qt::ScrollBarAlwaysOff );
121 view.setCacheMode(QGraphicsView::CacheBackground);
122 view.setViewportUpdateMode(QGraphicsView::BoundingRectViewportUpdate);
123 view.setOptimizationFlags(QGraphicsView::DontClipPainter
124 | QGraphicsView::DontSavePainterState
125 | QGraphicsView::DontAdjustForAntialiasing);
126 view.viewport()->setFocusProxy( this );
127 rocks.setAutoDelete( TRUE );
128 missiles.setAutoDelete( TRUE );
129 bits.setAutoDelete( TRUE );
130 powerups.setAutoDelete( TRUE );
131 exhaust.setAutoDelete( TRUE );
132
133 QPixmap pm( IMG_BACKGROUND );
134 field.setBackgroundBrush( pm );
135
136 textSprite = new QGraphicsTextItem( 0, &field );
137 QFont font( "helvetica", 18 );
138 textSprite->setFont( font );
139 textSprite->setCacheMode(QGraphicsItem::DeviceCoordinateCache);
140
141 shield = 0;
142 shieldOn = FALSE;
143 refreshRate = REFRESH_DELAY;
144
145 initialized = readSprites();
146
147 shieldTimer = new QTimer( this );
148 connect( shieldTimer, SIGNAL(timeout()), this, SLOT(hideShield()) );
149 mTimerId = -1;
150
151 shipPower = MAX_POWER_LEVEL;
152 vitalsChanged = TRUE;
153 can_destroy_powerups = FALSE;
154
155 mPaused = TRUE;
156
157 if ( !initialized ) {
158 textSprite->setHtml( tr("<font color=red>Error: Cannot read sprite images</font>") );
159 textSprite->setPos( (field.width()-textSprite->boundingRect().width()) / 2,
160 (field.height()-textSprite->boundingRect().height()) / 2 );
161 }
162}
163
164// - - -
165
166KAsteroidsView::~KAsteroidsView()
167{
168}
169
170// - - -
171
172void KAsteroidsView::reset()
173{
174 if ( !initialized )
175 return;
176 rocks.clear();
177 missiles.clear();
178 bits.clear();
179 powerups.clear();
180 exhaust.clear();
181
182 shotsFired = 0;
183 shotsHit = 0;
184
185 rockSpeed = 1.0;
186 powerupSpeed = 1.0;
187 mFrameNum = 0;
188 mPaused = FALSE;
189
190 ship->hide();
191 shield->hide();
192/*
193 if ( mTimerId >= 0 ) {
194 killTimer( mTimerId );
195 mTimerId = -1;
196 }
197*/
198}
199
200// - --
201
202void KAsteroidsView::newGame()
203{
204 if ( !initialized )
205 return;
206 if ( shieldOn )
207 {
208 shield->hide();
209 shieldOn = FALSE;
210 }
211 reset();
212 if ( mTimerId < 0 )
213 mTimerId = startTimer( REFRESH_DELAY );
214 emit updateVitals();
215}
216
217// - - -
218
219void KAsteroidsView::endGame()
220{
221}
222
223void KAsteroidsView::pause( bool p )
224{
225 if ( !initialized )
226 return;
227 if ( !mPaused && p ) {
228 if ( mTimerId >= 0 ) {
229 killTimer( mTimerId );
230 mTimerId = -1;
231 }
232 } else if ( mPaused && !p )
233 mTimerId = startTimer( REFRESH_DELAY );
234 mPaused = p;
235}
236
237// - - -
238
239void KAsteroidsView::newShip()
240{
241 if ( !initialized )
242 return;
243 ship->setPos( width()/2, height()/2 );
244 ship->setFrame( 0 );
245 shield->setPos( width()/2, height()/2 );
246 shield->setFrame( 0 );
247 ship->setVelocity( 0.0, 0.0 );
248 shipDx = 0;
249 shipDy = 0;
250 shipAngle = 0;
251 rotateL = FALSE;
252 rotateR = FALSE;
253 thrustShip = FALSE;
254 shootShip = FALSE;
255 brakeShip = FALSE;
256 teleportShip = FALSE;
257 shieldOn = TRUE;
258 shootDelay = 0;
259 shipPower = MAX_POWER_LEVEL;
260 rotateRate = ROTATE_RATE;
261 rotateSlow = 0;
262
263 mBrakeCount = 0;
264 mTeleportCount = 0;
265 mShootCount = 0;
266
267 ship->show();
268 shield->show();
269 mShieldCount = 1; // just in case the ship appears on a rock.
270 shieldTimer->start( 1000, TRUE );
271}
272
273void KAsteroidsView::setShield( bool s )
274{
275 if ( !initialized )
276 return;
277 if ( shieldTimer->isActive() && !s ) {
278 shieldTimer->stop();
279 hideShield();
280 } else {
281 shieldOn = s && mShieldCount;
282 }
283}
284
285void KAsteroidsView::brake( bool b )
286{
287 if ( !initialized )
288 return;
289 if ( mBrakeCount )
290 {
291 if ( brakeShip && !b )
292 {
293 rotateL = FALSE;
294 rotateR = FALSE;
295 thrustShip = FALSE;
296 rotateRate = ROTATE_RATE;
297 }
298
299 brakeShip = b;
300 }
301}
302
303// - - -
304
305bool KAsteroidsView::readSprites()
306{
307 QString sprites_prefix = ":/trolltech/examples/graphicsview/portedasteroids/sprites/";
308
309 int i = 0;
310 while ( kas_animations[i].id )
311 {
312 QList<QPixmap> anim;
313 QString wildcard = sprites_prefix + kas_animations[i].path;
314 wildcard.replace("%1", "*");
315 QFileInfo fi(wildcard);
316 foreach (QString entry, QDir(fi.path(), fi.fileName()).entryList())
317 anim << QPixmap(fi.path() + "/" + entry);
318 animation.insert( kas_animations[i].id, anim );
319 i++;
320 }
321
322 ship = new AnimatedPixmapItem( animation[ID_SHIP], &field );
323 ship->hide();
324
325 shield = new KShield( animation[ID_SHIELD], &field );
326 shield->hide();
327
328 return (!ship->image(0).isNull() && !shield->image(0).isNull());
329}
330
331// - - -
332
333void KAsteroidsView::addRocks( int num )
334{
335 if ( !initialized )
336 return;
337 for ( int i = 0; i < num; i++ )
338 {
339 KRock *rock = new KRock( animation[ID_ROCK_LARGE], &field,
340 ID_ROCK_LARGE, randInt(2), randInt(2) ? -1 : 1 );
341 double dx = (2.0 - randDouble()*4.0) * rockSpeed;
342 double dy = (2.0 - randDouble()*4.0) * rockSpeed;
343 rock->setVelocity( dx, dy );
344 rock->setFrame( randInt( rock->frameCount() ) );
345 if ( dx > 0 )
346 {
347 if ( dy > 0 )
348 rock->setPos( 5, 5 );
349 else
350 rock->setPos( 5, field.height() - 25 );
351 rock->setFrame( 0 );
352 }
353 else
354 {
355 if ( dy > 0 )
356 rock->setPos( field.width() - 25, 5 );
357 else
358 rock->setPos( field.width() - 25, field.height() - 25 );
359 rock->setFrame( 0 );
360 }
361 rock->show();
362 rocks.append( rock );
363 }
364}
365
366// - - -
367
368void KAsteroidsView::showText( const QString &text, const QColor &color, bool scroll )
369{
370 if ( !initialized )
371 return;
372 textSprite->setHtml( QString("<font color=#%1%2%3>%4</font>")
373 .arg(color.red(), 2, 16, QLatin1Char('0'))
374 .arg(color.green(), 2, 16, QLatin1Char('0'))
375 .arg(color.blue(), 2, 16, QLatin1Char('0'))
376 .arg(text) );
377 Q_UNUSED(color);
378 // ### Porting: no such thing textSprite->setColor( color );
379
380 if ( scroll ) {
381 textSprite->setPos( (field.width()-textSprite->boundingRect().width()) / 2,
382 -textSprite->boundingRect().height() );
383 textDy = TEXT_SPEED;
384 } else {
385 textSprite->setPos( (field.width()-textSprite->boundingRect().width()) / 2,
386 (field.height()-textSprite->boundingRect().height()) / 2 );
387 textDy = 0;
388 }
389 textSprite->show();
390}
391
392// - - -
393
394void KAsteroidsView::hideText()
395{
396 textDy = -TEXT_SPEED;
397}
398
399// - - -
400
401void KAsteroidsView::resizeEvent(QResizeEvent* event)
402{
403 QWidget::resizeEvent(event);
404 field.setSceneRect(0, 0, width()-4, height()-4);
405 view.resize(width(),height());
406}
407
408// - - -
409
410void KAsteroidsView::timerEvent( QTimerEvent * )
411{
412 field.advance();
413
414 AnimatedPixmapItem *rock;
415
416 // move rocks forward
417 for ( rock = rocks.first(); rock; rock = rocks.next() ) {
418 ((KRock *)rock)->nextFrame();
419 wrapSprite( rock );
420 }
421
422 wrapSprite( ship );
423
424 // check for missile collision with rocks.
425 processMissiles();
426
427 // these are generated when a ship explodes
428 for ( KBit *bit = bits.first(); bit; bit = bits.next() )
429 {
430 if ( bit->expired() )
431 {
432 bits.removeRef( bit );
433 }
434 else
435 {
436 bit->growOlder();
437 bit->setFrame( ( bit->frame()+1 ) % bit->frameCount() );
438 }
439 }
440
441 for ( KExhaust *e = exhaust.first(); e; e = exhaust.next() )
442 exhaust.removeRef( e );
443
444 // move / rotate ship.
445 // check for collision with a rock.
446 processShip();
447
448 // move powerups and check for collision with player and missiles
449 processPowerups();
450
451 if ( textSprite->isVisible() )
452 {
453 if ( textDy < 0 &&
454 textSprite->boundingRect().y() <= -textSprite->boundingRect().height() ) {
455 textSprite->hide();
456 } else {
457 textSprite->moveBy( 0, textDy );
458 }
459
460 if ( textSprite->sceneBoundingRect().y() > (field.height()-textSprite->boundingRect().height())/2 )
461 textDy = 0;
462 }
463
464 if ( vitalsChanged && !(mFrameNum % 10) ) {
465 emit updateVitals();
466 vitalsChanged = FALSE;
467 }
468
469 mFrameNum++;
470}
471
472void KAsteroidsView::wrapSprite( QGraphicsItem *s )
473{
474 int x = int(s->x() + s->boundingRect().width() / 2);
475 int y = int(s->y() + s->boundingRect().height() / 2);
476
477 if ( x > field.width() )
478 s->setPos( s->x() - field.width(), s->y() );
479 else if ( x < 0 )
480 s->setPos( field.width() + s->x(), s->y() );
481
482 if ( y > field.height() )
483 s->setPos( s->x(), s->y() - field.height() );
484 else if ( y < 0 )
485 s->setPos( s->x(), field.height() + s->y() );
486}
487
488// - - -
489
490void KAsteroidsView::rockHit( AnimatedPixmapItem *hit )
491{
492 KPowerup *nPup = 0;
493 int rnd = int(randDouble()*30.0) % 30;
494 switch( rnd )
495 {
496 case 4:
497 case 5:
498 nPup = new KPowerup( animation[ID_ENERGY_POWERUP], &field,
499 ID_ENERGY_POWERUP );
500 break;
501 case 10:
502// nPup = new KPowerup( animation[ID_TELEPORT_POWERUP], &field,
503// ID_TELEPORT_POWERUP );
504 break;
505 case 15:
506 nPup = new KPowerup( animation[ID_BRAKE_POWERUP], &field,
507 ID_BRAKE_POWERUP );
508 break;
509 case 20:
510 nPup = new KPowerup( animation[ID_SHIELD_POWERUP], &field,
511 ID_SHIELD_POWERUP );
512 break;
513 case 24:
514 case 25:
515 nPup = new KPowerup( animation[ID_SHOOT_POWERUP], &field,
516 ID_SHOOT_POWERUP );
517 break;
518 }
519 if ( nPup )
520 {
521 double r = 0.5 - randDouble();
522 nPup->setPos( hit->x(), hit->y() );
523 nPup->setFrame( 0 );
524 nPup->setVelocity( hit->xVelocity() + r, hit->yVelocity() + r );
525 powerups.append( nPup );
526 }
527
528 if ( hit->type() == ID_ROCK_LARGE || hit->type() == ID_ROCK_MEDIUM )
529 {
530 // break into smaller rocks
531 double addx[4] = { 1.0, 1.0, -1.0, -1.0 };
532 double addy[4] = { -1.0, 1.0, -1.0, 1.0 };
533
534 double dx = hit->xVelocity();
535 double dy = hit->yVelocity();
536
537 double maxRockSpeed = MAX_ROCK_SPEED * rockSpeed;
538 if ( dx > maxRockSpeed )
539 dx = maxRockSpeed;
540 else if ( dx < -maxRockSpeed )
541 dx = -maxRockSpeed;
542 if ( dy > maxRockSpeed )
543 dy = maxRockSpeed;
544 else if ( dy < -maxRockSpeed )
545 dy = -maxRockSpeed;
546
547 AnimatedPixmapItem *nrock;
548
549 for ( int i = 0; i < 4; i++ )
550 {
551 double r = rockSpeed/2 - randDouble()*rockSpeed;
552 if ( hit->type() == ID_ROCK_LARGE )
553 {
554 nrock = new KRock( animation[ID_ROCK_MEDIUM], &field,
555 ID_ROCK_MEDIUM, randInt(2), randInt(2) ? -1 : 1 );
556 emit rockHit( 0 );
557 }
558 else
559 {
560 nrock = new KRock( animation[ID_ROCK_SMALL], &field,
561 ID_ROCK_SMALL, randInt(2), randInt(2) ? -1 : 1 );
562 emit rockHit( 1 );
563 }
564
565 nrock->setPos( hit->x(), hit->y() );
566 nrock->setFrame( 0 );
567 nrock->setVelocity( dx+addx[i]*rockSpeed+r, dy+addy[i]*rockSpeed+r );
568 nrock->setFrame( randInt( nrock->frameCount() ) );
569 rocks.append( nrock );
570 }
571 }
572 else if ( hit->type() == ID_ROCK_SMALL )
573 emit rockHit( 2 );
574 rocks.removeRef( hit );
575 if ( rocks.count() == 0 )
576 emit rocksRemoved();
577}
578
579void KAsteroidsView::reducePower( int val )
580{
581 shipPower -= val;
582 if ( shipPower <= 0 )
583 {
584 shipPower = 0;
585 thrustShip = FALSE;
586 if ( shieldOn )
587 {
588 shieldOn = FALSE;
589 shield->hide();
590 }
591 }
592 vitalsChanged = TRUE;
593}
594
595void KAsteroidsView::addExhaust( double x, double y, double dx,
596 double dy, int count )
597{
598 for ( int i = 0; i < count; i++ )
599 {
600 KExhaust *e = new KExhaust( animation[ID_EXHAUST], &field );
601 e->setPos( x + 2 - randDouble()*4, y + 2 - randDouble()*4 );
602 e->setVelocity( dx, dy );
603 exhaust.append( e );
604 }
605}
606
607void KAsteroidsView::processMissiles()
608{
609 KMissile *missile;
610
611 // if a missile has hit a rock, remove missile and break rock into smaller
612 // rocks or remove completely.
613 Q3PtrListIterator<KMissile> it(missiles);
614
615 for ( ; it.current(); ++it )
616 {
617 missile = it.current();
618 missile->growOlder();
619
620 if ( missile->expired() )
621 {
622 missiles.removeRef( missile );
623 continue;
624 }
625
626 wrapSprite( missile );
627
628 QList<QGraphicsItem *> hits = missile->collidingItems(Qt::IntersectsItemBoundingRect);
629 QList<QGraphicsItem *>::Iterator hit;
630 for ( hit = hits.begin(); hit != hits.end(); ++hit )
631 {
632 if ( (*hit)->type() >= ID_ROCK_LARGE &&
633 (*hit)->type() <= ID_ROCK_SMALL && (*hit)->collidesWithItem(missile) )
634 {
635 shotsHit++;
636 rockHit( static_cast<AnimatedPixmapItem *>(*hit) );
637 missiles.removeRef( missile );
638 break;
639 }
640 }
641 }
642}
643
644// - - -
645
646void KAsteroidsView::processShip()
647{
648 if ( ship->isVisible() )
649 {
650 if ( shieldOn )
651 {
652 shield->show();
653 reducePower( SHIELD_ON_COST );
654 static int sf = 0;
655 sf++;
656
657 if ( sf % 2 )
658 shield->setFrame( (shield->frame()+1) % shield->frameCount() );
659 shield->setPos( ship->x() - 9, ship->y() - 9 );
660
661 QList<QGraphicsItem *> hits = shield->collidingItems(Qt::IntersectsItemBoundingRect);
662 QList<QGraphicsItem *>::Iterator it;
663 for ( it = hits.begin(); it != hits.end(); ++it )
664 {
665 if ( (*it)->type() >= ID_ROCK_LARGE &&
666 (*it)->type() <= ID_ROCK_SMALL && (*it)->collidesWithItem(shield) )
667 {
668 int factor;
669 switch ( (*it)->type() )
670 {
671 case ID_ROCK_LARGE:
672 factor = 3;
673 break;
674
675 case ID_ROCK_MEDIUM:
676 factor = 2;
677 break;
678
679 default:
680 factor = 1;
681 }
682
683 if ( factor > mShieldCount )
684 {
685 // shield not strong enough
686 shieldOn = FALSE;
687 break;
688 }
689 rockHit( static_cast<AnimatedPixmapItem *>(*it) );
690 // the more shields we have the less costly
691 reducePower( factor * (SHIELD_HIT_COST - mShieldCount*2) );
692 }
693 }
694 }
695
696 if ( !shieldOn )
697 {
698 shield->hide();
699 QList<QGraphicsItem *> hits = ship->collidingItems(Qt::IntersectsItemBoundingRect);
700 QList<QGraphicsItem *>::Iterator it;
701 for ( it = hits.begin(); it != hits.end(); ++it )
702 {
703 if ( (*it)->type() >= ID_ROCK_LARGE &&
704 (*it)->type() <= ID_ROCK_SMALL && (*it)->collidesWithItem(ship))
705 {
706 KBit *bit;
707 for ( int i = 0; i < 12; i++ )
708 {
709 bit = new KBit( animation[ID_BIT], &field );
710 bit->setPos( ship->x() + 5 - randDouble() * 10,
711 ship->y() + 5 - randDouble() * 10 );
712 bit->setFrame( randInt(bit->frameCount()) );
713 bit->setVelocity( 1-randDouble()*2,
714 1-randDouble()*2 );
715 bit->setDeath( 60 + randInt(60) );
716 bits.append( bit );
717 }
718 ship->hide();
719 shield->hide();
720 emit shipKilled();
721 break;
722 }
723 }
724 }
725
726
727 if ( rotateSlow )
728 rotateSlow--;
729
730 if ( rotateL )
731 {
732 shipAngle -= rotateSlow ? 1 : rotateRate;
733 if ( shipAngle < 0 )
734 shipAngle += SHIP_STEPS;
735 }
736
737 if ( rotateR )
738 {
739 shipAngle += rotateSlow ? 1 : rotateRate;
740 if ( shipAngle >= SHIP_STEPS )
741 shipAngle -= SHIP_STEPS;
742 }
743
744 double angle = shipAngle * PI_X_2 / SHIP_STEPS;
745 double cosangle = cos( angle );
746 double sinangle = sin( angle );
747
748 if ( brakeShip )
749 {
750 thrustShip = FALSE;
751 rotateL = FALSE;
752 rotateR = FALSE;
753 rotateRate = ROTATE_RATE;
754 if ( fabs(shipDx) < 2.5 && fabs(shipDy) < 2.5 )
755 {
756 shipDx = 0.0;
757 shipDy = 0.0;
758 ship->setVelocity( shipDx, shipDy );
759 brakeShip = FALSE;
760 }
761 else
762 {
763 double motionAngle = atan2( -shipDy, -shipDx );
764 if ( angle > M_PI )
765 angle -= PI_X_2;
766 double angleDiff = angle - motionAngle;
767 if ( angleDiff > M_PI )
768 angleDiff = PI_X_2 - angleDiff;
769 else if ( angleDiff < -M_PI )
770 angleDiff = PI_X_2 + angleDiff;
771 double fdiff = fabs( angleDiff );
772 if ( fdiff > 0.08 )
773 {
774 if ( angleDiff > 0 )
775 rotateL = TRUE;
776 else if ( angleDiff < 0 )
777 rotateR = TRUE;
778 if ( fdiff > 0.6 )
779 rotateRate = mBrakeCount + 1;
780 else if ( fdiff > 0.4 )
781 rotateRate = 2;
782 else
783 rotateRate = 1;
784
785 if ( rotateRate > 5 )
786 rotateRate = 5;
787 }
788 else if ( fabs(shipDx) > 1 || fabs(shipDy) > 1 )
789 {
790 thrustShip = TRUE;
791 // we'll make braking a bit faster
792 shipDx += cosangle/6 * (mBrakeCount - 1);
793 shipDy += sinangle/6 * (mBrakeCount - 1);
794 reducePower( BRAKE_ON_COST );
795 addExhaust( ship->x() + 20 - cosangle*22,
796 ship->y() + 20 - sinangle*22,
797 shipDx-cosangle, shipDy-sinangle,
798 mBrakeCount+1 );
799 }
800 }
801 }
802
803 if ( thrustShip )
804 {
805 // The ship has a terminal velocity, but trying to go faster
806 // still uses fuel (can go faster diagonally - don't care).
807 double thrustx = cosangle/4;
808 double thrusty = sinangle/4;
809 if ( fabs(shipDx + thrustx) < MAX_SHIP_SPEED )
810 shipDx += thrustx;
811 if ( fabs(shipDy + thrusty) < MAX_SHIP_SPEED )
812 shipDy += thrusty;
813 ship->setVelocity( shipDx, shipDy );
814 reducePower( 1 );
815 addExhaust( ship->x() + 20 - cosangle*20,
816 ship->y() + 20 - sinangle*20,
817 shipDx-cosangle, shipDy-sinangle, 3 );
818 }
819
820 ship->setFrame( shipAngle >> 1 );
821
822 if ( shootShip )
823 {
824 if ( !shootDelay && (int)missiles.count() < mShootCount + 2 )
825 {
826 KMissile *missile = new KMissile( animation[ID_MISSILE], &field );
827 missile->setPos( 21+ship->x()+cosangle*21,
828 21+ship->y()+sinangle*21 );
829 missile->setFrame( 0 );
830 missile->setVelocity( shipDx + cosangle*MISSILE_SPEED,
831 shipDy + sinangle*MISSILE_SPEED );
832 missiles.append( missile );
833 shotsFired++;
834 reducePower( 1 );
835
836 shootDelay = 5;
837 }
838
839 if ( shootDelay )
840 shootDelay--;
841 }
842
843 if ( teleportShip )
844 {
845 int ra = qrand() % 10;
846 if( ra == 0 )
847 ra += qrand() % 20;
848 int xra = ra * 60 + ( (qrand() % 20) * (qrand() % 20) );
849 int yra = ra * 50 - ( (qrand() % 20) * (qrand() % 20) );
850 ship->setPos( xra, yra );
851 }
852
853 vitalsChanged = TRUE;
854 }
855}
856
857// - - -
858
859void KAsteroidsView::processPowerups()
860{
861 if ( !powerups.isEmpty() )
862 {
863 // if player gets the powerup remove it from the screen, if option
864 // "Can destroy powerups" is enabled and a missile hits the powerup
865 // destroy it
866
867 KPowerup *pup;
868 Q3PtrListIterator<KPowerup> it( powerups );
869
870 for( ; it.current(); ++it )
871 {
872 pup = it.current();
873 pup->growOlder();
874
875 if( pup->expired() )
876 {
877 powerups.removeRef( pup );
878 continue;
879 }
880
881 wrapSprite( pup );
882
883 QList<QGraphicsItem *> hits = pup->collidingItems();
884 QList<QGraphicsItem *>::Iterator it;
885 for ( it = hits.begin(); it != hits.end(); ++it )
886 {
887 if ( (*it) == ship )
888 {
889 switch( pup->type() )
890 {
891 case ID_ENERGY_POWERUP:
892 shipPower += 150;
893 if ( shipPower > MAX_POWER_LEVEL )
894 shipPower = MAX_POWER_LEVEL;
895 break;
896 case ID_TELEPORT_POWERUP:
897 mTeleportCount++;
898 break;
899 case ID_BRAKE_POWERUP:
900 if ( mBrakeCount < MAX_BRAKES )
901 mBrakeCount++;
902 break;
903 case ID_SHIELD_POWERUP:
904 if ( mShieldCount < MAX_SHIELDS )
905 mShieldCount++;
906 break;
907 case ID_SHOOT_POWERUP:
908 if ( mShootCount < MAX_FIREPOWER )
909 mShootCount++;
910 break;
911 }
912
913 powerups.removeRef( pup );
914 vitalsChanged = TRUE;
915 }
916 else if ( (*it) == shield )
917 {
918 powerups.removeRef( pup );
919 }
920 else if ( (*it)->type() == ID_MISSILE )
921 {
922 if ( can_destroy_powerups )
923 {
924 powerups.removeRef( pup );
925 }
926 }
927 }
928 }
929 } // -- if( powerups.isEmpty() )
930}
931
932// - - -
933
934void KAsteroidsView::hideShield()
935{
936 shield->hide();
937 mShieldCount = 0;
938 shieldOn = FALSE;
939}
940
941double KAsteroidsView::randDouble()
942{
943 int v = qrand();
944 return (double)v / (double)RAND_MAX;
945}
946
947int KAsteroidsView::randInt( int range )
948{
949 return qrand() % range;
950}
951
952void KAsteroidsView::showEvent( QShowEvent *e )
953{
954#if defined( QT_LICENSE_PROFESSIONAL )
955 static bool wasThere = FALSE;
956
957 if ( !wasThere ) {
958 wasThere = TRUE;
959 QMessageBox::information( this, tr("QGraphicsView demo"),
960 tr("This game has been implemented using the QGraphicsView class.\n"
961 "The QGraphicsView class is not part of the Light Platform Edition. Please \n"
962 "contact Qt Software if you want to upgrade to the Full Platform Edition.") );
963 }
964#endif
965
966 QWidget::showEvent( e );
967}
Note: See TracBrowser for help on using the repository browser.