Skip to content

Commit dccf4d4

Browse files
committedApr 6, 2020
Only show objects on radar when scanned
1 parent 66948d5 commit dccf4d4

File tree

4 files changed

+152
-56
lines changed

4 files changed

+152
-56
lines changed
 

‎libplen/src/constants.rs

+4-1
Original file line numberDiff line numberDiff line change
@@ -94,4 +94,7 @@ pub const HURRICANE_EYE_SIZE: f32 = 100.;
9494
pub const HURRICANE_WIND_EFFECT_DECAY: f32 = 0.9;
9595
pub const HURRICANE_ROTATION_SPEED: f32 = 0.5;
9696

97-
pub const RADAR_SPEED: f32 = 1.0; // Speed that radar turns at, in radians/second
97+
// Speed that radar turns at, in radians/second
98+
pub const RADAR_SPEED: f32 = 3.0;
99+
// Time it takes for radar blips to fade out, in seconds
100+
pub const RADAR_FADEOUT_TIME: f32 = 1.0;

‎libplen/src/player.rs

+12-3
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,11 @@ impl Color {
108108
Color::Purple => (255, 0, 255, 255),
109109
}
110110
}
111+
112+
pub fn rgb(&self) -> (u8, u8, u8) {
113+
let (r, g, b, _) = self.rgba();
114+
(r, g, b)
115+
}
111116
}
112117

113118

@@ -136,9 +141,13 @@ pub struct Player {
136141

137142

138143
impl Player {
139-
pub fn new(id: u64, position: Vec2,
140-
plane_type: PlaneType, color: Color,
141-
name: String) -> Player {
144+
pub fn new(
145+
id: u64,
146+
position: Vec2,
147+
plane_type: PlaneType,
148+
color: Color,
149+
name: String
150+
) -> Player {
142151
Player {
143152
id: id,
144153
rotation: 0.,

‎src/client.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -142,7 +142,7 @@ impl MainState {
142142
return StateResult::GotoNext;
143143
}
144144

145-
self.map.update(elapsed.as_secs_f32(), &self.game_state);
145+
self.map.update(elapsed.as_secs_f32(), &self.game_state, self.my_id);
146146

147147
let shooting = keyboard_state.is_scancode_pressed(Scancode::Space);
148148
let activating_powerup = keyboard_state.is_scancode_pressed(Scancode::E);

‎src/map.rs

+135-51
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ use libplen::powerups::PowerUpKind;
1010
use libplen::constants;
1111
use libplen::gamestate::GameState;
1212
use libplen::projectiles::{ProjectileKind, Projectile};
13-
use libplen::math::{Vec2, vec2};
13+
use libplen::math::{self, Vec2, vec2};
1414

1515
use crate::assets::Assets;
1616
use crate::rendering;
@@ -83,10 +83,22 @@ pub struct SparkParticle {
8383
velocity: Vec2,
8484
}
8585

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+
8697
pub struct Map {
8798
smoke_particles: ParticleSystem<SmokeParticle>,
8899
explosion_particles: ParticleSystem<ExplosionParticle>,
89100
spark_particles: ParticleSystem<SparkParticle>,
101+
radar_objects: ParticleSystem<RadarObject>,
90102
smoke_timer: f32,
91103
spark_timer: f32,
92104
start_time: Instant,
@@ -99,6 +111,7 @@ impl Map {
99111
smoke_particles: ParticleSystem::new(200),
100112
explosion_particles: ParticleSystem::new(200),
101113
spark_particles: ParticleSystem::new(200),
114+
radar_objects: ParticleSystem::new(200),
102115
smoke_timer: 0.,
103116
spark_timer: 0.,
104117
start_time: Instant::now(),
@@ -126,9 +139,11 @@ impl Map {
126139
}));
127140
}
128141

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) {
130143
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+
}
132147
}
133148

134149
fn update_particles(&mut self, delta_time: f32, game_state: &GameState) {
@@ -204,6 +219,86 @@ impl Map {
204219
self.spark_particles.retain(|spark| spark.lifetime > 0.);
205220
}
206221

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+
207302
pub fn draw(
208303
&self,
209304
my_id: u64,
@@ -310,7 +405,7 @@ impl Map {
310405
Self::draw_red_hit_effect(hit_effect_timer, canvas);
311406

312407
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)?;
314409
}
315410

316411
Self::draw_ui(my_id, game_state, canvas, assets, powerup_rotation)?;
@@ -615,7 +710,6 @@ impl Map {
615710

616711
fn draw_mini_map(
617712
&self,
618-
game_state: &GameState,
619713
canvas: &mut Canvas<Window>,
620714
assets: &mut Assets,
621715
my_player: &player::Player,
@@ -630,62 +724,41 @@ impl Map {
630724
)
631725
)?;
632726

633-
let my_pos = my_player.position;
634727
let mini_map_center = vec2(
635728
screen_w as f32 - constants::MINI_MAP_SIZE * 0.5,
636729
screen_h as f32 - constants::MINI_MAP_SIZE * 0.5
637730
);
638731

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);
669750
}
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);
685757
}
686758
}
687759
}
688760

761+
// Draw radar line
689762
let mini_map_edge = mini_map_center + vec2(
690763
self.radar_angle.cos(),
691764
self.radar_angle.sin()
@@ -695,6 +768,17 @@ impl Map {
695768
(mini_map_edge.x as i32, mini_map_edge.y as i32)
696769
)?;
697770

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+
698782
Ok(())
699783
}
700784

0 commit comments

Comments
 (0)