Files
sailing/src/main.rs

143 lines
3.3 KiB
Rust
Raw Normal View History

2025-11-28 16:05:52 -05:00
use bevy::{prelude::*, sprite_render::Wireframe2dPlugin};
2025-11-27 19:49:04 -05:00
2025-11-28 10:16:58 -05:00
const MAX_SAILING_SPEED: f32 = 0.9;
const MAX_TURN_SPEED: f32 = 0.1;
#[derive(Component, Default)]
2025-11-27 19:49:04 -05:00
struct EntityPhysics {
x: f32,
y: f32,
speed: f32,
2025-11-28 10:16:58 -05:00
turn_speed: f32,
2025-11-27 19:49:04 -05:00
heading: f32,
}
2025-11-28 10:16:58 -05:00
#[derive(Component, Default)]
struct InputState {
x: f32,
y: f32,
}
2025-11-27 19:49:04 -05:00
fn main() {
let mut app = App::new();
2025-11-28 16:05:52 -05:00
app.add_plugins((DefaultPlugins, Wireframe2dPlugin::default()))
2025-11-27 19:49:04 -05:00
.add_systems(Startup, (hello_world, camera_setup, sprite_setup).chain())
.add_systems(Update, (handle_keys, player_physics).chain());
app.run();
}
fn hello_world() {
println!("Hello, world!");
}
fn camera_setup(mut clear_color: ResMut<ClearColor>, mut commands: Commands) {
2025-11-28 10:30:18 -05:00
*clear_color = ClearColor(Color::linear_rgb(0.1, 0.4, 0.7));
2025-11-27 19:49:04 -05:00
commands.spawn(Camera2d);
}
fn sprite_setup(assets: Res<AssetServer>, mut commands: Commands) {
2025-11-28 16:05:52 -05:00
let ship_sprite = assets.load("sprite-0001.png");
let sail_sprite = assets.load("sail.png");
commands
.spawn((
Sprite {
image: ship_sprite,
..default()
},
EntityPhysics::default(),
InputState::default(),
))
.with_child((
Sprite {
image: sail_sprite,
..default()
},
Transform {
translation: Vec3 {
x: 8.0,
y: 1.0,
z: 0.,
},
..default()
},
));
2025-11-27 19:49:04 -05:00
}
2025-11-28 10:16:58 -05:00
fn handle_keys(mut q_player: Query<&mut InputState>, keys: Res<ButtonInput<KeyCode>>) {
2025-11-27 19:49:04 -05:00
if keys.just_pressed(KeyCode::KeyQ) {
info!("Quit.");
}
2025-11-28 10:16:58 -05:00
let Ok(mut input) = q_player.single_mut() else {
2025-11-27 19:49:04 -05:00
return;
};
2025-11-28 10:16:58 -05:00
if keys.pressed(KeyCode::ArrowUp) {
input.y = 1.;
} else if keys.pressed(KeyCode::ArrowDown) {
input.y = -1.;
} else {
input.y = 0.;
2025-11-27 19:49:04 -05:00
}
2025-11-28 10:16:58 -05:00
if keys.pressed(KeyCode::ArrowRight) {
input.x = 1.;
} else if keys.pressed(KeyCode::ArrowLeft) {
input.x = -1.;
} else {
input.x = 0.;
2025-11-27 19:49:04 -05:00
}
}
2025-11-28 10:16:58 -05:00
fn player_physics(mut q_player: Query<(&InputState, &mut EntityPhysics, &mut Transform)>) {
let Ok((input, mut physics, mut transform)) = q_player.single_mut() else {
2025-11-27 19:49:04 -05:00
return;
};
2025-11-28 10:16:58 -05:00
if input.x < 0. {
physics.turn_speed -= 0.1;
} else if input.x > 0. {
physics.turn_speed += 0.1;
2025-11-28 10:30:18 -05:00
} else {
physics.turn_speed *= 0.99;
2025-11-28 10:16:58 -05:00
}
physics.turn_speed = physics.turn_speed.clamp(-MAX_TURN_SPEED, MAX_TURN_SPEED);
physics.heading += physics.turn_speed * 0.1;
if input.y > 0. {
physics.speed += 0.1;
} else if input.y < 0. {
physics.speed -= 0.1;
} else {
2025-11-28 10:30:18 -05:00
physics.speed *= 0.999;
2025-11-28 10:16:58 -05:00
}
physics.speed = physics.speed.clamp(-MAX_SAILING_SPEED, MAX_SAILING_SPEED);
2025-11-27 19:49:04 -05:00
let x_speed = physics.heading.sin() * physics.speed;
let y_speed = physics.heading.cos() * physics.speed;
physics.x += x_speed;
physics.y += y_speed;
transform.translation = Vec3 {
x: physics.x as f32,
y: physics.y as f32,
z: 0.,
};
transform.rotation = Quat::from_axis_angle(
Vec3 {
x: 0.,
y: 0.,
z: -1.,
},
physics.heading,
);
}