need changes
Merge branch 'main' into toolbar
BIN
assets/images/pixelart/Flashlight_click_0.png
Normal file
|
After Width: | Height: | Size: 14 KiB |
BIN
assets/images/pixelart/Flashlight_click_1.png
Normal file
|
After Width: | Height: | Size: 11 KiB |
BIN
assets/images/pixelart/Flashlight_click_2.png
Normal file
|
After Width: | Height: | Size: 14 KiB |
BIN
assets/images/pixelart/Flashlight_click_3.png
Normal file
|
After Width: | Height: | Size: 14 KiB |
BIN
assets/images/pixelart/Flashlight_click_4.png
Normal file
|
After Width: | Height: | Size: 14 KiB |
BIN
assets/images/pixelart/Flashlight_hold_0.png
Normal file
|
After Width: | Height: | Size: 14 KiB |
BIN
assets/images/pixelart/Flashlight_hold_1.png
Normal file
|
After Width: | Height: | Size: 14 KiB |
BIN
assets/images/pixelart/Flashlight_hold_2.png
Normal file
|
After Width: | Height: | Size: 14 KiB |
BIN
assets/images/pixelart/Flashlight_hold_3.png
Normal file
|
After Width: | Height: | Size: 14 KiB |
BIN
assets/images/pixelart/Flashlight_hold_4.png
Normal file
|
After Width: | Height: | Size: 14 KiB |
@@ -1,5 +1,6 @@
|
|||||||
({
|
({
|
||||||
"lebron": File (path: "images/KingLebron.png"),
|
"lebron": File (path: "images/KingLebron.png"),
|
||||||
|
"flash_hold_4": File (path: "images/pixelart/Flashlight_hold_4.png"),
|
||||||
"house": File (path: "meshes/House.glb"),
|
"house": File (path: "meshes/House.glb"),
|
||||||
"library": Folder (
|
"library": Folder (
|
||||||
path: "meshes/library",
|
path: "meshes/library",
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ pub(super) fn plugin(app: &mut App) {
|
|||||||
.continue_to_state(GameState::Menu)
|
.continue_to_state(GameState::Menu)
|
||||||
.with_dynamic_assets_file::<StandardDynamicAssetCollection>("main.assets.ron")
|
.with_dynamic_assets_file::<StandardDynamicAssetCollection>("main.assets.ron")
|
||||||
.load_collection::<ImageAssets>()
|
.load_collection::<ImageAssets>()
|
||||||
|
.load_collection::<FlashlightAssets>()
|
||||||
.load_collection::<GltfAssets>(),
|
.load_collection::<GltfAssets>(),
|
||||||
// .load_collection::<AudioAssets>()
|
// .load_collection::<AudioAssets>()
|
||||||
// .load_collection::<TextureAssets>()
|
// .load_collection::<TextureAssets>()
|
||||||
@@ -48,3 +49,9 @@ pub(crate) struct ImageAssets {
|
|||||||
#[asset(key = "lebron")]
|
#[asset(key = "lebron")]
|
||||||
pub(crate) king: Handle<Image>,
|
pub(crate) king: Handle<Image>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(AssetCollection, Resource, Clone)]
|
||||||
|
pub(crate) struct FlashlightAssets {
|
||||||
|
#[asset(key = "flash_hold_4")]
|
||||||
|
pub(crate) flash_hold_4: Handle<Image>,
|
||||||
|
}
|
||||||
|
|||||||
8
src/debugging.rs
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
use bevy::{app::App, diagnostic::FrameTimeDiagnosticsPlugin};
|
||||||
|
use bevy::diagnostic::LogDiagnosticsPlugin;
|
||||||
|
|
||||||
|
|
||||||
|
pub fn plugin(app: &mut App) {
|
||||||
|
app.add_plugins(FrameTimeDiagnosticsPlugin::default());
|
||||||
|
app.add_plugins(LogDiagnosticsPlugin::default());
|
||||||
|
}
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
use bevy::{gltf::GltfMesh, math::Vec3A, prelude::*, render::mesh::MeshAabb};
|
use bevy::{prelude::*};
|
||||||
use bevy_rapier3d::prelude::{Collider, RigidBody};
|
use bevy_rapier3d::prelude::{Collider, RigidBody};
|
||||||
|
|
||||||
use crate::{GameState, asset_loading::GltfAssets};
|
use crate::{GameState, asset_loading::GltfAssets};
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
use bevy::prelude::*;
|
use bevy::prelude::*;
|
||||||
|
use bevy_rapier3d::prelude::{Collider, RigidBody};
|
||||||
|
|
||||||
use crate::{asset_loading::GltfAssets, GameState};
|
use crate::{asset_loading::GltfAssets, GameState};
|
||||||
|
|
||||||
@@ -12,14 +13,84 @@ fn spawn_level(
|
|||||||
gltf_assets: Res<GltfAssets>
|
gltf_assets: Res<GltfAssets>
|
||||||
) {
|
) {
|
||||||
println!("LIBRARY: {:?}", gltf_assets.library);
|
println!("LIBRARY: {:?}", gltf_assets.library);
|
||||||
let mut x_offset = 0.0;
|
let mesh_names = ["corner_inside", "corner_outside", "wall", "door", "round_door", "round_hole"];
|
||||||
for mesh_name in ["corner_inside", "corner_outside", "wall", "door", "round_door", "round_hole"] {
|
let shapes = mesh_names.map(|mesh_name| {
|
||||||
|
let collider: Vec<(Collider, Transform)> = match mesh_name {
|
||||||
|
"corner_inside" => vec![
|
||||||
|
(Collider::cuboid(1.0, 0.1, 1.0), Transform::from_xyz(0.0, 0.0, 0.0))
|
||||||
|
],
|
||||||
|
"corner_outside" => vec![
|
||||||
|
(Collider::cuboid(1.0, 0.1, 1.0), Transform::from_xyz(0.0, 0.0, 0.0))
|
||||||
|
],
|
||||||
|
"wall" => vec![
|
||||||
|
(Collider::cuboid(1.0, 1.0, 0.1), Transform::from_xyz(0.0, 0.5, -1.0))
|
||||||
|
],
|
||||||
|
"door" => vec![
|
||||||
|
(Collider::cuboid(1.0, 0.1, 1.0), Transform::from_xyz(0.0, 0.0, 0.0))
|
||||||
|
],
|
||||||
|
"round_door" => vec![
|
||||||
|
(Collider::cuboid(1.0, 0.1, 1.0), Transform::from_xyz(0.0, 0.0, 0.0))
|
||||||
|
],
|
||||||
|
"round_hole" => vec![
|
||||||
|
(Collider::cuboid(1.0, 0.1, 1.0), Transform::from_xyz(0.0, 0.0, 0.0))
|
||||||
|
],
|
||||||
|
_ => vec![
|
||||||
|
(Collider::cuboid(1.0, 0.1, 1.0), Transform::from_xyz(0.0, 0.0, 0.0))
|
||||||
|
],
|
||||||
|
};
|
||||||
let path = format!("meshes/library/space_{}.glb", mesh_name);
|
let path = format!("meshes/library/space_{}.glb", mesh_name);
|
||||||
let handle = gltf_assets.library.get(&path).expect(&format!("Couldn't find {} in library", mesh_name));
|
let handle = gltf_assets.library.get(&path).expect(&format!("Couldn't find {} in library", mesh_name));
|
||||||
let gltf = models.get(handle).expect(&format!("No model for {}", mesh_name));
|
let gltf = models.get(handle).expect(&format!("No model for {}", mesh_name));
|
||||||
|
|
||||||
let asset = gltf.default_scene.as_ref().expect(&format!("No scene in {}", mesh_name));
|
let asset = gltf.default_scene.as_ref().expect(&format!("No scene in {}", mesh_name));
|
||||||
commands.spawn((SceneRoot(asset.clone()), TransformBundle::from_transform(Transform::from_xyz(x_offset, 0.0, 0.0))));
|
(SceneRoot(asset.clone()), collider)
|
||||||
x_offset += 2.0;
|
});
|
||||||
|
let [
|
||||||
|
corner_inside,
|
||||||
|
corner_outside,
|
||||||
|
wall,
|
||||||
|
door,
|
||||||
|
round_door,
|
||||||
|
round_hole
|
||||||
|
] = shapes;
|
||||||
|
for i in 0..30 {
|
||||||
|
commands.spawn((
|
||||||
|
wall.0.clone(),
|
||||||
|
Transform::from_xyz(i as f32 * 2.0, 0.0, 0.0),
|
||||||
|
)).with_children(|parent| {
|
||||||
|
for ele in wall.1.clone() {
|
||||||
|
parent.spawn((
|
||||||
|
RigidBody::Fixed,
|
||||||
|
ele.0,
|
||||||
|
ele.1,
|
||||||
|
));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
commands.spawn((
|
||||||
|
wall.0.clone(),
|
||||||
|
Transform::from_xyz(i as f32 * 2.0, 0.0, 0.0)
|
||||||
|
.with_rotation(Quat::from_rotation_y(std::f32::consts::PI)),
|
||||||
|
)).with_children(|parent| {
|
||||||
|
for ele in wall.1.clone() {
|
||||||
|
parent.spawn((
|
||||||
|
RigidBody::Fixed,
|
||||||
|
ele.0,
|
||||||
|
ele.1,
|
||||||
|
));
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// huge floor
|
||||||
|
commands.spawn((
|
||||||
|
RigidBody::Fixed,
|
||||||
|
Collider::cuboid(1000.0, 0.1, 1000.0),
|
||||||
|
Transform::from_xyz(-500.0, 0.0, -500.0),
|
||||||
|
));
|
||||||
|
commands.spawn((
|
||||||
|
RigidBody::Fixed,
|
||||||
|
Collider::cuboid(1000.0, 0.1, 1000.0),
|
||||||
|
Transform::from_xyz(-500.0, 3.0, -500.0),
|
||||||
|
));
|
||||||
}
|
}
|
||||||
|
|||||||
15
src/main.rs
@@ -1,5 +1,5 @@
|
|||||||
use asset_loading::ImageAssets;
|
use asset_loading::ImageAssets;
|
||||||
use bevy::prelude::*;
|
use bevy::{prelude::*};
|
||||||
use bevy_rapier3d::prelude::*;
|
use bevy_rapier3d::prelude::*;
|
||||||
|
|
||||||
mod asset_loading;
|
mod asset_loading;
|
||||||
@@ -9,6 +9,7 @@ mod level_instantiation;
|
|||||||
mod main_menu;
|
mod main_menu;
|
||||||
mod player;
|
mod player;
|
||||||
mod util;
|
mod util;
|
||||||
|
mod debugging;
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
App::new()
|
App::new()
|
||||||
@@ -17,10 +18,11 @@ fn main() {
|
|||||||
asset_loading::plugin,
|
asset_loading::plugin,
|
||||||
main_menu::plugin,
|
main_menu::plugin,
|
||||||
level_instantiation::map_plugin,
|
level_instantiation::map_plugin,
|
||||||
player::plugin,
|
|
||||||
interaction::plugin,
|
interaction::plugin,
|
||||||
RapierPhysicsPlugin::<NoUserData>::default(),
|
RapierPhysicsPlugin::<NoUserData>::default(),
|
||||||
RapierDebugRenderPlugin::default(),
|
RapierDebugRenderPlugin::default(),
|
||||||
|
player::plugin,
|
||||||
|
debugging::plugin
|
||||||
))
|
))
|
||||||
.init_state::<GameState>()
|
.init_state::<GameState>()
|
||||||
.add_systems(OnEnter(GameState::Playing), setup)
|
.add_systems(OnEnter(GameState::Playing), setup)
|
||||||
@@ -38,19 +40,16 @@ enum GameState {
|
|||||||
Menu,
|
Menu,
|
||||||
}
|
}
|
||||||
|
|
||||||
fn debug_our_king(mut commands: Commands, images: Res<ImageAssets>) {
|
|
||||||
commands.spawn(Sprite::from_image(images.king.clone()));
|
|
||||||
}
|
|
||||||
|
|
||||||
fn setup(
|
fn setup(
|
||||||
mut commands: Commands,
|
mut commands: Commands,
|
||||||
mut meshes: ResMut<Assets<Mesh>>,
|
mut meshes: ResMut<Assets<Mesh>>,
|
||||||
mut materials: ResMut<Assets<StandardMaterial>>,
|
mut materials: ResMut<Assets<StandardMaterial>>,
|
||||||
|
image: Res<ImageAssets>
|
||||||
) {
|
) {
|
||||||
// circular base
|
// circular base
|
||||||
commands.spawn((
|
commands.spawn((
|
||||||
Mesh3d(meshes.add(Circle::new(4.0))),
|
Mesh3d(meshes.add(Circle::new(4.0))),
|
||||||
MeshMaterial3d(materials.add(Color::WHITE)),
|
MeshMaterial3d(materials.add(image.king.clone())),
|
||||||
Transform::from_rotation(Quat::from_rotation_x(-std::f32::consts::FRAC_PI_2)),
|
Transform::from_rotation(Quat::from_rotation_x(-std::f32::consts::FRAC_PI_2)),
|
||||||
));
|
));
|
||||||
commands.spawn((RigidBody::Fixed, Collider::cylinder(0.1, 4.0)));
|
commands.spawn((RigidBody::Fixed, Collider::cylinder(0.1, 4.0)));
|
||||||
@@ -58,7 +57,7 @@ fn setup(
|
|||||||
commands.spawn((
|
commands.spawn((
|
||||||
Mesh3d(meshes.add(Cuboid::new(1.0, 1.0, 1.0))),
|
Mesh3d(meshes.add(Cuboid::new(1.0, 1.0, 1.0))),
|
||||||
MeshMaterial3d(materials.add(Color::srgb_u8(124, 144, 255))),
|
MeshMaterial3d(materials.add(Color::srgb_u8(124, 144, 255))),
|
||||||
Transform::from_xyz(3.0, 0.5, 0.0),
|
Transform::from_xyz(-3.0, 0.5, 0.0),
|
||||||
RigidBody::Fixed,
|
RigidBody::Fixed,
|
||||||
Collider::cuboid(0.5, 0.5, 0.5),
|
Collider::cuboid(0.5, 0.5, 0.5),
|
||||||
));
|
));
|
||||||
|
|||||||
238
src/player.rs
@@ -1,29 +1,18 @@
|
|||||||
|
|
||||||
use bevy::{
|
use bevy::{
|
||||||
input::mouse::AccumulatedMouseMotion, pbr::NotShadowCaster, prelude::*,
|
input::mouse::AccumulatedMouseMotion, prelude::*, render::view::RenderLayers, window::{PrimaryWindow, WindowResized}
|
||||||
render::view::RenderLayers, window::PrimaryWindow,
|
|
||||||
};
|
};
|
||||||
use bevy_rapier3d::prelude::*;
|
use bevy_rapier3d::prelude::*;
|
||||||
|
|
||||||
use crate::GameState;
|
pub mod toolbar;
|
||||||
|
|
||||||
mod toolbar;
|
use crate::{asset_loading::FlashlightAssets, GameState};
|
||||||
|
|
||||||
pub fn plugin(app: &mut App) {
|
#[derive(Debug, Component, Default)]
|
||||||
app.add_plugins(toolbar::plugin)
|
pub struct Player {
|
||||||
.add_systems(OnEnter(GameState::Playing), (init_player, hide_cursor))
|
pub speed_factor: f32,
|
||||||
.add_systems(
|
|
||||||
Update,
|
|
||||||
(move_camera, handle_input).run_if(in_state(GameState::Playing)),
|
|
||||||
)
|
|
||||||
.add_systems(
|
|
||||||
FixedUpdate,
|
|
||||||
apply_player_movement.run_if(in_state(GameState::Playing)),
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Component)]
|
|
||||||
pub struct Player;
|
|
||||||
|
|
||||||
#[derive(Debug, Component, Deref, DerefMut)]
|
#[derive(Debug, Component, Deref, DerefMut)]
|
||||||
pub struct CameraSensitivity(Vec2);
|
pub struct CameraSensitivity(Vec2);
|
||||||
impl Default for CameraSensitivity {
|
impl Default for CameraSensitivity {
|
||||||
@@ -33,31 +22,64 @@ impl Default for CameraSensitivity {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Component)]
|
#[derive(Debug, Component)]
|
||||||
struct WorldModelCamera;
|
pub struct WorldModelCamera;
|
||||||
|
|
||||||
#[derive(Debug, Component, Default)]
|
#[derive(Debug, Component, Default)]
|
||||||
pub struct PlayerInput {
|
pub struct PlayerInput {
|
||||||
movement_direction: Vec3,
|
movement_direction: Vec3,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// used by the view model camera and the player's arm.
|
#[derive(Component, Debug)]
|
||||||
|
pub struct HeadBob {
|
||||||
|
pub enabled: bool,
|
||||||
|
pub intensity: f32,
|
||||||
|
pub speed: f32,
|
||||||
|
pub time_offset: f32,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for HeadBob {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self {
|
||||||
|
enabled: true,
|
||||||
|
intensity: 0.05,
|
||||||
|
speed: 10.0,
|
||||||
|
time_offset: 0.0,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Component, Debug)]
|
||||||
|
pub struct BaseTransform(pub Transform);
|
||||||
|
|
||||||
|
pub fn plugin(app: &mut App) {
|
||||||
|
app.add_plugins(toolbar::plugin)
|
||||||
|
.add_systems(OnEnter(GameState::Playing), (init_player, hide_cursor))
|
||||||
|
.add_systems(
|
||||||
|
Update,
|
||||||
|
(move_camera, handle_input, apply_head_bob, on_resize_system).run_if(in_state(GameState::Playing)),
|
||||||
|
)
|
||||||
|
.add_systems(
|
||||||
|
FixedUpdate,
|
||||||
|
apply_player_movement.run_if(in_state(GameState::Playing)),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// used by the view model camera and the player's arm.
|
||||||
const STATIC_LAYER: usize = 1;
|
const STATIC_LAYER: usize = 1;
|
||||||
|
|
||||||
pub fn init_player(
|
pub fn init_player(
|
||||||
mut commands: Commands,
|
mut commands: Commands,
|
||||||
mut meshes: ResMut<Assets<Mesh>>,
|
flashlights: Res<FlashlightAssets>,
|
||||||
mut materials: ResMut<Assets<StandardMaterial>>,
|
window: Query<&Window>,
|
||||||
) {
|
) {
|
||||||
let arm = meshes.add(Cuboid::new(0.1, 0.1, 0.5));
|
|
||||||
let arm_material = materials.add(Color::WHITE);
|
|
||||||
|
|
||||||
commands
|
commands
|
||||||
.spawn((
|
.spawn((
|
||||||
Player,
|
Player::default(),
|
||||||
PlayerAction::default(),
|
PlayerAction::default(),
|
||||||
CameraSensitivity::default(),
|
CameraSensitivity::default(),
|
||||||
PlayerInput::default(),
|
PlayerInput::default(),
|
||||||
toolbar::Item::none(),
|
toolbar::Item::none(),
|
||||||
|
HeadBob::default(),
|
||||||
// rapier
|
// rapier
|
||||||
RigidBody::Dynamic,
|
RigidBody::Dynamic,
|
||||||
Collider::capsule(Vec3::new(0.0, -0.5, 0.0), Vec3::new(0.0, 0.5, 0.0), 0.5),
|
Collider::capsule(Vec3::new(0.0, -0.5, 0.0), Vec3::new(0.0, 0.5, 0.0), 0.5),
|
||||||
@@ -68,10 +90,7 @@ pub fn init_player(
|
|||||||
angular_damping: 1.0,
|
angular_damping: 1.0,
|
||||||
},
|
},
|
||||||
GravityScale(3.0),
|
GravityScale(3.0),
|
||||||
Transform::from_xyz(0.0, 1.0, 0.0),
|
Transform::from_xyz(0.0, 0.5, 0.0),
|
||||||
GlobalTransform::default(),
|
|
||||||
InheritedVisibility::default(),
|
|
||||||
ViewVisibility::default(),
|
|
||||||
))
|
))
|
||||||
.with_children(|parent| {
|
.with_children(|parent| {
|
||||||
parent.spawn((
|
parent.spawn((
|
||||||
@@ -81,47 +100,57 @@ pub fn init_player(
|
|||||||
fov: 90.0_f32.to_radians(),
|
fov: 90.0_f32.to_radians(),
|
||||||
..default()
|
..default()
|
||||||
}),
|
}),
|
||||||
Transform::default(),
|
|
||||||
GlobalTransform::default(),
|
|
||||||
Visibility::default(),
|
|
||||||
InheritedVisibility::default(),
|
|
||||||
ViewVisibility::default(),
|
|
||||||
));
|
));
|
||||||
|
|
||||||
// camera voor pitslampke
|
// camera voor pitslampke
|
||||||
parent.spawn((
|
parent.spawn((
|
||||||
Camera3d::default(),
|
Camera2d::default(),
|
||||||
Camera {
|
Camera {
|
||||||
order: 1,
|
order: 1,
|
||||||
..default()
|
..default()
|
||||||
},
|
},
|
||||||
Projection::from(PerspectiveProjection {
|
|
||||||
fov: 70.0_f32.to_radians(),
|
|
||||||
..default()
|
|
||||||
}),
|
|
||||||
RenderLayers::layer(STATIC_LAYER),
|
RenderLayers::layer(STATIC_LAYER),
|
||||||
Transform::default(),
|
|
||||||
GlobalTransform::default(),
|
|
||||||
Visibility::default(),
|
|
||||||
InheritedVisibility::default(),
|
|
||||||
ViewVisibility::default(),
|
|
||||||
));
|
));
|
||||||
|
|
||||||
// pitslampke
|
let window = window.single();
|
||||||
|
let transform = flashlight_base_transform(window.width(), window.height());
|
||||||
parent.spawn((
|
parent.spawn((
|
||||||
Mesh3d(arm),
|
Sprite::from_image(flashlights.flash_hold_4.clone()),
|
||||||
MeshMaterial3d(arm_material),
|
transform.0.clone(),
|
||||||
Transform::from_xyz(0.2, -0.1, -0.25),
|
transform,
|
||||||
GlobalTransform::default(),
|
|
||||||
RenderLayers::layer(STATIC_LAYER),
|
RenderLayers::layer(STATIC_LAYER),
|
||||||
NotShadowCaster,
|
|
||||||
Visibility::default(),
|
|
||||||
InheritedVisibility::default(),
|
|
||||||
ViewVisibility::default(),
|
|
||||||
));
|
));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn on_resize_system(
|
||||||
|
mut resize_reader: EventReader<WindowResized>,
|
||||||
|
mut sprites: Query<(&mut Transform, &mut BaseTransform), With<Sprite>>,
|
||||||
|
) {
|
||||||
|
for e in resize_reader.read() {
|
||||||
|
for (mut transform, mut base_transform) in sprites.iter_mut() {
|
||||||
|
let new_pos = flashlight_base_transform(e.width, e.height);
|
||||||
|
*transform = new_pos.0.clone();
|
||||||
|
*base_transform = new_pos;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn flashlight_base_transform(window_width: f32, window_height: f32) -> BaseTransform {
|
||||||
|
let window_size = Vec2::new(window_width, window_height);
|
||||||
|
let sprite_size = Vec2::new(101.0, 101.0);
|
||||||
|
let scale = window_width / 600.0;
|
||||||
|
let world_size = sprite_size * scale;
|
||||||
|
let xoffset = window_size.x / 4.0 - 40.0;
|
||||||
|
let yoffset = 15.0;
|
||||||
|
|
||||||
|
let mut transform = Transform::from_translation(
|
||||||
|
Vec3::new(window_size.x / 2.0 - world_size.x / 2.0 - xoffset, -window_size.y / 2.0 + world_size.y / 2.0 - yoffset, 0.0)
|
||||||
|
);
|
||||||
|
transform.scale = Vec3::new(scale, scale, 1.0);
|
||||||
|
return BaseTransform(transform);
|
||||||
|
}
|
||||||
|
|
||||||
fn hide_cursor(mut windows: Query<&mut Window, With<PrimaryWindow>>) {
|
fn hide_cursor(mut windows: Query<&mut Window, With<PrimaryWindow>>) {
|
||||||
for mut window in windows.iter_mut() {
|
for mut window in windows.iter_mut() {
|
||||||
window.cursor_options.visible = false;
|
window.cursor_options.visible = false;
|
||||||
@@ -157,13 +186,14 @@ pub(crate) enum PlayerAction {
|
|||||||
Sprint,
|
Sprint,
|
||||||
Jump,
|
Jump,
|
||||||
Interact,
|
Interact,
|
||||||
|
ToggleFlashlight
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn handle_input(
|
pub fn handle_input(
|
||||||
keyboard_input: Res<ButtonInput<KeyCode>>,
|
keyboard_input: Res<ButtonInput<KeyCode>>,
|
||||||
mut query: Query<(&Transform, &mut PlayerInput, &mut PlayerAction), With<Player>>,
|
mut query: Query<(&Transform, &mut PlayerInput, &mut PlayerAction, &mut Player), With<Player>>,
|
||||||
) {
|
) {
|
||||||
for (transform, mut input, mut action) in query.iter_mut() {
|
for (transform, mut input, mut action, mut player) in query.iter_mut() {
|
||||||
let forward = transform.forward();
|
let forward = transform.forward();
|
||||||
let right = transform.right();
|
let right = transform.right();
|
||||||
let mut movement_direction = Vec3::ZERO;
|
let mut movement_direction = Vec3::ZERO;
|
||||||
@@ -184,25 +214,34 @@ pub fn handle_input(
|
|||||||
movement_direction += Vec3::Y;
|
movement_direction += Vec3::Y;
|
||||||
}
|
}
|
||||||
if keyboard_input.pressed(KeyCode::ShiftLeft) {
|
if keyboard_input.pressed(KeyCode::ShiftLeft) {
|
||||||
movement_direction -= Vec3::Y;
|
player.speed_factor = 1.35;
|
||||||
|
*action = PlayerAction::Sprint
|
||||||
|
} else if keyboard_input.pressed(KeyCode::ControlLeft) {
|
||||||
|
player.speed_factor = 0.65;
|
||||||
|
} else {
|
||||||
|
player.speed_factor = 1.0;
|
||||||
}
|
}
|
||||||
if keyboard_input.pressed(KeyCode::KeyE) {
|
if keyboard_input.pressed(KeyCode::KeyE) {
|
||||||
*action = PlayerAction::Interact
|
*action = PlayerAction::Interact
|
||||||
}
|
}
|
||||||
|
if keyboard_input.pressed(KeyCode::KeyA) {
|
||||||
|
*action = PlayerAction::ToggleFlashlight;
|
||||||
|
}
|
||||||
|
|
||||||
input.movement_direction = movement_direction.normalize_or_zero();
|
input.movement_direction = movement_direction.normalize_or_zero();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn apply_player_movement(mut player_query: Query<(&PlayerInput, &mut Velocity), With<Player>>) {
|
pub fn apply_player_movement(mut player_query: Query<(&PlayerInput, &mut Velocity, &Player), With<Player>>) {
|
||||||
const SPEED: f32 = 3.0;
|
const SPEED: f32 = 2.6;
|
||||||
const JUMP_FORCE: f32 = 4.0;
|
const JUMP_FORCE: f32 = 4.0;
|
||||||
|
|
||||||
for (input, mut velocity) in player_query.iter_mut() {
|
for (input, mut velocity, player) in player_query.iter_mut() {
|
||||||
|
let speed = SPEED * player.speed_factor;
|
||||||
let horizontal_movement = Vec3::new(
|
let horizontal_movement = Vec3::new(
|
||||||
input.movement_direction.x * SPEED,
|
input.movement_direction.x * speed,
|
||||||
0.0,
|
0.0,
|
||||||
input.movement_direction.z * SPEED,
|
input.movement_direction.z * speed,
|
||||||
);
|
);
|
||||||
|
|
||||||
velocity.linvel.x = horizontal_movement.x;
|
velocity.linvel.x = horizontal_movement.x;
|
||||||
@@ -210,8 +249,75 @@ pub fn apply_player_movement(mut player_query: Query<(&PlayerInput, &mut Velocit
|
|||||||
|
|
||||||
if input.movement_direction.y > 0.0 {
|
if input.movement_direction.y > 0.0 {
|
||||||
velocity.linvel.y = JUMP_FORCE;
|
velocity.linvel.y = JUMP_FORCE;
|
||||||
} else if input.movement_direction.y < 0.0 {
|
}
|
||||||
velocity.linvel.y = -SPEED;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn apply_head_bob(
|
||||||
|
time: Res<Time>,
|
||||||
|
mut query: Query<(&PlayerInput, &mut HeadBob, &Player), With<Player>>,
|
||||||
|
mut camera_query: Query<&mut Transform, (With<WorldModelCamera>, Without<Player>)>,
|
||||||
|
mut sprite_query: Query<(&mut Transform, &Sprite, &BaseTransform), (With<Sprite>, Without<WorldModelCamera>, Without<Player>)>,
|
||||||
|
) {
|
||||||
|
let Ok((input, mut head_bob, player)) = query.get_single_mut() else {
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
|
||||||
|
// bob when moving horizontally
|
||||||
|
let horizontal_movement = Vec3::new(input.movement_direction.x, 0.0, input.movement_direction.z);
|
||||||
|
let is_moving = horizontal_movement.length_squared() > 0.01;
|
||||||
|
let bobbing_speed = head_bob.speed * player.speed_factor;
|
||||||
|
|
||||||
|
let mut offset = bobbing_speed * time.delta_secs();
|
||||||
|
if !is_moving {
|
||||||
|
// decrease bobbing frequency when stationary
|
||||||
|
offset *= 0.2;
|
||||||
|
|
||||||
|
// bob returns to neutral position when stopped
|
||||||
|
if let Some(camera_transform) = camera_query.iter_mut().next() {
|
||||||
|
let current_offset = camera_transform.translation.y;
|
||||||
|
if current_offset.abs() < 0.005 {
|
||||||
|
// cancel out so head_bob.time_offset
|
||||||
|
offset = -head_bob.time_offset;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
head_bob.time_offset += offset;
|
||||||
|
|
||||||
|
if head_bob.enabled {
|
||||||
|
// calculate vertical and horizontal offsets using sine and cosine
|
||||||
|
let vertical_offset = head_bob.intensity * f32::sin(head_bob.time_offset);
|
||||||
|
let horizontal_offset = (head_bob.intensity * 0.5) * f32::cos(head_bob.time_offset * 0.5);
|
||||||
|
|
||||||
|
// apply
|
||||||
|
for mut transform in camera_query.iter_mut() {
|
||||||
|
transform.translation.y = vertical_offset;
|
||||||
|
if is_moving {
|
||||||
|
transform.translation.x = horizontal_offset;
|
||||||
|
} else {
|
||||||
|
// decrease bobbing magnitued
|
||||||
|
transform.translation.x *= 0.8;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// apply offsets to flashlight
|
||||||
|
for (mut transform, _sprite, base_transform) in sprite_query.iter_mut() {
|
||||||
|
let scale_factor = 40.0 * player.speed_factor;
|
||||||
|
|
||||||
|
if is_moving {
|
||||||
|
transform.translation.x = base_transform.0.translation.x + horizontal_offset * scale_factor;
|
||||||
|
transform.translation.y = base_transform.0.translation.y + vertical_offset * scale_factor;
|
||||||
|
|
||||||
|
transform.rotation = Quat::from_euler(
|
||||||
|
EulerRot::XYZ,
|
||||||
|
0.0,
|
||||||
|
0.0,
|
||||||
|
horizontal_offset * 0.1,
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
transform.translation = transform.translation.lerp(base_transform.0.translation, 0.1);
|
||||||
|
transform.rotation = transform.rotation.slerp(Quat::IDENTITY, 0.1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||