Expand description
§landmass
A Rust crate to provide a navigation system for video game characters to walk around levels.
§What is a navigation system?
A navigation system is essentially the collection of tools needed for robust agent movement in video games. This generally involves 4 things:
- Path finding (e.g. A-star)
- Path simplification (e.g. SSFA)
- Steering (e.g. boids)
- Local collision avoidance
In addition, managing agents and the navigation meshes they walk on can be cumbersome, so a navigation system ideally will handle that for you.
Generally it is difficult to find a full, free system to handle all of these for
you, and the goal is for landmass to work relatively easily with other
languages so it can be used anywhere.
§Overview
landmass has five major components: Archipelagos, Islands, Agents,
Characters, and AnimationLinks. An Archipelago is composed of several
Islands, as well as the Agents and Characters that travel across those
Islands. Each Island holds a single
navigation mesh. Each game
character (controlled by AI) should correspond to one Agent. Player characters
or other characters not controlled by AI should correspond to one
Character. AnimationLinks (aka off-mesh links) allow connecting areas
outside the nav mesh, allowing more flexible navigation. To start using
landmass:
- Create an
Archipelago. - Create an
Island. - Add
Agents andCharacters to theArchipelago.
Each frame of the game:
- Set the position and velocity of each game character to its corresponding
AgentorCharacter. - Call
updateon theArchipelago. - Use the desired move from each
Agentto inform the corresponding game character where it should move.
Note: landmass intentionally does not update the Agents position itself.
Generally, characters are moved using some other method (like a physics
simulation) rather than just moving the character, so moving the Agent would
be confusing.
§Example
use glam::Vec3;
use landmass::*;
use std::{sync::Arc, collections::HashMap};
let mut archipelago =
Archipelago::<XYZ>::new(ArchipelagoOptions::from_agent_radius(0.5));
let nav_mesh = NavigationMesh {
vertices: vec![
Vec3::new(0.0, 0.0, 0.0),
Vec3::new(15.0, 0.0, 0.0),
Vec3::new(15.0, 15.0, 0.0),
Vec3::new(0.0, 15.0, 0.0),
],
polygons: vec![vec![0, 1, 2, 3]],
polygon_type_indices: vec![0],
height_mesh: None,
};
let valid_nav_mesh = Arc::new(
nav_mesh.validate().expect("Validation succeeds")
);
let island_id = archipelago
.add_island(Island::new(
Transform { translation: Vec3::ZERO, rotation: 0.0 },
valid_nav_mesh,
));
let agent_1 = archipelago.add_agent({
let mut agent = Agent::create(
/* position= */ Vec3::new(1.0, 1.0, 0.0),
/* velocity= */ Vec3::ZERO,
/* radius= */ 1.0,
/* desired_speed= */ 1.0,
/* max_speed= */ 2.0,
);
agent.current_target = Some(Vec3::new(11.0, 1.1, 0.0));
agent.target_reached_condition = TargetReachedCondition::Distance(Some(0.01));
agent
});
let agent_2 = archipelago.add_agent({
let mut agent = Agent::create(
/* position= */ Vec3::new(11.0, 1.1, 0.0),
/* velocity= */ Vec3::ZERO,
/* radius= */ 1.0,
/* desired_speed= */ 1.0,
/* max_speed= */ 2.0,
);
agent.current_target = Some(Vec3::new(1.0, 1.0, 0.0));
agent.target_reached_condition = TargetReachedCondition::Distance(Some(0.01));
agent
});
for i in 0..300 {
let delta_time = 1.0 / 10.0;
archipelago.update(delta_time);
for agent_id in archipelago.get_agent_ids().collect::<Vec<_>>() {
let agent = archipelago.get_agent_mut(agent_id).unwrap();
agent.velocity = *agent.get_desired_velocity();
agent.position += agent.velocity * delta_time;
}
}
assert!(archipelago
.get_agent(agent_1)
.unwrap()
.position
.abs_diff_eq(Vec3::new(11.0, 1.1, 0.0), 0.1));
assert!(archipelago
.get_agent(agent_2)
.unwrap()
.position
.abs_diff_eq(Vec3::new(1.0, 1.0, 0.0), 0.1));§License
License under either of
- Apache License, Version 2.0 (LICENSE-APACHE or http://www.apache.org/licenses/LICENSE-2.0)
- MIT license (LICENSE-MIT or http://opensource.org/licenses/MIT)
at your option.
§Contribution
Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions.
Modules§
Structs§
- Agent
- An agent in an archipelago.
- AgentId
- The ID of an agent.
- Animation
Link - A link connecting two edges where an agent must perform some action (or animation) to use the link.
- Animation
Link Id - The ID of an
AnimationLink. - Archipelago
- Archipelago
Options - Options that apply to the entire archipelago.
- Character
- A non-agent character. While agents are “managed” by the archipelago, characters are only as obstacles to be avoided by agents.
- Character
Id - The ID of a character.
- Height
Navigation Mesh - An (optional) part of the navigation mesh dedicated to “refining” the height of a point.
- Height
Polygon - A polygon specifically for “refining” the height of a point.
- Island
- An Island in an Archipelago. Each island holds a navigation mesh.
- Island
Id - The ID of an island.
- Island
Mut - A mutable borrow to an island.
- Navigation
Mesh - A navigation mesh.
- NotReached
Animation Link Error - Pathing
Result - The result of path finding.
- Point
Sample Distance3d - A
PointSampleDistancetype for 3D coordinate systems. - Reached
Animation Link - An animation link that an agent has reached (in order to use it).
- Sampled
Point - A point on the navigation meshes.
- Transform
- A transform that can be applied to Vec3’s.
- Valid
Navigation Mesh - A navigation mesh which has been validated and derived data has been computed.
- Vec3
- A 3-dimensional vector.
- XY
- A 2D coordinate system, where X points right, and Y points forward.
- XYZ
- The standard coordinate system, where X points right, Y points forward, and Z points up.
Enums§
- Agent
State - The state of an agent.
- Find
Path Error - An error from finding a path between two sampled points.
- Path
Step - A single step in a path.
- Permitted
Animation Links - Defines the list of animation links that an agent is allowed to use.
- Sample
Point Error - An error while sampling a point.
- SetType
Index Cost Error - An error for settings the cost of a type index.
- Target
Reached Condition - The condition to consider the agent as having reached its target. When this condition is satisfied, the agent will stop moving.
- Validation
Error - An error when validating a navigation mesh.
Traits§
- Coordinate
System - A coordinate system used to convert from a user-facing coordinate system
into landmass’s standard coordinate system. The standard coordinate system
is
crate::coords::XYZ. - From
Agent Radius - A trait to create a default instance based on an agent’s radius.
- Point
Sample Distance - A configuration of how a type relates to distances when sampling points. See
crate::Archipelago::sample_pointfor more.