feat: add basic player movement

Former-commit-id: 5efbf1711d0021bb86ec96b01419c43d5ca839e8
This commit is contained in:
Muhammad Nauman Raza 2023-12-04 21:02:59 +00:00
parent 6c12d4d5d6
commit 458689d9ce
Signed by: devraza
GPG key ID: 91EAD6081011574B
4 changed files with 148 additions and 13 deletions

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5 KiB

BIN
assets/player/player.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 397 B

68
assets/player/player.svg Normal file
View file

@ -0,0 +1,68 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
width="32"
height="40"
viewBox="0 0 8.4666665 10.583333"
version="1.1"
id="svg1"
inkscape:export-filename="player.png"
inkscape:export-xdpi="96"
inkscape:export-ydpi="96"
inkscape:version="1.3.1 (91b66b0783, 2023-11-16)"
sodipodi:docname="player.svg"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg">
<sodipodi:namedview
id="namedview1"
pagecolor="#ffffff"
bordercolor="#000000"
borderopacity="0.25"
inkscape:showpageshadow="2"
inkscape:pageopacity="0.0"
inkscape:pagecheckerboard="0"
inkscape:deskcolor="#d1d1d1"
inkscape:document-units="mm"
inkscape:zoom="8"
inkscape:cx="-11.9375"
inkscape:cy="24.75"
inkscape:window-width="2560"
inkscape:window-height="1080"
inkscape:window-x="0"
inkscape:window-y="0"
inkscape:window-maximized="1"
inkscape:current-layer="layer1" />
<defs
id="defs1" />
<g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1">
<rect
style="fill:#7ee6ae;fill-opacity:1;stroke:none;stroke-width:9.74117;stroke-opacity:0.434347"
id="rect1"
width="8.4666662"
height="8.4666662"
x="-2.220446e-16"
y="2.1166666" />
<path
sodipodi:type="star"
style="fill:#7ee6ae;fill-opacity:1;stroke:none;stroke-width:16.9333;stroke-opacity:0.434347"
id="path1"
inkscape:flatsided="true"
sodipodi:sides="3"
sodipodi:cx="3.3918092"
sodipodi:cy="0.56753963"
sodipodi:r1="2.674541"
sodipodi:r2="1.3372704"
sodipodi:arg1="-0.52359878"
sodipodi:arg2="0.52359878"
inkscape:rounded="0"
inkscape:randomized="0"
inkscape:transform-center-y="0.23402232"
transform="matrix(-1.8037062,0,0,-1,10.351161,3.2426846)" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 2.1 KiB

View file

@ -49,10 +49,11 @@ fn main() {
.init_resource::<UiState>()
.init_resource::<OpenWindows>()
.add_systems(Startup, (setup, setup_ui))
.add_systems(Update, render_ui)
.add_systems(Update, (render_ui, movement))
.run();
}
// Define UI resources
#[derive(Default, Resource)]
struct UiState {
username: String,
@ -64,6 +65,13 @@ struct OpenWindows {
login_open: bool,
}
// Define the player component
#[derive(Component)]
struct Player {
movement_speed: f32,
rotation_speed: f32,
}
// Bevy engine setup
fn setup(mut commands: Commands, asset_server: Res<AssetServer>) {
commands.spawn(Camera2dBundle {
@ -76,10 +84,13 @@ fn setup(mut commands: Commands, asset_server: Res<AssetServer>) {
});
commands.spawn((
SpriteBundle {
texture: asset_server.load("black-square.png"),
transform: Transform::from_xyz(100., 0., 0.),
texture: asset_server.load("player/player.png"),
..default()
}
},
Player {
movement_speed: 1024.,
rotation_speed: f32::to_radians(360.),
},
));
}
@ -99,13 +110,72 @@ fn setup_ui(mut contexts: EguiContexts) {
contexts.ctx_mut().set_fonts(fonts);
}
// Define the player movement system
fn movement(
time: Res<Time>,
keys: Res<Input<KeyCode>>,
mut windows: Query<&mut Window>,
mut query: Query<(&Player, &mut Transform)>,
) {
let (player, mut transform) = query.single_mut();
let mut rotation_factor = 0.;
let mut movement_factor = 0.;
let mut blink_factor = 0.;
if keys.pressed(KeyCode::W) {
movement_factor += 1.;
}
if keys.pressed(KeyCode::S) {
movement_factor -= 1.;
}
if keys.pressed(KeyCode::A) {
rotation_factor += 1.;
}
if keys.pressed(KeyCode::D) {
rotation_factor -= 1.;
}
if keys.pressed(KeyCode::Space) {
blink_factor += 4.;
}
if keys.pressed(KeyCode::Space) && keys.just_released(KeyCode::Right) {
blink_factor += 4.;
};
// Get the player's *forward* vector
let movement_direction = transform.rotation * Vec3::Y;
// Initialise the movement distance variable (to bring it into scope)
let movement_distance: f32;
if blink_factor == 0. {
movement_distance = movement_factor * player.movement_speed * time.delta_seconds();
// Change the player rotation around the Z-axis only if not blinking
transform.rotate_z(rotation_factor * player.rotation_speed * time.delta_seconds());
} else {
movement_distance = blink_factor * player.movement_speed * 0.1;
}
// Create the translation using the movement direction and distance
let translation_delta = movement_direction * movement_distance;
// Update the player translation with the created translation
transform.translation += translation_delta;
// Define the bounds of play (the window size)
let window = windows.single_mut();
let bounds = Vec3::from((
Vec2::new(window.resolution.width(), window.resolution.height()) / 2.,
0.,
));
transform.translation = transform.translation.min(bounds).max(-bounds);
}
// On update: render the UI
fn render_ui(
mut contexts: EguiContexts,
mut windows: Query<&mut Window>,
mut ui_state: ResMut<UiState>,
mut open_windows: ResMut<OpenWindows>,
asset_server: Res<AssetServer>,
keys: Res<Input<KeyCode>>,
) {
let window = windows.single_mut();
@ -114,11 +184,8 @@ fn render_ui(
let ctx = contexts.ctx_mut();
if keys.just_pressed(KeyCode::Space) {
}
if keys.pressed(KeyCode::W) {
}
if keys.just_pressed(KeyCode::Space) {}
if keys.pressed(KeyCode::W) {}
egui::Window::new("Login")
.anchor(egui::Align2::CENTER_CENTER, egui::Vec2::new(0., 0.))
@ -148,13 +215,13 @@ fn render_ui(
ui.add_space(window_height / 28.);
// The text inputs
let username = egui::TextEdit::singleline(&mut ui_state.username)
egui::TextEdit::singleline(&mut ui_state.username)
.hint_text("Username")
.margin(egui::vec2(10., 10.))
.desired_width(window_width / 4.)
.show(ui);
let password = egui::TextEdit::singleline(&mut ui_state.password)
egui::TextEdit::singleline(&mut ui_state.password)
.password(true)
.margin(egui::vec2(10., 10.))
.hint_text("Password")
@ -164,7 +231,7 @@ fn render_ui(
// Manually add some space between the text inputs and the 'confirm' button
ui.add_space(window_height / 26.);
let button = ui.add(egui::Button::new("Confirm").fill(black));
ui.add(egui::Button::new("Confirm").fill(black));
// Manually add some space between the button and the bottom border of the
// window...for scaling purposes