12 WMRadar::WMRadar(WMTextBar
* t
, WMSlider
* s
)
13 : angle(0), text_score(t
), speed(s
)
16 text_score
->settext(" 0", false);
17 speed
->settotal(50, false);
18 speed
->setvalue(8, false);
22 WMRadar::real_display()
26 setcolor(WMColor(Background
));
27 fill_rectangle(0, 0, b_width(), b_height()); //clear background
29 setcolor(WMColor(Dim
));
30 for (double i
= 0; i
< 2 * M_PI
; i
+= M_PI_4
)
31 draw_line(b_width() / 2, b_height() / 2, (1 + cos(i
)) * b_width() / 2,
32 (1 - sin(i
)) * b_height() / 2); //draw radial lines
34 draw_arc(b_width() / 3, b_height() / 3, b_width() / 3 - 1, b_height() / 3 - 1,
36 draw_arc(b_width() / 6, b_height() / 6, 2 * b_width() / 3,
37 2 * b_height() / 3, 0, 360 * 64); //draw circles
39 setcolor(Color(255, 0, 0));
40 for (clist::const_iterator i
= collisions
.begin(); i
!= collisions
.end(); ++i
)
41 fill_arc(i
->x
- 1, i
->y
- 1, 3, 3, 0, 360 * 64); //draw collision points
43 std::vector
<X::XPoint
> points(3);
44 for (plist::const_iterator i
= planes
.begin(); i
!= planes
.end(); ++i
)
46 setcolor(Color(0, 255 * i
->brightness
, 0)); // achieve a fading effect
49 points
[1].x
= int(i
->x
) + 7 * cos(i
->direction
+ 5.5 * M_PI
/ 6);
50 points
[1].y
= int(i
->y
) - 7 * sin(i
->direction
+ 5.5 * M_PI
/ 6);
51 points
[2].x
= int(i
->x
) + 7 * cos(i
->direction
+ 6.5 * M_PI
/ 6);
52 points
[2].y
= int(i
->y
) - 7 * sin(i
->direction
+ 6.5 * M_PI
/ 6);
53 // construct an isoceles triangle pointing in plane's direction of motion
54 fill_polygon(points
); // and draw it
57 setcolor(Color(0, 255, 0));
58 draw_line(b_width() / 2, b_height() / 2, (1 + cos(angle
)) * b_width() / 2,
59 (1 - sin(angle
)) * b_height() / 2); //draw radar line
61 WMImage::real_display(); //update window
64 double rand(double low
, double high
)
66 return low
+ std::rand() * (high
- low
) / RAND_MAX
;
72 if (planes
.size() > 4)
75 double theta
= rand(0, 2 * M_PI
); //put plane somewhere along edge
76 plane p
= { (1 + cos(theta
)) * b_width() / 2,
77 (1 - sin(theta
)) * b_height() / 2,
78 rand(theta
+ 3 * M_PI_4
, theta
+ 5 * M_PI_4
), //direction pointing inwards
84 inline double dist2 (double x1
, double y1
, double x2
, double y2
)
85 { //return distance squared between points
86 return std::pow(x1
- x2
, 2) + std::pow(y1
- y2
, 2);
89 inline double norm_angle(double angle
)
90 { //return angle shifted into the range [0, 2pi)
91 return angle
- 2 * M_PI
* std::floor(angle
/ (2 * M_PI
));
95 WMRadar::release(int, int x
, int y
)
100 if (contains(x
, y
) && planes
.size())
102 int newx
= x
- b_left(),
104 plist::iterator closest
;
105 double mindist2
= 10000;
106 for (plist::iterator i
= planes
.begin(); i
!= planes
.end(); ++i
)
108 double d2
= dist2(i
->x
, i
->y
, newx
, newy
);
115 closest
->direction
= norm_angle(atan2(double(int(closest
->y
) - newy
),
116 double(newx
- int(closest
->x
))));
117 //change nearest plane's direction towards (x, y)
125 WMRadar::increment_time()
127 for (plist::iterator i
= planes
.begin(); i
!= planes
.end();)
128 { //Collision test planes
129 if (!contains(i
->x
+ left(), i
->y
+ top()))
133 plist::iterator j
= i
;
134 bool collided
= false;
135 for (++j
; j
!= planes
.end();)
136 if (dist2(i
->x
, i
->y
, j
->x
, j
->y
) <= 0.75)
137 { //remove each collided plane and increment score
147 collision c
= { i
->x
, i
->y
};
148 collisions
.push_back(c
); //make record of collision location
156 const double angleinc
= M_PI
/ 125;
158 for (plist::iterator i
= planes
.begin(); i
!= planes
.end();)
160 double incx
= speed
->value() * cos(i
->direction
) / 100;
161 double incy
= -speed
->value() * sin(i
->direction
) / 100;
162 double nextx
= i
->x
+ incx
;
163 double nexty
= i
->y
+ incy
;
165 //to check if a plane crossed the radar line, approximate the plane's path
167 double& l_start_angle
= angle
; //make an interval of radar line's angles
168 const double l_end_angle
= l_start_angle
+ angleinc
;
170 //make an interval of the plane's angles
171 double p_start_angle
= norm_angle(atan2(b_height() / 2 - i
->y
,
172 i
->x
- b_width() / 2));
173 double p_end_angle
= norm_angle(atan2(b_height() / 2 - nexty
,
174 nextx
- b_width() / 2));
176 const double crossp
= (b_width() / 2 - i
->x
) * incy
177 - (b_height() / 2 - i
->y
) * incx
; //test whether plane is moving in
178 //a positive or a negative angle
179 if (crossp
< 0.0) //make angle increase counterclockwise
181 const double temp
= p_start_angle
;
182 p_start_angle
= p_end_angle
;
185 if (p_end_angle
< p_start_angle
)
186 p_end_angle
+= 2 * M_PI
; //make sure end is > start
188 //intersect radar line interval and plane interval. If result is non-empty,
189 //there was an intersection.
190 if (std::min(p_end_angle
, l_end_angle
)
191 >= std::max(p_start_angle
, l_start_angle
))
192 i
->brightness
= 1.0; //if plane crossed radar line, make it bright
194 i
->brightness
*= 0.996; //otherwise decay brightness
197 i
->x
= nextx
; //update plane's position
199 if (!WMWidget::contains(i
->x
+ b_left(), i
->y
+ b_top()))
200 i
= planes
.erase(i
); //cull planes outside of radar
205 angle
= norm_angle(angle
+ angleinc
); //increment radar direction
211 WMRadar::increment_score ()
214 istringstream
in(text_score
->text()); //get string from textbar
216 in
>> score
; //extract score
218 out
<< setw(6) << setfill(' ') << score
+ 1; //increment and put in a string
219 text_score
->settext(out
.str()); //put back in textbar