source: trunk/tutorial/t13/cannon.cpp@ 127

Last change on this file since 127 was 2, checked in by dmik, 20 years ago

Imported xplatform parts of the official release 3.3.1 from Trolltech

  • Property svn:keywords set to Id
File size: 4.9 KB
Line 
1/****************************************************************
2**
3** Implementation CannonField class, Qt tutorial 13
4**
5****************************************************************/
6
7#include "cannon.h"
8#include <qtimer.h>
9#include <qpainter.h>
10#include <qpixmap.h>
11#include <qdatetime.h>
12
13#include <math.h>
14#include <stdlib.h>
15
16
17CannonField::CannonField( QWidget *parent, const char *name )
18 : QWidget( parent, name )
19{
20 ang = 45;
21 f = 0;
22 timerCount = 0;
23 autoShootTimer = new QTimer( this, "movement handler" );
24 connect( autoShootTimer, SIGNAL(timeout()),
25 this, SLOT(moveShot()) );
26 shoot_ang = 0;
27 shoot_f = 0;
28 target = QPoint( 0, 0 );
29 gameEnded = FALSE;
30 setPalette( QPalette( QColor( 250, 250, 200) ) );
31 newTarget();
32}
33
34
35void CannonField::setAngle( int degrees )
36{
37 if ( degrees < 5 )
38 degrees = 5;
39 if ( degrees > 70 )
40 degrees = 70;
41 if ( ang == degrees )
42 return;
43 ang = degrees;
44 repaint( cannonRect(), FALSE );
45 emit angleChanged( ang );
46}
47
48
49void CannonField::setForce( int newton )
50{
51 if ( newton < 0 )
52 newton = 0;
53 if ( f == newton )
54 return;
55 f = newton;
56 emit forceChanged( f );
57}
58
59
60void CannonField::shoot()
61{
62 if ( isShooting() )
63 return;
64 timerCount = 0;
65 shoot_ang = ang;
66 shoot_f = f;
67 autoShootTimer->start( 50 );
68 emit canShoot( FALSE );
69}
70
71
72void CannonField::newTarget()
73{
74 static bool first_time = TRUE;
75 if ( first_time ) {
76 first_time = FALSE;
77 QTime midnight( 0, 0, 0 );
78 srand( midnight.secsTo(QTime::currentTime()) );
79 }
80 QRegion r( targetRect() );
81 target = QPoint( 200 + rand() % 190,
82 10 + rand() % 255 );
83 repaint( r.unite( targetRect() ) );
84}
85
86void CannonField::setGameOver()
87{
88 if ( gameEnded )
89 return;
90 if ( isShooting() )
91 autoShootTimer->stop();
92 gameEnded = TRUE;
93 repaint();
94}
95
96void CannonField::restartGame()
97{
98 if ( isShooting() )
99 autoShootTimer->stop();
100 gameEnded = FALSE;
101 repaint();
102 emit canShoot( TRUE );
103}
104
105void CannonField::moveShot()
106{
107 QRegion r( shotRect() );
108 timerCount++;
109
110 QRect shotR = shotRect();
111
112 if ( shotR.intersects( targetRect() ) ) {
113 autoShootTimer->stop();
114 emit hit();
115 emit canShoot( TRUE );
116 } else if ( shotR.x() > width() || shotR.y() > height() ) {
117 autoShootTimer->stop();
118 emit missed();
119 emit canShoot( TRUE );
120 } else {
121 r = r.unite( QRegion( shotR ) );
122 }
123
124 repaint( r );
125}
126
127
128void CannonField::paintEvent( QPaintEvent *e )
129{
130 QRect updateR = e->rect();
131 QPainter p( this );
132
133 if ( gameEnded ) {
134 p.setPen( black );
135 p.setFont( QFont( "Courier", 48, QFont::Bold ) );
136 p.drawText( rect(), AlignCenter, "Game Over" );
137 }
138 if ( updateR.intersects( cannonRect() ) )
139 paintCannon( &p );
140 if ( isShooting() && updateR.intersects( shotRect() ) )
141 paintShot( &p );
142 if ( !gameEnded && updateR.intersects( targetRect() ) )
143 paintTarget( &p );
144}
145
146
147void CannonField::paintShot( QPainter *p )
148{
149 p->setBrush( black );
150 p->setPen( NoPen );
151 p->drawRect( shotRect() );
152}
153
154
155void CannonField::paintTarget( QPainter *p )
156{
157 p->setBrush( red );
158 p->setPen( black );
159 p->drawRect( targetRect() );
160}
161
162
163const QRect barrelRect(33, -4, 15, 8);
164
165void CannonField::paintCannon( QPainter *p )
166{
167 QRect cr = cannonRect();
168 QPixmap pix( cr.size() );
169 pix.fill( this, cr.topLeft() );
170
171 QPainter tmp( &pix );
172 tmp.setBrush( blue );
173 tmp.setPen( NoPen );
174
175 tmp.translate( 0, pix.height() - 1 );
176 tmp.drawPie( QRect( -35,-35, 70, 70 ), 0, 90*16 );
177 tmp.rotate( -ang );
178 tmp.drawRect( barrelRect );
179 tmp.end();
180
181 p->drawPixmap( cr.topLeft(), pix );
182}
183
184
185QRect CannonField::cannonRect() const
186{
187 QRect r( 0, 0, 50, 50 );
188 r.moveBottomLeft( rect().bottomLeft() );
189 return r;
190}
191
192
193QRect CannonField::shotRect() const
194{
195 const double gravity = 4;
196
197 double time = timerCount / 4.0;
198 double velocity = shoot_f;
199 double radians = shoot_ang*3.14159265/180;
200
201 double velx = velocity*cos( radians );
202 double vely = velocity*sin( radians );
203 double x0 = ( barrelRect.right() + 5 )*cos(radians);
204 double y0 = ( barrelRect.right() + 5 )*sin(radians);
205 double x = x0 + velx*time;
206 double y = y0 + vely*time - 0.5*gravity*time*time;
207
208 QRect r = QRect( 0, 0, 6, 6 );
209 r.moveCenter( QPoint( qRound(x), height() - 1 - qRound(y) ) );
210 return r;
211}
212
213
214QRect CannonField::targetRect() const
215{
216 QRect r( 0, 0, 20, 10 );
217 r.moveCenter( QPoint(target.x(),height() - 1 - target.y()) );
218 return r;
219}
220
221
222bool CannonField::isShooting() const
223{
224 return autoShootTimer->isActive();
225}
226
227
228QSizePolicy CannonField::sizePolicy() const
229{
230 return QSizePolicy( QSizePolicy::Expanding, QSizePolicy::Expanding );
231}
Note: See TracBrowser for help on using the repository browser.