source: trunk/tutorial/t14/cannon.cpp@ 138

Last change on this file since 138 was 8, checked in by dmik, 20 years ago

Transferred Qt for OS/2 version 3.3.1-rc5 sources from the CVS

  • Property svn:keywords set to Id
File size: 6.2 KB
Line 
1/****************************************************************
2**
3** Implementation CannonField class, Qt tutorial 14
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 barrelPressed = FALSE;
31 setPalette( QPalette( QColor( 250, 250, 200) ) );
32 newTarget();
33}
34
35
36void CannonField::setAngle( int degrees )
37{
38 if ( degrees < 5 )
39 degrees = 5;
40 if ( degrees > 70 )
41 degrees = 70;
42 if ( ang == degrees )
43 return;
44 ang = degrees;
45 repaint( cannonRect(), FALSE );
46 emit angleChanged( ang );
47}
48
49
50void CannonField::setForce( int newton )
51{
52 if ( newton < 0 )
53 newton = 0;
54 if ( f == newton )
55 return;
56 f = newton;
57 emit forceChanged( f );
58}
59
60
61void CannonField::shoot()
62{
63 if ( isShooting() )
64 return;
65 timerCount = 0;
66 shoot_ang = ang;
67 shoot_f = f;
68 autoShootTimer->start( 50 );
69 emit canShoot( FALSE );
70}
71
72
73void CannonField::newTarget()
74{
75 static bool first_time = TRUE;
76 if ( first_time ) {
77 first_time = FALSE;
78 QTime midnight( 0, 0, 0 );
79 srand( midnight.secsTo(QTime::currentTime()) );
80 }
81 QRegion r( targetRect() );
82 target = QPoint( 200 + rand() % 190,
83 10 + rand() % 255 );
84 repaint( r.unite( targetRect() ) );
85}
86
87void CannonField::setGameOver()
88{
89 if ( gameEnded )
90 return;
91 if ( isShooting() )
92 autoShootTimer->stop();
93 gameEnded = TRUE;
94 repaint();
95}
96
97void CannonField::restartGame()
98{
99 if ( isShooting() )
100 autoShootTimer->stop();
101 gameEnded = FALSE;
102 repaint();
103 emit canShoot( TRUE );
104}
105
106void CannonField::moveShot()
107{
108 QRegion r( shotRect() );
109 timerCount++;
110
111 QRect shotR = shotRect();
112
113 if ( shotR.intersects( targetRect() ) ) {
114 autoShootTimer->stop();
115 emit hit();
116 emit canShoot( TRUE );
117 } else if ( shotR.x() > width() || shotR.y() > height() ||
118 shotR.intersects(barrierRect()) ) {
119 autoShootTimer->stop();
120 emit missed();
121 emit canShoot( TRUE );
122 } else {
123 r = r.unite( QRegion( shotR ) );
124 }
125
126 repaint( r );
127}
128
129
130void CannonField::mousePressEvent( QMouseEvent *e )
131{
132 if ( e->button() != LeftButton )
133 return;
134 if ( barrelHit( e->pos() ) )
135 barrelPressed = TRUE;
136}
137
138
139void CannonField::mouseMoveEvent( QMouseEvent *e )
140{
141 if ( !barrelPressed )
142 return;
143 QPoint pnt = e->pos();
144 if ( pnt.x() <= 0 )
145 pnt.setX( 1 );
146 if ( pnt.y() >= height() )
147 pnt.setY( height() - 1 );
148 double rad = atan(((double)rect().bottom()-pnt.y())/pnt.x());
149 setAngle( qRound ( rad*180/3.14159265 ) );
150}
151
152
153void CannonField::mouseReleaseEvent( QMouseEvent *e )
154{
155 if ( e->button() == LeftButton )
156 barrelPressed = FALSE;
157}
158
159
160void CannonField::paintEvent( QPaintEvent *e )
161{
162 QRect updateR = e->rect();
163 QPainter p( this );
164
165 if ( gameEnded ) {
166 p.setPen( black );
167 p.setFont( QFont( "Courier", 48, QFont::Bold ) );
168 p.drawText( rect(), AlignCenter, "Game Over" );
169 }
170 if ( updateR.intersects( cannonRect() ) )
171 paintCannon( &p );
172 if ( updateR.intersects( barrierRect() ) )
173 paintBarrier( &p );
174 if ( isShooting() && updateR.intersects( shotRect() ) )
175 paintShot( &p );
176 if ( !gameEnded && updateR.intersects( targetRect() ) )
177 paintTarget( &p );
178}
179
180void CannonField::paintShot( QPainter *p )
181{
182 p->setBrush( black );
183 p->setPen( NoPen );
184 p->drawRect( shotRect() );
185}
186
187
188void CannonField::paintTarget( QPainter *p )
189{
190 p->setBrush( red );
191 p->setPen( black );
192 p->drawRect( targetRect() );
193}
194
195void CannonField::paintBarrier( QPainter *p )
196{
197 p->setBrush( yellow );
198 p->setPen( black );
199 p->drawRect( barrierRect() );
200}
201
202const QRect barrelRect(33, -4, 15, 8);
203
204void CannonField::paintCannon( QPainter *p )
205{
206 QRect cr = cannonRect();
207 QPixmap pix( cr.size() );
208 pix.fill( this, cr.topLeft() );
209
210 QPainter tmp( &pix );
211 tmp.setBrush( blue );
212 tmp.setPen( NoPen );
213
214 tmp.translate( 0, pix.height() );
215 tmp.drawPie( QRect( -35,-35, 70, 70 ), 0, 90*16 );
216 tmp.rotate( -ang );
217 tmp.drawRect( barrelRect );
218 tmp.end();
219
220 p->drawPixmap( cr.topLeft(), pix );
221}
222
223
224QRect CannonField::cannonRect() const
225{
226 QRect r( 0, 0, 50, 50 );
227 r.moveBottomLeft( rect().bottomLeft() );
228 return r;
229}
230
231
232QRect CannonField::shotRect() const
233{
234 const double gravity = 4;
235
236 double time = timerCount / 4.0;
237 double velocity = shoot_f;
238 double radians = shoot_ang*3.14159265/180;
239
240 double velx = velocity*cos( radians );
241 double vely = velocity*sin( radians );
242 double x0 = ( barrelRect.right() + 5 )*cos(radians);
243 double y0 = ( barrelRect.right() + 5 )*sin(radians);
244 double x = x0 + velx*time;
245 double y = y0 + vely*time - 0.5*gravity*time*time;
246
247 QRect r = QRect( 0, 0, 6, 6 );
248 r.moveCenter( QPoint( qRound(x), height() - 1 - qRound(y) ) );
249 return r;
250}
251
252
253QRect CannonField::targetRect() const
254{
255 QRect r( 0, 0, 20, 10 );
256 r.moveCenter( QPoint(target.x(),height() - 1 - target.y()) );
257 return r;
258}
259
260
261QRect CannonField::barrierRect() const
262{
263 return QRect( 145, height() - 100, 15, 100 );
264}
265
266
267bool CannonField::barrelHit( const QPoint &p ) const
268{
269 QWMatrix mtx;
270 mtx.translate( 0, height() - 1 );
271 mtx.rotate( -ang );
272 mtx = mtx.invert();
273 return barrelRect.contains( mtx.map(p) );
274}
275
276
277bool CannonField::isShooting() const
278{
279 return autoShootTimer->isActive();
280}
281
282
283QSize CannonField::sizeHint() const
284{
285 return QSize( 400, 300 );
286}
287
288
289QSizePolicy CannonField::sizePolicy() const
290{
291 return QSizePolicy( QSizePolicy::Expanding, QSizePolicy::Expanding );
292}
Note: See TracBrowser for help on using the repository browser.