#Not a programmer.... Lots of questions

16 messages · Page 1 of 1 (latest)

median locust
#

well I'll start with this easy one.

==============================================================
fn camera_movement(
mut q_movement: Query<(&mut Transform), With<Camera>>,){

q_movement.translation // why do i NOT have access to the translation here???
}

fn camera_movement(
mut q_movement: Single<(&mut Transform), With<Camera>>,){

q_movement.translation // but i DO have access to the translation here.....
}

I thought that Single was just a Query that wouldn't run if it found more that one Camera.

in hind sight this probably wasn't the best language and game engine to start with, but here we are.

strong flare
#

(for future, use triple graves ``` to start and end a code block)

old folio
#

queries provide something called an “iterator”. it’s a list you can loop over

like for q_movement in q_movement_query.iter_mut()

singles expect only one value to exist in the entire world, and panic* if that isn’t true

*: configurable

median locust
#

Thanks. I will read that. I've been learning to code by myself and its been a slow grind.

south charm
median locust
late jolt
#

I will not help with rotation but as general advice, you can do let Ok(mut t) = q_camera.single_mut() else {return;}; on the first line of the function and use that one t everywhere, reducing the nesting and making the code more compact 🙂

old folio
#
  • remove time.delta_secs() from the rotation adjustments. it’s used for consistent movement amounts in keypress, but MouseMotions are just collected in a list each frame. we don’t care about limiting it to delta time, as players who rotate more in a 3d first-person game are not at any advantage or inconsistency
  • negate the input you stick in y (see: https://bevy-cheatbook.github.io/fundamentals/coords.html#ui
  • you might need to swap the x and y with mouse movement (busy now but can explain later, summary is that it’s a frame tf thing)

here’s a lil pseudocode to kinda show what I mean

for ev in mouse_events {
     rotation.x += ev.delta.y * sensitivity;
    rotation.y += -ev.delta.x * sensitivity;
}
#

lmk if this works, if not I’ll give a more thorough answer when time allows :)

#

oh, and pseudocode assumes rotation storage in radians. your rotate methods might work, haven’t tried them as my projects manually construct the quats for better consistency with my character controller

#

if it’s not working, ensure the input unit matches what the Transform::rotate_(…)` methods want

median locust
#

It does work better. my forward movement is still not relative to the cameras direction but instead whatever was forward when it spawned in.

#

i had it working once... i have to go find what i did before. i put like a .forward() somewhere but i just did it because i saw somebody else do it and i cant remember how or where it went.

old folio
#

@median locust ok i got time lol, here's a working version :D

use bevy::{input::mouse::MouseMotion, prelude::*};

fn main() -> AppExit {
    let mut app: App = App::new();

    // add basic bevy plugins
    app.add_plugins(DefaultPlugins);

    // on startup, spawn the player and the floor
    app.add_systems(Startup, spawn_camera_and_floor);

    // each frame, adjust the player's camera view
    app.add_systems(Update, handle_player_look);

    app.run()
}

#[derive(Component)]
struct Player;

#[derive(Component)]
struct PlayerHead;

fn spawn_camera_and_floor(
    mut commands: Commands,
    mut materials: ResMut<Assets<StandardMaterial>>,
    mut meshes: ResMut<Assets<Mesh>>,
) {
    // spawn the player
    commands.spawn((
        Transform::default().with_translation(Vec3::ONE),
        Player,
        children![(PlayerHead, Camera3d::default())],
    ));

    // then, spawn the floor
    let plane = Plane3d::new(Vec3::new(0.0, 1.0, 0.0), Vec2::new(10.0, 10.0)).mesh();
    commands.spawn((
        Mesh3d(meshes.add(plane)),
        MeshMaterial3d(materials.add(Color::srgb(0.3, 0.5, 0.3))),
        Transform::default(),
    ));

    // and on the third `Commands::spawn` call, they said "let there be light"
    commands.spawn(AmbientLight {
        brightness: 200.0,
        ..Default::default()
    });
}

fn handle_player_look(
    mut rdr: EventReader<MouseMotion>,
    //
    // sooo... you might ask "paramset? what the fart is that??"
    //
    // good question!
    //
    // in Bevy, the internal engine holds entities and their attached data
    // (which are just components) together. a parent-child relationship like
    // this makes it hard to tell which transform you want.
    //
    // so, if you instead use the queries outside this set, bevy will panic
    // saying you might be accessing two Transforms at the same time.
    //
    // that'd break Rust's "XOR" mutability rules, so we use this "parameter
    // set" such that we only have the data when we need it. that's why those
    // extra curly brackets are down there - the "0th" param (player tf) drops,
    // then we can grab the "1st" param (head tf) afterward.
    mut param_set: ParamSet<(
        Single<&mut Transform, With<Player>>,
        Single<&mut Transform, With<PlayerHead>>,
    )>,
) {
    const SENS: f32 = 0.002;

    for ev in rdr.read() {
        // first, handle the player rotation (on the y axis, so x/side-to-side
        // movement)
        {
            let player_tf: &mut Mut<Transform> = &mut *param_set.p0();
            player_tf.rotate_y(-ev.delta.x * SENS);
        }

        // then, do the head rotation (x axis, so y/up-down movement)
        {
            let head_tf: &mut Mut<Transform> = &mut *param_set.p1();

            // note: local is important to avoid changing parent's rotation!
            head_tf.rotate_local_x(-ev.delta.y * SENS);

            // avoid having the player's head upside down by clamping the
            // up-down rotation.
            //
            // TODO: in my FPS game, I track rotation over time in another
            // component, clamping it as needed, then build the Quat manually
            //
            // you'll probably need something similar to do a clamp here.
        }
    }
}