Improved radar ui
parent
381dd4a383
commit
3e944d1172
|
@ -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",
|
||||||
]
|
]
|
||||||
|
|
2
TODO.md
2
TODO.md
|
@ -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
2
assets
|
@ -1 +1 @@
|
||||||
Subproject commit 62fd7fc297a2631691b588b898694e220d58cf78
|
Subproject commit b53acd48a98987914ceb196af18ba679a222fa10
|
|
@ -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]
|
||||||
|
|
|
@ -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"
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
|
@ -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"
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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,
|
||||||
);
|
);
|
||||||
|
|
Loading…
Reference in New Issue