Skip to content

Commit 5c8fd75

Browse files
authored
Client fixes (#64)
* fix unit selection * show advances of other players * show advances of other players * multiline log * multiline log * fix combat arrow * format * improve unit ui * improve unit ui * improve building ui * improve port ui
1 parent 6c833c2 commit 5c8fd75

9 files changed

+119
-85
lines changed

client/src/advance_ui.rs

+19-15
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ use server::resource_pile::AdvancePaymentOptions;
1212
use server::status_phase::{StatusPhaseAction, StatusPhaseState};
1313

1414
use crate::client_state::{ActiveDialog, ShownPlayer, StateUpdate};
15-
use crate::dialog_ui::dialog_window;
15+
use crate::dialog_ui::dialog;
1616
use crate::payment_ui::{payment_dialog, HasPayment, Payment, ResourcePayment};
1717
use crate::resource_ui::{new_resource_map, ResourceType};
1818
use crate::select_ui::HasCountSelectableObject;
@@ -99,24 +99,28 @@ pub fn show_generic_advance_menu(
9999
close_button: bool,
100100
new_update: impl Fn(String) -> StateUpdate,
101101
) -> StateUpdate {
102-
dialog_window(player, title, close_button, |ui| {
102+
dialog(title, close_button, |ui| {
103+
let p = player.get(game);
103104
for a in get_all() {
104105
let name = a.name;
105-
let p = player.get(game);
106-
if p.has_advance(&name) {
107-
ui.label(None, &name);
108-
} else {
109-
let can = if matches!(
110-
game.state,
111-
GameState::StatusPhase(StatusPhaseState::FreeAdvance)
112-
) {
113-
p.can_advance_free(&name)
106+
if player.can_play_action {
107+
if p.has_advance(&name) {
108+
ui.label(None, &name);
114109
} else {
115-
player.can_control && p.can_advance(&name)
116-
};
117-
if can && ui.button(None, name.clone()) {
118-
return new_update(name);
110+
let can = if matches!(
111+
game.state,
112+
GameState::StatusPhase(StatusPhaseState::FreeAdvance)
113+
) {
114+
p.can_advance_free(&name)
115+
} else {
116+
player.can_control && p.can_advance(&name)
117+
};
118+
if can && ui.button(None, name.clone()) {
119+
return new_update(name);
120+
}
119121
}
122+
} else if p.has_advance(&name) {
123+
ui.label(None, &name);
120124
}
121125
}
122126
StateUpdate::None

client/src/city_ui.rs

+17-16
Original file line numberDiff line numberDiff line change
@@ -168,27 +168,28 @@ pub fn draw_city(owner: &Player, city: &City, state: &State) {
168168

169169
let mut i = 0;
170170
city.pieces.wonders.iter().for_each(|w| {
171-
let p = hex_ui::rotate_around(c, 30.0, 90 * i);
172-
draw_text(
173-
&w.name,
174-
p.x - 10.0,
175-
p.y + 10.0,
176-
40.0,
177-
player_ui::player_color(owner.index),
178-
);
171+
let p = hex_ui::rotate_around(c, 20.0, 90 * i);
172+
draw_circle(p.x, p.y, 18.0, player_ui::player_color(owner.index));
173+
draw_text(&w.name, p.x - 10.0, p.y + 10.0, 40.0, BLACK);
179174
i += 1;
180175
});
181176

182177
for player_index in 0..4 {
183178
for b in &city.pieces.buildings(Some(player_index)) {
184-
let p = hex_ui::rotate_around(c, 30.0, 90 * i);
185-
draw_text(
186-
building_symbol(b),
187-
p.x - 10.0,
188-
p.y + 10.0,
189-
40.0,
190-
player_ui::player_color(player_index),
191-
);
179+
let p = if matches!(b, Building::Port) {
180+
hex_ui::rotate_around_rad(
181+
c,
182+
60.0,
183+
city.position
184+
.coordinate()
185+
.directions_to(city.port_position.unwrap().coordinate())[0]
186+
.to_radians_pointy(),
187+
)
188+
} else {
189+
hex_ui::rotate_around(c, 20.0, 90 * i)
190+
};
191+
draw_circle(p.x, p.y, 12.0, player_ui::player_color(player_index));
192+
draw_text(building_symbol(b), p.x - 7.0, p.y + 8.0, 30.0, BLACK);
192193
i += 1;
193194
}
194195
}

client/src/dialog_ui.rs

+9-15
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,13 @@ pub fn active_dialog_window<F>(player: &ShownPlayer, title: &str, f: F) -> State
99
where
1010
F: FnOnce(&mut Ui) -> StateUpdate,
1111
{
12-
dialog_window(player, title, false, f)
12+
dialog(title, false, |ui| {
13+
if player.can_control {
14+
f(ui)
15+
} else {
16+
StateUpdate::None
17+
}
18+
})
1319
}
1420

1521
pub fn closeable_dialog_window<F>(title: &str, f: F) -> StateUpdate
@@ -19,27 +25,15 @@ where
1925
dialog(title, true, f)
2026
}
2127

22-
pub fn dialog_window<F>(player: &ShownPlayer, title: &str, close_button: bool, f: F) -> StateUpdate
23-
where
24-
F: FnOnce(&mut Ui) -> StateUpdate,
25-
{
26-
dialog(title, close_button, |ui| {
27-
if player.can_control {
28-
f(ui)
29-
} else {
30-
StateUpdate::None
31-
}
32-
})
33-
}
34-
35-
fn dialog<F>(title: &str, close_button: bool, f: F) -> StateUpdate
28+
pub fn dialog<F>(title: &str, close_button: bool, f: F) -> StateUpdate
3629
where
3730
F: FnOnce(&mut Ui) -> StateUpdate,
3831
{
3932
let window = Window::new(hash!(), vec2(1100., 400.), vec2(800., 350.))
4033
.titlebar(true)
4134
.movable(false)
4235
.label(title)
36+
.movable(true)
4337
.close_button(close_button);
4438

4539
let ui = &mut root_ui();

client/src/hex_ui.rs

+4-1
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,10 @@ pub fn pixel_to_coordinate(x: f32, y: f32) -> Coordinate {
5555
}
5656

5757
pub fn rotate_around(center: Point, radius: f32, angle_deg: i32) -> Point {
58-
let angle_rad = PI / 180.0 * (angle_deg as f32);
58+
rotate_around_rad(center, radius, PI / 180.0 * (angle_deg as f32))
59+
}
60+
61+
pub fn rotate_around_rad(center: Point, radius: f32, angle_rad: f32) -> Point {
5962
Point {
6063
x: center.x + radius * f32::cos(angle_rad),
6164
y: center.y + radius * f32::sin(angle_rad),

client/src/local_client.rs

+19
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,25 @@ pub fn setup_local_game() -> Game {
9999
.get_city_mut(Position::from_offset("A1"))
100100
.unwrap()
101101
.increase_mood_state();
102+
game.players[player_index1]
103+
.get_city_mut(Position::from_offset("C2"))
104+
.unwrap()
105+
.pieces
106+
.academy = Some(1);
107+
game.players[player_index1]
108+
.get_city_mut(Position::from_offset("C2"))
109+
.unwrap()
110+
.pieces
111+
.port = Some(1);
112+
game.players[player_index1]
113+
.get_city_mut(Position::from_offset("C2"))
114+
.unwrap()
115+
.port_position = Some(Position::from_offset("D2"));
116+
game.players[player_index1]
117+
.get_city_mut(Position::from_offset("C2"))
118+
.unwrap()
119+
.pieces
120+
.wonders = vec![game.wonders_left.pop().unwrap()];
102121
game.players[player_index1]
103122
.get_city_mut(Position::from_offset("C2"))
104123
.unwrap()

client/src/log_ui.rs

+19-2
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
use macroquad::ui::Ui;
12
use server::game::Game;
23

34
use crate::client_state::StateUpdate;
@@ -6,9 +7,25 @@ use crate::dialog_ui::closeable_dialog_window;
67
pub fn show_log(game: &Game) -> StateUpdate {
78
closeable_dialog_window("Log", |ui| {
89
game.log.iter().for_each(|l| {
9-
ui.label(None, l);
10+
multiline(ui, l);
1011
});
11-
1212
StateUpdate::None
1313
})
1414
}
15+
16+
fn multiline(ui: &mut Ui, text: &str) {
17+
let mut line = String::new();
18+
text.split(' ').for_each(|s| {
19+
if line.len() + s.len() > 100 {
20+
ui.label(None, &line);
21+
line = String::new();
22+
}
23+
if !line.is_empty() {
24+
line.push(' ');
25+
}
26+
line.push_str(s);
27+
});
28+
if !line.is_empty() {
29+
ui.label(None, &line);
30+
}
31+
}

client/src/map_ui.rs

+9-4
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ use itertools::Itertools;
22
use macroquad::math::vec2;
33
use macroquad::prelude::*;
44
use macroquad::ui::Ui;
5+
use std::ops::{Add, Mul, Sub};
56

67
use server::action::Action;
78
use server::combat::Combat;
@@ -94,11 +95,15 @@ fn alpha(game: &Game, state: &State, pos: Position) -> f32 {
9495
fn draw_combat_arrow(c: &Combat) {
9596
let from = hex_ui::center(c.attacker_position);
9697
let to = hex_ui::center(c.defender_position);
97-
draw_line(from.x, from.y, to.x, to.y, 10., BLACK);
98+
let to_vec = vec2(to.x, to.y);
99+
let from_vec = vec2(from.x, from.y);
100+
let end = from_vec.add(to_vec.sub(from_vec).mul(0.7));
101+
draw_line(from.x, from.y, end.x, end.y, 10., BLACK);
102+
let angle = from_vec.sub(to_vec).normalize();
98103
draw_triangle(
99-
vec2(to.x, to.y),
100-
vec2(to.x + 30., to.y + 30.),
101-
vec2(to.x - 30., to.y + 30.),
104+
to_vec.add(angle.rotate(vec2(10., 0.))),
105+
to_vec.add(angle.rotate(vec2(30., 30.))),
106+
to_vec.add(angle.rotate(vec2(30., -30.))),
102107
BLACK,
103108
);
104109
}

client/src/move_ui.rs

+3-1
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,9 @@ pub fn move_units_dialog(game: &Game, sel: &MoveSelection, player: &ShownPlayer)
4545
}
4646

4747
fn update_possible_destinations(game: &Game, mut sel: MoveSelection) -> StateUpdate {
48-
if let Some(start) = sel.start {
48+
if sel.units.is_empty() {
49+
sel.destinations.clear();
50+
} else if let Some(start) = sel.start {
4951
sel.destinations = possible_destinations(game, start, sel.player_index, &sel.units);
5052
} else {
5153
sel.destinations.clear();

client/src/unit_ui.rs

+20-31
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
1-
use std::collections::{HashMap, HashSet};
2-
1+
use macroquad::color::BLACK;
32
use macroquad::math::u32;
43
use macroquad::prelude::draw_text;
4+
use macroquad::shapes::draw_circle;
55
use macroquad::ui::Ui;
66

77
use server::game::Game;
@@ -13,21 +13,15 @@ use crate::dialog_ui::active_dialog_window;
1313
use crate::select_ui::{confirm_update, ConfirmSelection};
1414
use crate::{hex_ui, player_ui};
1515

16+
use itertools::Itertools;
17+
1618
pub fn draw_unit(unit: &Unit, index: u32) {
1719
let c = hex_ui::center(unit.position);
18-
let r = if unit.unit_type == UnitType::Settler {
19-
25.
20-
} else {
21-
40.
22-
};
23-
let p = hex_ui::rotate_around(c, r, (90 * index) as i32 + 45);
24-
draw_text(
25-
unit_symbol(unit),
26-
p.x - 7.0,
27-
p.y + 7.0,
28-
25.0,
29-
player_ui::player_color(unit.player_index),
30-
);
20+
let r = 40.0;
21+
let p = hex_ui::rotate_around(c, r, (40 * index) as i32 + 45);
22+
draw_circle(p.x, p.y, 11.0, BLACK);
23+
draw_circle(p.x, p.y, 9.0, player_ui::player_color(unit.player_index));
24+
draw_text(unit_symbol(unit), p.x - 5.0, p.y + 5.0, 20.0, BLACK);
3125
}
3226

3327
fn unit_symbol(unit: &Unit) -> &str {
@@ -52,22 +46,17 @@ pub fn non_leader_names() -> [(UnitType, &'static str); 5] {
5246
}
5347

5448
pub fn draw_units(game: &Game) {
55-
for p in &game.players {
56-
let mut positions: HashSet<&Position> = HashSet::new();
57-
let mut city_unit_index: HashMap<Position, u32> = HashMap::new();
58-
let mut settler_index: HashMap<Position, u32> = HashMap::new();
59-
for unit in &p.units {
60-
let map = if unit.unit_type == UnitType::Settler {
61-
&mut settler_index
62-
} else {
63-
&mut city_unit_index
64-
};
65-
let e = map.entry(unit.position).or_default();
66-
*e += 1;
67-
draw_unit(unit, *e);
68-
69-
if positions.insert(&unit.position) {}
70-
}
49+
for (_pos, units) in &game
50+
.players
51+
.iter()
52+
.flat_map(|p| &p.units)
53+
.sorted_by_key(|u| u.position)
54+
.chunk_by(|a| a.position)
55+
{
56+
let vec = units.collect::<Vec<_>>();
57+
vec.iter().enumerate().for_each(|(i, u)| {
58+
draw_unit(u, i.try_into().unwrap());
59+
});
7160
}
7261
}
7362

0 commit comments

Comments
 (0)