1 /****************************************************************************
2 **
3 ** Copyright (C) 2015 The Qt Company Ltd.
4 ** Contact: http://www.qt.io/licensing/
5 **
6 ** This file is part of the examples of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:BSD$
9 ** You may use this file under the terms of the BSD license as follows:
10 **
11 ** "Redistribution and use in source and binary forms, with or without
12 ** modification, are permitted provided that the following conditions are
13 ** met:
14 **   * Redistributions of source code must retain the above copyright
15 **     notice, this list of conditions and the following disclaimer.
16 **   * Redistributions in binary form must reproduce the above copyright
17 **     notice, this list of conditions and the following disclaimer in
18 **     the documentation and/or other materials provided with the
19 **     distribution.
20 **   * Neither the name of The Qt Company Ltd nor the names of its
21 **     contributors may be used to endorse or promote products derived
22 **     from this software without specific prior written permission.
23 **
24 **
25 ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
26 ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
27 ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
28 ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
29 ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
30 ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
31 ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
32 ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
33 ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
34 ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
35 ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
36 **
37 ** $QT_END_LICENSE$
38 **
39 ****************************************************************************/
40 
41 /*
42  * KAsteroids - Copyright (c) Martin R. Jones 1997
43  *
44  * Part of the KDE project
45  */
46 //	--- toplevel.cpp ---
47 #include <QAction>
48 #include <QLabel>
49 #include <QLayout>
50 #include <QLCDNumber>
51 #include <QPushButton>
52 
53 #include <QApplication>
54 #include <QHBoxLayout>
55 #include <QShowEvent>
56 #include <QFrame>
57 #include <QPixmap>
58 #include <QHideEvent>
59 #include <QKeyEvent>
60 #include <QVBoxLayout>
61 
62 #include "toplevel.h"
63 #include "ledmeter.h"
64 
65 
66 #define SB_SCORE	1
67 #define SB_LEVEL	2
68 #define SB_SHIPS	3
69 
70 struct SLevel
71 {
72     int    nrocks;
73     double rockSpeed;
74 };
75 
76 #define MAX_LEVELS	16
77 
78 SLevel levels[MAX_LEVELS] =
79 {
80     { 1, 0.4 },
81     { 1, 0.6 },
82     { 2, 0.5 },
83     { 2, 0.7 },
84     { 2, 0.8 },
85     { 3, 0.6 },
86     { 3, 0.7 },
87     { 3, 0.8 },
88     { 4, 0.6 },
89     { 4, 0.7 },
90     { 4, 0.8 },
91     { 5, 0.7 },
92     { 5, 0.8 },
93     { 5, 0.9 },
94     { 5, 1.0 }
95 };
96 
97 const char *soundEvents[] =
98 {
99     "ShipDestroyed",
100     "RockDestroyed",
101     0
102 };
103 
104 const char *soundDefaults[] =
105 {
106     "Explosion.wav",
107     "ploop.wav",
108     0
109 };
110 
111 
KAstTopLevel(QWidget * parent)112 KAstTopLevel::KAstTopLevel( QWidget *parent)
113     : QMainWindow(parent)
114 {
115     QWidget *border = new QWidget( this );
116 
117     QPalette palette;
118     palette.setColor(border->backgroundRole(), Qt::black);
119     border->setPalette(palette);
120 
121     setCentralWidget( border );
122 
123     QVBoxLayout *borderLayout = new QVBoxLayout( border );
124     borderLayout->addStretch( 1 );
125 
126     QWidget *mainWin = new QWidget( border );
127 #if defined(Q_WS_MAEMO_5)
128     mainWin->setFixedSize(800, 430);
129 #elif defined(Q_OS_SYMBIAN)
130     mainWin->setFixedSize(640, 340);
131 #else
132     mainWin->setFixedSize(640, 480);
133 #endif
134     borderLayout->addWidget( mainWin, 0, Qt::AlignHCenter );
135 
136     borderLayout->addStretch( 1 );
137 
138     view = new KAsteroidsView( mainWin );
139     view->setFocusPolicy( Qt::StrongFocus );
140     connect( view, SIGNAL(shipKilled()), SLOT(slotShipKilled()) );
141     connect( view, SIGNAL(rockHit(int)), SLOT(slotRockHit(int)) );
142     connect( view, SIGNAL(rocksRemoved()), SLOT(slotRocksRemoved()) );
143     connect( view, SIGNAL(updateVitals()), SLOT(slotUpdateVitals()) );
144 
145     QVBoxLayout *vb = new QVBoxLayout( mainWin );
146     QHBoxLayout *hb = new QHBoxLayout;
147     QHBoxLayout *hbd = new QHBoxLayout;
148     vb->addLayout( hb );
149 
150 #if defined(Q_OS_SYMBIAN)
151     QFont labelFont( "helvetica", 8 );
152 #else
153     QFont labelFont( "helvetica", 24 );
154 #endif
155 
156     QPalette pal(Qt::darkGreen, Qt::black, QColor( 128, 128, 128 ), QColor( 64, 64, 64 ), Qt::black, Qt::darkGreen, Qt::black);
157 
158     mainWin->setPalette( pal );
159 
160     hb->addSpacing( 10 );
161 
162     QLabel *label;
163     label = new QLabel( tr("Score"), mainWin );
164     label->setFont( labelFont );
165     label->setPalette( pal );
166     label->setFixedWidth( label->sizeHint().width() );
167     hb->addWidget( label );
168 
169     scoreLCD = new QLCDNumber( 6, mainWin );
170     scoreLCD->setFrameStyle( QFrame::NoFrame );
171     scoreLCD->setSegmentStyle( QLCDNumber::Flat );
172     scoreLCD->setFixedWidth( 150 );
173     scoreLCD->setPalette( pal );
174     hb->addWidget( scoreLCD );
175     hb->addStretch( 10 );
176 
177     label = new QLabel( tr("Level"), mainWin );
178     label->setFont( labelFont );
179     label->setPalette( pal );
180     label->setFixedWidth( label->sizeHint().width() );
181     hb->addWidget( label );
182 
183     levelLCD = new QLCDNumber( 2, mainWin );
184     levelLCD->setFrameStyle( QFrame::NoFrame );
185     levelLCD->setSegmentStyle( QLCDNumber::Flat );
186     levelLCD->setFixedWidth( 70 );
187     levelLCD->setPalette( pal );
188     hb->addWidget( levelLCD );
189     hb->addStretch( 10 );
190 
191     label = new QLabel( tr("Ships"), mainWin );
192     label->setFont( labelFont );
193     label->setFixedWidth( label->sizeHint().width() );
194     label->setPalette( pal );
195     hb->addWidget( label );
196 
197     shipsLCD = new QLCDNumber( 1, mainWin );
198     shipsLCD->setFrameStyle( QFrame::NoFrame );
199     shipsLCD->setSegmentStyle( QLCDNumber::Flat );
200     shipsLCD->setFixedWidth( 40 );
201     shipsLCD->setPalette( pal );
202     hb->addWidget( shipsLCD );
203 
204     hb->addStrut( 30 );
205 
206     vb->addWidget( view, 10 );
207 
208 // -- bottom layout:
209     vb->addLayout( hbd );
210 
211 #if defined(Q_OS_SYMBIAN)
212     QFont smallFont( "helvetica", 6 );
213 #else
214     QFont smallFont( "helvetica", 14 );
215 #endif
216     hbd->addSpacing( 10 );
217 
218     QString sprites_prefix = ":/trolltech/examples/graphicsview/portedasteroids/sprites/";
219 /*
220     label = new QLabel( tr( "T" ), mainWin );
221     label->setFont( smallFont );
222     label->setFixedWidth( label->sizeHint().width() );
223     label->setPalette( pal );
224     hbd->addWidget( label );
225 
226     teleportsLCD = new QLCDNumber( 1, mainWin );
227     teleportsLCD->setFrameStyle( QFrame::NoFrame );
228     teleportsLCD->setSegmentStyle( QLCDNumber::Flat );
229     teleportsLCD->setPalette( pal );
230     teleportsLCD->setFixedHeight( 20 );
231     hbd->addWidget( teleportsLCD );
232 
233     hbd->addSpacing( 10 );
234 */
235     QPixmap pm( sprites_prefix + "powerups/brake.png" );
236     label = new QLabel( mainWin );
237     label->setPixmap( pm );
238     label->setFixedWidth( label->sizeHint().width() );
239     label->setPalette( pal );
240     hbd->addWidget( label );
241 
242     brakesLCD = new QLCDNumber( 1, mainWin );
243     brakesLCD->setFrameStyle( QFrame::NoFrame );
244     brakesLCD->setSegmentStyle( QLCDNumber::Flat );
245     brakesLCD->setPalette( pal );
246     brakesLCD->setFixedHeight( 20 );
247     hbd->addWidget( brakesLCD );
248 
249     hbd->addSpacing( 10 );
250 
251     pm.load( sprites_prefix + "powerups/shield.png" );
252     label = new QLabel( mainWin );
253     label->setPixmap( pm );
254     label->setFixedWidth( label->sizeHint().width() );
255     label->setPalette( pal );
256     hbd->addWidget( label );
257 
258     shieldLCD = new QLCDNumber( 1, mainWin );
259     shieldLCD->setFrameStyle( QFrame::NoFrame );
260     shieldLCD->setSegmentStyle( QLCDNumber::Flat );
261     shieldLCD->setPalette( pal );
262     shieldLCD->setFixedHeight( 20 );
263     hbd->addWidget( shieldLCD );
264 
265     hbd->addSpacing( 10 );
266 
267     pm.load( sprites_prefix + "powerups/shoot.png" );
268     label = new QLabel( mainWin );
269     label->setPixmap( pm );
270     label->setFixedWidth( label->sizeHint().width() );
271     label->setPalette( pal );
272     hbd->addWidget( label );
273 
274     shootLCD = new QLCDNumber( 1, mainWin );
275     shootLCD->setFrameStyle( QFrame::NoFrame );
276     shootLCD->setSegmentStyle( QLCDNumber::Flat );
277     shootLCD->setPalette( pal );
278     shootLCD->setFixedHeight( 20 );
279     hbd->addWidget( shootLCD );
280 
281     hbd->addStretch( 1 );
282 
283     label = new QLabel( tr( "Fuel" ), mainWin );
284     label->setFont( smallFont );
285     label->setFixedWidth( label->sizeHint().width() + 10 );
286     label->setPalette( pal );
287     hbd->addWidget( label );
288 
289     powerMeter = new KALedMeter( mainWin );
290     powerMeter->setFrameStyle( QFrame::Box | QFrame::Plain );
291     powerMeter->setRange( MAX_POWER_LEVEL );
292     powerMeter->addColorRange( 10, Qt::darkRed );
293     powerMeter->addColorRange( 20, QColor(160, 96, 0) );
294     powerMeter->addColorRange( 70, Qt::darkGreen );
295     powerMeter->setCount( 40 );
296     powerMeter->setPalette( pal );
297     powerMeter->setFixedSize( 200, 12 );
298     hbd->addWidget( powerMeter );
299 
300     shipsRemain = 3;
301     showHiscores = FALSE;
302 
303     actions.insert( Qt::Key_Up, Thrust );
304     actions.insert( Qt::Key_Left, RotateLeft );
305     actions.insert( Qt::Key_Right, RotateRight );
306     actions.insert( Qt::Key_Space, Shoot );
307     actions.insert( Qt::Key_Z, Teleport );
308     actions.insert( Qt::Key_X, Brake );
309     actions.insert( Qt::Key_S, Shield );
310     actions.insert( Qt::Key_P, Pause );
311     actions.insert( Qt::Key_L, Launch );
312     actions.insert( Qt::Key_N, NewGame );
313 
314 #if defined(Q_OS_SYMBIAN)
315     actions.insert( 122, Teleport );
316     actions.insert( 120, Brake );
317     actions.insert( 115, Shield );
318     actions.insert( 112, Pause );
319     actions.insert( 108, Launch );
320     actions.insert( 110, NewGame );
321 #endif
322 
323     view->showText( tr( "Press N to start playing" ), Qt::yellow );
324 }
325 
~KAstTopLevel()326 KAstTopLevel::~KAstTopLevel()
327 {
328 }
329 
playSound(const char *)330 void KAstTopLevel::playSound( const char * )
331 {
332 }
333 
keyPressEvent(QKeyEvent * event)334 void KAstTopLevel::keyPressEvent( QKeyEvent *event )
335 {
336     if ( event->isAutoRepeat() || !actions.contains( event->key() ) )
337     {
338         event->ignore();
339         return;
340     }
341 
342     Action a = actions[ event->key() ];
343 
344     switch ( a )
345     {
346         case RotateLeft:
347             view->rotateLeft( TRUE );
348             break;
349 
350         case RotateRight:
351             view->rotateRight( TRUE );
352             break;
353 
354         case Thrust:
355             view->thrust( TRUE );
356             break;
357 
358         case Shoot:
359             view->shoot( TRUE );
360             break;
361 
362         case Shield:
363             view->setShield( TRUE );
364             break;
365 
366         case Teleport:
367             view->teleport( TRUE );
368             break;
369 
370         case Brake:
371             view->brake( TRUE );
372             break;
373 
374         default:
375             event->ignore();
376             return;
377     }
378     event->accept();
379 }
380 
keyReleaseEvent(QKeyEvent * event)381 void KAstTopLevel::keyReleaseEvent( QKeyEvent *event )
382 {
383     if ( event->isAutoRepeat() || !actions.contains( event->key() ) )
384     {
385         event->ignore();
386         return;
387     }
388 
389     Action a = actions[ event->key() ];
390 
391     switch ( a )
392     {
393         case RotateLeft:
394             view->rotateLeft( FALSE );
395             break;
396 
397         case RotateRight:
398             view->rotateRight( FALSE );
399             break;
400 
401         case Thrust:
402             view->thrust( FALSE );
403             break;
404 
405         case Shoot:
406             view->shoot( FALSE );
407             break;
408 
409         case Brake:
410             view->brake( FALSE );
411             break;
412 
413         case Shield:
414             view->setShield( FALSE );
415             break;
416 
417         case Teleport:
418             view->teleport( FALSE );
419             break;
420 
421         case Launch:
422             if ( waitShip )
423             {
424                 view->newShip();
425                 waitShip = FALSE;
426                 view->hideText();
427             }
428             else
429             {
430                 event->ignore();
431                 return;
432             }
433             break;
434 
435 	case NewGame:
436 	    slotNewGame();
437 	    break;
438 /*
439         case Pause:
440             {
441                 view->pause( TRUE );
442                 QMessageBox::information( this,
443                                           tr("KAsteroids is paused"),
444                                           tr("Paused") );
445                 view->pause( FALSE );
446             }
447             break;
448 */
449         default:
450             event->ignore();
451             return;
452     }
453 
454     event->accept();
455 }
456 
showEvent(QShowEvent * e)457 void KAstTopLevel::showEvent( QShowEvent *e )
458 {
459     QMainWindow::showEvent( e );
460     view->pause( FALSE );
461     view->setFocus();
462 }
463 
hideEvent(QHideEvent * e)464 void KAstTopLevel::hideEvent( QHideEvent *e )
465 {
466     QMainWindow::hideEvent( e );
467     view->pause( TRUE );
468 }
469 
slotNewGame()470 void KAstTopLevel::slotNewGame()
471 {
472     score = 0;
473     shipsRemain = SB_SHIPS;
474     scoreLCD->display( 0 );
475     level = 0;
476     levelLCD->display( level+1 );
477     shipsLCD->display( shipsRemain-1 );
478     view->newGame();
479     view->setRockSpeed( levels[0].rockSpeed );
480     view->addRocks( levels[0].nrocks );
481 //    view->showText( tr( "Press L to launch." ), yellow );
482     view->newShip();
483     waitShip = FALSE;
484     view->hideText();
485     isPaused = FALSE;
486 }
487 
slotShipKilled()488 void KAstTopLevel::slotShipKilled()
489 {
490     shipsRemain--;
491     shipsLCD->display( shipsRemain-1 );
492 
493     playSound( "ShipDestroyed" );
494 
495     if ( shipsRemain )
496     {
497         waitShip = TRUE;
498         view->showText( tr( "Ship Destroyed. Press L to launch."), Qt::yellow );
499     }
500     else
501     {
502         view->showText( tr("Game Over!"), Qt::red );
503         view->endGame();
504 	doStats();
505 //        highscore->addEntry( score, level, showHiscores );
506     }
507 }
508 
slotRockHit(int size)509 void KAstTopLevel::slotRockHit( int size )
510 {
511     switch ( size )
512     {
513 	case 0:
514 	    score += 10;
515 	     break;
516 
517 	case 1:
518 	    score += 20;
519 	    break;
520 
521 	default:
522 	    score += 40;
523       }
524 
525     playSound( "RockDestroyed" );
526 
527     scoreLCD->display( score );
528 }
529 
slotRocksRemoved()530 void KAstTopLevel::slotRocksRemoved()
531 {
532     level++;
533 
534     if ( level >= MAX_LEVELS )
535 	level = MAX_LEVELS - 1;
536 
537     view->setRockSpeed( levels[level-1].rockSpeed );
538     view->addRocks( levels[level-1].nrocks );
539 
540     levelLCD->display( level+1 );
541 }
542 
doStats()543 void KAstTopLevel::doStats()
544 {
545     QString r( "0.00" );
546     if ( view->shots() )
547 	 r = QString::number( (double)view->hits() / view->shots() * 100.0,
548 			     'g', 2 );
549 
550 /* multi-line text broken in Qt 3
551     QString s = tr( "Game Over\n\nShots fired:\t%1\n  Hit:\t%2\n  Missed:\t%3\nHit ratio:\t%4 %\n\nPress N for a new game" )
552       .arg(view->shots()).arg(view->hits())
553       .arg(view->shots() - view->hits())
554       .arg(r);
555 */
556 
557     view->showText( "Game Over.   Press N for a new game.", Qt::yellow, FALSE );
558 }
559 
slotUpdateVitals()560 void KAstTopLevel::slotUpdateVitals()
561 {
562     brakesLCD->display( view->brakeCount() );
563     shieldLCD->display( view->shieldCount() );
564     shootLCD->display( view->shootCount() );
565 //    teleportsLCD->display( view->teleportCount() );
566     powerMeter->setValue( view->power() );
567 }
568