Skip to content

Commit

Permalink
feat: HexLayout rect size constructor (#194)
Browse files Browse the repository at this point in the history
> Closes #192
  • Loading branch information
ManevilleF authored Jan 4, 2025
1 parent f7d79f9 commit 02f2534
Show file tree
Hide file tree
Showing 4 changed files with 62 additions and 11 deletions.
5 changes: 3 additions & 2 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
- `inverse_transform_vector`
- `invert_x`
- `invert_y`
* Added `HexLayout::with_rect_size` to construct hexagons matching sprite dimensions (#194)
* Added `hex_edge_corners` utility method (#170)

### Mesh generation (#170)
Expand All @@ -32,8 +33,8 @@
* (**BREAKING**) `HexOffsetMode` now has only 2 variants `Even` and `Odd`
* (**BREAKING**) `Hex::to_offset_coordinates` and `Hex::from_offset_coordinates`
take a new `HexOrientation` parameter (#189)
* Orientation matrices are now `glam::Mat2` (#191)
* Added `world_unit_vector` methods to `EdgeDirection` and `VertexDirection` (#190)
* Added `world_unit_vector` methods to `EdgeDirection` and `VertexDirection` (#190)
* Orientation matrices are now `glam::Mat2` (#191)

## 0.19.1

Expand Down
12 changes: 4 additions & 8 deletions examples/sprite_sheet.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@ use bevy::{prelude::*, utils::HashMap, window::PrimaryWindow};
use glam::uvec2;
use hexx::{shapes, *};

const HEX_SIZE: Vec2 = Vec2::splat(20.0);
// 10% of the real individual texture sizes
const SPRITE_SIZE: Vec2 = Vec2::new(24.0, 28.0);

pub fn main() {
App::new()
Expand Down Expand Up @@ -38,12 +39,7 @@ fn setup_grid(
let atlas_layout =
TextureAtlasLayout::from_grid(uvec2(120, 140), 7, 6, Some(uvec2(2, 2)), None);
let atlas_layout = atlas_layouts.add(atlas_layout);
let layout = HexLayout {
orientation: HexOrientation::Pointy,
scale: HEX_SIZE,
..default()
};
let sprite_size = layout.rect_size();
let layout = HexLayout::new(HexOrientation::Pointy).with_rect_size(SPRITE_SIZE);
let entities = shapes::pointy_rectangle([-14, 14, -16, 16])
.enumerate()
.map(|(i, coord)| {
Expand All @@ -52,7 +48,7 @@ fn setup_grid(
let entity = commands
.spawn((
Sprite {
custom_size: Some(sprite_size),
custom_size: Some(SPRITE_SIZE),
image: texture.clone(),
texture_atlas: Some(TextureAtlas {
index,
Expand Down
53 changes: 53 additions & 0 deletions src/layout.rs
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,15 @@ use glam::Vec2;
/// // Invert the y axis, which will now go down. Will change `scale.y` to `-3.0`
/// layout.invert_y();
/// ```
///
/// ## Working with Sprites
///
/// If you intend to use the hexagonal grid to place images/sprites you may use
/// `HexLayout::with_rect_size` to make the hexagon scale fit the your sprite
/// dimensions.
///
/// You can also retrieve the matching rect size from any layout using
/// `HexLayout::rect_size()`
#[derive(Debug, Clone)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[cfg_attr(feature = "bevy_reflect", derive(bevy_reflect::Reflect))]
Expand Down Expand Up @@ -272,6 +281,23 @@ impl HexLayout {
self
}

#[inline]
#[must_use]
/// Specifies the world/pixel size of individual hexagons to match
/// the given `rect_size`. This is useful if you want hexagons
/// to match a sprite size
pub fn with_rect_size(self, rect_size: Vec2) -> Self {
const FLAT_RECT: Vec2 = Vec2::new(0.5, 1.0 / SQRT_3);
const POINTY_RECT: Vec2 = Vec2::new(1.0 / SQRT_3, 0.5);

let scale = rect_size
* match self.orientation {
HexOrientation::Pointy => POINTY_RECT,
HexOrientation::Flat => FLAT_RECT,
};
self.with_scale(scale)
}

#[must_use]
#[inline]
/// Specifies the world/pixel scale of individual hexagons.
Expand All @@ -294,6 +320,8 @@ impl Default for HexLayout {

#[cfg(test)]
mod tests {
use approx::assert_relative_eq;

use super::*;

#[test]
Expand Down Expand Up @@ -357,4 +385,29 @@ mod tests {
]
);
}

#[test]
fn rect_size() {
let sizes = [
Vec2::ZERO,
Vec2::ONE,
Vec2::X,
Vec2::Y,
Vec2::NEG_ONE,
Vec2::NEG_X,
Vec2::NEG_Y,
Vec2::new(10.0, 5.0),
Vec2::new(-10.0, 31.1),
Vec2::new(110.0, 25.0),
Vec2::new(-210.54, -54.0),
];
for size in sizes {
for orientation in [HexOrientation::Flat, HexOrientation::Pointy] {
let layout = HexLayout::new(orientation).with_rect_size(size);
let rect = layout.rect_size();
assert_relative_eq!(rect.x, size.x, epsilon = 0.00001);
assert_relative_eq!(rect.y, size.y, epsilon = 0.00001);
}
}
}
}
3 changes: 2 additions & 1 deletion src/orientation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,10 @@ use glam::{vec2, Mat2, Vec2};
use std::ops::Deref;

pub(crate) const SQRT_3: f32 = 1.732_050_8;
pub(crate) const HALF_SQRT_3: f32 = SQRT_3 / 2.0;

// Mat2 shearing factor
const FORWARD_SHEAR: f32 = SQRT_3 / 2.0;
const FORWARD_SHEAR: f32 = HALF_SQRT_3;
const INVERSE_SHEAR: f32 = -1.0 / 3.0;

// Mat2 scale diagonal.
Expand Down

0 comments on commit 02f2534

Please sign in to comment.