mirror of
https://github.com/eliasstepanik/Bevy-TileSystem.git
synced 2026-01-10 21:28:29 +00:00
Working 2
This commit is contained in:
parent
e42586384a
commit
1f065361ba
@ -1,7 +1,9 @@
|
|||||||
use bevy::input::ButtonInput;
|
use bevy::input::ButtonInput;
|
||||||
|
use bevy::input::mouse::MouseWheel;
|
||||||
use bevy::log::info;
|
use bevy::log::info;
|
||||||
use bevy::prelude::{Camera, Camera2dBundle, Commands, Component, GlobalTransform, KeyCode, Query, Res, Time, Transform, Vec3, With, Without};
|
use bevy::prelude::{Camera, Camera2dBundle, Commands, Component, EventReader, GlobalTransform, KeyCode, Query, Res, Time, Transform, Vec3, With, Without};
|
||||||
use bevy::utils::default;
|
use bevy::utils::default;
|
||||||
|
use crate::components::world::{CAMERA_SCALE, PLAYER_SPEED};
|
||||||
|
|
||||||
#[derive(Component)]
|
#[derive(Component)]
|
||||||
pub struct Player {
|
pub struct Player {
|
||||||
@ -20,7 +22,7 @@ pub fn setup(mut commands: Commands) {
|
|||||||
info!("Adding Camera");
|
info!("Adding Camera");
|
||||||
commands.spawn(Camera2dBundle {
|
commands.spawn(Camera2dBundle {
|
||||||
transform: Transform {
|
transform: Transform {
|
||||||
scale: Vec3::splat(0.5), // Zoom in by reducing the scale (smaller scale means a larger view)
|
scale: Vec3::splat(CAMERA_SCALE), // Zoom in by reducing the scale (smaller scale means a larger view)
|
||||||
..default()
|
..default()
|
||||||
},
|
},
|
||||||
..default()
|
..default()
|
||||||
@ -30,7 +32,7 @@ pub fn setup(mut commands: Commands) {
|
|||||||
// Setup player with initial position
|
// Setup player with initial position
|
||||||
info!("Spawning player");
|
info!("Spawning player");
|
||||||
commands.spawn((
|
commands.spawn((
|
||||||
Player::new(500.0, Vec3::new(0.0, 0.0, 0.0)), // Initial player speed and position
|
Player::new(PLAYER_SPEED, Vec3::new(0.0, 0.0, 0.0)), // Initial player speed and position
|
||||||
Transform::from_translation(Vec3::new(0.0, 0.0, 0.0)),
|
Transform::from_translation(Vec3::new(0.0, 0.0, 0.0)),
|
||||||
GlobalTransform::default(),
|
GlobalTransform::default(),
|
||||||
));
|
));
|
||||||
@ -38,6 +40,7 @@ pub fn setup(mut commands: Commands) {
|
|||||||
|
|
||||||
pub fn update_movement(
|
pub fn update_movement(
|
||||||
keyboard_input: Res<ButtonInput<KeyCode>>,
|
keyboard_input: Res<ButtonInput<KeyCode>>,
|
||||||
|
mut mouse_wheel_events: EventReader<MouseWheel>,
|
||||||
time: Res<Time>,
|
time: Res<Time>,
|
||||||
mut query: Query<(&mut Player, &mut Transform)>,
|
mut query: Query<(&mut Player, &mut Transform)>,
|
||||||
mut camera_query: Query<&mut Transform, (With<Camera>, Without<Player>)>,
|
mut camera_query: Query<&mut Transform, (With<Camera>, Without<Player>)>,
|
||||||
@ -61,7 +64,26 @@ pub fn update_movement(
|
|||||||
|
|
||||||
// Update the player's transform
|
// Update the player's transform
|
||||||
player_transform.translation = player.position;
|
player_transform.translation = player.position;
|
||||||
|
|
||||||
|
// Adjust speed exponentially with mouse wheel
|
||||||
|
for event in mouse_wheel_events.read() {
|
||||||
|
// Define a base factor for exponential change
|
||||||
|
let base_factor = 1.1f32; // Adjust this value to control sensitivity
|
||||||
|
|
||||||
|
// Calculate the factor to multiply with speed
|
||||||
|
let factor = base_factor.powf(event.y);
|
||||||
|
|
||||||
|
// Update the controller speed exponentially
|
||||||
|
player.speed *= factor;
|
||||||
|
|
||||||
|
// Ensure the speed doesn't go below a minimum value
|
||||||
|
if player.speed < 0.01 {
|
||||||
|
player.speed = 0.01;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// Update the camera transform to match the player's position
|
// Update the camera transform to match the player's position
|
||||||
if let Ok(mut camera_transform) = camera_query.get_single_mut() {
|
if let Ok(mut camera_transform) = camera_query.get_single_mut() {
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use bevy::prelude::*;
|
use bevy::prelude::*;
|
||||||
use noise::{NoiseFn, Perlin};
|
use noise::{NoiseFn, Perlin};
|
||||||
use crate::components::world::CHUNK_SIZE;
|
use crate::components::world::{CHUNK_SIZE, NOISE_SCALE, SEED};
|
||||||
|
|
||||||
pub struct Chunk {
|
pub struct Chunk {
|
||||||
pub tiles: Vec<Tile>,
|
pub tiles: Vec<Tile>,
|
||||||
@ -12,7 +12,7 @@ impl Chunk {
|
|||||||
pub(crate) fn new(chunk_coords: (i64, i64)) -> Self {
|
pub(crate) fn new(chunk_coords: (i64, i64)) -> Self {
|
||||||
info!("Generating chunk at coordinates: {:?}", chunk_coords);
|
info!("Generating chunk at coordinates: {:?}", chunk_coords);
|
||||||
|
|
||||||
let perlin = Perlin::new(1321231231);
|
let perlin = Perlin::new(SEED);
|
||||||
let mut tiles = Vec::new();
|
let mut tiles = Vec::new();
|
||||||
|
|
||||||
for x in 0..CHUNK_SIZE {
|
for x in 0..CHUNK_SIZE {
|
||||||
@ -20,7 +20,7 @@ impl Chunk {
|
|||||||
let world_x = chunk_coords.0 * CHUNK_SIZE as i64 + x as i64;
|
let world_x = chunk_coords.0 * CHUNK_SIZE as i64 + x as i64;
|
||||||
let world_y = chunk_coords.1 * CHUNK_SIZE as i64 + y as i64;
|
let world_y = chunk_coords.1 * CHUNK_SIZE as i64 + y as i64;
|
||||||
|
|
||||||
let noise_value = perlin.get([world_x as f64 * 0.1, world_y as f64 * 0.1]);
|
let noise_value = perlin.get([world_x as f64 * NOISE_SCALE, world_y as f64 * NOISE_SCALE]);
|
||||||
|
|
||||||
let tile_type = if noise_value > 0.5 {
|
let tile_type = if noise_value > 0.5 {
|
||||||
TileType::Grass
|
TileType::Grass
|
||||||
|
|||||||
@ -1,21 +1,24 @@
|
|||||||
use bevy::asset::AssetServer;
|
use bevy::asset::AssetServer;
|
||||||
use bevy::prelude::{default, Camera, Color, Commands, Component, Query, Res, Text, TextBundle, TextStyle, Transform, Val, With};
|
use bevy::prelude::{default, Camera, Color, Commands, Component, Query, Res, Text, TextBundle, TextStyle, Time, Transform, Val, With};
|
||||||
use bevy::ui::{PositionType, Style};
|
use bevy::ui::{PositionType, Style};
|
||||||
use crate::components::player::Player;
|
use crate::components::player::Player;
|
||||||
|
|
||||||
#[derive(Component)]
|
#[derive(Component)]
|
||||||
pub struct SpeedDisplay;
|
pub struct SpeedDisplay;
|
||||||
|
|
||||||
|
#[derive(Component)]
|
||||||
|
pub struct FpsText;
|
||||||
|
|
||||||
pub fn setup(mut commands: Commands, asset_server: Res<AssetServer>) {
|
pub fn setup(mut commands: Commands, asset_server: Res<AssetServer>) {
|
||||||
|
|
||||||
// Spawn UI text for debugging speed
|
// Spawn UI text for debugging speed
|
||||||
commands.spawn((
|
commands.spawn((
|
||||||
TextBundle {
|
TextBundle {
|
||||||
text: Text::from_section(
|
text: Text::from_section(
|
||||||
"Speed: 5.0", // Initial text
|
"Speed: 5.0\nFPS: 60", // Initial text
|
||||||
TextStyle {
|
TextStyle {
|
||||||
font: asset_server.load("fonts/minecraft_font.ttf"), // Load a font
|
font: asset_server.load("fonts/minecraft_font.ttf"), // Load a font
|
||||||
font_size: 40.0,
|
font_size: 30.0,
|
||||||
color: Color::WHITE,
|
color: Color::WHITE,
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
@ -34,17 +37,21 @@ pub fn setup(mut commands: Commands, asset_server: Res<AssetServer>) {
|
|||||||
pub fn update(
|
pub fn update(
|
||||||
player_query: Query<&Player>,
|
player_query: Query<&Player>,
|
||||||
mut query_text: Query<&mut Text, With<SpeedDisplay>>,
|
mut query_text: Query<&mut Text, With<SpeedDisplay>>,
|
||||||
|
time: Res<Time>,
|
||||||
) {
|
) {
|
||||||
let player = player_query.single();
|
let player = player_query.single();
|
||||||
let mut text = query_text.single_mut();
|
let mut text = query_text.single_mut();
|
||||||
|
|
||||||
|
let fps = 1.0 / time.delta_seconds();
|
||||||
|
|
||||||
// Update the text with the current speed and position
|
// Update the text with the current speed and position
|
||||||
text.sections[0].value = format!(
|
text.sections[0].value = format!(
|
||||||
"Speed: {:.2}\nPosition: ({:.2}, {:.2}, {:.2})",
|
"Speed: {:.2}\nPosition: ({:.2}, {:.2}, {:.2})\nFps:{:2}",
|
||||||
player.speed,
|
player.speed,
|
||||||
player.position.x,
|
player.position.x,
|
||||||
player.position.y,
|
player.position.y,
|
||||||
player.position.z,
|
player.position.z,
|
||||||
|
fps
|
||||||
);
|
);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -3,16 +3,26 @@ use bevy::prelude::*;
|
|||||||
use bevy::render::mesh::PrimitiveTopology;
|
use bevy::render::mesh::PrimitiveTopology;
|
||||||
use bevy::render::render_asset::RenderAssetUsages;
|
use bevy::render::render_asset::RenderAssetUsages;
|
||||||
use bevy::sprite::{MaterialMesh2dBundle, Mesh2dHandle};
|
use bevy::sprite::{MaterialMesh2dBundle, Mesh2dHandle};
|
||||||
|
use bevy::tasks::{AsyncComputeTaskPool, Task};
|
||||||
|
use bevy::tasks::futures_lite::future;
|
||||||
use crate::components::tilemap::{Chunk, TileMap, TileType};
|
use crate::components::tilemap::{Chunk, TileMap, TileType};
|
||||||
|
|
||||||
pub const CHUNK_SIZE: i32 = 64;
|
pub const CHUNK_SIZE: i32 = 64;
|
||||||
|
pub const LOAD_RADIUS: i64 = 7;
|
||||||
|
pub const SEED: u32 = 123123;
|
||||||
|
pub const PLAYER_SPEED: f32 = 1000.0;
|
||||||
|
|
||||||
|
pub const NOISE_SCALE: f64 = 0.02;
|
||||||
|
pub const CAMERA_SCALE: f32 = 1.0;
|
||||||
|
|
||||||
|
|
||||||
|
#[derive(Component)]
|
||||||
|
pub struct ChunkLoadingTask(Task<(i64, i64, Chunk)>);
|
||||||
|
|
||||||
pub(crate) fn chunk_loader_system(
|
pub(crate) fn chunk_loader_system(
|
||||||
mut commands: Commands,
|
mut commands: Commands,
|
||||||
mut tile_map: ResMut<TileMap>,
|
mut tile_map: ResMut<TileMap>,
|
||||||
camera_query: Query<&Transform, With<Camera>>,
|
camera_query: Query<&Transform, With<Camera>>,
|
||||||
mut meshes: ResMut<Assets<Mesh>>,
|
|
||||||
mut materials: ResMut<Assets<ColorMaterial>>,
|
|
||||||
) {
|
) {
|
||||||
// Get the camera position
|
// Get the camera position
|
||||||
let camera_transform = camera_query.single();
|
let camera_transform = camera_query.single();
|
||||||
@ -22,15 +32,20 @@ pub(crate) fn chunk_loader_system(
|
|||||||
let chunk_x = (camera_position.x / (CHUNK_SIZE as f32 * 2.0)).floor() as i64;
|
let chunk_x = (camera_position.x / (CHUNK_SIZE as f32 * 2.0)).floor() as i64;
|
||||||
let chunk_y = (camera_position.y / (CHUNK_SIZE as f32 * 2.0)).floor() as i64;
|
let chunk_y = (camera_position.y / (CHUNK_SIZE as f32 * 2.0)).floor() as i64;
|
||||||
|
|
||||||
let load_radius = 5; // Number of chunks to load around the camera
|
|
||||||
|
|
||||||
// Load chunks within the radius of the camera position
|
// Load chunks within the radius of the camera position
|
||||||
for x in (chunk_x - load_radius)..=(chunk_x + load_radius) {
|
let task_pool = AsyncComputeTaskPool::get(); // Access the async compute task pool directly
|
||||||
for y in (chunk_y - load_radius)..=(chunk_y + load_radius) {
|
|
||||||
|
for x in (chunk_x - LOAD_RADIUS)..=(chunk_x + LOAD_RADIUS) {
|
||||||
|
for y in (chunk_y - LOAD_RADIUS)..=(chunk_y + LOAD_RADIUS) {
|
||||||
if !tile_map.chunks.contains_key(&(x, y)) {
|
if !tile_map.chunks.contains_key(&(x, y)) {
|
||||||
let mut new_chunk = Chunk::new((x, y));
|
// Spawn a new async task to generate the chunk
|
||||||
render_chunk(&mut new_chunk, &mut commands, &mut meshes, &mut materials);
|
let task = task_pool.spawn(async move {
|
||||||
tile_map.chunks.insert((x, y), new_chunk);
|
let chunk = Chunk::new((x, y));
|
||||||
|
(x, y, chunk)
|
||||||
|
});
|
||||||
|
|
||||||
|
commands.spawn(ChunkLoadingTask(task));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -39,7 +54,7 @@ pub(crate) fn chunk_loader_system(
|
|||||||
let chunks_to_unload: Vec<(i64, i64)> = tile_map
|
let chunks_to_unload: Vec<(i64, i64)> = tile_map
|
||||||
.chunks
|
.chunks
|
||||||
.keys()
|
.keys()
|
||||||
.filter(|&&(x, y)| (x - chunk_x).abs() > load_radius || (y - chunk_y).abs() > load_radius)
|
.filter(|&&(x, y)| (x - chunk_x).abs() > LOAD_RADIUS || (y - chunk_y).abs() > LOAD_RADIUS)
|
||||||
.cloned()
|
.cloned()
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
@ -51,6 +66,28 @@ pub(crate) fn chunk_loader_system(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
pub(crate) fn poll_chunk_tasks(
|
||||||
|
mut commands: Commands,
|
||||||
|
mut tile_map: ResMut<TileMap>,
|
||||||
|
mut tasks: Query<(Entity, &mut ChunkLoadingTask)>,
|
||||||
|
mut meshes: ResMut<Assets<Mesh>>,
|
||||||
|
mut materials: ResMut<Assets<ColorMaterial>>,
|
||||||
|
) {
|
||||||
|
for (entity, mut task) in tasks.iter_mut() {
|
||||||
|
if let Some((x, y, chunk)) = future::block_on(future::poll_once(&mut task.0)) {
|
||||||
|
// The chunk loading is complete, insert the chunk into the map
|
||||||
|
tile_map.chunks.insert((x, y), chunk);
|
||||||
|
|
||||||
|
// Now render the chunk
|
||||||
|
if let Some(mut chunk) = tile_map.chunks.get_mut(&(x, y)) {
|
||||||
|
render_chunk(&mut chunk, &mut commands, &mut meshes, &mut materials);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Despawn the task entity
|
||||||
|
commands.entity(entity).despawn();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn render_chunk(
|
fn render_chunk(
|
||||||
chunk: &mut Chunk,
|
chunk: &mut Chunk,
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user