Added radar frame
parent
aa2a1943b2
commit
a85a0f8188
10
TODO.md
10
TODO.md
|
@ -1,3 +1,13 @@
|
||||||
|
## Specific Jobs
|
||||||
|
- UI: health, shield, fuel, heat, energy bars
|
||||||
|
- UI: text arranger
|
||||||
|
- Sound system
|
||||||
|
- Particles, impact effects
|
||||||
|
- Debris on ship death
|
||||||
|
- Radar: dynamic colors, size, planets and suns
|
||||||
|
|
||||||
|
----------------------------------
|
||||||
|
|
||||||
## Game & Story
|
## Game & Story
|
||||||
- Landmarks to determine speed?
|
- Landmarks to determine speed?
|
||||||
- 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
|
||||||
|
|
2
assets
2
assets
|
@ -1 +1 @@
|
||||||
Subproject commit 8205d79e8aa9d7e4976fe8a7794e83819ec19688
|
Subproject commit 91377416617d049acec68bb5a17647dcac7acd0e
|
|
@ -24,3 +24,6 @@ path = "ui/radar.png"
|
||||||
|
|
||||||
[texture."ui::blip"]
|
[texture."ui::blip"]
|
||||||
path = "ui/blip.png"
|
path = "ui/blip.png"
|
||||||
|
|
||||||
|
[texture."ui::radarframe"]
|
||||||
|
path = "ui/radarframe.png"
|
||||||
|
|
|
@ -356,28 +356,46 @@ impl GPUState {
|
||||||
let width = s.dimensions.x;
|
let width = s.dimensions.x;
|
||||||
let height = s.dimensions.y;
|
let height = s.dimensions.y;
|
||||||
|
|
||||||
|
// Compute square scale, since we must apply screen aspect ratio
|
||||||
|
// AFTER rotation.
|
||||||
let scale = Matrix4::from_nonuniform_scale(
|
let scale = Matrix4::from_nonuniform_scale(
|
||||||
width / logical_size.width,
|
width / logical_size.height,
|
||||||
height / logical_size.height,
|
height / logical_size.height,
|
||||||
1.0,
|
1.0,
|
||||||
);
|
);
|
||||||
let rotate = Matrix4::from_angle_z(s.angle);
|
let rotate = Matrix4::from_angle_z(s.angle);
|
||||||
let translate = Matrix4::from_translation(match s.pos {
|
let translate = Matrix4::from_translation(match s.pos {
|
||||||
super::AnchoredUiPosition::NorthWest(p) => Vector3 {
|
super::AnchoredUiPosition::NwC(p) => Vector3 {
|
||||||
// Note the signs. Positive y points north!
|
// Note the signs. Positive y points north!
|
||||||
|
x: -1.0 + p.x / (logical_size.width / 2.0),
|
||||||
|
y: 1.0 + p.y / (logical_size.height / 2.0),
|
||||||
|
z: 0.0,
|
||||||
|
},
|
||||||
|
super::AnchoredUiPosition::NwNw(p) => Vector3 {
|
||||||
x: -1.0 + (width / 2.0 + p.x) / (logical_size.width / 2.0),
|
x: -1.0 + (width / 2.0 + p.x) / (logical_size.width / 2.0),
|
||||||
y: 1.0 - (height / 2.0 - p.y) / (logical_size.height / 2.0),
|
y: 1.0 - (height / 2.0 - p.y) / (logical_size.height / 2.0),
|
||||||
z: 0.0,
|
z: 0.0,
|
||||||
},
|
},
|
||||||
_ => Vector3 {
|
super::AnchoredUiPosition::NwNe(p) => Vector3 {
|
||||||
x: 0.0,
|
x: -1.0 - (width / 2.0 - p.x) / (logical_size.width / 2.0),
|
||||||
y: 0.0,
|
y: 1.0 - (height / 2.0 - p.y) / (logical_size.height / 2.0),
|
||||||
|
z: 0.0,
|
||||||
|
},
|
||||||
|
super::AnchoredUiPosition::NwSw(p) => Vector3 {
|
||||||
|
x: -1.0 + (width / 2.0 + p.x) / (logical_size.width / 2.0),
|
||||||
|
y: 1.0 + (height / 2.0 + p.y) / (logical_size.height / 2.0),
|
||||||
|
z: 0.0,
|
||||||
|
},
|
||||||
|
super::AnchoredUiPosition::NwSe(p) => Vector3 {
|
||||||
|
x: -1.0 - (width / 2.0 - p.x) / (logical_size.width / 2.0),
|
||||||
|
y: 1.0 + (height / 2.0 + p.y) / (logical_size.height / 2.0),
|
||||||
z: 0.0,
|
z: 0.0,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
let screen_aspect = Matrix4::from_nonuniform_scale(1.0 / self.window_aspect, 1.0, 1.0);
|
||||||
|
|
||||||
instances.push(SpriteInstance {
|
instances.push(SpriteInstance {
|
||||||
transform: (OPENGL_TO_WGPU_MATRIX * translate * rotate * scale).into(),
|
transform: (OPENGL_TO_WGPU_MATRIX * translate * screen_aspect * rotate * scale).into(),
|
||||||
texture_index: texture.index,
|
texture_index: texture.index,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,13 +8,25 @@ use cgmath::{Deg, Point2, Point3};
|
||||||
/// positive X always points right.
|
/// positive X always points right.
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub enum AnchoredUiPosition {
|
pub enum AnchoredUiPosition {
|
||||||
|
/// Position of this sprite's center,
|
||||||
|
/// relative to the nw corner of the window.
|
||||||
|
NwC(Point2<f32>),
|
||||||
|
|
||||||
/// Position of this sprite's nw corner,
|
/// Position of this sprite's nw corner,
|
||||||
/// relative to the nw corner of the window.
|
/// relative to the nw corner of the window.
|
||||||
NorthWest(Point2<f32>),
|
NwNw(Point2<f32>),
|
||||||
|
|
||||||
|
/// Position of this sprite's ne corner,
|
||||||
|
/// relative to the nw corner of the window.
|
||||||
|
NwNe(Point2<f32>),
|
||||||
|
|
||||||
/// Position of this sprite's sw corner,
|
/// Position of this sprite's sw corner,
|
||||||
/// relative to the sw corner of the window.
|
/// relative to the nw corner of the window.
|
||||||
SouthWest(Point2<f32>),
|
NwSw(Point2<f32>),
|
||||||
|
|
||||||
|
/// Position of this sprite's se corner,
|
||||||
|
/// relative to the nw corner of the window.
|
||||||
|
NwSe(Point2<f32>),
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A sprite that represents a ui element
|
/// A sprite that represents a ui element
|
||||||
|
|
|
@ -1,12 +1,15 @@
|
||||||
use cgmath::{Deg, InnerSpace, Point2};
|
use cgmath::{Deg, InnerSpace, Point2, Vector2};
|
||||||
use galactica_content as content;
|
use galactica_content as content;
|
||||||
use galactica_render::{AnchoredUiPosition, UiSprite};
|
use galactica_render::{AnchoredUiPosition, UiSprite};
|
||||||
use galactica_world::{util, ShipPhysicsHandle, World};
|
use galactica_world::{util, ShipPhysicsHandle, World};
|
||||||
|
|
||||||
|
// TODO: camera as one unit
|
||||||
pub fn build_radar(
|
pub fn build_radar(
|
||||||
|
ct: &content::Content,
|
||||||
player: &ShipPhysicsHandle,
|
player: &ShipPhysicsHandle,
|
||||||
physics: &World,
|
physics: &World,
|
||||||
ct: &content::Content,
|
camera_zoom: f32,
|
||||||
|
camera_aspect: f32,
|
||||||
) -> Vec<UiSprite> {
|
) -> Vec<UiSprite> {
|
||||||
let mut out = Vec::new();
|
let mut out = Vec::new();
|
||||||
|
|
||||||
|
@ -15,7 +18,7 @@ pub fn build_radar(
|
||||||
|
|
||||||
out.push(UiSprite {
|
out.push(UiSprite {
|
||||||
texture: ct.get_texture_handle("ui::radar"),
|
texture: ct.get_texture_handle("ui::radar"),
|
||||||
pos: AnchoredUiPosition::NorthWest(Point2 { x: 10.0, y: -10.0 }),
|
pos: AnchoredUiPosition::NwNw(Point2 { x: 10.0, y: -10.0 }),
|
||||||
dimensions: Point2 {
|
dimensions: Point2 {
|
||||||
x: radar_size,
|
x: radar_size,
|
||||||
y: radar_size,
|
y: radar_size,
|
||||||
|
@ -23,26 +26,98 @@ pub fn build_radar(
|
||||||
angle: Deg(0.0),
|
angle: Deg(0.0),
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// 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);
|
||||||
|
println!("{:?}", d);
|
||||||
|
if m < 0.8 {
|
||||||
|
let texture = ct.get_texture_handle("ui::radarframe");
|
||||||
|
let dimensions = Point2 {
|
||||||
|
x: texture.aspect,
|
||||||
|
y: 1.0,
|
||||||
|
} * 7.0f32.min((0.8 - m) * 70.0);
|
||||||
|
out.push(UiSprite {
|
||||||
|
texture,
|
||||||
|
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),
|
||||||
|
});
|
||||||
|
|
||||||
|
out.push(UiSprite {
|
||||||
|
texture,
|
||||||
|
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),
|
||||||
|
});
|
||||||
|
|
||||||
|
out.push(UiSprite {
|
||||||
|
texture,
|
||||||
|
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),
|
||||||
|
});
|
||||||
|
|
||||||
|
out.push(UiSprite {
|
||||||
|
texture,
|
||||||
|
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),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
let (_, pr) = physics.get_ship_body(player).unwrap();
|
let (_, pr) = physics.get_ship_body(player).unwrap();
|
||||||
let pr = util::rigidbody_position(pr);
|
let pr = util::rigidbody_position(pr);
|
||||||
|
let texture = ct.get_texture_handle("ui::blip");
|
||||||
for (s, r) in physics.iter_ship_body() {
|
for (s, r) in physics.iter_ship_body() {
|
||||||
if s.physics_handle == *player {
|
let p = util::rigidbody_position(r);
|
||||||
continue;
|
let d = p - pr;
|
||||||
}
|
|
||||||
let r = util::rigidbody_position(r);
|
|
||||||
let d = r - pr;
|
|
||||||
let m = d.magnitude() / radar_range;
|
let m = d.magnitude() / radar_range;
|
||||||
if m < 0.8 {
|
let angle: Deg<f32> = util::rigidbody_rotation(r)
|
||||||
|
.angle(Vector2 { x: 0.0, y: 1.0 })
|
||||||
|
.into();
|
||||||
|
if s.physics_handle == *player {
|
||||||
out.push(UiSprite {
|
out.push(UiSprite {
|
||||||
texture: ct.get_texture_handle("ui::blip"),
|
texture,
|
||||||
pos: AnchoredUiPosition::NorthWest(
|
pos: AnchoredUiPosition::NwC(Point2 {
|
||||||
|
x: radar_size / 2.0 + 10.0,
|
||||||
|
y: radar_size / -2.0 - 10.0,
|
||||||
|
}),
|
||||||
|
dimensions: Point2 {
|
||||||
|
x: texture.aspect,
|
||||||
|
y: 1.0,
|
||||||
|
} * 5.0f32.min((0.8 - m) * 50.0),
|
||||||
|
angle: -angle,
|
||||||
|
});
|
||||||
|
} else if m < 0.8 {
|
||||||
|
out.push(UiSprite {
|
||||||
|
texture,
|
||||||
|
pos: AnchoredUiPosition::NwC(
|
||||||
Point2 {
|
Point2 {
|
||||||
x: radar_size / 2.0 + 10.0,
|
x: radar_size / 2.0 + 10.0,
|
||||||
y: radar_size / -2.0 - 10.0,
|
y: radar_size / -2.0 - 10.0,
|
||||||
} + (d / radar_range * 150.0),
|
} + (d / radar_range * (radar_size / 2.0)),
|
||||||
),
|
),
|
||||||
dimensions: Point2 { x: 1.0, y: 1.0 } * 5.0f32.min((0.8 - m) * 50.0),
|
dimensions: Point2 {
|
||||||
angle: Deg(0.0),
|
x: texture.aspect,
|
||||||
|
y: 1.0,
|
||||||
|
} * 5.0f32.min((0.8 - m) * 50.0),
|
||||||
|
angle: -angle,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,4 +8,7 @@ pub struct Camera {
|
||||||
/// Camera zoom
|
/// Camera zoom
|
||||||
/// (How many game units tall is the viewport?)
|
/// (How many game units tall is the viewport?)
|
||||||
pub zoom: f32,
|
pub zoom: f32,
|
||||||
|
|
||||||
|
/// Aspect ratio of viewport (width / height)
|
||||||
|
pub aspect: f32,
|
||||||
}
|
}
|
||||||
|
|
|
@ -86,6 +86,7 @@ impl Game {
|
||||||
camera: Camera {
|
camera: Camera {
|
||||||
pos: (0.0, 0.0).into(),
|
pos: (0.0, 0.0).into(),
|
||||||
zoom: 500.0,
|
zoom: 500.0,
|
||||||
|
aspect: 1.0,
|
||||||
},
|
},
|
||||||
system: object::System::new(&ct, SystemHandle { index: 0 }),
|
system: object::System::new(&ct, SystemHandle { index: 0 }),
|
||||||
|
|
||||||
|
@ -179,6 +180,12 @@ impl Game {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_ui_sprites(&self) -> Vec<UiSprite> {
|
pub fn get_ui_sprites(&self) -> Vec<UiSprite> {
|
||||||
return ui::build_radar(&self.player, &self.physics, &self.content);
|
return ui::build_radar(
|
||||||
|
&self.content,
|
||||||
|
&self.player,
|
||||||
|
&self.physics,
|
||||||
|
self.camera.zoom,
|
||||||
|
self.camera.aspect,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,6 +27,7 @@ fn main() -> Result<()> {
|
||||||
|
|
||||||
let mut game = game::Game::new(content);
|
let mut game = game::Game::new(content);
|
||||||
gpu.update_starfield_buffer();
|
gpu.update_starfield_buffer();
|
||||||
|
game.camera.aspect = gpu.window_size.width as f32 / gpu.window_size.height as f32;
|
||||||
|
|
||||||
event_loop.run(move |event, _, control_flow| {
|
event_loop.run(move |event, _, control_flow| {
|
||||||
match event {
|
match event {
|
||||||
|
@ -75,9 +76,13 @@ fn main() -> Result<()> {
|
||||||
}
|
}
|
||||||
WindowEvent::Resized(_) => {
|
WindowEvent::Resized(_) => {
|
||||||
gpu.resize();
|
gpu.resize();
|
||||||
|
game.camera.aspect =
|
||||||
|
gpu.window_size.width as f32 / gpu.window_size.height as f32;
|
||||||
}
|
}
|
||||||
WindowEvent::ScaleFactorChanged { .. } => {
|
WindowEvent::ScaleFactorChanged { .. } => {
|
||||||
gpu.resize();
|
gpu.resize();
|
||||||
|
game.camera.aspect =
|
||||||
|
gpu.window_size.width as f32 / gpu.window_size.height as f32;
|
||||||
}
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
},
|
},
|
||||||
|
|
Loading…
Reference in New Issue