diff --git a/assets/images/pixelart/Flashlight_click_0.png b/assets/images/pixelart/Flashlight_click_0.png new file mode 100644 index 0000000..0519c7e Binary files /dev/null and b/assets/images/pixelart/Flashlight_click_0.png differ diff --git a/assets/images/pixelart/Flashlight_click_1.png b/assets/images/pixelart/Flashlight_click_1.png new file mode 100644 index 0000000..8810341 Binary files /dev/null and b/assets/images/pixelart/Flashlight_click_1.png differ diff --git a/assets/images/pixelart/Flashlight_click_2.png b/assets/images/pixelart/Flashlight_click_2.png new file mode 100644 index 0000000..26adff5 Binary files /dev/null and b/assets/images/pixelart/Flashlight_click_2.png differ diff --git a/assets/images/pixelart/Flashlight_click_3.png b/assets/images/pixelart/Flashlight_click_3.png new file mode 100644 index 0000000..7945d8f Binary files /dev/null and b/assets/images/pixelart/Flashlight_click_3.png differ diff --git a/assets/images/pixelart/Flashlight_click_4.png b/assets/images/pixelart/Flashlight_click_4.png new file mode 100644 index 0000000..bd824d9 Binary files /dev/null and b/assets/images/pixelart/Flashlight_click_4.png differ diff --git a/assets/images/pixelart/Flashlight_hold_0.png b/assets/images/pixelart/Flashlight_hold_0.png new file mode 100644 index 0000000..d8d846d Binary files /dev/null and b/assets/images/pixelart/Flashlight_hold_0.png differ diff --git a/assets/images/pixelart/Flashlight_hold_1.png b/assets/images/pixelart/Flashlight_hold_1.png new file mode 100644 index 0000000..a299321 Binary files /dev/null and b/assets/images/pixelart/Flashlight_hold_1.png differ diff --git a/assets/images/pixelart/Flashlight_hold_2.png b/assets/images/pixelart/Flashlight_hold_2.png new file mode 100644 index 0000000..c177578 Binary files /dev/null and b/assets/images/pixelart/Flashlight_hold_2.png differ diff --git a/assets/images/pixelart/Flashlight_hold_3.png b/assets/images/pixelart/Flashlight_hold_3.png new file mode 100644 index 0000000..6c1ddd1 Binary files /dev/null and b/assets/images/pixelart/Flashlight_hold_3.png differ diff --git a/assets/images/pixelart/Flashlight_hold_4.png b/assets/images/pixelart/Flashlight_hold_4.png new file mode 100644 index 0000000..e3956a8 Binary files /dev/null and b/assets/images/pixelart/Flashlight_hold_4.png differ diff --git a/assets/main.assets.ron b/assets/main.assets.ron index 3b1df6a..a89d4f7 100644 --- a/assets/main.assets.ron +++ b/assets/main.assets.ron @@ -1,5 +1,6 @@ ({ "lebron": File (path: "images/KingLebron.png"), + "flash_hold_4": File (path: "images/pixelart/Flashlight_hold_4.png"), "house": File (path: "meshes/House.glb"), "library": Folder ( path: "meshes/library", diff --git a/assets/meshes/library/creepy_jumbo.glb b/assets/meshes/library/creepy_jumbo.glb deleted file mode 100644 index e8ef174..0000000 Binary files a/assets/meshes/library/creepy_jumbo.glb and /dev/null differ diff --git a/assets/meshes/library/space2.glb b/assets/meshes/library/space2.glb deleted file mode 100644 index 80b162a..0000000 Binary files a/assets/meshes/library/space2.glb and /dev/null differ diff --git a/assets/meshes/library/space_corner_inside.glb b/assets/meshes/library/space_corner_inside.glb index c7564f4..8102447 100644 Binary files a/assets/meshes/library/space_corner_inside.glb and b/assets/meshes/library/space_corner_inside.glb differ diff --git a/assets/meshes/library/space_corner_outside.glb b/assets/meshes/library/space_corner_outside.glb index 46e443b..07cf38b 100644 Binary files a/assets/meshes/library/space_corner_outside.glb and b/assets/meshes/library/space_corner_outside.glb differ diff --git a/assets/meshes/library/space_door.glb b/assets/meshes/library/space_door.glb index ea3f2e4..acabc1f 100644 Binary files a/assets/meshes/library/space_door.glb and b/assets/meshes/library/space_door.glb differ diff --git a/assets/meshes/library/space_round_door.glb b/assets/meshes/library/space_round_door.glb index 0c2da67..c0c8256 100644 Binary files a/assets/meshes/library/space_round_door.glb and b/assets/meshes/library/space_round_door.glb differ diff --git a/assets/meshes/library/space_round_hole.glb b/assets/meshes/library/space_round_hole.glb index 0f220bf..f309915 100644 Binary files a/assets/meshes/library/space_round_hole.glb and b/assets/meshes/library/space_round_hole.glb differ diff --git a/assets/meshes/library/space_wall.glb b/assets/meshes/library/space_wall.glb index 33ecba6..c955f08 100644 Binary files a/assets/meshes/library/space_wall.glb and b/assets/meshes/library/space_wall.glb differ diff --git a/assets/meshes/library/wall.glb b/assets/meshes/library/wall.glb deleted file mode 100644 index 2fcf23d..0000000 Binary files a/assets/meshes/library/wall.glb and /dev/null differ diff --git a/assets/space2.blend b/assets/space2.blend index 678d808..67cd602 100644 Binary files a/assets/space2.blend and b/assets/space2.blend differ diff --git a/src/asset_loading/mod.rs b/src/asset_loading/mod.rs index 1d248f7..f2ff0f8 100644 --- a/src/asset_loading/mod.rs +++ b/src/asset_loading/mod.rs @@ -14,6 +14,7 @@ pub(super) fn plugin(app: &mut App) { .continue_to_state(GameState::Menu) .with_dynamic_assets_file::("main.assets.ron") .load_collection::() + .load_collection::() .load_collection::(), // .load_collection::() // .load_collection::() @@ -48,3 +49,9 @@ pub(crate) struct ImageAssets { #[asset(key = "lebron")] pub(crate) king: Handle, } + +#[derive(AssetCollection, Resource, Clone)] +pub(crate) struct FlashlightAssets { + #[asset(key = "flash_hold_4")] + pub(crate) flash_hold_4: Handle, +} diff --git a/src/debugging.rs b/src/debugging.rs new file mode 100644 index 0000000..b49f8ca --- /dev/null +++ b/src/debugging.rs @@ -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()); +} diff --git a/src/interaction/objects.rs b/src/interaction/objects.rs index bcf6650..fefcdd1 100644 --- a/src/interaction/objects.rs +++ b/src/interaction/objects.rs @@ -1,4 +1,4 @@ -use bevy::{gltf::GltfMesh, math::Vec3A, prelude::*, render::mesh::MeshAabb}; +use bevy::{prelude::*}; use bevy_rapier3d::prelude::{Collider, RigidBody}; use crate::{GameState, asset_loading::GltfAssets}; diff --git a/src/level_instantiation/mod.rs b/src/level_instantiation/mod.rs index 84dcecd..30a92d9 100644 --- a/src/level_instantiation/mod.rs +++ b/src/level_instantiation/mod.rs @@ -1,4 +1,5 @@ use bevy::prelude::*; +use bevy_rapier3d::prelude::{Collider, RigidBody}; use crate::{asset_loading::GltfAssets, GameState}; @@ -12,14 +13,84 @@ fn spawn_level( gltf_assets: Res ) { println!("LIBRARY: {:?}", gltf_assets.library); - let mut x_offset = 0.0; - for mesh_name in ["corner_inside", "corner_outside", "wall", "door", "round_door", "round_hole"] { + let mesh_names = ["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 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 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)))); - x_offset += 2.0; + (SceneRoot(asset.clone()), collider) + }); + 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), + )); } diff --git a/src/main.rs b/src/main.rs index 15ff5f9..cf1bac4 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,5 +1,5 @@ use asset_loading::ImageAssets; -use bevy::prelude::*; +use bevy::{prelude::*}; use bevy_rapier3d::prelude::*; mod asset_loading; @@ -9,6 +9,7 @@ mod level_instantiation; mod main_menu; mod player; mod util; +mod debugging; fn main() { App::new() @@ -17,10 +18,11 @@ fn main() { asset_loading::plugin, main_menu::plugin, level_instantiation::map_plugin, - player::plugin, interaction::plugin, RapierPhysicsPlugin::::default(), RapierDebugRenderPlugin::default(), + player::plugin, + debugging::plugin )) .init_state::() .add_systems(OnEnter(GameState::Playing), setup) @@ -38,19 +40,16 @@ enum GameState { Menu, } -fn debug_our_king(mut commands: Commands, images: Res) { - commands.spawn(Sprite::from_image(images.king.clone())); -} - fn setup( mut commands: Commands, mut meshes: ResMut>, mut materials: ResMut>, + image: Res ) { // circular base commands.spawn(( 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)), )); commands.spawn((RigidBody::Fixed, Collider::cylinder(0.1, 4.0))); @@ -58,7 +57,7 @@ fn setup( commands.spawn(( Mesh3d(meshes.add(Cuboid::new(1.0, 1.0, 1.0))), 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, Collider::cuboid(0.5, 0.5, 0.5), )); diff --git a/src/player.rs b/src/player.rs index 31e2176..be909ac 100644 --- a/src/player.rs +++ b/src/player.rs @@ -1,29 +1,18 @@ + use bevy::{ - input::mouse::AccumulatedMouseMotion, pbr::NotShadowCaster, prelude::*, - render::view::RenderLayers, window::PrimaryWindow, + input::mouse::AccumulatedMouseMotion, prelude::*, render::view::RenderLayers, window::{PrimaryWindow, WindowResized} }; use bevy_rapier3d::prelude::*; -use crate::GameState; +pub mod toolbar; -mod toolbar; +use crate::{asset_loading::FlashlightAssets, GameState}; -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).run_if(in_state(GameState::Playing)), - ) - .add_systems( - FixedUpdate, - apply_player_movement.run_if(in_state(GameState::Playing)), - ); +#[derive(Debug, Component, Default)] +pub struct Player { + pub speed_factor: f32, } -#[derive(Debug, Component)] -pub struct Player; - #[derive(Debug, Component, Deref, DerefMut)] pub struct CameraSensitivity(Vec2); impl Default for CameraSensitivity { @@ -33,31 +22,64 @@ impl Default for CameraSensitivity { } #[derive(Debug, Component)] -struct WorldModelCamera; +pub struct WorldModelCamera; #[derive(Debug, Component, Default)] pub struct PlayerInput { 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; pub fn init_player( mut commands: Commands, - mut meshes: ResMut>, - mut materials: ResMut>, + flashlights: Res, + window: Query<&Window>, ) { - let arm = meshes.add(Cuboid::new(0.1, 0.1, 0.5)); - let arm_material = materials.add(Color::WHITE); - commands .spawn(( - Player, + Player::default(), PlayerAction::default(), CameraSensitivity::default(), PlayerInput::default(), toolbar::Item::none(), + HeadBob::default(), // rapier RigidBody::Dynamic, 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, }, GravityScale(3.0), - Transform::from_xyz(0.0, 1.0, 0.0), - GlobalTransform::default(), - InheritedVisibility::default(), - ViewVisibility::default(), + Transform::from_xyz(0.0, 0.5, 0.0), )) .with_children(|parent| { parent.spawn(( @@ -81,47 +100,57 @@ pub fn init_player( fov: 90.0_f32.to_radians(), ..default() }), - Transform::default(), - GlobalTransform::default(), - Visibility::default(), - InheritedVisibility::default(), - ViewVisibility::default(), )); // camera voor pitslampke parent.spawn(( - Camera3d::default(), + Camera2d::default(), Camera { order: 1, ..default() }, - Projection::from(PerspectiveProjection { - fov: 70.0_f32.to_radians(), - ..default() - }), 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(( - Mesh3d(arm), - MeshMaterial3d(arm_material), - Transform::from_xyz(0.2, -0.1, -0.25), - GlobalTransform::default(), + Sprite::from_image(flashlights.flash_hold_4.clone()), + transform.0.clone(), + transform, RenderLayers::layer(STATIC_LAYER), - NotShadowCaster, - Visibility::default(), - InheritedVisibility::default(), - ViewVisibility::default(), )); }); } +fn on_resize_system( + mut resize_reader: EventReader, + mut sprites: Query<(&mut Transform, &mut BaseTransform), With>, +) { + 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>) { for mut window in windows.iter_mut() { window.cursor_options.visible = false; @@ -157,13 +186,14 @@ pub(crate) enum PlayerAction { Sprint, Jump, Interact, + ToggleFlashlight } pub fn handle_input( keyboard_input: Res>, - mut query: Query<(&Transform, &mut PlayerInput, &mut PlayerAction), With>, + mut query: Query<(&Transform, &mut PlayerInput, &mut PlayerAction, &mut Player), With>, ) { - 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 right = transform.right(); let mut movement_direction = Vec3::ZERO; @@ -184,25 +214,34 @@ pub fn handle_input( movement_direction += Vec3::Y; } 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) { *action = PlayerAction::Interact } + if keyboard_input.pressed(KeyCode::KeyA) { + *action = PlayerAction::ToggleFlashlight; + } input.movement_direction = movement_direction.normalize_or_zero(); } } -pub fn apply_player_movement(mut player_query: Query<(&PlayerInput, &mut Velocity), With>) { - const SPEED: f32 = 3.0; +pub fn apply_player_movement(mut player_query: Query<(&PlayerInput, &mut Velocity, &Player), With>) { + const SPEED: f32 = 2.6; 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( - input.movement_direction.x * SPEED, + input.movement_direction.x * speed, 0.0, - input.movement_direction.z * SPEED, + input.movement_direction.z * speed, ); 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 { velocity.linvel.y = JUMP_FORCE; - } else if input.movement_direction.y < 0.0 { - velocity.linvel.y = -SPEED; - } + } } } + +pub fn apply_head_bob( + time: Res