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