M crates/client/src/components.rs => crates/client/src/components.rs +6 -0
@@ 13,6 13,12 @@ pub struct Transform {
pub rotation: Rotation2<f32>,
pub scale: Scale3<f32>,
}
+#[derive(Resource, Debug)]
+pub struct PlayerResources {
+ pub fuel_amount: u32,
+ pub fuel_max: u32
+}
+
impl Transform {
pub fn to_matrix(&self) -> Matrix4<f32> {
self.translation.to_homogeneous()
M crates/client/src/lib.rs => crates/client/src/lib.rs +6 -0
@@ 6,6 6,7 @@ use rendering::{assets::Assets, App};
use starkingdoms_common::packet::Packet;
use tracing::info;
use winit::event_loop::{ControlFlow, EventLoop};
+use crate::components::PlayerResources;
#[cfg(target_arch = "wasm32")]
#[path = "wasm/mod.rs"]
@@ 17,6 18,7 @@ pub mod platform;
pub mod components;
pub mod networking;
pub mod rendering;
+pub mod ui;
// Hi, you've found the real main function! This is called AFTER platform-specific initialization code.
pub fn start() {
@@ 43,6 45,10 @@ pub fn start() {
world.insert_resource(Assets::new());
world.insert_resource(Ws::new());
+ world.insert_resource(PlayerResources {
+ fuel_amount: 0,
+ fuel_max: 0,
+ });
let mut send_packet_events = Events::<SendPacket>::default();
let recv_packet_events = Events::<RecvPacket>::default();
M crates/client/src/networking/mod.rs => crates/client/src/networking/mod.rs +6 -10
@@ 9,10 9,7 @@ use bevy_ecs::{
use nalgebra::{Rotation2, Scale2, Scale3, Translation3};
use starkingdoms_common::{packet::Packet, PartType, PlanetType};
-use crate::components::{
- Camera, Part, Planet, Player, RecvPacket, SendPacket, ServerId, SpriteBundle, Texture,
- Transform,
-};
+use crate::components::{Camera, Part, Planet, Player, PlayerResources, RecvPacket, SendPacket, ServerId, SpriteBundle, Texture, Transform};
#[cfg(target_arch = "wasm32")]
#[path = "ws_wasm.rs"]
@@ 51,8 48,6 @@ pub fn process_packets(
send_packet_events: &mut Events<SendPacket>,
recv_packet_events: &mut Events<RecvPacket>,
planet_types: &mut HashMap<PlanetType, (Entity, u32)>,
- amount: &mut u32,
- max: &mut u32,
) {
use Packet::*;
let mut recv_cursor = recv_packet_events.get_cursor();
@@ 201,11 196,12 @@ pub fn process_packets(
}
}
EnergyUpdate {
- amount: m_amount,
- max: m_max,
+ amount,
+ max,
} => {
- *amount = *m_amount;
- *max = *m_max;
+ let mut r = world.resource_mut::<PlayerResources>();
+ r.fuel_amount = *amount;
+ r.fuel_max = *max;
}
PlayerLeave { id } => {
let mut part_query = world.query_filtered::<(Entity, &ServerId), With<Part>>();
M crates/client/src/networking/ws_wasm.rs => crates/client/src/networking/ws_wasm.rs +3 -3
@@ 29,12 29,12 @@ pub struct Ws {
impl Ws {
pub fn new() -> Self {
let window = web_sys::window().unwrap();
- let ws = WebSocket::new(&format!(
+ /*let ws = WebSocket::new(&format!(
"ws://{}:{}",
window.location().hostname().unwrap(),
PORT
- ))
- .expect("Couldn't connect to server");
+ ))*/
+ let ws = WebSocket::new("ws://100.64.0.45:3000").expect("Couldn't connect to server");
let (packet_sender, receiver) = unbounded();
//let packet_sender = Rc::new(RwLock::new(packet_sender));
let (sender, packet_receiver) = unbounded();
M crates/client/src/rendering/mod.rs => crates/client/src/rendering/mod.rs +6 -19
@@ 46,6 46,8 @@ use winit::{
use crate::components::{Camera, Player, RecvPacket, SendPacket, Texture, Transform};
use crate::networking::process_packets;
use crate::networking::ws::Ws;
+use crate::ui::{draw_ui, init_ui};
+
#[cfg(not(target_arch = "wasm32"))]
#[path = "assets_native.rs"]
pub mod assets;
@@ 79,8 81,6 @@ pub struct App {
left: bool,
right: bool,
- amount: u32,
- max: u32,
mouse_pos: PhysicalPosition<f64>,
}
@@ 332,6 332,9 @@ impl ApplicationHandler for App {
));
let egui_glow = egui_glow::EguiGlow::new(event_loop, gl.clone(), None, None, true);
+
+ init_ui(egui_glow.egui_ctx.clone());
+
self.egui_glow = Some(egui_glow);
self.gl = Some(gl);
}
@@ 484,8 487,6 @@ impl ApplicationHandler for App {
&mut self.send_packet_events,
&mut self.recv_packet_events,
&mut self.planet_types,
- &mut self.amount,
- &mut self.max,
);
let window = self.window.as_ref().unwrap();
@@ 497,21 498,7 @@ impl ApplicationHandler for App {
.as_mut()
.unwrap()
.run(self.window.as_ref().unwrap(), |ctx| {
- egui::Window::new("Main Menu")
- .resizable(false)
- .show(ctx, |ui| {
- ui.heading("Starkingdoms.tk");
-
- ui.add(Label::new("Fuel:"));
- ui.add(
- ProgressBar::new((self.amount as f32) / (self.max as f32))
- .corner_radius(0),
- );
- ui.add(Label::new(format!(
- "Pos: {}, {}",
- player.translation.x as u32, player.translation.y as u32
- )));
- });
+ draw_ui(ctx, &mut self.world);
});
let camera = self.world.get_resource::<Camera>().unwrap();
A crates/client/src/ui/colors.rs => crates/client/src/ui/colors.rs +32 -0
@@ 0,0 1,32 @@
+macro_rules! color {
+ ($n:ident,rgb($r:expr, $g:expr, $b:expr)) => {
+ pub const $n: ::egui::Color32 = ::egui::Color32::from_rgb($r, $g, $b);
+ };
+}
+
+color!(ROSEWATER, rgb(245, 224, 220));
+color!(FLAMINGO, rgb(242, 205, 205));
+color!(PINK, rgb(245, 194, 231));
+color!(MAUVE, rgb(203, 166, 247));
+color!(RED, rgb(243, 139, 168));
+color!(MAROON, rgb(235, 160, 172));
+color!(PEACH, rgb(250, 179, 135));
+color!(YELLOW, rgb(249, 226, 175));
+color!(GREEN, rgb(166, 227, 161));
+color!(TEAL, rgb(148, 226, 213));
+color!(SKY, rgb(137, 220, 235));
+color!(SAPPHIRE, rgb(116, 199, 236));
+color!(BLUE, rgb(137, 180, 250));
+color!(LAVENDER, rgb(180, 190, 254));
+color!(TEXT, rgb(205, 214, 244));
+color!(SUBTEXT_1, rgb(186, 194, 222));
+color!(SUBTEXT_0, rgb(166, 173, 200));
+color!(OVERLAY_2, rgb(147, 153, 178));
+color!(OVERLAY_1, rgb(127, 132, 156));
+color!(OVERLAY_0, rgb(108, 112, 132));
+color!(SURFACE_2, rgb(88, 91, 112));
+color!(SURFACE_1, rgb(69, 71, 90));
+color!(SURFACE_0, rgb(49, 50, 68));
+color!(BASE, rgb(30, 30, 46));
+color!(MANTLE, rgb(24, 24, 37));
+color!(CRUST, rgb(17, 17, 27));<
\ No newline at end of file
A crates/client/src/ui/mod.rs => crates/client/src/ui/mod.rs +91 -0
@@ 0,0 1,91 @@
+mod colors;
+mod widgets;
+
+use bevy_ecs::prelude::With;
+use bevy_ecs::world::World;
+use egui::{Align, Align2, CornerRadius, CursorIcon, Layout, Order, ProgressBar, RichText, Shadow, Stroke, Visuals};
+use crate::components::{Player, PlayerResources, Transform};
+use crate::ui::widgets::{progress_bar, RichTextExt};
+
+pub fn init_ui(ctx: egui::Context) {
+ // set colors
+ let mut style = egui::Style::default();
+
+ let mut visuals = Visuals::default();
+ visuals.dark_mode = true;
+
+
+ // TODO(core): code_bg_colors
+
+ visuals.warn_fg_color = colors::YELLOW; // used for warning text
+ visuals.error_fg_color = colors::RED; // used for error text
+
+ visuals.window_shadow = Shadow::NONE;
+ visuals.window_fill = colors::MANTLE; // window background color
+ visuals.extreme_bg_color = colors::CRUST; // must be darker than window_fill
+ visuals.faint_bg_color = colors::BASE; // slightly different than window background color
+ visuals.window_stroke.color = colors::SURFACE_0;
+ visuals.window_highlight_topmost = false;
+
+ visuals.text_cursor.stroke.color = colors::ROSEWATER;
+
+ // TODO(core): button_frame, collapsing_header_frame
+ visuals.striped = true;
+
+ visuals.interact_cursor = Some(CursorIcon::PointingHand);
+
+ visuals.selection.bg_fill = colors::OVERLAY_2.gamma_multiply(0.2); // selection background
+
+ visuals.hyperlink_color = colors::BLUE;
+
+
+
+ visuals.widgets.noninteractive.fg_stroke.color = colors::TEXT; // standard text color
+
+
+ style.visuals = visuals;
+
+ ctx.set_style(style);
+}
+
+pub fn draw_ui(ctx: &egui::Context, world: &mut World) {
+ draw_hud(ctx, world);
+}
+
+pub fn draw_hud(ctx: &egui::Context, world: &mut World) {
+ let mut player = world.query_filtered::<&Transform, With<Player>>();
+ let player_position = player.single(&world);
+ let player_resources = world.resource::<PlayerResources>();
+
+ egui::Window::new("hud")
+ .title_bar(false)
+ .movable(false)
+ .resizable(false)
+ .order(Order::Foreground)
+ .anchor(Align2::CENTER_BOTTOM, [0.0, -5.0])
+ .show(ctx, |ui| {
+
+ ui.horizontal(|ui| {
+ ui.vertical(|ui| {
+ ui.label(RichText::new("Position:").stk_weak());
+ ui.label(RichText::new(format!("{:.0}, {:.0}", player_position.translation.x / 10.0, player_position.translation.y / 10.0)))
+ });
+
+ ui.add_space(8.0);
+
+ ui.vertical(|ui| {
+ ui.horizontal(|ui| {
+ ui.label(RichText::new("Fuel:").stk_weak());
+ ui.with_layout(Layout::right_to_left(Align::Center), |ui| {
+ ui.label(RichText::new(format!("{}/{} ({:.2}%)", player_resources.fuel_amount, player_resources.fuel_max, player_resources.fuel_amount as f32 / player_resources.fuel_max as f32 * 100.0)))
+ });
+
+ });
+
+ ui.add(
+ progress_bar(player_resources.fuel_amount as f32 / player_resources.fuel_max as f32)
+ );
+ })
+ });
+ });
+}<
\ No newline at end of file
A crates/client/src/ui/widgets.rs => crates/client/src/ui/widgets.rs +16 -0
@@ 0,0 1,16 @@
+use egui::RichText;
+
+pub fn progress_bar(progress: f32) -> egui::ProgressBar {
+ egui::ProgressBar::new(progress)
+ .fill(super::colors::BLUE)
+ .corner_radius(0)
+}
+
+pub trait RichTextExt {
+ fn stk_weak(self) -> Self;
+}
+impl RichTextExt for RichText {
+ fn stk_weak(self) -> Self {
+ self.color(super::colors::OVERLAY_2)
+ }
+}<
\ No newline at end of file