Skip to content

Commit

Permalink
Merge pull request #61 from sinproject-iwasaki/60-create-window-size-…
Browse files Browse the repository at this point in the history
…struct

Create WindowSize Struct #60
  • Loading branch information
sinproject-iwasaki authored Mar 13, 2024
2 parents 8575925 + 7ac3350 commit 0ca8cc3
Show file tree
Hide file tree
Showing 8 changed files with 192 additions and 128 deletions.
121 changes: 23 additions & 98 deletions src/config.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use crate::constants::{UNIT_LENGTH, UNIT_SIZE, WINDOW_TITLE};
use crate::constants::WINDOW_TITLE;
use crate::validator;
use crate::window_size::WindowSize;

pub struct Title(String);

Expand All @@ -14,63 +15,36 @@ impl Title {
}
}

pub struct Width(u32);

impl Width {
pub fn new(width: u32) -> Result<Self, String> {
validator::validate_numeric_range(width, 1, 1000)?;
Ok(Self(width))
}

pub fn value(&self) -> u32 {
self.0
}
}

pub struct Height(u32);

impl Height {
pub fn new(height: u32) -> Result<Self, String> {
validator::validate_numeric_range(height, 1, 1000)?;
Ok(Self(height))
}

pub fn value(&self) -> u32 {
self.0
}
}

pub struct WindowConfig {
pub title: Title,
pub width: Width,
pub height: Height,
title: Title,
window_size: WindowSize,
}

impl WindowConfig {
pub fn new(title: &str, width: u32, height: u32) -> Result<WindowConfig, String> {
Ok(Self {
title: Title::new(title)?,
width: Width::new(width)?,
height: Height::new(height)?,
})
pub fn new() -> Self {
let title = Title::new(WINDOW_TITLE).unwrap();
let window_size = WindowSize::new_by_unit_size();

Self { title, window_size }
}

fn calculate_window_size() -> (u32, u32) {
(UNIT_SIZE.0 * UNIT_LENGTH.0, UNIT_SIZE.1 * UNIT_LENGTH.1)
pub fn title(&self) -> &str {
self.title.value()
}

fn create_with_default_size(title: &str) -> Result<WindowConfig, String> {
let (width, height) = Self::calculate_window_size();
Self::new(title, width, height)
pub fn width(&self) -> u32 {
self.window_size.width().value()
}
}

pub fn create_window_config() -> Result<WindowConfig, String> {
WindowConfig::create_with_default_size(WINDOW_TITLE)
pub fn height(&self) -> u32 {
self.window_size.height().value()
}
}

#[cfg(test)]
mod tests {
use crate::constants::{UNIT_LENGTH, UNIT_SIZE};

use super::*;
use rstest::rstest;

Expand All @@ -86,61 +60,12 @@ mod tests {
assert!(Title::new(title).is_ok());
}

#[rstest]
#[case::min_1(1)]
#[case::max_1000(1000)]
#[case::normal(50)]
#[should_panic]
#[case::min_0(0)]
#[should_panic]
#[case::max_1001(1001)]
fn test_width_new(#[case] width: u32) {
assert!(Width::new(width).is_ok());
}

#[rstest]
#[case::min_1(1)]
#[case::max_1000(1000)]
#[case::normal(50)]
#[should_panic]
#[case::min_0(0)]
#[should_panic]
#[case::max_1001(1001)]
fn test_height_new(#[case] height: u32) {
assert!(Height::new(height).is_ok());
}

#[rstest]
#[case::normal("Test Window", 800, 600)]
#[case::min_1("T", 1, 1)]
#[case::max_1000("12345678901234567890123456789012345678901234567890", 1000, 1000)]
#[should_panic]
#[case::panic_title("", 1, 1)]
#[should_panic]
#[case::panic_width("T", 0, 1)]
#[should_panic]
#[case::panic_height("T", 1, 0)]
fn test_window_config_creation(#[case] title: &str, #[case] width: u32, #[case] height: u32) {
let window_config = WindowConfig::new(title, width, height).unwrap();

assert_eq!(window_config.title.value(), title);
assert_eq!(window_config.width.value(), width);
assert_eq!(window_config.height.value(), height);
}

#[test]
fn test_default_window_size() {
let window_config = WindowConfig::create_with_default_size("Default Size Window").unwrap();
let expected_size = WindowConfig::calculate_window_size();

assert_eq!(
(window_config.width.value(), window_config.height.value()),
expected_size
);
}
fn test_window_config_new() {
let window_config = WindowConfig::new();

#[test]
fn test_create_window_config() {
create_window_config().unwrap();
assert_eq!(window_config.title(), WINDOW_TITLE);
assert_eq!(window_config.width(), UNIT_SIZE.0 * UNIT_LENGTH.0);
assert_eq!(window_config.height(), UNIT_SIZE.1 * UNIT_LENGTH.1);
}
}
1 change: 1 addition & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ mod text_resources;
mod utils;
mod validator;
mod window;
mod window_size;

use my_app::MyApp;

Expand Down
70 changes: 53 additions & 17 deletions src/position.rs
Original file line number Diff line number Diff line change
@@ -1,20 +1,48 @@
use bevy::prelude::*;

use crate::{game_timer::GameTimer, utils};
use crate::{constants::UNIT_LENGTH, game_timer::GameTimer, utils, validator};

#[derive(Component)]
pub struct Position {
x: i32,
y: i32,
struct PosX(i32);

impl PosX {
fn new(x: i32) -> Result<Self, String> {
validator::validate_numeric_range(x, 0, (UNIT_LENGTH.0 - 1) as i32)?;

Ok(Self(x))
}

pub fn value(&self) -> i32 {
self.0
}
}

struct PosY(i32);

impl PosY {
fn new(y: i32) -> Result<Self, String> {
validator::validate_numeric_range(y, 0, (UNIT_LENGTH.1 - 1) as i32)?;

Ok(Self(y))
}

pub fn value(&self) -> i32 {
self.0
}
}

#[derive(Component)]
pub struct Position(PosX, PosY);

impl Position {
pub fn new(x: i32, y: i32) -> Self {
Self { x, y }
pub fn new(x: i32, y: i32) -> Result<Self, String> {
let pos_x = PosX::new(x)?;
let pos_y = PosY::new(y)?;

Ok(Self(pos_x, pos_y))
}

pub fn vec2(&self) -> Vec2 {
Vec2::new(self.x as f32, self.y as f32)
Vec2::new(self.x() as f32, self.y() as f32)
}

pub fn translation(&self, origin: Vec2) -> Vec3 {
Expand All @@ -30,9 +58,17 @@ impl Position {
}

for mut position in position_query.iter_mut() {
position.y -= 1;
*position = Position::new(position.x(), position.y() - 1).unwrap();
}
}

pub fn x(&self) -> i32 {
self.0.value()
}

pub fn y(&self) -> i32 {
self.1.value()
}
}

#[cfg(test)]
Expand All @@ -43,26 +79,26 @@ mod tests {

#[test]
fn test_position_new() {
let position = Position::new(10, 20);
assert_eq!(position.x, 10);
assert_eq!(position.y, 20);
let position = Position::new(5, 1).unwrap();
assert_eq!(position.x(), 5);
assert_eq!(position.y(), 1);
}

#[test]
fn test_position_vec2() {
let position: Position = Position::new(10, 20);
let position: Position = Position::new(4, 9).unwrap();
let vec2 = position.vec2();
assert_eq!(vec2, Vec2::new(10.0, 20.0));
assert_eq!(vec2, Vec2::new(4.0, 9.0));
}

#[test]
fn test_position_translation() {
let position = Position::new(10, 20);
let position = Position::new(3, 8).unwrap();
let origin = Vec2::new(-100.0, 5.0);
let translation = position.translation(origin);

let expected_x = unit_size().x * position.x as f32 + origin.x;
let expected_y = unit_size().y * position.y as f32 + origin.y;
let expected_x = unit_size().x * position.x() as f32 + origin.x;
let expected_y = unit_size().y * position.y() as f32 + origin.y;

let expected_translation = Vec3::new(expected_x, expected_y, 0.0);
assert_eq!(translation, expected_translation);
Expand Down
2 changes: 1 addition & 1 deletion src/sprite.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ pub fn spawn_block(commands: &mut Commands, block_patterns: &mut Res<BlockPatter
let initial_y = (constants::UNIT_LENGTH.1 - 4) as i32;

block.positions.iter().for_each(|(x, y)| {
let position = Position::new(x + initial_x, y + initial_y);
let position = Position::new(x + initial_x, y + initial_y).unwrap();

spawn_block_element(commands, position, block.color);
});
Expand Down
15 changes: 9 additions & 6 deletions src/utils.rs
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
use bevy::prelude::*;

use crate::constants;
use crate::constants::UNIT_SIZE;

pub fn vec2_from_tuple(tuple: (u32, u32)) -> Vec2 {
Vec2::new(tuple.0 as f32, tuple.1 as f32)
pub fn vec2_from_tuple<T: Into<f32> + Copy>(tuple: (T, T)) -> Vec2 {
Vec2::new(tuple.0.into(), tuple.1.into())
}

pub fn unit_size() -> Vec2 {
vec2_from_tuple(constants::UNIT_SIZE)
vec2_from_tuple((UNIT_SIZE.0 as u16, UNIT_SIZE.1 as u16))
}

#[cfg(test)]
Expand All @@ -18,14 +18,17 @@ mod tests {
#[rstest]
#[case::tuple((100, 50), Vec2::new(100.0, 50.0))]
#[case::tuple((200, 100), Vec2::new(200.0, 100.0))]
fn test_vec2_from_tuple(#[case] tuple: (u32, u32), #[case] expected: Vec2) {
fn test_vec2_from_tuple(#[case] tuple: (u8, u8), #[case] expected: Vec2) {
let actual = vec2_from_tuple(tuple);
assert_eq!(actual, expected);
}

#[test]
fn test_unit_size() {
let actual = unit_size();
assert_eq!(actual, vec2_from_tuple(constants::UNIT_SIZE));
assert_eq!(
actual,
vec2_from_tuple((UNIT_SIZE.0 as u16, UNIT_SIZE.1 as u16))
);
}
}
6 changes: 5 additions & 1 deletion src/validator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,11 @@ pub fn validate_string_length(value: &str, min: usize, max: usize) -> Result<(),
}
}

pub fn validate_numeric_range(value: u32, min: u32, max: u32) -> Result<(), String> {
pub fn validate_numeric_range<T: PartialOrd + Copy + std::fmt::Display>(
value: T,
min: T,
max: T,
) -> Result<(), String> {
if (min..=max).contains(&value) {
Ok(())
} else {
Expand Down
10 changes: 5 additions & 5 deletions src/window.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use bevy::prelude::*;

use crate::{config, utils::unit_size};
use crate::{config::WindowConfig, utils::unit_size};

fn create_window(title: &str, width: u32, height: u32) -> Window {
Window {
Expand All @@ -11,12 +11,12 @@ fn create_window(title: &str, width: u32, height: u32) -> Window {
}

pub fn init_window() -> Window {
let window_config = config::create_window_config().unwrap();
let window_config = WindowConfig::new();

create_window(
window_config.title.value(),
window_config.width.value(),
window_config.height.value(),
window_config.title(),
window_config.width(),
window_config.height(),
)
}

Expand Down
Loading

0 comments on commit 0ca8cc3

Please sign in to comment.