2个版本
0.1.1 | 2021年10月30日 |
---|---|
0.1.0 | 2021年8月9日 |
#2306 in 数据结构
用于andiskaz
200KB
5.5K SLoC
gardiz
一个专注于游戏的二维整数几何库。支持泛型二维向量(作为实际向量、点或大小)、矩形、平面上点的数据映射、平面上点的集合、平面上点的简单图(可能是非平面图)。详见文档。
主分支文档
https://brunoczim.github.io/gardiz/gardiz/
特性
impl-serde
启用此功能可以使数据结构如Vec2
和Map
实现serde序列化和反序列化特性。
lib.rs
:
二维几何空间库(又称“平面”)。该库专注于整数几何,旨在用于离散二维游戏。
该库支持对二维泛型向量进行算术操作(包括点积和模长),这些向量可以表示点、大小、实际向量等。它还定义了平面中的“直线”基本方向(即上、左、下、右),使用轴作为索引和矩形。
它使用点作为键实现了专门的映射和集合。你可以将映射视为将数据与平面上的点关联起来,而集合可以被视为子平面的规范。两者都支持获取给定方向中的第一个或最后一个邻居。
最后,该库有简单的图,其顶点是平面上的点,并且它们可以连接(形成边)。这对于创建平面图(即没有边交叉)非常有用,但实现不会阻止你形成非平面图,尽管图仍然在二维平面上。图还实现了“A星”(或“A*”)算法,用于在两个点之间创建路径,仅使用给定区域(如果需要,则创建顶点)。
以下是一个A*算法的执行示例
use gardiz::{
coord::Vec2,
graph::Graph,
direc::{Direction, DirecVector},
};
use std::collections::HashSet;
// `i64` is the type of the coordinate of the points.
let mut graph = Graph::<i64>::new();
// Initial and final points.
let start = Vec2 { x: -3, y: -3 };
let goal = Vec2 { x: 2, y: 4 };
graph.create_vertex(start);
graph.create_vertex(goal);
// Penalty whenever the path takes a turn.
let penalty = 2;
// Valid points to be used in the path.
let mut valid_points = HashSet::new();
for x in -3 .. 1 {
for y in -3 .. 0 {
valid_points.insert(Vec2 { x, y });
}
}
for x in 0 .. 3 {
for y in 0 .. 2 {
valid_points.insert(Vec2 { x, y });
}
}
for x in -1 .. 2 {
for y in 2 .. 3 {
valid_points.insert(Vec2 { x, y });
}
}
for x in -2 .. 0 {
for y in 3 .. 5 {
valid_points.insert(Vec2 { x, y });
}
}
for x in -3 .. 7 {
for y in 5 .. 7 {
valid_points.insert(Vec2 { x, y });
}
}
for x in 1 .. 9 {
for y in 4 .. 9 {
valid_points.insert(Vec2 { x, y });
}
}
// Cloning the graph before making the path (which will modify it).
let mut expected = graph.clone();
// Runs A*
let directions = graph.make_path(
&start,
&goal,
&penalty,
|point| valid_points.contains(&point)
);
// Checks whether the computed directions are correct.
assert_eq!(
directions,
Some(vec![
// x = -3, y = -3
DirecVector { direction: Direction::Right, magnitude: 3 },
// x = 0, y = -3
DirecVector { direction: Direction::Down, magnitude: 5 },
// x = 0, y = 2
DirecVector { direction: Direction::Left, magnitude: 1 },
// x = -1, y = 2
DirecVector { direction: Direction::Down, magnitude: 3 },
// x = -1, y = 5
DirecVector { direction: Direction::Right, magnitude: 3 },
// x = 2, y = 5
DirecVector { direction: Direction::Up, magnitude: 1 },
// x = 2, y = 4
])
);
// Insert the vertices created when making the path.
expected.create_vertex(Vec2 { x: 0, y: -3 });
expected.create_vertex(Vec2 { x: 0, y: 2 });
expected.create_vertex(Vec2 { x: -1, y: 2 });
expected.create_vertex(Vec2 { x: -1, y: 5 });
expected.create_vertex(Vec2 { x: 2, y: 5 });
// Connect the vertices in the path.
expected
.connect(Vec2 { x: -3, y: -3 }.as_ref(), Vec2 { x: 0, y: -3 }.as_ref());
expected
.connect(Vec2 { x: 0, y: 2 }.as_ref(), Vec2 { x: 0, y: -3 }.as_ref());
expected
.connect(Vec2 { x: 0, y: 2 }.as_ref(), Vec2 { x: -1, y: 2 }.as_ref());
expected
.connect(Vec2 { x: -1, y: 5 }.as_ref(), Vec2 { x: -1, y: 2 }.as_ref());
expected
.connect(Vec2 { x: -1, y: 5 }.as_ref(), Vec2 { x: 2, y: 5 }.as_ref());
expected
.connect(Vec2 { x: 2, y: 4 }.as_ref(), Vec2 { x: 2, y: 5 }.as_ref());
// Test if the graph produced by `make_path` is the expected one we built.
assert_eq!(graph, expected);
依赖关系
~2MB
~31K SLoC