From 5d0fedac8cb6ec720c35c06684b3e3938a21f9cf Mon Sep 17 00:00:00 2001 From: CoCoSol007 Date: Tue, 13 Feb 2024 19:08:42 +0100 Subject: [PATCH] add hex utils --- crates/border-wars/src/hex.rs | 99 +++++++++++++++++++++++++++++++++++ crates/border-wars/src/lib.rs | 1 + 2 files changed, 100 insertions(+) create mode 100644 crates/border-wars/src/hex.rs diff --git a/crates/border-wars/src/hex.rs b/crates/border-wars/src/hex.rs new file mode 100644 index 0000000..a5523b0 --- /dev/null +++ b/crates/border-wars/src/hex.rs @@ -0,0 +1,99 @@ +//! This file contains utilities for working with hex coordinates. + +use std::collections::HashSet; + +/// Contains all ``HexPosition`` neighbors of a ``HexPosition`` +pub struct GroupHexPosition(HashSet); + +impl GroupHexPosition { + /// Return an intersection of two ``GroupHexPosition`` + /// + /// ## example + /// ``` + /// use border_wars::hex::GroupHexPosition; + /// + /// let vec1 = GroupHexPosition( + /// vec![HexPosition { q: 0, r: 0 }, HexPosition { q: 1, r: -1 }] + /// ); + /// let vec2 = GroupHexPosition( + /// vec![HexPosition { q: 0, r: 0 }, HexPosition { q: 0, r: -1 }] + /// ); + /// let iter = vec1.iter_with(&vec2); + /// assert_eq!(iter, vec![HexPosition { q: 0, r: 0 }]); + pub fn iter_with(&self, other: &GroupHexPosition) -> Vec { + let mut result = Vec::new(); + for pos_1 in self.0.iter() { + if other.0.contains(pos_1) { + result.push(*pos_1); + } + } + result + } + + /// Removes the origin (``HexPosition { q: 0, r: 0 }``) of a + /// ``GroupHexPosition`` + /// + /// ## example + /// ``` + /// use border_wars::hex::GroupHexPosition; + /// + /// let mut vec = GroupHexPosition(vec![ + /// HexPosition { q: 0, r: 0 }, + /// HexPosition { q: 1, r: -1 }, + /// ]); + /// vec.remove_origin(); + /// assert_eq!(vec.0, vec![HexPosition { q: 1, r: -1 }]); + /// ``` + pub fn remove_origin(&mut self) -> &mut Self { + self.0.remove(&HexPosition { q: 0, r: 0 }); + self + } +} + +/// Hex position (in a hexagonal grid). +/// +/// usnig this doc : https://www.redblobgames.com/grids/hexagons/ +#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] +pub struct HexPosition { + /// Q coordinate + pub q: i32, + + /// R coordinate + pub r: i32, +} + +impl HexPosition { + /// Returns the distance between two ``HexPosition`` + /// + /// ## example + /// ``` + /// let hex1 = HexPosition { q: 0, r: 0 }; + /// let hex2 = HexPosition { q: 1, r: 1 }; + /// let distance = hex1.distance_to(&hex2); + /// assert_eq!(distance, 2); + /// ``` + pub fn distance_to(&self, other: &HexPosition) -> f32 { + (((self.q - other.q).abs() + + (self.r - other.r).abs() + + (self.q + self.r - other.q - other.r).abs()) + / 2) as f32 + } + + /// Returns all positions in a given range + /// + /// ## example + /// ``` + /// let hex = HexPosition { q: 0, r: 0 }; + /// let positions = hex.range(1); + /// assert_eq!(positions.len(), 6); + /// ``` + pub fn range(&self, range: i32) -> GroupHexPosition { + let mut positions = HashSet::new(); + for q in (-range)..=range { + for r in (-range).max(-q - range)..=range.min(-q + range) { + positions.insert(HexPosition { q, r }); + } + } + GroupHexPosition(positions) + } +} diff --git a/crates/border-wars/src/lib.rs b/crates/border-wars/src/lib.rs index c85940e..e475a9e 100644 --- a/crates/border-wars/src/lib.rs +++ b/crates/border-wars/src/lib.rs @@ -2,6 +2,7 @@ use bevy::prelude::*; +pub mod hex; pub mod scenes; /// The current scene of the game.