Improved radar ui

master
Mark 2024-01-02 15:59:50 -08:00
parent 381dd4a383
commit 3e944d1172
Signed by: Mark
GPG Key ID: C6D63995FE72FD80
10 changed files with 137 additions and 41 deletions

1
Cargo.lock generated
View File

@ -657,6 +657,7 @@ version = "0.0.0"
dependencies = [ dependencies = [
"cgmath", "cgmath",
"galactica-content", "galactica-content",
"galactica-gameobject",
"galactica-render", "galactica-render",
"galactica-world", "galactica-world",
] ]

View File

@ -4,7 +4,6 @@
- Sound system - Sound system
- Particles, impact effects - Particles, impact effects
- Debris on ship death - 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 - How to keep player in system bounds, what to do if they fly far away
- Max chase distance, physics-enforced area? - Max chase distance, physics-enforced area?
- (Soft limits, you shouldn't go too far unless you decide to.) - (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?) - How to handle death -- save scum should not be the norm (hollow knight?)
- Jumping between systems -- how? - Jumping between systems -- how?
- Locks and keys -> variation? - Locks and keys -> variation?

2
assets

@ -1 +1 @@
Subproject commit 62fd7fc297a2631691b588b898694e220d58cf78 Subproject commit b53acd48a98987914ceb196af18ba679a222fa10

View File

@ -1,9 +1,11 @@
[faction."player"] [faction."player"]
display_name = "Player" display_name = "Player"
relationship.player = "neutral"
relationship.enemy = "hostile" relationship.enemy = "hostile"
color = [0.0, 1.0, 0.0] color = [0.0, 1.0, 0.0]
[faction."enemy"] [faction."enemy"]
display_name = "Enemy" display_name = "Enemy"
relationship.enemy = "neutral"
relationship.player = "hostile" relationship.player = "hostile"
color = [1.0, 0.0, 0.0] color = [1.0, 0.0, 0.0]

View File

@ -22,8 +22,14 @@ path = "ship/gypsum.png"
[texture."ui::radar"] [texture."ui::radar"]
path = "ui/radar.png" path = "ui/radar.png"
[texture."ui::blip"] [texture."ui::shipblip"]
path = "ui/blip.png" path = "ui/ship-blip.png"
[texture."ui::planetblip"]
path = "ui/planet-blip.png"
[texture."ui::radarframe"] [texture."ui::radarframe"]
path = "ui/radarframe.png" path = "ui/radarframe.png"
[texture."ui::centerarrow"]
path = "ui/center-arrow.png"

View File

@ -1,4 +1,4 @@
use anyhow::Result; use anyhow::{bail, Result};
use serde::Deserialize; use serde::Deserialize;
use std::collections::HashMap; 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 { ct.factions.push(Self {
name: faction_name.to_owned(), name: faction_name.to_owned(),
handle: h, handle: h,

View File

@ -4,7 +4,7 @@ use galactica_render::ObjectSprite;
pub struct System { pub struct System {
pub name: String, pub name: String,
bodies: Vec<SystemObject>, pub bodies: Vec<SystemObject>,
} }
impl System { impl System {

View File

@ -7,4 +7,5 @@ edition = "2021"
galactica-content = { path = "../content" } galactica-content = { path = "../content" }
galactica-world = { path = "../world" } galactica-world = { path = "../world" }
galactica-render = { path = "../render" } galactica-render = { path = "../render" }
galactica-gameobject = { path = "../gameobject" }
cgmath = "0.18.0" cgmath = "0.18.0"

View File

@ -1,5 +1,6 @@
use cgmath::{Deg, InnerSpace, Point2, Vector2}; use cgmath::{Deg, InnerSpace, Point2, Vector2};
use galactica_content as content; use galactica_content as content;
use galactica_gameobject as object;
use galactica_render::{AnchoredUiPosition, UiSprite}; use galactica_render::{AnchoredUiPosition, UiSprite};
use galactica_world::{util, ShipPhysicsHandle, World}; use galactica_world::{util, ShipPhysicsHandle, World};
@ -8,13 +9,24 @@ pub fn build_radar(
ct: &content::Content, ct: &content::Content,
player: &ShipPhysicsHandle, player: &ShipPhysicsHandle,
physics: &World, physics: &World,
system: &object::System,
camera_zoom: f32, camera_zoom: f32,
camera_aspect: f32, camera_aspect: f32,
) -> Vec<UiSprite> { ) -> Vec<UiSprite> {
let mut out = Vec::new(); let mut out = Vec::new();
let radar_range = 2000.0; let radar_range = 4000.0;
let radar_size = 300.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 { out.push(UiSprite {
texture: ct.get_texture_handle("ui::radar"), texture: ct.get_texture_handle("ui::radar"),
@ -27,14 +39,84 @@ pub fn build_radar(
color: None, 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<f32> = 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 // Draw viewport frame
let d = Vector2 { let d = Vector2 {
x: (camera_zoom / 2.0) * camera_aspect, x: (camera_zoom / 2.0) * camera_aspect,
y: camera_zoom / 2.0, y: camera_zoom / 2.0,
}; } / radar_range;
let m = d.magnitude() / radar_range; let m = d.magnitude();
let d = d / radar_range * (radar_size / 2.0); let d = d * (radar_size / 2.0);
let color = Some([0.5, 0.5, 0.5, 1.0]); let color = Some([0.3, 0.3, 0.3, 1.0]);
if m < 0.8 { if m < 0.8 {
let texture = ct.get_texture_handle("ui::radarframe"); let texture = ct.get_texture_handle("ui::radarframe");
let dimensions = Point2 { let dimensions = Point2 {
@ -86,36 +168,26 @@ pub fn build_radar(
}); });
} }
let (_, pr) = physics.get_ship_body(player).unwrap(); // Arrow to center of system
let pr = util::rigidbody_position(pr); let q = Point2 { x: 0.0, y: 0.0 } - player_position;
let texture = ct.get_texture_handle("ui::blip"); let m = q.magnitude();
for (s, r) in physics.iter_ship_body() { if m > 200.0 {
let p = util::rigidbody_position(r); let player_angle: Deg<f32> = q.angle(Vector2 { x: 0.0, y: 1.0 }).into();
let d = p - pr; out.push(UiSprite {
let m = d.magnitude() / radar_range; texture: arrow_texture,
if m < 0.8 { pos: AnchoredUiPosition::NwC(
let angle: Deg<f32> = util::rigidbody_rotation(r) Point2 {
.angle(Vector2 { x: 0.0, y: 1.0 }) x: radar_size / 2.0 + 10.0,
.into(); y: radar_size / -2.0 - 10.0,
let f = ct.get_faction(s.ship.faction).color; } + ((q.normalize() * 0.865) * (radar_size / 2.0)),
let f = [f[0], f[1], f[2], 1.0]; ),
dimensions: Point2 {
out.push(UiSprite { x: arrow_texture.aspect,
texture, y: 1.0,
pos: AnchoredUiPosition::NwC( } * 10.0,
Point2 { angle: -player_angle,
x: radar_size / 2.0 + 10.0, color: Some([1.0, 1.0, 1.0, 1f32.min((m - 200.0) / 400.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),
});
}
} }
return out; return out;

View File

@ -187,6 +187,7 @@ impl Game {
&self.content, &self.content,
&self.player, &self.player,
&self.physics, &self.physics,
&self.system,
self.camera.zoom, self.camera.zoom,
self.camera.aspect, self.camera.aspect,
); );