Skip to content

Commit f1b4854

Browse files
committed
refactor player component and entity hierarchy, and add some documentation
1 parent 546c69d commit f1b4854

File tree

3 files changed

+93
-43
lines changed

3 files changed

+93
-43
lines changed

src/main.rs

+71-38
Original file line numberDiff line numberDiff line change
@@ -26,57 +26,90 @@ fn setup(
2626
mut meshes: ResMut<Assets<Mesh>>,
2727
mut materials: ResMut<Assets<StandardMaterial>>,
2828
) {
29-
cmds.spawn((
29+
/*
30+
Lowercase denotes an entity, and uppercase denotes a component:
31+
32+
player
33+
├── Player
34+
├── TransformBundle
35+
├── VisibilityBundle
36+
├── body
37+
│   └── BodyBundle
38+
└── head
39+
├── Head (marker)
40+
├── TransformBundle (offsets the head from the player)
41+
├── VisibilityBundle (camera needs to be child of a visible entity)
42+
└── camera
43+
├── AtmosphereCamera (cancels atmosphere translation)
44+
├── Camera3dBundle
45+
├── CameraMode (first or third person)
46+
├── Fxaa
47+
└── TransformBundle (moves camera w.r.t. head orientation)
48+
*/
49+
50+
let visibility_bundle = || VisibilityBundle {
51+
visibility: Visibility::Visible,
52+
..default()
53+
};
54+
55+
let player_bundle = (
3056
player::Player,
31-
VisibilityBundle {
32-
visibility: Visibility::Visible,
33-
..default()
34-
},
57+
visibility_bundle(),
3558
TransformBundle {
3659
local: Transform::from_xyz(2.0, 170.0, 2.0).looking_to(Vec3::Z, Vec3::Y),
3760
..default()
3861
},
39-
))
40-
.with_children(|player| {
41-
player.spawn(player::Body).insert(MaterialMeshBundle {
62+
);
63+
64+
let body_bundle = player::BodyBundle {
65+
material_mesh_bundle: MaterialMeshBundle {
4266
mesh: meshes.add(Mesh::from(shape::Box::new(0.5, 1.8, 0.5))),
4367
material: materials.add(StandardMaterial {
4468
base_color: Color::WHITE,
4569
..default()
4670
}),
4771
transform: Transform::IDENTITY.looking_to(Vec3::Z, Vec3::Y),
4872
..default()
49-
});
73+
},
74+
..default()
75+
};
5076

51-
player
52-
.spawn((
53-
player::Head,
54-
TransformBundle {
55-
// head is 1.8m above feet
56-
local: Transform::from_translation(Vec3::new(0.0, 0.9, 0.0))
57-
.looking_to(Vec3::Z, Vec3::Y),
58-
..default()
59-
},
60-
))
61-
.with_children(|head| {
62-
// spawn camera as a child of head
63-
head.spawn(Camera3dBundle {
64-
projection: bevy::render::camera::Projection::Perspective(
65-
PerspectiveProjection {
66-
fov: PI / 2.,
67-
far: 2048.0,
68-
..Default::default()
69-
},
70-
),
71-
transform: Transform::from_translation(Vec3::new(0.0, 0.0, -5.0))
72-
.looking_to(Vec3::Z, Vec3::Y),
73-
..Default::default()
74-
})
75-
.insert(CameraMode::ThirdPersonForward);
76-
});
77-
})
78-
.insert(Fxaa::default())
79-
.insert(bevy_atmosphere::plugin::AtmosphereCamera::default());
77+
let head_bundle = (
78+
player::Head,
79+
visibility_bundle(),
80+
TransformBundle {
81+
// head is 1.8m above feet or 0.9m above the center
82+
local: Transform::from_translation(Vec3::new(0.0, 0.9, 0.0))
83+
.looking_to(Vec3::Z, Vec3::Y),
84+
..default()
85+
},
86+
);
87+
88+
let camera_bundle = (
89+
CameraMode::ThirdPersonForward,
90+
visibility_bundle(),
91+
Camera3dBundle {
92+
projection: bevy::render::camera::Projection::Perspective(PerspectiveProjection {
93+
fov: PI / 2.,
94+
far: 2048.0,
95+
..Default::default()
96+
}),
97+
transform: Transform::from_translation(Vec3::new(0.0, 0.0, -5.0))
98+
.looking_to(Vec3::Z, Vec3::Y),
99+
..default()
100+
},
101+
Fxaa::default(),
102+
bevy_atmosphere::plugin::AtmosphereCamera::default(),
103+
);
104+
105+
cmds.spawn(player_bundle).with_children(|player| {
106+
player.spawn(body_bundle);
107+
108+
player.spawn(head_bundle).with_children(|head| {
109+
// spawn camera as a child of head
110+
head.spawn(camera_bundle);
111+
});
112+
});
80113

81114
cmds.insert_resource(AmbientLight {
82115
color: Color::WHITE,

src/voxel/world/chunks.rs

+10-4
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,26 @@
11
use bevy::{
22
math::IVec3,
33
prelude::{
4-
Changed, Commands, CoreSet, Entity, GlobalTransform, IntoSystemConfig, IntoSystemConfigs,
5-
IntoSystemSetConfig, Plugin, Query, Res, ResMut, Resource, SystemSet, With,
4+
Changed, Commands, Component, CoreSet, Entity, GlobalTransform, IntoSystemConfig,
5+
IntoSystemConfigs, IntoSystemSetConfig, Plugin, Query, Res, ResMut, Resource, SystemSet,
6+
With,
67
},
78
utils::{HashMap, HashSet},
89
};
910
use float_ord::FloatOrd;
1011

11-
use super::{player, Chunk, ChunkShape, CHUNK_LENGTH};
12+
use super::{Chunk, ChunkShape, CHUNK_LENGTH};
1213
use crate::voxel::storage::ChunkMap;
1314
use crate::voxel::Voxel;
1415

16+
// @todo: should this contain a radius so that different entities could cause chunk loading in different ranges?
17+
#[derive(Component, Default)]
18+
/// Marker component for entities with a [GlobalTransform] which are tracked for the purpose of loading terrain.
19+
pub struct LoadChunksAround;
20+
1521
/// Updates the current chunk position for the current player.
1622
fn update_player_pos(
17-
player: Query<&GlobalTransform, (With<player::Body>, Changed<GlobalTransform>)>,
23+
player: Query<&GlobalTransform, (With<LoadChunksAround>, Changed<GlobalTransform>)>,
1824
mut chunk_pos: ResMut<CurrentLocalPlayerChunk>,
1925
) {
2026
if let Ok(ply) = player.get_single() {

src/voxel/world/player.rs

+12-1
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,24 @@ use std::f32::consts::FRAC_PI_2;
44

55
use crate::debug::DebugUISet;
66

7+
use super::chunks::LoadChunksAround;
8+
79
const BODY_ROTATION_SLERP: f32 = 0.5;
810

911
#[derive(Component)]
1012
pub struct Player;
1113

14+
#[derive(Bundle, Default)]
15+
pub struct BodyBundle<M: Material> {
16+
pub material_mesh_bundle: MaterialMeshBundle<M>,
17+
18+
// defaults are fine for these:
19+
pub body: Body,
20+
pub load_chunks_around: LoadChunksAround,
21+
}
22+
1223
/// Marker component for player body.
13-
#[derive(Component)]
24+
#[derive(Component, Default)]
1425
pub struct Body;
1526

1627
#[derive(Component)]

0 commit comments

Comments
 (0)