Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Client fixes #64

Merged
merged 11 commits into from
Oct 3, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 19 additions & 15 deletions client/src/advance_ui.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ use server::resource_pile::AdvancePaymentOptions;
use server::status_phase::{StatusPhaseAction, StatusPhaseState};

use crate::client_state::{ActiveDialog, ShownPlayer, StateUpdate};
use crate::dialog_ui::dialog_window;
use crate::dialog_ui::dialog;
use crate::payment_ui::{payment_dialog, HasPayment, Payment, ResourcePayment};
use crate::resource_ui::{new_resource_map, ResourceType};
use crate::select_ui::HasCountSelectableObject;
Expand Down Expand Up @@ -99,24 +99,28 @@ pub fn show_generic_advance_menu(
close_button: bool,
new_update: impl Fn(String) -> StateUpdate,
) -> StateUpdate {
dialog_window(player, title, close_button, |ui| {
dialog(title, close_button, |ui| {
let p = player.get(game);
for a in get_all() {
let name = a.name;
let p = player.get(game);
if p.has_advance(&name) {
ui.label(None, &name);
} else {
let can = if matches!(
game.state,
GameState::StatusPhase(StatusPhaseState::FreeAdvance)
) {
p.can_advance_free(&name)
if player.can_play_action {
if p.has_advance(&name) {
ui.label(None, &name);
} else {
player.can_control && p.can_advance(&name)
};
if can && ui.button(None, name.clone()) {
return new_update(name);
let can = if matches!(
game.state,
GameState::StatusPhase(StatusPhaseState::FreeAdvance)
) {
p.can_advance_free(&name)
} else {
player.can_control && p.can_advance(&name)
};
if can && ui.button(None, name.clone()) {
return new_update(name);
}
}
} else if p.has_advance(&name) {
ui.label(None, &name);
}
}
StateUpdate::None
Expand Down
33 changes: 17 additions & 16 deletions client/src/city_ui.rs
Original file line number Diff line number Diff line change
Expand Up @@ -168,27 +168,28 @@ pub fn draw_city(owner: &Player, city: &City, state: &State) {

let mut i = 0;
city.pieces.wonders.iter().for_each(|w| {
let p = hex_ui::rotate_around(c, 30.0, 90 * i);
draw_text(
&w.name,
p.x - 10.0,
p.y + 10.0,
40.0,
player_ui::player_color(owner.index),
);
let p = hex_ui::rotate_around(c, 20.0, 90 * i);
draw_circle(p.x, p.y, 18.0, player_ui::player_color(owner.index));
draw_text(&w.name, p.x - 10.0, p.y + 10.0, 40.0, BLACK);
i += 1;
});

for player_index in 0..4 {
for b in &city.pieces.buildings(Some(player_index)) {
let p = hex_ui::rotate_around(c, 30.0, 90 * i);
draw_text(
building_symbol(b),
p.x - 10.0,
p.y + 10.0,
40.0,
player_ui::player_color(player_index),
);
let p = if matches!(b, Building::Port) {
hex_ui::rotate_around_rad(
c,
60.0,
city.position
.coordinate()
.directions_to(city.port_position.unwrap().coordinate())[0]
.to_radians_pointy(),
)
} else {
hex_ui::rotate_around(c, 20.0, 90 * i)
};
draw_circle(p.x, p.y, 12.0, player_ui::player_color(player_index));
draw_text(building_symbol(b), p.x - 7.0, p.y + 8.0, 30.0, BLACK);
i += 1;
}
}
Expand Down
24 changes: 9 additions & 15 deletions client/src/dialog_ui.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,13 @@ pub fn active_dialog_window<F>(player: &ShownPlayer, title: &str, f: F) -> State
where
F: FnOnce(&mut Ui) -> StateUpdate,
{
dialog_window(player, title, false, f)
dialog(title, false, |ui| {
if player.can_control {
f(ui)
} else {
StateUpdate::None
}
})
}

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

pub fn dialog_window<F>(player: &ShownPlayer, title: &str, close_button: bool, f: F) -> StateUpdate
where
F: FnOnce(&mut Ui) -> StateUpdate,
{
dialog(title, close_button, |ui| {
if player.can_control {
f(ui)
} else {
StateUpdate::None
}
})
}

fn dialog<F>(title: &str, close_button: bool, f: F) -> StateUpdate
pub fn dialog<F>(title: &str, close_button: bool, f: F) -> StateUpdate
where
F: FnOnce(&mut Ui) -> StateUpdate,
{
let window = Window::new(hash!(), vec2(1100., 400.), vec2(800., 350.))
.titlebar(true)
.movable(false)
.label(title)
.movable(true)
.close_button(close_button);

let ui = &mut root_ui();
Expand Down
5 changes: 4 additions & 1 deletion client/src/hex_ui.rs
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,10 @@ pub fn pixel_to_coordinate(x: f32, y: f32) -> Coordinate {
}

pub fn rotate_around(center: Point, radius: f32, angle_deg: i32) -> Point {
let angle_rad = PI / 180.0 * (angle_deg as f32);
rotate_around_rad(center, radius, PI / 180.0 * (angle_deg as f32))
}

pub fn rotate_around_rad(center: Point, radius: f32, angle_rad: f32) -> Point {
Point {
x: center.x + radius * f32::cos(angle_rad),
y: center.y + radius * f32::sin(angle_rad),
Expand Down
19 changes: 19 additions & 0 deletions client/src/local_client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,25 @@ pub fn setup_local_game() -> Game {
.get_city_mut(Position::from_offset("A1"))
.unwrap()
.increase_mood_state();
game.players[player_index1]
.get_city_mut(Position::from_offset("C2"))
.unwrap()
.pieces
.academy = Some(1);
game.players[player_index1]
.get_city_mut(Position::from_offset("C2"))
.unwrap()
.pieces
.port = Some(1);
game.players[player_index1]
.get_city_mut(Position::from_offset("C2"))
.unwrap()
.port_position = Some(Position::from_offset("D2"));
game.players[player_index1]
.get_city_mut(Position::from_offset("C2"))
.unwrap()
.pieces
.wonders = vec![game.wonders_left.pop().unwrap()];
game.players[player_index1]
.get_city_mut(Position::from_offset("C2"))
.unwrap()
Expand Down
21 changes: 19 additions & 2 deletions client/src/log_ui.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
use macroquad::ui::Ui;
use server::game::Game;

use crate::client_state::StateUpdate;
Expand All @@ -6,9 +7,25 @@ use crate::dialog_ui::closeable_dialog_window;
pub fn show_log(game: &Game) -> StateUpdate {
closeable_dialog_window("Log", |ui| {
game.log.iter().for_each(|l| {
ui.label(None, l);
multiline(ui, l);
});

StateUpdate::None
})
}

fn multiline(ui: &mut Ui, text: &str) {
let mut line = String::new();
text.split(' ').for_each(|s| {
if line.len() + s.len() > 100 {
ui.label(None, &line);
line = String::new();
}
if !line.is_empty() {
line.push(' ');
}
line.push_str(s);
});
if !line.is_empty() {
ui.label(None, &line);
}
}
13 changes: 9 additions & 4 deletions client/src/map_ui.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ use itertools::Itertools;
use macroquad::math::vec2;
use macroquad::prelude::*;
use macroquad::ui::Ui;
use std::ops::{Add, Mul, Sub};

use server::action::Action;
use server::combat::Combat;
Expand Down Expand Up @@ -94,11 +95,15 @@ fn alpha(game: &Game, state: &State, pos: Position) -> f32 {
fn draw_combat_arrow(c: &Combat) {
let from = hex_ui::center(c.attacker_position);
let to = hex_ui::center(c.defender_position);
draw_line(from.x, from.y, to.x, to.y, 10., BLACK);
let to_vec = vec2(to.x, to.y);
let from_vec = vec2(from.x, from.y);
let end = from_vec.add(to_vec.sub(from_vec).mul(0.7));
draw_line(from.x, from.y, end.x, end.y, 10., BLACK);
let angle = from_vec.sub(to_vec).normalize();
draw_triangle(
vec2(to.x, to.y),
vec2(to.x + 30., to.y + 30.),
vec2(to.x - 30., to.y + 30.),
to_vec.add(angle.rotate(vec2(10., 0.))),
to_vec.add(angle.rotate(vec2(30., 30.))),
to_vec.add(angle.rotate(vec2(30., -30.))),
BLACK,
);
}
Expand Down
4 changes: 3 additions & 1 deletion client/src/move_ui.rs
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,9 @@ pub fn move_units_dialog(game: &Game, sel: &MoveSelection, player: &ShownPlayer)
}

fn update_possible_destinations(game: &Game, mut sel: MoveSelection) -> StateUpdate {
if let Some(start) = sel.start {
if sel.units.is_empty() {
sel.destinations.clear();
} else if let Some(start) = sel.start {
sel.destinations = possible_destinations(game, start, sel.player_index, &sel.units);
} else {
sel.destinations.clear();
Expand Down
51 changes: 20 additions & 31 deletions client/src/unit_ui.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use std::collections::{HashMap, HashSet};

use macroquad::color::BLACK;
use macroquad::math::u32;
use macroquad::prelude::draw_text;
use macroquad::shapes::draw_circle;
use macroquad::ui::Ui;

use server::game::Game;
Expand All @@ -13,21 +13,15 @@ use crate::dialog_ui::active_dialog_window;
use crate::select_ui::{confirm_update, ConfirmSelection};
use crate::{hex_ui, player_ui};

use itertools::Itertools;

pub fn draw_unit(unit: &Unit, index: u32) {
let c = hex_ui::center(unit.position);
let r = if unit.unit_type == UnitType::Settler {
25.
} else {
40.
};
let p = hex_ui::rotate_around(c, r, (90 * index) as i32 + 45);
draw_text(
unit_symbol(unit),
p.x - 7.0,
p.y + 7.0,
25.0,
player_ui::player_color(unit.player_index),
);
let r = 40.0;
let p = hex_ui::rotate_around(c, r, (40 * index) as i32 + 45);
draw_circle(p.x, p.y, 11.0, BLACK);
draw_circle(p.x, p.y, 9.0, player_ui::player_color(unit.player_index));
draw_text(unit_symbol(unit), p.x - 5.0, p.y + 5.0, 20.0, BLACK);
}

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

pub fn draw_units(game: &Game) {
for p in &game.players {
let mut positions: HashSet<&Position> = HashSet::new();
let mut city_unit_index: HashMap<Position, u32> = HashMap::new();
let mut settler_index: HashMap<Position, u32> = HashMap::new();
for unit in &p.units {
let map = if unit.unit_type == UnitType::Settler {
&mut settler_index
} else {
&mut city_unit_index
};
let e = map.entry(unit.position).or_default();
*e += 1;
draw_unit(unit, *e);

if positions.insert(&unit.position) {}
}
for (_pos, units) in &game
.players
.iter()
.flat_map(|p| &p.units)
.sorted_by_key(|u| u.position)
.chunk_by(|a| a.position)
{
let vec = units.collect::<Vec<_>>();
vec.iter().enumerate().for_each(|(i, u)| {
draw_unit(u, i.try_into().unwrap());
});
}
}

Expand Down