25 个版本 (16 个破坏性版本)

0.17.0 2024 年 4 月 15 日
0.16.1 2024 年 3 月 28 日
0.15.0 2024 年 2 月 21 日
0.12.0 2023 年 11 月 30 日
0.5.3 2023 年 3 月 26 日

#60 in 游戏开发

Download history 22/week @ 2024-04-29 25/week @ 2024-05-06 6/week @ 2024-05-13 29/week @ 2024-05-20 52/week @ 2024-05-27 16/week @ 2024-06-03 22/week @ 2024-06-10 47/week @ 2024-06-17 24/week @ 2024-06-24 63/week @ 2024-07-01 32/week @ 2024-07-08 89/week @ 2024-07-15 97/week @ 2024-07-22 51/week @ 2024-07-29 34/week @ 2024-08-05 23/week @ 2024-08-12

每月 213 次下载
2 个存储库中使用 (通过 lettuces)

Apache-2.0

5.5MB
5K SLoC

Hexx

workflow License unsafe forbidden Crates.io Docs.rs dependency status

Rust 的六边形工具库。

受此 RedBlobGames 文章Sander Evers 的工作启发

此库允许您

  • 操作六边形坐标
  • 生成具有自定义布局和方向的六边形地图
  • 生成六边形网格(平面或列)

出于性能和实用性的原因,我选择了使用 轴向坐标,但 Hex 类型具有与 立方双倍hexmod偏移 坐标的转换工具。

参见 六边形坐标系

安装

在您的项目中运行 cargo add hexx 或将以下行添加到您的 Cargo.toml

  • hexx= "0.17"

Cargo 功能

hexx 支持使用 serde 对大多数类型的序列化和反序列化,通过 serde 功能门。要启用它,请将以下行添加到您的 Cargo.toml

  • hexx= {version= "0.17",features= ["serde"] }

默认情况下,Hex 使用 Rust 经典内存布局,如果您想通过 FFI 使用 hexx 或希望 Hex 无任何内存填充存储,则 packed 功能会将 Hex repr(C)。要启用此行为,请将以下行添加到您的 Cargo.toml

  • hexx= {version= "0.17",features= ["packed"] }

hexx 通过 bevy_reflect 功能支持 Bevy Reflection。要启用它,请将以下行添加到您的 Cargo.toml

  • hexx= {version= "0.17",features= ["bevy_reflect"] }

hexx支持使用Hex作为面、GridVertex作为顶点和GridEdge作为边来处理Face/Vertex/Edge网格。要启用它,请将以下行添加到您的Cargo.toml

  • hexx= {version= "0.17",features= ["网格"] }

功能

hexx提供带有以下内容的Hex坐标

  • 距离
  • 邻居和方向
  • 线
  • 范围
  • 螺旋
  • 旋转
  • 对称性
  • 向量操作
  • 转换为其他坐标系
    • 立方坐标
    • 偏移坐标
    • 双倍坐标
    • Hexmod坐标
  • 多分辨率

基本用法

 use hexx::*;

 // Declare points in hexagonal spaces
 let point_a = hex(10, -5); // Equivalent of `Hex::new(10, -5)`
 let point_b = hex(-8, 15);
 // Find distance between them
 let dist = point_a.unsigned_distance_to(point_b);
 // Compute a line between points
 let line: Vec<Hex> = point_a.line_to(point_b).collect();
 // Compute a ring from `point_a` containing `point_b`
 let ring: Vec<Hex> = point_a.ring(dist).collect();
 // Rotate `point_b` around `point_a` by 2 times 60 degrees clockwise
 let rotated = point_b.rotate_cw_around(point_a, 2);
 // Find the direction between the two points
 let dir_a = point_a.main_direction_to(point_b);
 let dir_b = point_b.main_direction_to(point_a);
 assert!(dir_a == -dir_b);
 // Compute a wedge from `point_a` to `point_b`
 let wedge = point_a.wedge_to(point_b);
 // Get the average value of the wedge
 let avg = wedge.average();

布局用法

HexLayout是您的世界/屏幕/像素坐标系和六边形坐标系之间的桥梁。

 use hexx::*;

 // Define your layout
 let layout = HexLayout {
     hex_size: Vec2::new(1.0, 1.0),
     orientation: HexOrientation::Flat,
     ..Default::default()
 };
 // Get the hex coordinate at the world position `world_pos`.
 let world_pos = Vec2::new(53.52, 189.28);
 let point = layout.world_pos_to_hex(world_pos);
 // Get the world position of `point`
 let point = hex(123, 45);
 let world_pos = layout.hex_to_world_pos(point);

包装

HexBounds定义了围绕中心坐标的边界六边形。它可以用于边界和交叉检查,也可以用于包装坐标。坐标包装将点转换为边界内的点。这允许无缝或重复包装地图。

use hexx::*;

let center = hex(23, -45);
let radius = 5;
let bounds = HexBounds::new(center, radius);
let outside_coord = hex(12345, 98765);
assert!(!bounds.is_in_bounds(outside_coord));
let wrapped_coord = bounds.wrap(outside_coord);
assert!(bounds.is_in_bounds(wrapped_coord));

分辨率和块

Hex支持多分辨率坐标。在实践中,这意味着您可以转换坐标到不同的分辨率

  • 到较低的分辨率,即获取坐标
  • 到较高的分辨率,即获取中心坐标

分辨率是抽象的,唯一有用的信息是分辨率<强>半径

例如,如果您使用一个大网格,半径为100,您可能希望将网格均匀分割成包含10个半径坐标的大六边形,并可能在这些块内进行本地操作。

因此,您可以直接使用一个大范围

use hexx::*;

const MAP_RADIUS: u32 = 100;

// Our big grid with hundreds of hexagons
let big_grid = Hex::ZERO.range(MAP_RADIUS);

您可能定义一个较小的网格,然后将它分割到更高的分辨率

use hexx::*;

const CHUNK_RADIUS: u32 = 10;
const MAP_RADIUS: u32 = 20;

let chunks = Hex::ZERO.range(MAP_RADIUS);
for chunk in chunks {
    // We can retrieve the center of that chunk by increasing the resolution
    let center = chunk.to_higher_res(CHUNK_RADIUS);
    // And retrieve the other coordinates in the chunk
    let children = center.range(CHUNK_RADIUS);
    // We can retrieve the chunk coordinates from any coordinate..
    for coord in children {
        // .. by reducing the resolution
        assert_eq!(coord.to_lower_res(CHUNK_RADIUS), chunk);
    }
}

另一种用法可能是绘制一个无限六边形网格,显示不同分辨率,根据用户缩放级别动态更改。

Bevy中的使用

如果您想在bevy中生成3D六边形网格并使用它,您可以这样做

 use bevy::{
     prelude::Mesh,
     render::{
         mesh::Indices, render_asset::RenderAssetUsages, render_resource::PrimitiveTopology,
     },
 };
 use hexx::MeshInfo;

 pub fn hexagonal_plane(mesh_info: MeshInfo) -> Mesh {
     Mesh::new(
         PrimitiveTopology::TriangleList,
         // Means you won't edit the mesh afterwards, check bevy docs for more information
         RenderAssetUsages::RENDER_WORLD,
     )
     .with_inserted_attribute(Mesh::ATTRIBUTE_POSITION, mesh_info.vertices)
     .with_inserted_attribute(Mesh::ATTRIBUTE_NORMAL, mesh_info.normals)
     .with_inserted_attribute(Mesh::ATTRIBUTE_UV_0, mesh_info.uvs)
     .with_inserted_indices(Indices::U16(mesh_info.indices))
 }

MeshInfo可以从PlaneMeshBuilderColumnMeshBuilder生成。

有关bevy使用的示例,请参阅示例

问答

为什么不在PartialOrd, Ord上派生?

将这些特质添加到Hex意味着要定义一个绝对规则来解决这个问题

let a = hex(-10, 20);
let b = hex(1, 2);
a > b

根据您如何看待这个问题,至少有3种可能的规则

  • a.y大于b.y所以它是true
  • a.x 小于 b.x 因此它是 false
  • a 的长度大于 b 的长度,所以它是 true

如果我想要在 BtreeMapBTreeSetBinaryHeap 中使用它怎么办?

使用带有 OrdPartialOrd 特性的包装器。您可以复制并粘贴以下代码片段到您的项目中

/// [`Ordering`] wrapper around [`Hex`], comparing [`Hex::y`] then [`Hex::x`].
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct OrdByYX(pub Hex);

impl Ord for OrdByYX {
    fn cmp(&self, other: &Self) -> Ordering {
        self.0.y.cmp(&other.0.y).then(self.0.x.cmp(&other.0.x))
    }
}

impl PartialOrd for OrdByYX {
    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
        Some(self.cmp(other))
    }
}

示例

hexx 提供了展示各种功能的交互式示例

六边形网格

hex_grid

cargo运行 --示例hex_grid

此示例展示了六边形范围、环、楔形、旋转和线条

六边形区域

hex_grid

cargo运行 --示例hex_area

此示例展示了如何使用网格工具和组件生成六边形区域,以及如何在同一网格上使用两种布局。

滚动地图

scroll_map

cargo运行 --示例scroll_map

此示例展示了用于滚动地图的 HexMap 结构

包装地图

wrap_map

cargo运行 --示例wrap_map

此示例展示了用于循环/包装地图的 HexMap 结构

A 星路径查找

a_star

cargo运行 --示例a_star

此示例展示了 A 星算法,您可以通过交互式路径查找在起点和光标之间进行路径查找。点击图块可以切换其可用性

视野

fov

cargo运行 --示例field_of_view

此示例展示了视野算法,展示了围绕光标的交互式范围视野。点击图块可以切换其可见性。

移动区域

fov

cargo运行 --示例field_of_movement

此示例展示了移动区域算法,交互式显示光标周围的可用移动范围。

3d 列

columns

cargo运行 --示例3d_columns

此示例展示了 3d 六边形列的生成

网格构建器

mesh

cargo运行 --示例mesh_builder --featuresbevy_reflect

此示例展示了如何使用网格构建器定制六边形列的生成

chunks

cargo运行 --示例chunks

此示例展示了六边形分辨率系统,允许在均匀大小的块中进行瓦片坐标

合并块

merged_chunks

cargo运行 --示例merged_columns --featuresbevy_reflect

此示例展示了如何构建一个简单的六边形块系统,每个块都是一个单独的网格

精灵图集

sprite_sheet

cargo运行 --示例sprite_sheet

此示例展示了如何使用 hexx 与 2D 精灵图集

形状

shapes

cargo运行 --示例shapes --featuresbevy_reflect

此示例展示了如何使用 hexx 形状模块

依赖项