feat: add basic player movement
Former-commit-id: 5efbf1711d0021bb86ec96b01419c43d5ca839e8
This commit is contained in:
parent
c1ac90fa97
commit
0205259454
Binary file not shown.
Before Width: | Height: | Size: 5 KiB |
BIN
assets/player/player.png
Normal file
BIN
assets/player/player.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 397 B |
68
assets/player/player.svg
Normal file
68
assets/player/player.svg
Normal 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 |
93
src/main.rs
93
src/main.rs
|
@ -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
|
||||
|
|
Reference in a new issue