diff --git a/Cargo.lock b/Cargo.lock index 9513f45..9b2e090 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -657,6 +657,7 @@ version = "0.0.0" dependencies = [ "cgmath", "galactica-content", + "galactica-gameobject", "galactica-render", "galactica-world", ] diff --git a/TODO.md b/TODO.md index 866b5c8..10a1da7 100644 --- a/TODO.md +++ b/TODO.md @@ -4,7 +4,6 @@ - Sound system - Particles, impact effects - Debris on ship death - - Radar: ship size, planets and suns ---------------------------------- @@ -13,6 +12,7 @@ - How to keep player in system bounds, what to do if they fly far away - Max chase distance, physics-enforced area? - (Soft limits, you shouldn't go too far unless you decide to.) + - Enforce: silently teleport to the other end - How to handle death -- save scum should not be the norm (hollow knight?) - Jumping between systems -- how? - Locks and keys -> variation? diff --git a/assets b/assets index 62fd7fc..b53acd4 160000 --- a/assets +++ b/assets @@ -1 +1 @@ -Subproject commit 62fd7fc297a2631691b588b898694e220d58cf78 +Subproject commit b53acd48a98987914ceb196af18ba679a222fa10 diff --git a/content/factions.toml b/content/factions.toml index bd56d15..18c9bbd 100644 --- a/content/factions.toml +++ b/content/factions.toml @@ -1,9 +1,11 @@ [faction."player"] display_name = "Player" +relationship.player = "neutral" relationship.enemy = "hostile" color = [0.0, 1.0, 0.0] [faction."enemy"] display_name = "Enemy" +relationship.enemy = "neutral" relationship.player = "hostile" color = [1.0, 0.0, 0.0] diff --git a/content/textures.toml b/content/textures.toml index ce25a2c..1c26b7a 100644 --- a/content/textures.toml +++ b/content/textures.toml @@ -22,8 +22,14 @@ path = "ship/gypsum.png" [texture."ui::radar"] path = "ui/radar.png" -[texture."ui::blip"] -path = "ui/blip.png" +[texture."ui::shipblip"] +path = "ui/ship-blip.png" + +[texture."ui::planetblip"] +path = "ui/planet-blip.png" [texture."ui::radarframe"] path = "ui/radarframe.png" + +[texture."ui::centerarrow"] +path = "ui/center-arrow.png" diff --git a/crates/content/src/part/faction.rs b/crates/content/src/part/faction.rs index d596b17..a732d68 100644 --- a/crates/content/src/part/faction.rs +++ b/crates/content/src/part/faction.rs @@ -1,4 +1,4 @@ -use anyhow::Result; +use anyhow::{bail, Result}; use serde::Deserialize; use std::collections::HashMap; @@ -99,6 +99,19 @@ impl crate::Build for Faction { } } + if faction.color[0] > 1.0 + || faction.color[0] < 0.0 + || faction.color[1] > 1.0 + || faction.color[1] < 0.0 + || faction.color[2] > 1.0 + || faction.color[2] < 0.0 + { + bail!( + "Invalid color for faction `{}`. Value out of range.", + faction_name + ); + } + ct.factions.push(Self { name: faction_name.to_owned(), handle: h, diff --git a/crates/gameobject/src/system.rs b/crates/gameobject/src/system.rs index 7484289..90fa05b 100644 --- a/crates/gameobject/src/system.rs +++ b/crates/gameobject/src/system.rs @@ -4,7 +4,7 @@ use galactica_render::ObjectSprite; pub struct System { pub name: String, - bodies: Vec, + pub bodies: Vec, } impl System { diff --git a/crates/ui/Cargo.toml b/crates/ui/Cargo.toml index 5862151..6266d63 100644 --- a/crates/ui/Cargo.toml +++ b/crates/ui/Cargo.toml @@ -7,4 +7,5 @@ edition = "2021" galactica-content = { path = "../content" } galactica-world = { path = "../world" } galactica-render = { path = "../render" } +galactica-gameobject = { path = "../gameobject" } cgmath = "0.18.0" diff --git a/crates/ui/src/radar.rs b/crates/ui/src/radar.rs index fca4ca3..f02c04d 100644 --- a/crates/ui/src/radar.rs +++ b/crates/ui/src/radar.rs @@ -1,5 +1,6 @@ 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}; @@ -8,13 +9,24 @@ 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 = 2000.0; + 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 / 10.0; + + let (_, player_body) = physics.get_ship_body(player).unwrap(); + let player_position = util::rigidbody_position(player_body); + let planet_texture = ct.get_texture_handle("ui::planetblip"); + let ship_texture = ct.get_texture_handle("ui::shipblip"); + let arrow_texture = ct.get_texture_handle("ui::centerarrow"); out.push(UiSprite { texture: ct.get_texture_handle("ui::radar"), @@ -27,14 +39,84 @@ pub fn build_radar( 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 { + texture: planet_texture, + 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_texture.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_texture.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 { + texture: ship_texture, + 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_texture.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, - }; - let m = d.magnitude() / radar_range; - let d = d / radar_range * (radar_size / 2.0); - let color = Some([0.5, 0.5, 0.5, 1.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 texture = ct.get_texture_handle("ui::radarframe"); let dimensions = Point2 { @@ -86,36 +168,26 @@ pub fn build_radar( }); } - let (_, pr) = physics.get_ship_body(player).unwrap(); - let pr = util::rigidbody_position(pr); - let texture = ct.get_texture_handle("ui::blip"); - for (s, r) in physics.iter_ship_body() { - let p = util::rigidbody_position(r); - let d = p - pr; - let m = d.magnitude() / radar_range; - if m < 0.8 { - 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 { - texture, - pos: AnchoredUiPosition::NwC( - Point2 { - x: radar_size / 2.0 + 10.0, - y: radar_size / -2.0 - 10.0, - } + (d / radar_range * (radar_size / 2.0)), - ), - dimensions: Point2 { - x: texture.aspect, - y: 1.0, - } * 5.0f32.min((0.8 - m) * 50.0), - angle: -angle, - color: Some(f), - }); - } + // 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 { + texture: arrow_texture, + 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_texture.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; diff --git a/src/game.rs b/src/game.rs index 2817095..68d5489 100644 --- a/src/game.rs +++ b/src/game.rs @@ -187,6 +187,7 @@ impl Game { &self.content, &self.player, &self.physics, + &self.system, self.camera.zoom, self.camera.aspect, );