source: trunk/tutorial/t12/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.3 KB
Line 
1/****************************************************************
2**
3** Implementation CannonField class, Qt tutorial 12
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 setPalette( QPalette( QColor( 250, 250, 200) ) );
30 newTarget();
31}
32
33
34void CannonField::setAngle( int degrees )
35{
36 if ( degrees < 5 )
37 degrees = 5;
38 if ( degrees > 70 )
39 degrees = 70;
40 if ( ang == degrees )
41 return;
42 ang = degrees;
43 repaint( cannonRect(), FALSE );
44 emit angleChanged( ang );
45}
46
47
48void CannonField::setForce( int newton )
49{
50 if ( newton < 0 )
51 newton = 0;
52 if ( f == newton )
53 return;
54 f = newton;
55 emit forceChanged( f );
56}
57
58
59void CannonField::shoot()
60{
61 if ( autoShootTimer->isActive() )
62 return;
63 timerCount = 0;
64 shoot_ang = ang;
65 shoot_f = f;
66 autoShootTimer->start( 50 );
67}
68
69
70void CannonField::newTarget()
71{
72 static bool first_time = TRUE;
73 if ( first_time ) {
74 first_time = FALSE;
75 QTime midnight( 0, 0, 0 );
76 srand( midnight.secsTo(QTime::currentTime()) );
77 }
78 QRegion r( targetRect() );
79 target = QPoint( 200 + rand() % 190,
80 10 + rand() % 255 );
81 repaint( r.unite( targetRect() ) );
82}
83
84
85void CannonField::moveShot()
86{
87 QRegion r( shotRect() );
88 timerCount++;
89
90 QRect shotR = shotRect();
91
92 if ( shotR.intersects( targetRect() ) ) {
93 autoShootTimer->stop();
94 emit hit();
95 } else if ( shotR.x() > width() || shotR.y() > height() ) {
96 autoShootTimer->stop();
97 emit missed();
98 } else {
99 r = r.unite( QRegion( shotR ) );
100 }
101
102 repaint( r );
103}
104
105
106void CannonField::paintEvent( QPaintEvent *e )
107{
108 QRect updateR = e->rect();
109 QPainter p( this );
110
111 if ( updateR.intersects( cannonRect() ) )
112 paintCannon( &p );
113 if ( autoShootTimer->isActive() &&
114 updateR.intersects( shotRect() ) )
115 paintShot( &p );
116 if ( updateR.intersects( targetRect() ) )
117 paintTarget( &p );
118}
119
120
121void CannonField::paintShot( QPainter *p )
122{
123 p->setBrush( black );
124 p->setPen( NoPen );
125 p->drawRect( shotRect() );
126}
127
128
129void CannonField::paintTarget( QPainter *p )
130{
131 p->setBrush( red );
132 p->setPen( black );
133 p->drawRect( targetRect() );
134}
135
136
137const QRect barrelRect(33, -4, 15, 8);
138
139void CannonField::paintCannon( QPainter *p )
140{
141 QRect cr = cannonRect();
142 QPixmap pix( cr.size() );
143 pix.fill( this, cr.topLeft() );
144
145 QPainter tmp( &pix );
146 tmp.setBrush( blue );
147 tmp.setPen( NoPen );
148
149 tmp.translate( 0, pix.height() - 1 );
150 tmp.drawPie( QRect( -35,-35, 70, 70 ), 0, 90*16 );
151 tmp.rotate( -ang );
152 tmp.drawRect( barrelRect );
153 tmp.end();
154
155 p->drawPixmap( cr.topLeft(), pix );
156}
157
158
159QRect CannonField::cannonRect() const
160{
161 QRect r( 0, 0, 50, 50 );
162 r.moveBottomLeft( rect().bottomLeft() );
163 return r;
164}
165
166
167QRect CannonField::shotRect() const
168{
169 const double gravity = 4;
170
171 double time = timerCount / 4.0;
172 double velocity = shoot_f;
173 double radians = shoot_ang*3.14159265/180;
174
175 double velx = velocity*cos( radians );
176 double vely = velocity*sin( radians );
177 double x0 = ( barrelRect.right() + 5 )*cos(radians);
178 double y0 = ( barrelRect.right() + 5 )*sin(radians);
179 double x = x0 + velx*time;
180 double y = y0 + vely*time - 0.5*gravity*time*time;
181
182 QRect r = QRect( 0, 0, 6, 6 );
183 r.moveCenter( QPoint( qRound(x), height() - 1 - qRound(y) ) );
184 return r;
185}
186
187
188QRect CannonField::targetRect() const
189{
190 QRect r( 0, 0, 20, 10 );
191 r.moveCenter( QPoint(target.x(),height() - 1 - target.y()) );
192 return r;
193}
194
195
196QSizePolicy CannonField::sizePolicy() const
197{
198 return QSizePolicy( QSizePolicy::Expanding, QSizePolicy::Expanding );
199}
Note: See TracBrowser for help on using the repository browser.