forked from StarArawn/bevy_ecs_tilemap
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathchunking.rs
119 lines (110 loc) · 4.32 KB
/
chunking.rs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
use bevy::{math::Vec3Swizzles, prelude::*, render::texture::ImageSettings, utils::HashSet};
use bevy_ecs_tilemap::prelude::*;
mod helpers;
const TILE_SIZE: TilemapTileSize = TilemapTileSize { x: 16.0, y: 16.0 };
const CHUNK_SIZE: TilemapSize = TilemapSize { x: 4, y: 4 };
fn spawn_chunk(commands: &mut Commands, asset_server: &AssetServer, chunk_pos: IVec2) {
let tilemap_entity = commands.spawn().id();
let mut tile_storage = TileStorage::empty(CHUNK_SIZE);
// Spawn the elements of the tilemap.
for x in 0..CHUNK_SIZE.x {
for y in 0..CHUNK_SIZE.y {
let tile_pos = TilePos { x, y };
let tile_entity = commands
.spawn()
.insert_bundle(TileBundle {
position: tile_pos,
tilemap_id: TilemapId(tilemap_entity),
..Default::default()
})
.id();
commands.entity(tilemap_entity).add_child(tile_entity);
tile_storage.set(&tile_pos, Some(tile_entity));
}
}
let transform = Transform::from_translation(Vec3::new(
chunk_pos.x as f32 * CHUNK_SIZE.x as f32 * TILE_SIZE.x,
chunk_pos.y as f32 * CHUNK_SIZE.y as f32 * TILE_SIZE.y,
0.0,
));
let texture_handle: Handle<Image> = asset_server.load("tiles.png");
commands
.entity(tilemap_entity)
.insert_bundle(TilemapBundle {
grid_size: TILE_SIZE.into(),
size: CHUNK_SIZE,
storage: tile_storage,
texture: TilemapTexture(texture_handle),
tile_size: TILE_SIZE,
transform,
..Default::default()
});
}
fn startup(mut commands: Commands) {
commands.spawn_bundle(Camera2dBundle::default());
}
fn camera_pos_to_chunk_pos(camera_pos: &Vec2) -> IVec2 {
let camera_pos = camera_pos.as_ivec2();
let chunk_size: IVec2 = IVec2::new(CHUNK_SIZE.x as i32, CHUNK_SIZE.y as i32);
let tile_size: IVec2 = IVec2::new(TILE_SIZE.x as i32, TILE_SIZE.y as i32);
camera_pos / (chunk_size * tile_size)
}
fn spawn_chunks_around_camera(
mut commands: Commands,
asset_server: Res<AssetServer>,
camera_query: Query<&Transform, With<Camera>>,
mut chunk_manager: ResMut<ChunkManager>,
) {
for transform in camera_query.iter() {
let camera_chunk_pos = camera_pos_to_chunk_pos(&transform.translation.xy());
for y in (camera_chunk_pos.y - 2)..(camera_chunk_pos.y + 2) {
for x in (camera_chunk_pos.x - 2)..(camera_chunk_pos.x + 2) {
if !chunk_manager.spawned_chunks.contains(&IVec2::new(x, y)) {
chunk_manager.spawned_chunks.insert(IVec2::new(x, y));
spawn_chunk(&mut commands, &asset_server, IVec2::new(x, y));
}
}
}
}
}
fn despawn_outofrange_chunks(
mut commands: Commands,
camera_query: Query<&Transform, With<Camera>>,
chunks_query: Query<(Entity, &Transform, &TileStorage)>,
mut chunk_manager: ResMut<ChunkManager>,
) {
for camera_transform in camera_query.iter() {
for (entity, chunk_transform, tile_storage) in chunks_query.iter() {
let chunk_pos = chunk_transform.translation.xy();
let distance = camera_transform.translation.xy().distance(chunk_pos);
if distance > 320.0 {
let x = (chunk_pos.x as f32 / (CHUNK_SIZE.x as f32 * TILE_SIZE.x)).floor() as i32;
let y = (chunk_pos.y as f32 / (CHUNK_SIZE.y as f32 * TILE_SIZE.y)).floor() as i32;
chunk_manager.spawned_chunks.remove(&IVec2::new(x, y));
commands.entity(entity).despawn_recursive();
}
}
}
}
#[derive(Default, Debug)]
struct ChunkManager {
pub spawned_chunks: HashSet<IVec2>,
}
fn main() {
App::new()
.insert_resource(WindowDescriptor {
width: 1270.0,
height: 720.0,
title: String::from("Basic Chunking Example"),
..Default::default()
})
.insert_resource(ImageSettings::default_nearest())
.add_plugins(DefaultPlugins)
.add_plugin(TilemapPlugin)
.insert_resource(ChunkManager::default())
.add_startup_system(startup)
.add_system(helpers::camera::movement)
.add_system(spawn_chunks_around_camera)
.add_system(despawn_outofrange_chunks)
.run();
}