use cgmath::{Deg, InnerSpace, Point2, Vector2}; use galactica_content as content; use galactica_gameobject as object; use galactica_render::{AnchoredUiPosition, UiSprite}; use galactica_world::{util, ShipPhysicsHandle, World}; // TODO: args as one unit pub fn build_radar( ct: &content::Content, player: ShipPhysicsHandle, physics: &World, system: &object::System, camera_zoom: f32, camera_aspect: f32, ) -> Vec { let mut out = Vec::new(); let radar_range = 4000.0; let radar_size = 300.0; let hide_range = 0.85; let shrink_distance = 20.0; let system_object_scale = 1.0 / 600.0; let ship_scale = 1.0 / 15.0; let (_, player_body) = physics.get_ship_body(player).unwrap(); let player_position = util::rigidbody_position(player_body); let planet_sprite = ct.get_sprite_handle("ui::planetblip"); let ship_sprite = ct.get_sprite_handle("ui::shipblip"); let arrow_sprite = ct.get_sprite_handle("ui::centerarrow"); out.push(UiSprite { sprite: ct.get_sprite_handle("ui::radar"), pos: AnchoredUiPosition::NwNw(Point2 { x: 10.0, y: -10.0 }), dimensions: Point2 { x: radar_size, y: radar_size, }, angle: Deg(0.0), color: None, }); // Draw system objects for o in &system.bodies { let size = (o.size / o.pos.z) / (radar_range * system_object_scale); let p = Point2 { x: o.pos.x, y: o.pos.y, }; let d = (p - player_position) / radar_range; // Add half the blip sprite's height to distance let m = d.magnitude() + (size / (2.0 * radar_size)); if m < hide_range { // Shrink blips as they get closeto the edge let size = size.min((hide_range - m) * size * shrink_distance); if size <= 2.0 { // Don't draw super tiny sprites, they flicker continue; } out.push(UiSprite { sprite: planet_sprite, pos: AnchoredUiPosition::NwC( Point2 { x: radar_size / 2.0 + 10.0, y: radar_size / -2.0 - 10.0, } + (d * (radar_size / 2.0)), ), dimensions: Point2 { x: planet_sprite.aspect, y: 1.0, } * size, angle: o.angle, color: Some([0.5, 0.5, 0.5, 1.0]), }); } } // Draw ships for (s, r) in physics.iter_ship_body() { let ship = ct.get_ship(s.ship.handle); let size = (ship.size * ship.sprite.aspect) * ship_scale; let p = util::rigidbody_position(r); let d = (p - player_position) / radar_range; let m = d.magnitude() + (size / (2.0 * radar_size)); if m < hide_range { let size = size.min((hide_range - m) * size * shrink_distance); if size < 2.0 { continue; } let angle: Deg = util::rigidbody_rotation(r) .angle(Vector2 { x: 0.0, y: 1.0 }) .into(); let f = ct.get_faction(s.ship.faction).color; let f = [f[0], f[1], f[2], 1.0]; out.push(UiSprite { sprite: ship_sprite, pos: AnchoredUiPosition::NwC( Point2 { x: radar_size / 2.0 + 10.0, y: radar_size / -2.0 - 10.0, } + (d * (radar_size / 2.0)), ), dimensions: Point2 { x: ship_sprite.aspect, y: 1.0, } * size, angle: -angle, color: Some(f), }); } } // Draw viewport frame let d = Vector2 { x: (camera_zoom / 2.0) * camera_aspect, y: camera_zoom / 2.0, } / radar_range; let m = d.magnitude(); let d = d * (radar_size / 2.0); let color = Some([0.3, 0.3, 0.3, 1.0]); if m < 0.8 { let sprite = ct.get_sprite_handle("ui::radarframe"); let dimensions = Point2 { x: sprite.aspect, y: 1.0, } * 7.0f32.min((0.8 - m) * 70.0); out.push(UiSprite { sprite, pos: AnchoredUiPosition::NwNw(Point2 { x: (radar_size / 2.0 + 10.0) - d.x, y: (radar_size / -2.0 - 10.0) + d.y, }), dimensions, angle: Deg(0.0), color, }); out.push(UiSprite { sprite, pos: AnchoredUiPosition::NwSw(Point2 { x: (radar_size / 2.0 + 10.0) - d.x, y: (radar_size / -2.0 - 10.0) - d.y, }), dimensions, angle: Deg(90.0), color, }); out.push(UiSprite { sprite, pos: AnchoredUiPosition::NwSe(Point2 { x: (radar_size / 2.0 + 10.0) + d.x, y: (radar_size / -2.0 - 10.0) - d.y, }), dimensions, angle: Deg(180.0), color, }); out.push(UiSprite { sprite, pos: AnchoredUiPosition::NwNe(Point2 { x: (radar_size / 2.0 + 10.0) + d.x, y: (radar_size / -2.0 - 10.0) + d.y, }), dimensions, angle: Deg(270.0), color, }); } // Arrow to center of system let q = Point2 { x: 0.0, y: 0.0 } - player_position; let m = q.magnitude(); if m > 200.0 { let player_angle: Deg = q.angle(Vector2 { x: 0.0, y: 1.0 }).into(); out.push(UiSprite { sprite: arrow_sprite, pos: AnchoredUiPosition::NwC( Point2 { x: radar_size / 2.0 + 10.0, y: radar_size / -2.0 - 10.0, } + ((q.normalize() * 0.865) * (radar_size / 2.0)), ), dimensions: Point2 { x: arrow_sprite.aspect, y: 1.0, } * 10.0, angle: -player_angle, color: Some([1.0, 1.0, 1.0, 1f32.min((m - 200.0) / 400.0)]), }); } return out; }