Random cards
This commit is contained in:
parent
b931079a71
commit
c9438aa49d
4 changed files with 133 additions and 28 deletions
23
Cargo.lock
generated
23
Cargo.lock
generated
|
@ -95,6 +95,7 @@ name = "ants"
|
||||||
version = "0.0.0"
|
version = "0.0.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"nannou",
|
"nannou",
|
||||||
|
"rand_derive2",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -1580,6 +1581,16 @@ dependencies = [
|
||||||
"unicode-ident",
|
"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]]
|
[[package]]
|
||||||
name = "profiling"
|
name = "profiling"
|
||||||
version = "1.0.15"
|
version = "1.0.15"
|
||||||
|
@ -1657,6 +1668,18 @@ dependencies = [
|
||||||
"getrandom 0.2.14",
|
"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]]
|
[[package]]
|
||||||
name = "rand_hc"
|
name = "rand_hc"
|
||||||
version = "0.2.0"
|
version = "0.2.0"
|
||||||
|
|
|
@ -27,3 +27,6 @@ codegen-units = 1
|
||||||
|
|
||||||
[dependencies.nannou]
|
[dependencies.nannou]
|
||||||
version = "0.19"
|
version = "0.19"
|
||||||
|
|
||||||
|
[dependencies.rand_derive2]
|
||||||
|
version = "0.1"
|
||||||
|
|
112
src/main.rs
112
src/main.rs
|
@ -1,12 +1,17 @@
|
||||||
#![warn(clippy::all, clippy::pedantic, clippy::nursery)]
|
#![warn(clippy::all, clippy::pedantic, clippy::nursery)]
|
||||||
|
|
||||||
|
mod card;
|
||||||
pub(crate) mod rect_helper;
|
pub(crate) mod rect_helper;
|
||||||
|
|
||||||
|
use std::sync::RwLock;
|
||||||
|
|
||||||
use crate::rect_helper::RectHelper;
|
use crate::rect_helper::RectHelper;
|
||||||
|
use card::Card;
|
||||||
use nannou::{
|
use nannou::{
|
||||||
image::{self, ImageFormat},
|
image::{self, ImageFormat},
|
||||||
prelude::*,
|
prelude::*,
|
||||||
text::Font,
|
text::Font,
|
||||||
|
winit::window::CursorIcon,
|
||||||
};
|
};
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
|
@ -22,7 +27,8 @@ struct Model {
|
||||||
font: Font,
|
font: Font,
|
||||||
texture: wgpu::Texture,
|
texture: wgpu::Texture,
|
||||||
ups: f64,
|
ups: f64,
|
||||||
ant_count: u8,
|
just_clicked: RwLock<bool>,
|
||||||
|
hand: [Card; HAND_CARD_COUNT],
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Model {
|
impl Model {
|
||||||
|
@ -56,53 +62,101 @@ impl Model {
|
||||||
)))
|
)))
|
||||||
.expect("Failed to load font"),
|
.expect("Failed to load font"),
|
||||||
ups: 0f64,
|
ups: 0f64,
|
||||||
ant_count: 1,
|
just_clicked: RwLock::new(false),
|
||||||
|
hand: random(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn update(_app: &App, model: &mut Model, update: Update) {
|
fn update(_app: &App, model: &mut Model, update: Update) {
|
||||||
model.ups = (1f64 / update.since_last.as_secs_f64()).round();
|
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
|
// 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);
|
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.
|
// Draw the state of your `Model` into the given `Frame` here.
|
||||||
fn view(app: &App, model: &Model, frame: Frame) {
|
fn view(app: &App, model: &Model, frame: Frame) {
|
||||||
let window = app.window(model.window).unwrap();
|
let window = app.window(model.window).unwrap();
|
||||||
|
window.set_cursor_icon(CursorIcon::Default);
|
||||||
frame.clear(BLACK);
|
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 draw = app.draw();
|
||||||
|
|
||||||
let rect = window.rect().bottom_part(0.2);
|
let window_rect = window.rect();
|
||||||
draw.rect().wh(rect.wh()).xy(rect.xy()).color(RED).finish();
|
let hand_bounds = window_rect.bottom_part(0.3);
|
||||||
let rect = window.rect().left_part(0.2);
|
#[allow(clippy::cast_precision_loss)]
|
||||||
draw.rect().wh(rect.wh()).xy(rect.xy()).color(BLUE).finish();
|
let hand_rect = Rect::from_x_y_w_h(
|
||||||
let rect = window.rect().right_part(0.2);
|
hand_bounds.x(),
|
||||||
draw.rect()
|
hand_bounds.y(),
|
||||||
.wh(rect.wh())
|
HAND_CARD_COUNT as f32 * HAND_ASPECT_WIDTH,
|
||||||
.xy(rect.xy())
|
HAND_ASPECT_HEIGHT,
|
||||||
.color(YELLOW)
|
)
|
||||||
.finish();
|
.fit_into(&hand_bounds)
|
||||||
let rect = window.rect().top_part(0.2);
|
.align_bottom_of(hand_bounds);
|
||||||
draw.rect()
|
|
||||||
.wh(rect.wh())
|
|
||||||
.xy(rect.xy())
|
|
||||||
.color(GREEN)
|
|
||||||
.finish();
|
|
||||||
|
|
||||||
for rect in rect.split_horizontal::<HAND_COUNT>() {
|
for (idx, rect) in hand_rect
|
||||||
draw.texture(&model.texture).xy(rect.xy()).wh(rect.wh());
|
.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) {
|
if cfg!(debug_assertions) {
|
||||||
|
@ -113,6 +167,8 @@ fn view(app: &App, model: &Model, frame: Frame) {
|
||||||
.left_justify();
|
.left_justify();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
*model.just_clicked.write().expect("click handler poisoned") = false;
|
||||||
|
|
||||||
draw.to_frame(app, &frame).unwrap();
|
draw.to_frame(app, &frame).unwrap();
|
||||||
drop(frame);
|
drop(frame);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
use nannou::geom::Rect;
|
use nannou::geom::Rect;
|
||||||
|
|
||||||
pub trait RectHelper {
|
pub trait RectHelper {
|
||||||
|
fn fit_into(&self, bounds: &Rect<f32>) -> Rect<f32>;
|
||||||
|
|
||||||
fn bottom_half(&self) -> Rect<f32>;
|
fn bottom_half(&self) -> Rect<f32>;
|
||||||
fn bottom_part(&self, part: f32) -> Rect<f32>;
|
fn bottom_part(&self, part: f32) -> Rect<f32>;
|
||||||
|
|
||||||
|
@ -20,6 +22,27 @@ pub trait RectHelper {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl RectHelper for Rect<f32> {
|
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 {
|
fn bottom_half(&self) -> Self {
|
||||||
Self::from_corners(self.mid_left(), self.bottom_right())
|
Self::from_corners(self.mid_left(), self.bottom_right())
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue