@@ -10,7 +10,7 @@ use libplen::powerups::PowerUpKind;
10
10
use libplen:: constants;
11
11
use libplen:: gamestate:: GameState ;
12
12
use libplen:: projectiles:: { ProjectileKind , Projectile } ;
13
- use libplen:: math:: { Vec2 , vec2} ;
13
+ use libplen:: math:: { self , Vec2 , vec2} ;
14
14
15
15
use crate :: assets:: Assets ;
16
16
use crate :: rendering;
@@ -83,10 +83,22 @@ pub struct SparkParticle {
83
83
velocity : Vec2 ,
84
84
}
85
85
86
+ enum RadarObjectType {
87
+ Plane { rotation : f32 , color : ( u8 , u8 , u8 ) } ,
88
+ PowerUp
89
+ }
90
+
91
+ pub struct RadarObject {
92
+ object_type : RadarObjectType ,
93
+ lifetime : f32 ,
94
+ position : Vec2 ,
95
+ }
96
+
86
97
pub struct Map {
87
98
smoke_particles : ParticleSystem < SmokeParticle > ,
88
99
explosion_particles : ParticleSystem < ExplosionParticle > ,
89
100
spark_particles : ParticleSystem < SparkParticle > ,
101
+ radar_objects : ParticleSystem < RadarObject > ,
90
102
smoke_timer : f32 ,
91
103
spark_timer : f32 ,
92
104
start_time : Instant ,
@@ -99,6 +111,7 @@ impl Map {
99
111
smoke_particles : ParticleSystem :: new ( 200 ) ,
100
112
explosion_particles : ParticleSystem :: new ( 200 ) ,
101
113
spark_particles : ParticleSystem :: new ( 200 ) ,
114
+ radar_objects : ParticleSystem :: new ( 200 ) ,
102
115
smoke_timer : 0. ,
103
116
spark_timer : 0. ,
104
117
start_time : Instant :: now ( ) ,
@@ -126,9 +139,11 @@ impl Map {
126
139
} ) ) ;
127
140
}
128
141
129
- pub fn update ( & mut self , delta_time : f32 , game_state : & GameState ) {
142
+ pub fn update ( & mut self , delta_time : f32 , game_state : & GameState , my_id : u64 ) {
130
143
self . update_particles ( delta_time, game_state) ;
131
- self . radar_angle += delta_time * constants:: RADAR_SPEED ;
144
+ if let Some ( my_player) = game_state. get_player_by_id ( my_id) {
145
+ self . update_radar ( delta_time, game_state, my_player) ;
146
+ }
132
147
}
133
148
134
149
fn update_particles ( & mut self , delta_time : f32 , game_state : & GameState ) {
@@ -204,6 +219,86 @@ impl Map {
204
219
self . spark_particles . retain ( |spark| spark. lifetime > 0. ) ;
205
220
}
206
221
222
+ pub fn update_radar (
223
+ & mut self ,
224
+ delta_time : f32 ,
225
+ game_state : & GameState ,
226
+ my_player : & player:: Player
227
+ ) {
228
+ let old_radar_angle = self . radar_angle ;
229
+ let radar_angle =
230
+ ( self . radar_angle + delta_time * constants:: RADAR_SPEED ) % ( PI * 2. ) ;
231
+ self . radar_angle = radar_angle;
232
+
233
+ let in_radar_range = |position : Vec2 | {
234
+ let dist_squared = position. x . powi ( 2 ) + position. y . powi ( 2 ) ;
235
+ if dist_squared > ( constants:: MINI_MAP_SIZE /2. ) . powi ( 2 ) {
236
+ return false
237
+ }
238
+
239
+ // atan2 gives an angle in the range (-pi, pi]
240
+ let angle = math:: modulo ( position. angle ( ) , PI * 2. ) ;
241
+
242
+ // Angle wraparound creates some special cases
243
+ if radar_angle >= old_radar_angle {
244
+ old_radar_angle <= angle && angle <= radar_angle
245
+ } else {
246
+ old_radar_angle <= angle || angle <= radar_angle
247
+ }
248
+ } ;
249
+
250
+ let my_pos = my_player. position ;
251
+
252
+ for tile_x in & [ -1. , 0. , 1. ] {
253
+ for tile_y in & [ -1. , 0. , 1. ] {
254
+ let offset = vec2 (
255
+ tile_x * constants:: MINI_MAP_SIZE ,
256
+ tile_y * constants:: MINI_MAP_SIZE ,
257
+ ) ;
258
+ let scale = constants:: MINI_MAP_SIZE / constants:: WORLD_SIZE ;
259
+ self . radar_objects . add_particles (
260
+ game_state. players . iter ( ) . filter_map ( |player| {
261
+ if player. id == my_player. id || player. is_invisible ( ) {
262
+ // don't draw player if invisible
263
+ // and my player is always drawn
264
+ return None ;
265
+ }
266
+ let position = ( player. position - my_pos) * scale + offset;
267
+ if in_radar_range ( position) {
268
+ return Some ( RadarObject {
269
+ object_type : RadarObjectType :: Plane {
270
+ rotation : player. rotation ,
271
+ color : player. color . rgb ( ) ,
272
+ } ,
273
+ position : position,
274
+ lifetime : constants:: RADAR_FADEOUT_TIME ,
275
+ } ) ;
276
+ }
277
+ None
278
+ } )
279
+ ) ;
280
+ self . radar_objects . add_particles (
281
+ game_state. powerups . iter ( ) . filter_map ( |powerup| {
282
+ let position = ( powerup. position - my_pos) * scale + offset;
283
+ if in_radar_range ( position) {
284
+ return Some ( RadarObject {
285
+ object_type : RadarObjectType :: PowerUp ,
286
+ position : position,
287
+ lifetime : constants:: RADAR_FADEOUT_TIME ,
288
+ } ) ;
289
+ }
290
+ None
291
+ } )
292
+ ) ;
293
+ }
294
+ }
295
+
296
+ for obj in self . radar_objects . iter_mut ( ) {
297
+ obj. lifetime -= delta_time;
298
+ }
299
+ self . radar_objects . retain ( |obj| obj. lifetime > 0. ) ;
300
+ }
301
+
207
302
pub fn draw (
208
303
& self ,
209
304
my_id : u64 ,
@@ -310,7 +405,7 @@ impl Map {
310
405
Self :: draw_red_hit_effect ( hit_effect_timer, canvas) ;
311
406
312
407
if let Some ( my_player) = game_state. get_player_by_id ( my_id) {
313
- self . draw_mini_map ( game_state , canvas, assets, & my_player) ?;
408
+ self . draw_mini_map ( canvas, assets, my_player) ?;
314
409
}
315
410
316
411
Self :: draw_ui ( my_id, game_state, canvas, assets, powerup_rotation) ?;
@@ -615,7 +710,6 @@ impl Map {
615
710
616
711
fn draw_mini_map (
617
712
& self ,
618
- game_state : & GameState ,
619
713
canvas : & mut Canvas < Window > ,
620
714
assets : & mut Assets ,
621
715
my_player : & player:: Player ,
@@ -630,62 +724,41 @@ impl Map {
630
724
)
631
725
) ?;
632
726
633
- let my_pos = my_player. position ;
634
727
let mini_map_center = vec2 (
635
728
screen_w as f32 - constants:: MINI_MAP_SIZE * 0.5 ,
636
729
screen_h as f32 - constants:: MINI_MAP_SIZE * 0.5
637
730
) ;
638
731
639
- for tile_x in & [ -1. , 0. , 1. ] {
640
- for tile_y in & [ -1. , 0. , 1. ] {
641
- let offset = vec2 (
642
- tile_x * constants:: MINI_MAP_SIZE ,
643
- tile_y * constants:: MINI_MAP_SIZE ,
644
- ) ;
645
- let scale = constants:: MINI_MAP_SIZE
646
- / constants:: WORLD_SIZE ;
647
- for player in & game_state. players {
648
- if player. is_invisible ( ) && my_player. id != player. id {
649
- // don't draw player if invisible
650
- continue ;
651
- }
652
- let position = vec2 (
653
- ( player. position . x - my_pos. x ) * scale,
654
- ( player. position . y - my_pos. y ) * scale,
655
- ) ;
656
- let dist = ( ( position. x + offset. x ) . powi ( 2 )
657
- + ( position. y + offset. y ) . powi ( 2 ) ) . sqrt ( ) ;
658
- if dist <= constants:: MINI_MAP_SIZE /2. {
659
- let ( r, g, b, _) = player. color . rgba ( ) ;
660
- assets. miniplane . set_color_mod ( r, g, b) ;
661
- rendering:: draw_texture_rotated_and_scaled (
662
- canvas,
663
- & assets. miniplane ,
664
- position + offset + mini_map_center,
665
- player. rotation ,
666
- vec2 ( 0.5 , 0.5 )
667
- ) ?;
668
- }
732
+ for radar_object in self . radar_objects . iter ( ) {
733
+ let pos = mini_map_center + radar_object. position ;
734
+ let alpha =
735
+ ( radar_object. lifetime / constants:: RADAR_FADEOUT_TIME * 255. ) as u8 ;
736
+
737
+ match radar_object. object_type {
738
+ RadarObjectType :: Plane { rotation, color } => {
739
+ let ( r, g, b) = color;
740
+ assets. miniplane . set_color_mod ( r, g, b) ;
741
+ assets. miniplane . set_alpha_mod ( alpha) ;
742
+ rendering:: draw_texture_rotated_and_scaled (
743
+ canvas,
744
+ & assets. miniplane ,
745
+ pos,
746
+ rotation,
747
+ vec2 ( 0.5 , 0.5 )
748
+ ) ?;
749
+ assets. miniplane . set_alpha_mod ( 255 ) ;
669
750
}
670
- for powerup in & game_state. powerups {
671
- let position = vec2 (
672
- ( powerup. position . x - my_pos. x ) * scale,
673
- ( powerup. position . y - my_pos. y ) * scale,
674
- ) ;
675
- let dist = ( ( position. x + offset. x ) . powi ( 2 )
676
- + ( position. y + offset. y ) . powi ( 2 ) ) . sqrt ( ) ;
677
- if dist <= constants:: MINI_MAP_SIZE /2. {
678
- let pos = position + offset + mini_map_center;
679
- rendering:: draw_texture_centered (
680
- canvas,
681
- & assets. minimap_powerup ,
682
- pos
683
- ) ?;
684
- }
751
+ RadarObjectType :: PowerUp => {
752
+ assets. minimap_powerup . set_alpha_mod ( alpha) ;
753
+ rendering:: draw_texture_centered (
754
+ canvas, & assets. minimap_powerup , pos
755
+ ) ?;
756
+ assets. minimap_powerup . set_alpha_mod ( 255 ) ;
685
757
}
686
758
}
687
759
}
688
760
761
+ // Draw radar line
689
762
let mini_map_edge = mini_map_center + vec2 (
690
763
self . radar_angle . cos ( ) ,
691
764
self . radar_angle . sin ( )
@@ -695,6 +768,17 @@ impl Map {
695
768
( mini_map_edge. x as i32 , mini_map_edge. y as i32 )
696
769
) ?;
697
770
771
+ // Draw my plane
772
+ let ( r, g, b) = my_player. color . rgb ( ) ;
773
+ assets. miniplane . set_color_mod ( r, g, b) ;
774
+ rendering:: draw_texture_rotated_and_scaled (
775
+ canvas,
776
+ & assets. miniplane ,
777
+ mini_map_center,
778
+ my_player. rotation ,
779
+ vec2 ( 0.5 , 0.5 )
780
+ ) ?;
781
+
698
782
Ok ( ( ) )
699
783
}
700
784
0 commit comments