Skip to content

Commit

Permalink
add skin (#67)
Browse files Browse the repository at this point in the history
* build in release mode

* fix raze city

* cleanup local client

* fix raze city

* add skin

* add skin

* add skin

* add skin for advances

* add skin for advances

* add skin for advances

* add skin for advances

* add skin for advances
  • Loading branch information
zeitlinger authored Oct 6, 2024
1 parent 4a656f9 commit e0ee8a0
Show file tree
Hide file tree
Showing 29 changed files with 689 additions and 421 deletions.
Binary file added client/assets/HTOWERT.TTF
Binary file not shown.
Binary file added client/assets/button_background.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added client/assets/button_clicked_background.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added client/assets/button_hovered_background.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added client/assets/window_background.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
199 changes: 121 additions & 78 deletions client/src/advance_ui.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
use crate::client_state::{ActiveDialog, ShownPlayer, StateUpdate};
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;
use itertools::Itertools;
use macroquad::hash;
use macroquad::math::{bool, vec2};
use std::cmp::min;
use std::collections::HashMap;

use macroquad::math::{bool, vec2, Vec2};
use macroquad::ui::widgets::Checkbox;
use server::action::Action;
use server::advance::{Advance, Bonus};
use server::content::advances;
Expand All @@ -13,12 +16,8 @@ use server::player::Player;
use server::playing_actions::PlayingAction;
use server::resource_pile::AdvancePaymentOptions;
use server::status_phase::{StatusPhaseAction, StatusPhaseState};

use crate::client_state::{ActiveDialog, ShownPlayer, StateUpdate};
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;
use std::cmp::min;
use std::collections::HashMap;

#[derive(Clone)]
pub struct AdvancePayment {
Expand Down Expand Up @@ -80,83 +79,120 @@ impl HasPayment for AdvancePayment {
}

pub fn show_advance_menu(game: &Game, player: &ShownPlayer) -> StateUpdate {
show_generic_advance_menu("Advances", game, player, |name| {
show_generic_advance_menu("Advances", game, player, |a| {
StateUpdate::SetDialog(ActiveDialog::AdvancePayment(AdvancePayment::new(
game,
player.index,
name,
a.name.as_str(),
)))
})
}

pub fn show_free_advance_menu(game: &Game, player: &ShownPlayer) -> StateUpdate {
show_generic_advance_menu("Select a free advance", game, player, |name| {
StateUpdate::status_phase(StatusPhaseAction::FreeAdvance(name.to_string()))
show_generic_advance_menu("Select a free advance", game, player, |a| {
if can_advance(game, player, a) {
return StateUpdate::execute_with_confirm(
description(game.get_player(player.index), a),
Action::StatusPhase(StatusPhaseAction::FreeAdvance(a.name.clone())),
);
}
advance_info(game, player, a)
})
}

fn advance_info(game: &Game, player: &ShownPlayer, a: &Advance) -> StateUpdate {
StateUpdate::execute_with_cancel(description(game.get_player(player.index), a))
}

pub fn show_generic_advance_menu(
title: &str,
game: &Game,
player: &ShownPlayer,
new_update: impl Fn(&str) -> StateUpdate,
new_update: impl Fn(&Advance) -> StateUpdate,
) -> StateUpdate {
dialog(player, title, |ui| {
let p = player.get(game);
let mut update = StateUpdate::None;
let mut current_group = None;
for (_a, list) in &advances::get_all().iter().chunk_by(|a| {
if a.required.is_none() {
current_group = Some(&a.name);
&a.name
} else {
current_group.unwrap()
}
}) {
let advances = list.collect::<Vec<_>>();
ui.group(hash!(&advances[0].name), vec2(1500., 90.), |ui| {
for a in advances {
let name = &a.name;
let can_advance = if player.can_play_action {
p.can_advance(name)
} else if player.can_control
&& matches!(
game.state,
GameState::StatusPhase(StatusPhaseState::FreeAdvance)
)
{
p.can_advance_free(name)
} else {
false
};

let desc = description(p, a);
if p.has_advance(name) {
ui.label(None, &desc);
} else if can_advance {
if ui.button(None, desc) {
update = new_update(name);
}
} else {
ui.label(None, &desc);
};

for advances in groups() {
let pos = group_pos(&advances[0]);
for (i, a) in advances.into_iter().enumerate() {
let pos = pos * vec2(140., 210.) + vec2(0., i as f32 * 35.);
let name = &a.name;
let can_advance = can_advance(game, player, &a);

if can_advance || p.has_advance(name) {
let mut data = p.has_advance(name);
Checkbox::new(hash!(name))
// .label(name)
.pos(pos + vec2(60., 50.))
.size(vec2(0., 0.))
.ui(ui, &mut data);
if data != p.has_advance(name) {
return new_update(&a);
}
}
});
// Button::new(name.clone()).position(pos + vec2(0., 0.)).ui(ui);
ui.label(pos + vec2(0., 0.), name);
}
}
update
StateUpdate::None
})
}

fn description(p: &Player, a: &Advance) -> String {
fn can_advance(game: &Game, player: &ShownPlayer, a: &Advance) -> bool {
let name = &a.name;
let p = player.get(game);
if player.can_play_action {
p.can_advance(name)
} else if player.can_control
&& matches!(
game.state,
GameState::StatusPhase(StatusPhaseState::FreeAdvance)
)
{
p.can_advance_free(name)
} else {
false
}
}

fn groups() -> Vec<Vec<Advance>> {
let mut current_group = None;
advances::get_all()
.into_iter()
.chunk_by(|a| {
if a.required.is_none() {
current_group = Some(a.name.clone());
a.name.clone()
} else {
current_group.as_ref().unwrap().clone()
}
})
.into_iter()
.map(|(_k, a)| a.collect::<Vec<_>>())
.collect::<Vec<_>>()
}

fn group_pos(advance: &Advance) -> Vec2 {
match advance.name.as_str() {
"Farming" => vec2(0., 0.),
"Mining" => vec2(1., 0.),
"Fishing" => vec2(2., 0.),
"Philosophy" => vec2(3., 0.),
"Tactics" => vec2(4., 0.),
"Math" => vec2(2., 1.),
"Voting" => vec2(3., 1.),
"Dogma" => vec2(5., 1.),
_ => panic!("Unknown advance: {}", advance.name),
}
}

fn description(p: &Player, a: &Advance) -> Vec<String> {
let name = &a.name;
let desc = &a.description;

let mut parts = vec![];
parts.push(if p.has_advance(name) {
format!("+ {name}")
} else {
format!(" {name}")
});
let mut parts: Vec<String> = vec![];
parts.push(name.clone());
parts.push(desc.clone());
parts.push(format!("Cost: {}", p.advance_cost(name)));
if let Some(r) = &a.required {
Expand All @@ -181,25 +217,32 @@ fn description(p: &Player, a: &Advance) -> String {
parts.push(format!("Unlocks: {u}"));
}

parts.join(", ")
parts
}

pub fn pay_advance_dialog(ap: &AdvancePayment, player: &ShownPlayer) -> StateUpdate {
payment_dialog(
player,
&format!("Pay for advance {}", ap.name),
ap,
AdvancePayment::valid,
|ap| {
StateUpdate::Execute(Action::Playing(PlayingAction::Advance {
advance: ap.name.to_string(),
payment: ap.payment.to_resource_pile(),
}))
},
|ap, r| ap.payment.get(r).selectable.max > 0,
|ap, r| add(ap, r, 1),
|ap, r| add(ap, r, -1),
)
pub fn pay_advance_dialog(ap: &AdvancePayment, player: &ShownPlayer, game: &Game) -> StateUpdate {
let a = advances::get_advance_by_name(ap.name.as_str()).unwrap();

if can_advance(game, player, &a) {
payment_dialog(
player,
&format!("Pay for advance {}", ap.name),
description(game.get_player(player.index), &a),
ap,
AdvancePayment::valid,
|ap| {
StateUpdate::Execute(Action::Playing(PlayingAction::Advance {
advance: ap.name.to_string(),
payment: ap.payment.to_resource_pile(),
}))
},
|ap, r| ap.payment.get(r).selectable.max > 0,
|ap, r| add(ap, r, 1),
|ap, r| add(ap, r, -1),
)
} else {
advance_info(game, player, &a)
}
}

fn add(ap: &AdvancePayment, r: ResourceType, i: i32) -> StateUpdate {
Expand Down
111 changes: 108 additions & 3 deletions client/src/assets.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
use crate::client::Features;
use macroquad::prelude::{load_texture, Texture2D};
use macroquad::prelude::{load_texture, load_ttf_font, Color, Image, RectOffset, Texture2D};
use macroquad::ui::{root_ui, Skin};
use server::map::Terrain;
use server::unit::UnitType;
use std::collections::HashMap;

pub struct Assets {
pub terrain: HashMap<Terrain, Texture2D>,
pub units: HashMap<UnitType, Texture2D>,
pub skin: Skin,
// pub cities: HashMap<CityType, Texture2D>,
// pub resources: HashMap<Resource, Texture2D>,
}
Expand All @@ -16,6 +18,7 @@ impl Assets {
Self {
terrain: Self::terrain(features).await,
units: HashMap::new(),
skin: Self::skin(features).await,
// cities: HashMap::new(),
// resources: HashMap::new(),
}
Expand All @@ -31,9 +34,111 @@ impl Assets {
(Terrain::Forest, "forest.png"),
(Terrain::Water, "water.png"),
] {
let url = &features.assets_url;
map.insert(t, load_texture(&format!("{url}{f}")).await.unwrap());
map.insert(t, load_texture(&features.get_asset(f)).await.unwrap());
}
map
}

async fn skin(features: &Features) -> Skin {
let font = load_ttf_font(&features.get_asset("HTOWERT.TTF"))
.await
.unwrap();
let image =
Image::from_file_with_format(include_bytes!("../assets/button_background.png"), None)
.unwrap();
let label_style = root_ui()
.style_builder()
.background(image.clone())
.background_margin(RectOffset::new(37.0, 37.0, 5.0, 5.0))
.margin(RectOffset::new(10.0, 10.0, 0.0, 0.0))
.with_font(&font)
.unwrap()
.text_color(Color::from_rgba(180, 180, 120, 255))
.font_size(20)
.build();

let window_style = root_ui()
.style_builder()
.background(
Image::from_file_with_format(
include_bytes!("../assets/window_background.png"),
None,
)
.unwrap(),
)
.background_margin(RectOffset::new(20.0, 20.0, 10.0, 10.0))
.margin(RectOffset::new(-20.0, -30.0, 0.0, 0.0))
.build();

let button_style = root_ui()
.style_builder()
.background(image)
.background_margin(RectOffset::new(37.0, 37.0, 5.0, 5.0))
.margin(RectOffset::new(10.0, 10.0, 0.0, 0.0))
.background_hovered(
Image::from_file_with_format(
include_bytes!("../assets/button_hovered_background.png"),
None,
)
.unwrap(),
)
.background_clicked(
Image::from_file_with_format(
include_bytes!("../assets/button_clicked_background.png"),
None,
)
.unwrap(),
)
.with_font(&font)
.unwrap()
.text_color(Color::from_rgba(180, 180, 100, 255))
.font_size(20)
.build();

let editbox_style = root_ui()
.style_builder()
.background_margin(RectOffset::new(0., 0., 0., 0.))
.with_font(&font)
.unwrap()
.text_color(Color::from_rgba(120, 120, 120, 255))
.color_selected(Color::from_rgba(190, 190, 190, 255))
.font_size(50)
.build();

// let checkbox_style = root_ui()
// .style_builder()
// .background(
// Image::from_file_with_format(
// include_bytes!("../examples/ui_assets/checkbox_background.png"),
// None,
// )
// .unwrap(),
// )
// .background_hovered(
// Image::from_file_with_format(
// include_bytes!("../examples/ui_assets/checkbox_hovered_background.png"),
// None,
// )
// .unwrap(),
// )
// .background_clicked(
// Image::from_file_with_format(
// include_bytes!("../examples/ui_assets/checkbox_clicked_background.png"),
// None,
// )
// .unwrap(),
// )
// .build();

Skin {
editbox_style,
window_style,
button_style,
window_titlebar_style: label_style.clone(),
label_style,
// checkbox_style,
title_height: 30.,
..root_ui().default_skin()
}
}
}
Loading

0 comments on commit e0ee8a0

Please sign in to comment.