Compare commits
No commits in common. "afc34ef76618a6a8b49ccd9c5f5e0901e4d10ad5" and "03ebb738f3b6b4420f6084c18056df4f9550ae28" have entirely different histories.
afc34ef766
...
03ebb738f3
11 changed files with 979 additions and 1066 deletions
1480
Cargo.lock
generated
1480
Cargo.lock
generated
File diff suppressed because it is too large
Load diff
|
@ -1,9 +1,10 @@
|
||||||
[package]
|
[package]
|
||||||
name = "moria"
|
name = "moria"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
edition = "2021"
|
edition = "2018"
|
||||||
|
|
||||||
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
bevy = "0.7.0"
|
bevy = "0.5.0"
|
||||||
bevy_mod_raycast = "0.5.0"
|
bevy_mod_raycast = "0.2.2"
|
||||||
bevy_prototype_debug_lines = { version = "0.7", features = ["3d"] }
|
|
||||||
|
|
|
@ -1,11 +1,10 @@
|
||||||
use bevy::prelude::*;
|
use bevy::prelude::*;
|
||||||
use bevy_mod_raycast::{RayCastMethod, RayCastSource};
|
use bevy_mod_raycast::{RayCastMethod, RayCastSource};
|
||||||
|
|
||||||
use crate::{pillar::UnlitPillar, player::*};
|
use crate::player::*;
|
||||||
|
|
||||||
pub struct MyRaycastSet;
|
pub struct MyRaycastSet;
|
||||||
|
|
||||||
#[derive(Component)]
|
|
||||||
pub struct Camera;
|
pub struct Camera;
|
||||||
pub fn spawn_camera(commands: &mut Commands) {
|
pub fn spawn_camera(commands: &mut Commands) {
|
||||||
commands
|
commands
|
||||||
|
@ -25,7 +24,7 @@ pub fn camera_follow_player(
|
||||||
};
|
};
|
||||||
|
|
||||||
for (mut trans, _) in camera.iter_mut() {
|
for (mut trans, _) in camera.iter_mut() {
|
||||||
trans.translation = player_pos + Vec3::new(-100.0, 200.0, 100.0);
|
trans.translation = player_pos + Vec3::new(-50.0, 100.0, 50.0);
|
||||||
trans.look_at(player_pos, Vec3::Y);
|
trans.look_at(player_pos, Vec3::Y);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -44,38 +43,16 @@ pub fn update_raycast_with_cursor(
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
pub struct MouseCoords {
|
pub struct MouseCoords(pub Vec3);
|
||||||
/// The mouse coordinates on the floor, as they are
|
|
||||||
pub raw: Vec3,
|
|
||||||
/// The mouse coordinates, after being snapped to pillars and stuff
|
|
||||||
pub processed: Vec3,
|
|
||||||
}
|
|
||||||
|
|
||||||
// Update our `RayCastSource` with the current cursor position every frame.
|
// Update our `RayCastSource` with the current cursor position every frame.
|
||||||
pub fn update_raw_mouse_coords(
|
pub fn update_mouse_coords(
|
||||||
query: Query<&RayCastSource<MyRaycastSet>>,
|
query: Query<&RayCastSource<MyRaycastSet>>,
|
||||||
mut coords: ResMut<MouseCoords>,
|
mut coords: ResMut<MouseCoords>,
|
||||||
) {
|
) {
|
||||||
for pick_source in query.iter() {
|
for pick_source in query.iter() {
|
||||||
if let Some((_, intersection)) = pick_source.intersect_top() {
|
if let Some((_, intersection)) = pick_source.intersect_top() {
|
||||||
coords.raw = intersection.position();
|
coords.0 = intersection.position();
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// checks for pillars and stuff
|
|
||||||
pub fn update_processed_mouse_coords(
|
|
||||||
query: Query<(&Transform, &UnlitPillar)>,
|
|
||||||
mut coords: ResMut<MouseCoords>,
|
|
||||||
) {
|
|
||||||
let mut dis = 20.0;
|
|
||||||
coords.processed = coords.raw;
|
|
||||||
|
|
||||||
for (trans, _) in query.iter() {
|
|
||||||
let d = trans.translation.distance(coords.raw);
|
|
||||||
if d < dis {
|
|
||||||
coords.processed = trans.translation;
|
|
||||||
dis = d;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
49
src/debug.rs
49
src/debug.rs
|
@ -1,49 +0,0 @@
|
||||||
use std::f32::consts::TAU;
|
|
||||||
|
|
||||||
use bevy::{ecs::schedule::ShouldRun, prelude::*};
|
|
||||||
use bevy_prototype_debug_lines::*;
|
|
||||||
|
|
||||||
use crate::illumination::Illumination;
|
|
||||||
|
|
||||||
#[derive(Default)]
|
|
||||||
pub struct Debug {
|
|
||||||
on: bool,
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn debug_run_criteria(debug: Res<Debug>) -> ShouldRun {
|
|
||||||
if debug.on {
|
|
||||||
ShouldRun::Yes
|
|
||||||
} else {
|
|
||||||
ShouldRun::No
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn debug_draw_illumination(
|
|
||||||
query: Query<(&GlobalTransform, &Illumination)>,
|
|
||||||
mut lines: ResMut<DebugLines>,
|
|
||||||
) {
|
|
||||||
for (trans, illumination) in query.iter() {
|
|
||||||
draw_sphere(&mut lines, trans.translation, illumination.radius);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn draw_sphere(lines: &mut DebugLines, c: Vec3, r: f32) {
|
|
||||||
const THICKNESS: f32 = 0.1;
|
|
||||||
const MAX_LINES: usize = 10;
|
|
||||||
|
|
||||||
for i in 0..MAX_LINES {
|
|
||||||
let angle1 = (i as f32 / MAX_LINES as f32) * TAU;
|
|
||||||
let angle2 = ((i + 1) as f32 / MAX_LINES as f32) * TAU;
|
|
||||||
|
|
||||||
let start = Vec3::new(r * f32::cos(angle1), 1.0, r * f32::sin(angle1)) + c;
|
|
||||||
let end = Vec3::new(r * f32::cos(angle2), 1.0, r * f32::sin(angle2)) + c;
|
|
||||||
|
|
||||||
lines.line(start, end, THICKNESS);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn toggle_debug(mut debug: ResMut<Debug>, input: Res<Input<KeyCode>>) {
|
|
||||||
if input.pressed(KeyCode::J) && input.pressed(KeyCode::K) && input.just_pressed(KeyCode::L) {
|
|
||||||
debug.on = !debug.on;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,6 +0,0 @@
|
||||||
use bevy::prelude::*;
|
|
||||||
|
|
||||||
#[derive(Component)]
|
|
||||||
pub struct Illumination {
|
|
||||||
pub radius: f32,
|
|
||||||
}
|
|
|
@ -1,10 +1,9 @@
|
||||||
use bevy::{pbr::CubemapVisibleEntities, prelude::*, render::primitives::CubemapFrusta};
|
use bevy::prelude::*;
|
||||||
|
|
||||||
use crate::{illumination::Illumination, player::Player};
|
use crate::player::Player;
|
||||||
|
|
||||||
const RANGE: f32 = 25.0;
|
const RANGE: f32 = 25.0;
|
||||||
|
|
||||||
#[derive(Component)]
|
|
||||||
pub struct LightBall;
|
pub struct LightBall;
|
||||||
pub fn light_up_ball_when_close_to_player(
|
pub fn light_up_ball_when_close_to_player(
|
||||||
mut commands: Commands,
|
mut commands: Commands,
|
||||||
|
@ -14,8 +13,7 @@ pub fn light_up_ball_when_close_to_player(
|
||||||
&Transform,
|
&Transform,
|
||||||
&LightBall,
|
&LightBall,
|
||||||
&mut Handle<StandardMaterial>,
|
&mut Handle<StandardMaterial>,
|
||||||
Option<&mut PointLight>,
|
Option<&mut Light>,
|
||||||
Option<&mut Illumination>,
|
|
||||||
)>,
|
)>,
|
||||||
materials: Res<LightBallMaterials>,
|
materials: Res<LightBallMaterials>,
|
||||||
) {
|
) {
|
||||||
|
@ -25,7 +23,7 @@ pub fn light_up_ball_when_close_to_player(
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
|
|
||||||
for (entity, trans, _, mut material, light, illumination) in thingies.iter_mut() {
|
for (entity, trans, _, mut material, light) in thingies.iter_mut() {
|
||||||
let dis = trans.translation.distance(player_pos);
|
let dis = trans.translation.distance(player_pos);
|
||||||
if dis < RANGE {
|
if dis < RANGE {
|
||||||
*material = materials.lit.clone();
|
*material = materials.lit.clone();
|
||||||
|
@ -35,30 +33,18 @@ pub fn light_up_ball_when_close_to_player(
|
||||||
if let Some(mut l) = light {
|
if let Some(mut l) = light {
|
||||||
l.intensity = 300.0 * (RANGE - dis) / RANGE;
|
l.intensity = 300.0 * (RANGE - dis) / RANGE;
|
||||||
} else {
|
} else {
|
||||||
commands.entity(entity).insert(PointLight {
|
commands.entity(entity).insert(Light {
|
||||||
color: Color::rgb(15.0, 15.0, 15.0),
|
color: Color::rgb(15.0, 15.0, 15.0),
|
||||||
intensity: 300.0 * (RANGE - dis) / RANGE,
|
intensity: 300.0 * (RANGE - dis) / RANGE,
|
||||||
..Default::default()
|
..Default::default()
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// same with illumination
|
|
||||||
if let Some(mut l) = illumination {
|
|
||||||
l.radius = 15.0 * ((RANGE - dis) / RANGE).sqrt();
|
|
||||||
} else {
|
|
||||||
commands.entity(entity).insert(Illumination {
|
|
||||||
radius: 15.0 * ((RANGE - dis) / RANGE).sqrt().sqrt(),
|
|
||||||
});
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
*material = materials.unlit.clone();
|
*material = materials.unlit.clone();
|
||||||
|
|
||||||
// remove light if there is one
|
// remove light if there is one
|
||||||
if light.is_some() {
|
if light.is_some() {
|
||||||
commands.entity(entity).remove::<PointLight>();
|
commands.entity(entity).remove::<Light>();
|
||||||
}
|
|
||||||
if illumination.is_some() {
|
|
||||||
commands.entity(entity).remove::<Illumination>();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -76,8 +62,6 @@ pub fn spawn_light_ball(
|
||||||
transform: Transform::from_translation(translation),
|
transform: Transform::from_translation(translation),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
})
|
})
|
||||||
.insert(CubemapFrusta::default())
|
|
||||||
.insert(CubemapVisibleEntities::default())
|
|
||||||
.insert(LightBall);
|
.insert(LightBall);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,12 +1,12 @@
|
||||||
use bevy::{
|
use bevy::{
|
||||||
prelude::*,
|
prelude::*,
|
||||||
render::render_resource::{AddressMode, FilterMode},
|
render::texture::{AddressMode, FilterMode},
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::AppState;
|
use crate::AppState;
|
||||||
|
|
||||||
pub struct LoadedAssets {
|
pub struct LoadedAssets {
|
||||||
pub floor: Handle<Image>,
|
pub floor: Handle<Texture>,
|
||||||
}
|
}
|
||||||
impl FromWorld for LoadedAssets {
|
impl FromWorld for LoadedAssets {
|
||||||
fn from_world(world: &mut World) -> Self {
|
fn from_world(world: &mut World) -> Self {
|
||||||
|
@ -19,14 +19,14 @@ impl FromWorld for LoadedAssets {
|
||||||
|
|
||||||
pub fn loading(
|
pub fn loading(
|
||||||
assets: Res<LoadedAssets>,
|
assets: Res<LoadedAssets>,
|
||||||
mut textures: ResMut<Assets<Image>>,
|
mut textures: ResMut<Assets<Texture>>,
|
||||||
mut state: ResMut<State<AppState>>,
|
mut state: ResMut<State<AppState>>,
|
||||||
) {
|
) {
|
||||||
if let Some(t) = textures.get_mut(&assets.floor) {
|
if let Some(t) = textures.get_mut(&assets.floor) {
|
||||||
t.sampler_descriptor.address_mode_u = AddressMode::MirrorRepeat;
|
t.sampler.address_mode_u = AddressMode::MirrorRepeat;
|
||||||
t.sampler_descriptor.address_mode_v = AddressMode::Repeat;
|
t.sampler.address_mode_v = AddressMode::Repeat;
|
||||||
t.sampler_descriptor.address_mode_w = AddressMode::Repeat;
|
t.sampler.address_mode_w = AddressMode::Repeat;
|
||||||
t.sampler_descriptor.mipmap_filter = FilterMode::Linear;
|
t.sampler.mipmap_filter = FilterMode::Linear;
|
||||||
|
|
||||||
state.set(AppState::Game).unwrap();
|
state.set(AppState::Game).unwrap();
|
||||||
}
|
}
|
||||||
|
|
90
src/main.rs
90
src/main.rs
|
@ -1,20 +1,15 @@
|
||||||
use bevy::{input::system::exit_on_esc_system, pbr::AmbientLight, prelude::*};
|
use bevy::{input::system::exit_on_esc_system, pbr::AmbientLight, prelude::*};
|
||||||
use bevy_mod_raycast::{DefaultRaycastingPlugin, RayCastMesh, RaycastSystem};
|
use bevy_mod_raycast::{build_rays, update_raycast, PluginState, RayCastMesh, RaycastSystem};
|
||||||
use bevy_prototype_debug_lines::*;
|
|
||||||
|
|
||||||
mod camera;
|
mod camera;
|
||||||
mod columns;
|
mod columns;
|
||||||
mod debug;
|
|
||||||
mod illumination;
|
|
||||||
mod light_balls;
|
mod light_balls;
|
||||||
mod loading;
|
mod loading;
|
||||||
mod pillar;
|
|
||||||
mod player;
|
mod player;
|
||||||
|
mod rendering;
|
||||||
|
|
||||||
use camera::*;
|
use camera::*;
|
||||||
use debug::*;
|
|
||||||
use light_balls::*;
|
use light_balls::*;
|
||||||
use pillar::*;
|
|
||||||
use player::*;
|
use player::*;
|
||||||
|
|
||||||
#[derive(Clone, PartialEq, Eq, Hash, Debug)]
|
#[derive(Clone, PartialEq, Eq, Hash, Debug)]
|
||||||
|
@ -24,51 +19,52 @@ pub enum AppState {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
App::new()
|
App::build()
|
||||||
.insert_resource(Msaa { samples: 4 })
|
.insert_resource(Msaa { samples: 4 })
|
||||||
.insert_resource(ClearColor(Color::rgb(0.0, 0.0, 0.0)))
|
.insert_resource(ClearColor(Color::rgb(0.0, 0.0, 0.0)))
|
||||||
.add_plugins(DefaultPlugins)
|
.add_plugins(rendering::CustomPlugins)
|
||||||
.add_plugin(DebugLinesPlugin::with_depth_test(true))
|
|
||||||
.init_resource::<Debug>()
|
|
||||||
.init_resource::<LightBallMaterials>()
|
.init_resource::<LightBallMaterials>()
|
||||||
.init_resource::<PillarMaterials>()
|
|
||||||
.init_resource::<MouseCoords>()
|
.init_resource::<MouseCoords>()
|
||||||
.init_resource::<FloatingOrbsInterpolationState>()
|
.init_resource::<FloatingOrbsInterpolationState>()
|
||||||
.init_resource::<PillarActivationProgress>()
|
|
||||||
.init_resource::<LightExcitationState>()
|
|
||||||
.init_resource::<loading::LoadedAssets>()
|
.init_resource::<loading::LoadedAssets>()
|
||||||
.add_state(AppState::Loading)
|
.add_state(AppState::Loading)
|
||||||
// raycasting
|
// raycasting
|
||||||
.add_plugin(DefaultRaycastingPlugin::<MyRaycastSet>::default())
|
.init_resource::<PluginState<MyRaycastSet>>()
|
||||||
|
.add_system_to_stage(
|
||||||
|
CoreStage::PostUpdate,
|
||||||
|
build_rays::<MyRaycastSet>
|
||||||
|
.system()
|
||||||
|
.label(RaycastSystem::BuildRays),
|
||||||
|
)
|
||||||
|
.add_system_to_stage(
|
||||||
|
CoreStage::PostUpdate,
|
||||||
|
update_raycast::<MyRaycastSet>
|
||||||
|
.system()
|
||||||
|
.label(RaycastSystem::UpdateRaycast)
|
||||||
|
.after(RaycastSystem::BuildRays),
|
||||||
|
)
|
||||||
.add_system_to_stage(
|
.add_system_to_stage(
|
||||||
CoreStage::PreUpdate,
|
CoreStage::PreUpdate,
|
||||||
update_raycast_with_cursor.before(RaycastSystem::<MyRaycastSet>::BuildRays),
|
update_raycast_with_cursor
|
||||||
|
.system()
|
||||||
|
.before(RaycastSystem::BuildRays),
|
||||||
)
|
)
|
||||||
// loading
|
// loading
|
||||||
.add_system_set(SystemSet::on_update(AppState::Loading).with_system(loading::loading))
|
|
||||||
// game
|
|
||||||
.add_system_set(SystemSet::on_enter(AppState::Game).with_system(setup))
|
|
||||||
.add_system_set(
|
.add_system_set(
|
||||||
SystemSet::on_update(AppState::Game)
|
SystemSet::on_update(AppState::Loading).with_system(loading::loading.system()),
|
||||||
.with_system(update_raw_mouse_coords)
|
|
||||||
.with_system(update_processed_mouse_coords)
|
|
||||||
.with_system(exit_on_esc_system)
|
|
||||||
.with_system(light_movement)
|
|
||||||
.with_system(move_light_friends)
|
|
||||||
.with_system(update_floating_orbs_interpolation)
|
|
||||||
.with_system(move_player)
|
|
||||||
.with_system(camera_follow_player)
|
|
||||||
.with_system(light_up_ball_when_close_to_player)
|
|
||||||
.with_system(increase_progress_when_activating_pillar)
|
|
||||||
.with_system(activate_pillar_when_progress_is_1)
|
|
||||||
.with_system(decrease_pillar_strength)
|
|
||||||
.with_system(update_light_excitation_state)
|
|
||||||
.with_system(toggle_debug),
|
|
||||||
)
|
)
|
||||||
|
// game
|
||||||
|
.add_system_set(SystemSet::on_enter(AppState::Game).with_system(setup.system()))
|
||||||
.add_system_set(
|
.add_system_set(
|
||||||
SystemSet::on_update(AppState::Game)
|
SystemSet::on_update(AppState::Game)
|
||||||
.with_run_criteria(debug_run_criteria)
|
.with_system(update_mouse_coords.system())
|
||||||
.with_system(debug_draw_illumination),
|
.with_system(exit_on_esc_system.system())
|
||||||
|
.with_system(light_movement.system())
|
||||||
|
.with_system(move_light_friends.system())
|
||||||
|
.with_system(update_floating_orbs_interpolation.system())
|
||||||
|
.with_system(move_player.system())
|
||||||
|
.with_system(camera_follow_player.system())
|
||||||
|
.with_system(light_up_ball_when_close_to_player.system()),
|
||||||
)
|
)
|
||||||
.run();
|
.run();
|
||||||
}
|
}
|
||||||
|
@ -80,7 +76,6 @@ fn setup(
|
||||||
mut materials: ResMut<Assets<StandardMaterial>>,
|
mut materials: ResMut<Assets<StandardMaterial>>,
|
||||||
mut ambient: ResMut<AmbientLight>,
|
mut ambient: ResMut<AmbientLight>,
|
||||||
light_ball_materials: Res<LightBallMaterials>,
|
light_ball_materials: Res<LightBallMaterials>,
|
||||||
pillar_materials: Res<PillarMaterials>,
|
|
||||||
) {
|
) {
|
||||||
// set ambient light to very low
|
// set ambient light to very low
|
||||||
ambient.color = Color::rgb(0.3, 0.3, 0.3);
|
ambient.color = Color::rgb(0.3, 0.3, 0.3);
|
||||||
|
@ -111,30 +106,11 @@ fn setup(
|
||||||
// columns
|
// columns
|
||||||
// columns::spawn_columns(&mut commands, &mut meshes, &mut materials);
|
// columns::spawn_columns(&mut commands, &mut meshes, &mut materials);
|
||||||
|
|
||||||
spawn_pillar(
|
|
||||||
&mut commands,
|
|
||||||
&pillar_materials,
|
|
||||||
&mut materials,
|
|
||||||
Vec3::new(0.0, 1.0, 50.0),
|
|
||||||
);
|
|
||||||
spawn_pillar(
|
|
||||||
&mut commands,
|
|
||||||
&pillar_materials,
|
|
||||||
&mut materials,
|
|
||||||
Vec3::new(-30.0, 1.0, 50.0),
|
|
||||||
);
|
|
||||||
spawn_pillar(
|
|
||||||
&mut commands,
|
|
||||||
&pillar_materials,
|
|
||||||
&mut materials,
|
|
||||||
Vec3::new(30.0, 1.0, 50.0),
|
|
||||||
);
|
|
||||||
|
|
||||||
// player
|
// player
|
||||||
spawn_player(&mut commands, &mut meshes, &mut materials);
|
spawn_player(&mut commands, &mut meshes, &mut materials);
|
||||||
|
|
||||||
// light balls
|
// light balls
|
||||||
for i in 2..12 {
|
for i in 1..10 {
|
||||||
spawn_light_ball(
|
spawn_light_ball(
|
||||||
&mut commands,
|
&mut commands,
|
||||||
&light_ball_materials,
|
&light_ball_materials,
|
||||||
|
|
166
src/pillar.rs
166
src/pillar.rs
|
@ -1,166 +0,0 @@
|
||||||
use bevy::prelude::*;
|
|
||||||
|
|
||||||
use crate::{camera::MouseCoords, player::LightFriends};
|
|
||||||
|
|
||||||
const SIZE: f32 = 10.0;
|
|
||||||
const HEIGHT: f32 = 20.0;
|
|
||||||
|
|
||||||
#[derive(Component)]
|
|
||||||
pub struct UnlitPillar;
|
|
||||||
#[derive(Component)]
|
|
||||||
pub struct LitPillar {
|
|
||||||
created_at: f64,
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn spawn_pillar(
|
|
||||||
commands: &mut Commands,
|
|
||||||
pillar_mats: &PillarMaterials,
|
|
||||||
materials: &mut Assets<StandardMaterial>,
|
|
||||||
pos: Vec3,
|
|
||||||
) {
|
|
||||||
let mut unlit: StandardMaterial = Color::rgb(0.9, 0.9, 0.9).into();
|
|
||||||
unlit.metallic = 0.0;
|
|
||||||
unlit.reflectance = 0.0;
|
|
||||||
let unlit = materials.add(unlit);
|
|
||||||
commands
|
|
||||||
.spawn_bundle(PbrBundle {
|
|
||||||
mesh: pillar_mats.mesh.clone(),
|
|
||||||
material: unlit,
|
|
||||||
transform: Transform::from_translation(pos),
|
|
||||||
..Default::default()
|
|
||||||
})
|
|
||||||
.insert(UnlitPillar);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Default)]
|
|
||||||
pub struct PillarActivationProgress(pub Option<(Entity, f32)>);
|
|
||||||
|
|
||||||
pub fn increase_progress_when_activating_pillar(
|
|
||||||
pillars: Query<(Entity, &Transform, &UnlitPillar)>,
|
|
||||||
friends: Query<(&Transform, &LightFriends)>,
|
|
||||||
mut progress: ResMut<PillarActivationProgress>,
|
|
||||||
input: Res<Input<MouseButton>>,
|
|
||||||
mouse: Res<MouseCoords>,
|
|
||||||
) {
|
|
||||||
if !input.pressed(MouseButton::Left) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
let (friends_trans, _) = if let Some(f) = friends.iter().next() {
|
|
||||||
f
|
|
||||||
} else {
|
|
||||||
return;
|
|
||||||
};
|
|
||||||
|
|
||||||
for (entity, trans, _) in pillars.iter() {
|
|
||||||
let friends_d = trans.translation.distance(friends_trans.translation);
|
|
||||||
let mouse_d = trans.translation.distance(mouse.processed);
|
|
||||||
if friends_d < 10.0 && mouse_d < 1.0 {
|
|
||||||
// set as the one on progress and increase
|
|
||||||
if let Some(p) = &mut progress.0 {
|
|
||||||
if p.0 == entity {
|
|
||||||
p.1 = (p.1 + 0.008).clamp(0.0, 1.0);
|
|
||||||
} else {
|
|
||||||
*p = (entity, 0.0);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
progress.0 = Some((entity, 0.0));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn activate_pillar_when_progress_is_1(
|
|
||||||
mut commands: Commands,
|
|
||||||
mut progress_res: ResMut<PillarActivationProgress>,
|
|
||||||
query: Query<(&Handle<StandardMaterial>, &UnlitPillar)>,
|
|
||||||
mut materials: ResMut<Assets<StandardMaterial>>,
|
|
||||||
time: Res<Time>,
|
|
||||||
) {
|
|
||||||
if let Some((entity, progress)) = progress_res.0 {
|
|
||||||
if progress >= 1.0 {
|
|
||||||
progress_res.0 = None;
|
|
||||||
|
|
||||||
// activate pillar
|
|
||||||
commands
|
|
||||||
.entity(entity)
|
|
||||||
.remove::<UnlitPillar>()
|
|
||||||
.insert(LitPillar {
|
|
||||||
created_at: time.seconds_since_startup(),
|
|
||||||
})
|
|
||||||
.insert(PointLight {
|
|
||||||
color: Color::rgb(15.0, 15.0, 15.0),
|
|
||||||
intensity: 500.0,
|
|
||||||
..Default::default()
|
|
||||||
});
|
|
||||||
|
|
||||||
if let Ok((handle, _)) = query.get(entity) {
|
|
||||||
if let Some(mat) = materials.get_mut(handle) {
|
|
||||||
mat.base_color = Color::rgb(15.0, 15.0, 15.0);
|
|
||||||
mat.emissive = Color::rgb(15.0, 15.0, 15.0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if let Ok((handle, _)) = query.get(entity) {
|
|
||||||
if let Some(mat) = materials.get_mut(handle) {
|
|
||||||
mat.base_color = Color::rgb(15.0, 15.0, 15.0) * progress;
|
|
||||||
mat.emissive = Color::rgb(15.0, 15.0, 15.0) * progress;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn decrease_pillar_strength(
|
|
||||||
mut commands: Commands,
|
|
||||||
mut query: Query<(
|
|
||||||
Entity,
|
|
||||||
&mut PointLight,
|
|
||||||
&Handle<StandardMaterial>,
|
|
||||||
&LitPillar,
|
|
||||||
)>,
|
|
||||||
mut materials: ResMut<Assets<StandardMaterial>>,
|
|
||||||
time: Res<Time>,
|
|
||||||
) {
|
|
||||||
let t = time.seconds_since_startup();
|
|
||||||
for (entity, mut light, handle, pillar) in query.iter_mut() {
|
|
||||||
let d = t - pillar.created_at;
|
|
||||||
const DUR: f32 = 10.0;
|
|
||||||
let i = (DUR - d as f32) / DUR;
|
|
||||||
|
|
||||||
if i < 0.0 {
|
|
||||||
// deactivate pillar
|
|
||||||
commands
|
|
||||||
.entity(entity)
|
|
||||||
.remove::<LitPillar>()
|
|
||||||
.remove::<PointLight>()
|
|
||||||
.insert(UnlitPillar);
|
|
||||||
|
|
||||||
if let Some(mat) = materials.get_mut(handle) {
|
|
||||||
mat.base_color = Color::rgb(0.9, 0.9, 0.9);
|
|
||||||
mat.emissive = Color::rgb(0., 0., 0.);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
light.intensity = i * 500.0;
|
|
||||||
|
|
||||||
if let Some(mat) = materials.get_mut(handle) {
|
|
||||||
mat.base_color = Color::rgb(15.0, 15.0, 15.0) * i.powf(1.3);
|
|
||||||
mat.emissive = Color::rgb(15.0, 15.0, 15.0) * i.powf(1.3);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct PillarMaterials {
|
|
||||||
mesh: Handle<Mesh>,
|
|
||||||
}
|
|
||||||
impl FromWorld for PillarMaterials {
|
|
||||||
fn from_world(world: &mut World) -> Self {
|
|
||||||
let world = world.cell();
|
|
||||||
let mut meshes = world.get_resource_mut::<Assets<Mesh>>().unwrap();
|
|
||||||
|
|
||||||
let mesh = meshes.add(Mesh::from(shape::Box::new(SIZE, HEIGHT, SIZE)));
|
|
||||||
|
|
||||||
Self { mesh }
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,10 +1,8 @@
|
||||||
use bevy::prelude::*;
|
use bevy::prelude::*;
|
||||||
|
|
||||||
use crate::{camera::MouseCoords, illumination::Illumination, pillar::PillarActivationProgress};
|
use crate::camera::MouseCoords;
|
||||||
|
|
||||||
#[derive(Component)]
|
|
||||||
pub struct Player;
|
pub struct Player;
|
||||||
#[derive(Component)]
|
|
||||||
pub struct PlayerLight {
|
pub struct PlayerLight {
|
||||||
i: u8,
|
i: u8,
|
||||||
}
|
}
|
||||||
|
@ -27,22 +25,19 @@ pub fn spawn_player(
|
||||||
.insert(Player);
|
.insert(Player);
|
||||||
|
|
||||||
// light
|
// light
|
||||||
|
let mut light_material: StandardMaterial = Color::rgb(0.737255, 0.560784, 0.560784).into();
|
||||||
|
light_material.metallic = 0.5;
|
||||||
|
light_material.reflectance = 0.5;
|
||||||
|
light_material.emissive = Color::rgb(7.52, 5.72, 5.72);
|
||||||
|
let light_material = materials.add(light_material);
|
||||||
|
|
||||||
commands
|
commands
|
||||||
.spawn()
|
.spawn()
|
||||||
.insert(LightFriends)
|
.insert(LightFriends)
|
||||||
.insert(Transform::default())
|
.insert(Transform::default())
|
||||||
.insert(GlobalTransform::default())
|
.insert(GlobalTransform::default())
|
||||||
.with_children(|children| {
|
.with_children(|children| {
|
||||||
let count = 6;
|
for i in 0..6 {
|
||||||
for i in 0..count {
|
|
||||||
let color = Color::hsl(360.0 * i as f32 / count as f32, 0.5, 0.5);
|
|
||||||
|
|
||||||
let mut light_material: StandardMaterial = color.into();
|
|
||||||
light_material.metallic = 0.5;
|
|
||||||
light_material.reflectance = 0.5;
|
|
||||||
light_material.emissive = color.as_rgba() * 10.0;
|
|
||||||
let light_material = materials.add(light_material);
|
|
||||||
|
|
||||||
children
|
children
|
||||||
.spawn_bundle(PbrBundle {
|
.spawn_bundle(PbrBundle {
|
||||||
mesh: meshes.add(Mesh::from(shape::Icosphere {
|
mesh: meshes.add(Mesh::from(shape::Icosphere {
|
||||||
|
@ -53,21 +48,19 @@ pub fn spawn_player(
|
||||||
transform: Transform::from_xyz(0.0, 0.5, 0.0),
|
transform: Transform::from_xyz(0.0, 0.5, 0.0),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
})
|
})
|
||||||
.insert_bundle(PointLightBundle {
|
.insert_bundle(LightBundle {
|
||||||
transform: Transform::from_xyz(0.0, 0.0, 0.0),
|
transform: Transform::from_xyz(0.0, 0.0, 0.0),
|
||||||
point_light: PointLight {
|
light: Light {
|
||||||
color: color.as_rgba() * 10.0,
|
color: Color::rgb(7.52, 5.72, 5.72),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
},
|
},
|
||||||
..Default::default()
|
..Default::default()
|
||||||
})
|
})
|
||||||
.insert(PlayerLight { i: i as u8 + 1 })
|
.insert(PlayerLight { i: i as u8 + 1 });
|
||||||
.insert(Illumination { radius: 13.0 });
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Component)]
|
|
||||||
pub struct LightFriends;
|
pub struct LightFriends;
|
||||||
pub fn move_light_friends(
|
pub fn move_light_friends(
|
||||||
mut query: Query<(&mut Transform, &LightFriends)>,
|
mut query: Query<(&mut Transform, &LightFriends)>,
|
||||||
|
@ -85,7 +78,7 @@ pub fn move_light_friends(
|
||||||
for (mut trans, _light) in query.iter_mut() {
|
for (mut trans, _light) in query.iter_mut() {
|
||||||
// interpolate between player pos and mouse click pos
|
// interpolate between player pos and mouse click pos
|
||||||
let i = interpolation.0;
|
let i = interpolation.0;
|
||||||
let center = i * coords.processed + (1.0 - i) * player_pos;
|
let center = i * coords.0 + (1.0 - i) * player_pos;
|
||||||
|
|
||||||
let mut d = trans.translation - center;
|
let mut d = trans.translation - center;
|
||||||
d.y = 0.0;
|
d.y = 0.0;
|
||||||
|
@ -93,42 +86,15 @@ pub fn move_light_friends(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Default)]
|
pub fn light_movement(mut query: Query<(&mut Transform, &PlayerLight)>, time: Res<Time>) {
|
||||||
pub struct LightExcitationState(f32);
|
|
||||||
pub fn update_light_excitation_state(
|
|
||||||
pillar_progress: Res<PillarActivationProgress>,
|
|
||||||
mut excitation: ResMut<LightExcitationState>,
|
|
||||||
) {
|
|
||||||
// light pillar activation progress
|
|
||||||
let p = pillar_progress.0.map(|(_, p)| p).unwrap_or(0.0);
|
|
||||||
|
|
||||||
if p > excitation.0 {
|
|
||||||
excitation.0 = (excitation.0 + 0.008).clamp(0.0, 1.0);
|
|
||||||
} else {
|
|
||||||
excitation.0 = (excitation.0 - 0.008).clamp(0.0, 1.0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn light_movement(
|
|
||||||
mut query: Query<(&mut Transform, &PlayerLight)>,
|
|
||||||
time: Res<Time>,
|
|
||||||
interpolation: Res<FloatingOrbsInterpolationState>,
|
|
||||||
excitation: Res<LightExcitationState>,
|
|
||||||
) {
|
|
||||||
let t = time.seconds_since_startup();
|
let t = time.seconds_since_startup();
|
||||||
let p = excitation.0;
|
|
||||||
|
|
||||||
// make the friends go further when the button is pressed, but close in when activating a pillar
|
|
||||||
let width = (5.0 + interpolation.0 * 7.0) * (1.0 - p);
|
|
||||||
|
|
||||||
let p = 1.0 + 0.8 * p as f64;
|
|
||||||
for (mut trans, light) in query.iter_mut() {
|
for (mut trans, light) in query.iter_mut() {
|
||||||
let i = light.i as f64;
|
let i = light.i as f64;
|
||||||
let i2 = i / 2.0;
|
let i2 = i / 2.0;
|
||||||
trans.translation = Vec3::new(
|
trans.translation = Vec3::new(
|
||||||
width * i2 as f32 * (t * 0.4 * i2 + i * p).cos() as f32,
|
5.0 * i2 as f32 * (t * 0.4 * i2 + i).cos() as f32,
|
||||||
3.0 * (t * 1.1 * i2 + i * p).sin() as f32 + 4.0,
|
3.0 * (t * 1.1 * i2 + i).sin() as f32 + 4.0,
|
||||||
width * (t * 0.4 * i + i * p).sin() as f32,
|
5.0 * (t * 0.4 * i + i).sin() as f32,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
102
src/rendering/mod.rs
Normal file
102
src/rendering/mod.rs
Normal file
|
@ -0,0 +1,102 @@
|
||||||
|
use bevy::app::{PluginGroup, PluginGroupBuilder};
|
||||||
|
use bevy::pbr::render_graph::{LightsNode, PBR_PIPELINE_HANDLE};
|
||||||
|
use bevy::prelude::*;
|
||||||
|
use bevy::render::{
|
||||||
|
pipeline::PipelineDescriptor,
|
||||||
|
render_graph::{base, AssetRenderResourcesNode, RenderGraph, RenderResourcesNode},
|
||||||
|
shader::Shader,
|
||||||
|
};
|
||||||
|
|
||||||
|
mod pipeline;
|
||||||
|
use pipeline::build_pbr_pipeline;
|
||||||
|
|
||||||
|
pub struct CustomPlugins;
|
||||||
|
impl PluginGroup for CustomPlugins {
|
||||||
|
fn build(&mut self, group: &mut PluginGroupBuilder) {
|
||||||
|
group.add(bevy::log::LogPlugin::default());
|
||||||
|
group.add(bevy::core::CorePlugin::default());
|
||||||
|
group.add(bevy::transform::TransformPlugin::default());
|
||||||
|
group.add(bevy::diagnostic::DiagnosticsPlugin::default());
|
||||||
|
group.add(bevy::input::InputPlugin::default());
|
||||||
|
group.add(bevy::window::WindowPlugin::default());
|
||||||
|
group.add(bevy::asset::AssetPlugin::default());
|
||||||
|
group.add(bevy::scene::ScenePlugin::default());
|
||||||
|
|
||||||
|
group.add(bevy::render::RenderPlugin::default());
|
||||||
|
group.add(bevy::sprite::SpritePlugin::default());
|
||||||
|
group.add(CustomPbrPlugin::default());
|
||||||
|
group.add(bevy::ui::UiPlugin::default());
|
||||||
|
group.add(bevy::text::TextPlugin::default());
|
||||||
|
group.add(bevy::gilrs::GilrsPlugin::default());
|
||||||
|
group.add(bevy::gltf::GltfPlugin::default());
|
||||||
|
group.add(bevy::winit::WinitPlugin::default());
|
||||||
|
group.add(bevy::wgpu::WgpuPlugin::default());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Default)]
|
||||||
|
pub struct CustomPbrPlugin;
|
||||||
|
impl Plugin for CustomPbrPlugin {
|
||||||
|
fn build(&self, app: &mut AppBuilder) {
|
||||||
|
app.add_asset::<StandardMaterial>()
|
||||||
|
.register_type::<Light>()
|
||||||
|
.add_system_to_stage(
|
||||||
|
CoreStage::PostUpdate,
|
||||||
|
bevy::render::shader::asset_shader_defs_system::<StandardMaterial>.system(),
|
||||||
|
)
|
||||||
|
.init_resource::<bevy::pbr::AmbientLight>();
|
||||||
|
add_pbr_graph(app.world_mut());
|
||||||
|
|
||||||
|
// add default StandardMaterial
|
||||||
|
let mut materials = app
|
||||||
|
.world_mut()
|
||||||
|
.get_resource_mut::<Assets<StandardMaterial>>()
|
||||||
|
.unwrap();
|
||||||
|
materials.set_untracked(
|
||||||
|
Handle::<StandardMaterial>::default(),
|
||||||
|
StandardMaterial {
|
||||||
|
base_color: Color::PINK,
|
||||||
|
unlit: true,
|
||||||
|
..Default::default()
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// the names of pbr graph nodes
|
||||||
|
mod node {
|
||||||
|
pub const TRANSFORM: &str = "transform";
|
||||||
|
pub const STANDARD_MATERIAL: &str = "standard_material";
|
||||||
|
pub const LIGHTS: &str = "lights";
|
||||||
|
}
|
||||||
|
|
||||||
|
fn add_pbr_graph(world: &mut World) {
|
||||||
|
{
|
||||||
|
let mut graph = world.get_resource_mut::<RenderGraph>().unwrap();
|
||||||
|
graph.add_system_node(
|
||||||
|
node::TRANSFORM,
|
||||||
|
RenderResourcesNode::<GlobalTransform>::new(true),
|
||||||
|
);
|
||||||
|
graph.add_system_node(
|
||||||
|
node::STANDARD_MATERIAL,
|
||||||
|
AssetRenderResourcesNode::<StandardMaterial>::new(true),
|
||||||
|
);
|
||||||
|
graph.add_system_node(node::LIGHTS, LightsNode::new(30));
|
||||||
|
|
||||||
|
// TODO: replace these with "autowire" groups
|
||||||
|
graph
|
||||||
|
.add_node_edge(node::STANDARD_MATERIAL, base::node::MAIN_PASS)
|
||||||
|
.unwrap();
|
||||||
|
graph
|
||||||
|
.add_node_edge(node::TRANSFORM, base::node::MAIN_PASS)
|
||||||
|
.unwrap();
|
||||||
|
graph
|
||||||
|
.add_node_edge(node::LIGHTS, base::node::MAIN_PASS)
|
||||||
|
.unwrap();
|
||||||
|
}
|
||||||
|
let pipeline = build_pbr_pipeline(&mut world.get_resource_mut::<Assets<Shader>>().unwrap());
|
||||||
|
let mut pipelines = world
|
||||||
|
.get_resource_mut::<Assets<PipelineDescriptor>>()
|
||||||
|
.unwrap();
|
||||||
|
pipelines.set_untracked(PBR_PIPELINE_HANDLE, pipeline);
|
||||||
|
}
|
Loading…
Reference in a new issue