Random cards

This commit is contained in:
Tobias Berger 2024-04-09 19:41:22 +02:00
parent b931079a71
commit c9438aa49d
Signed by: toby
GPG key ID: 2D05EFAB764D6A88
4 changed files with 133 additions and 28 deletions

23
Cargo.lock generated
View file

@ -95,6 +95,7 @@ name = "ants"
version = "0.0.0"
dependencies = [
"nannou",
"rand_derive2",
]
[[package]]
@ -1580,6 +1581,16 @@ dependencies = [
"unicode-ident",
]
[[package]]
name = "proc_macro2_helper"
version = "0.2.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "79528bef70da112116feb5ecb6b64f1394e5360660d6474a760789ea07885501"
dependencies = [
"proc-macro2",
"syn 2.0.58",
]
[[package]]
name = "profiling"
version = "1.0.15"
@ -1657,6 +1668,18 @@ dependencies = [
"getrandom 0.2.14",
]
[[package]]
name = "rand_derive2"
version = "0.1.21"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7e07d80c051ce2007c5cbb87ae0a6be7c5e5345cb03e06717b64ed5c426cbfb3"
dependencies = [
"proc-macro2",
"proc_macro2_helper",
"quote",
"syn 2.0.58",
]
[[package]]
name = "rand_hc"
version = "0.2.0"

View file

@ -27,3 +27,6 @@ codegen-units = 1
[dependencies.nannou]
version = "0.19"
[dependencies.rand_derive2]
version = "0.1"

View file

@ -1,12 +1,17 @@
#![warn(clippy::all, clippy::pedantic, clippy::nursery)]
mod card;
pub(crate) mod rect_helper;
use std::sync::RwLock;
use crate::rect_helper::RectHelper;
use card::Card;
use nannou::{
image::{self, ImageFormat},
prelude::*,
text::Font,
winit::window::CursorIcon,
};
fn main() {
@ -22,7 +27,8 @@ struct Model {
font: Font,
texture: wgpu::Texture,
ups: f64,
ant_count: u8,
just_clicked: RwLock<bool>,
hand: [Card; HAND_CARD_COUNT],
}
impl Model {
@ -56,53 +62,101 @@ impl Model {
)))
.expect("Failed to load font"),
ups: 0f64,
ant_count: 1,
just_clicked: RwLock::new(false),
hand: random(),
}
}
}
fn update(_app: &App, model: &mut Model, update: Update) {
model.ups = (1f64 / update.since_last.as_secs_f64()).round();
let new_ant_count = ((update.since_start.as_secs() + 1) % 12)
.try_into()
.expect("Failed to convert number to u8");
if model.ant_count != new_ant_count {
model.ant_count = new_ant_count;
}
}
// Handle events related to the window and update the model if necessary
fn event(_app: &App, _model: &mut Model, event: WindowEvent) {
fn event(_app: &App, model: &mut Model, event: WindowEvent) {
match event {
MousePressed(MouseButton::Left) => {
let mut just_clicked = model.just_clicked.write().expect("click handler poisoned");
if !*just_clicked {
*just_clicked = true;
}
}
MouseReleased(MouseButton::Left) => {
let mut just_clicked = model.just_clicked.write().expect("click handler poisoned");
if *just_clicked {
*just_clicked = false;
}
}
KeyPressed(Key::R) => {
model.hand = random();
}
_ => {}
}
drop(event);
}
const HAND_COUNT: usize = 8;
const HAND_CARD_COUNT: usize = 8;
const HAND_ASPECT_WIDTH: f32 = 1f32;
const HAND_ASPECT_HEIGHT: f32 = 2f32;
// Draw the state of your `Model` into the given `Frame` here.
fn view(app: &App, model: &Model, frame: Frame) {
let window = app.window(model.window).unwrap();
window.set_cursor_icon(CursorIcon::Default);
frame.clear(BLACK);
let mut can_click = *model.just_clicked.read().expect("click handler poisoned");
let mouse = &app.mouse;
let mouse_position = if mouse.window == Some(model.window) {
Some(mouse.position())
} else {
None
};
let draw = app.draw();
let rect = window.rect().bottom_part(0.2);
draw.rect().wh(rect.wh()).xy(rect.xy()).color(RED).finish();
let rect = window.rect().left_part(0.2);
draw.rect().wh(rect.wh()).xy(rect.xy()).color(BLUE).finish();
let rect = window.rect().right_part(0.2);
draw.rect()
.wh(rect.wh())
.xy(rect.xy())
.color(YELLOW)
.finish();
let rect = window.rect().top_part(0.2);
draw.rect()
.wh(rect.wh())
.xy(rect.xy())
.color(GREEN)
.finish();
let window_rect = window.rect();
let hand_bounds = window_rect.bottom_part(0.3);
#[allow(clippy::cast_precision_loss)]
let hand_rect = Rect::from_x_y_w_h(
hand_bounds.x(),
hand_bounds.y(),
HAND_CARD_COUNT as f32 * HAND_ASPECT_WIDTH,
HAND_ASPECT_HEIGHT,
)
.fit_into(&hand_bounds)
.align_bottom_of(hand_bounds);
for rect in rect.split_horizontal::<HAND_COUNT>() {
draw.texture(&model.texture).xy(rect.xy()).wh(rect.wh());
for (idx, rect) in hand_rect
.split_horizontal::<HAND_CARD_COUNT>()
.iter()
.enumerate()
{
#[allow(clippy::cast_precision_loss)]
draw.rect()
.xy(rect.xy())
.wh(rect.wh())
.color(model.hand[idx].color());
let image_rect = Rect::from_x_y_w_h(rect.x(), rect.y(), 1401f32, 1061f32)
.fit_into(rect)
.align_bottom_of(*rect);
draw.texture(&model.texture)
.xy(image_rect.xy())
.wh(image_rect.wh());
if matches!(mouse_position, Some(mouse_position) if rect.contains(mouse_position)) {
window.set_cursor_icon(CursorIcon::Hand);
if can_click {
println!(
"Click! {idx} {:?} {:?}",
model.hand[idx],
model.hand[idx].color()
);
can_click = false;
}
}
}
if cfg!(debug_assertions) {
@ -113,6 +167,8 @@ fn view(app: &App, model: &Model, frame: Frame) {
.left_justify();
}
*model.just_clicked.write().expect("click handler poisoned") = false;
draw.to_frame(app, &frame).unwrap();
drop(frame);
}

View file

@ -1,6 +1,8 @@
use nannou::geom::Rect;
pub trait RectHelper {
fn fit_into(&self, bounds: &Rect<f32>) -> Rect<f32>;
fn bottom_half(&self) -> Rect<f32>;
fn bottom_part(&self, part: f32) -> Rect<f32>;
@ -20,6 +22,27 @@ pub trait RectHelper {
}
impl RectHelper for Rect<f32> {
fn fit_into(&self, bounds: &Rect<f32>) -> Self {
let content_aspect_ratio = self.w() / self.h();
let bounds_aspect_ratio = bounds.w() / bounds.h();
if bounds_aspect_ratio > content_aspect_ratio {
Self::from_x_y_w_h(
self.x(),
self.y(),
self.w() * bounds.h() / self.h(),
bounds.h(),
)
} else {
Self::from_x_y_w_h(
self.x(),
self.y(),
bounds.w(),
self.h() * bounds.w() / self.w(),
)
}
}
fn bottom_half(&self) -> Self {
Self::from_corners(self.mid_left(), self.bottom_right())
}