说在前面
- 操作系统:win11
- rust版本:rustc 1.77.0-nightly
- bevy版本:0.12
步骤
- rust安装
这里windows
下建议使用msvc
版本 -
bevy
安装
这里 - clone代码
git clone https://github.com/NiklasEi/bevy_game_template.git
- 运行
cargo run
- 结果
进入3D
- template中的例子是2d的,我们稍微修改下
- 首先增加一个
CameraController
,代码在bevy
的例程中也可以找到//! A freecam-style camera controller plugin. //! To use in your own application: //! - Copy the code for the [`CameraControllerPlugin`] and add the plugin to your App. //! - Attach the [`CameraController`] component to an entity with a [`Camera3dBundle`]. use bevy::window::CursorGrabMode; use bevy::{input::mouse::MouseMotion, prelude::*}; use std::f32::consts::*; use std::fmt; /// Based on Valorant's default sensitivity, not entirely sure why it is exactly 1.0 / 180.0, /// but I'm guessing it is a misunderstanding between degrees/radians and then sticking with /// it because it felt nice. pub const RADIANS_PER_DOT: f32 = 1.0 / 180.0; #[derive(Component)] pub struct CameraController { pub enabled: bool, pub initialized: bool, pub sensitivity: f32, pub key_forward: KeyCode, pub key_back: KeyCode, pub key_left: KeyCode, pub key_right: KeyCode, pub key_up: KeyCode, pub key_down: KeyCode, pub key_run: KeyCode, pub mouse_key_enable_mouse: MouseButton, pub keyboard_key_enable_mouse: KeyCode, pub walk_speed: f32, pub run_speed: f32, pub friction: f32, pub pitch: f32, pub yaw: f32, pub velocity: Vec3, } impl Default for CameraController { fn default() -> Self { Self { enabled: true, initialized: false, sensitivity: 1.0, key_forward: KeyCode::W, key_back: KeyCode::S, key_left: KeyCode::A, key_right: KeyCode::D, key_up: KeyCode::E, key_down: KeyCode::Q, key_run: KeyCode::ShiftLeft, mouse_key_enable_mouse: MouseButton::Left, keyboard_key_enable_mouse: KeyCode::M, walk_speed: 5.0, run_speed: 15.0, friction: 0.5, pitch: 0.0, yaw: 0.0, velocity: Vec3::ZERO, } } } impl fmt::Display for CameraController { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!( f, " Freecam Controls: MOUSE\t- Move camera orientation {:?}/{:?}\t- Enable mouse movement {:?}{:?}\t- forward/backward {:?}{:?}\t- strafe left/right {:?}\t- 'run' {:?}\t- up {:?}\t- down", self.mouse_key_enable_mouse, self.keyboard_key_enable_mouse, self.key_forward, self.key_back, self.key_left, self.key_right, self.key_run, self.key_up, self.key_down ) } } pub struct CameraControllerPlugin; impl Plugin for CameraControllerPlugin { fn build(&self, app: &mut App) { app.add_systems(Update, camera_controller); } } fn camera_controller( time: Res<Time>, mut windows: Query<&mut Window>, mut mouse_events: EventReader<MouseMotion>, mouse_button_input: Res<Input<MouseButton>>, key_input: Res<Input<KeyCode>>, mut move_toggled: Local<bool>, mut query: Query<(&mut Transform, &mut CameraController), With<Camera>>, ) { let dt = time.delta_seconds(); if let Ok((mut transform, mut options)) = query.get_single_mut() { if !options.initialized { let (yaw, pitch, _roll) = transform.rotation.to_euler(EulerRot::YXZ); options.yaw = yaw; options.pitch = pitch; options.initialized = true; } if !options.enabled { return; } // Handle key input let mut axis_input = Vec3::ZERO; if key_input.pressed(options.key_forward) { axis_input.z += 1.0; } if key_input.pressed(options.key_back) { axis_input.z -= 1.0; } if key_input.pressed(options.key_right) { axis_input.x += 1.0; } if key_input.pressed(options.key_left) { axis_input.x -= 1.0; } if key_input.pressed(options.key_up) { axis_input.y += 1.0; } if key_input.pressed(options.key_down) { axis_input.y -= 1.0; } if key_input.just_pressed(options.keyboard_key_enable_mouse) { *move_toggled = !*move_toggled; } // Apply movement update if axis_input != Vec3::ZERO { let max_speed = if key_input.pressed(options.key_run) { options.run_speed } else { options.walk_speed }; options.velocity = axis_input.normalize() * max_speed; } else { let friction = options.friction.clamp(0.0, 1.0); options.velocity *= 1.0 - friction; if options.velocity.length_squared() < 1e-6 { options.velocity = Vec3::ZERO; } } let forward = transform.forward(); let right = transform.right(); transform.translation += options.velocity.x * dt * right + options.velocity.y * dt * Vec3::Y + options.velocity.z * dt * forward; // Handle mouse input let mut mouse_delta = Vec2::ZERO; if mouse_button_input.pressed(options.mouse_key_enable_mouse) || *move_toggled { for mut window in &mut windows { if !window.focused { continue; } window.cursor.grab_mode = CursorGrabMode::Locked; window.cursor.visible = false; } for mouse_event in mouse_events.read() { mouse_delta += mouse_event.delta; } } if mouse_button_input.just_released(options.mouse_key_enable_mouse) { for mut window in &mut windows { window.cursor.grab_mode = CursorGrabMode::None; window.cursor.visible = true; } } if mouse_delta != Vec2::ZERO { // Apply look update options.pitch = (options.pitch - mouse_delta.y * RADIANS_PER_DOT * options.sensitivity) .clamp(-PI / 2., PI / 2.); options.yaw -= mouse_delta.x * RADIANS_PER_DOT * options.sensitivity; transform.rotation = Quat::from_euler(EulerRot::ZYX, 0.0, options.yaw, options.pitch); } } }
- 再添加一个
SceneSetup
,用于初始化场景和相机use bevy::prelude::*; use bevy::app::{Plugin, App, Startup}; use crate::camera::CameraController; pub struct SceneSetupPlugin; impl Plugin for SceneSetupPlugin { fn build(&self, app: &mut App) { app.add_systems(Startup, setup); } } /// set up a simple 3D scene fn setup( mut commands: Commands, mut meshes: ResMut<Assets<Mesh>>, mut materials: ResMut<Assets<StandardMaterial>>, ) { // circular base commands.spawn(PbrBundle { mesh: meshes.add(shape::Circle::new(4.0).into()), material: materials.add(Color::WHITE.into()), transform: Transform::from_rotation(Quat::from_rotation_x(-std::f32::consts::FRAC_PI_2)), ..default() }); // cube commands.spawn(PbrBundle { mesh: meshes.add(Mesh::from(shape::Cube { size: 1.0 })), material: materials.add(Color::rgb_u8(124, 144, 255).into()), transform: Transform::from_xyz(0.0, 0.5, 0.0), ..default() }); // light commands.spawn(PointLightBundle { point_light: PointLight { intensity: 1500.0, shadows_enabled: true, ..default() }, transform: Transform::from_xyz(4.0, 8.0, 4.0), ..default() }); let camera_controller = CameraController::default(); // camera commands.spawn((Camera3dBundle { transform: Transform::from_xyz(-2.5, 4.5, 9.0).looking_at(Vec3::ZERO, Vec3::Y), ..default() },camera_controller)); }
- 将GamePlugin中的代码修改下进行测试
impl Plugin for GamePlugin { fn build(&self, app: &mut App) { app.add_state::<GameState>().add_plugins(( // LoadingPlugin, // MenuPlugin, SceneSetupPlugin, // ActionsPlugin, // InternalAudioPlugin, // PlayerPlugin, CameraControllerPlugin )); #[cfg(debug_assertions)] { app.add_plugins((FrameTimeDiagnosticsPlugin, LogDiagnosticsPlugin::default())); } } }
- 结果
控制方块
- 上面的测试中我们将游戏流程注释掉了,现在我们尝试加回来,并将方块作为我们的
Player
- 首先将player设置为方块(不要忘记将上面场景中的方块去掉)
fn spawn_player(mut commands: Commands, mut meshes: ResMut<Assets<Mesh>>, mut materials: ResMut<Assets<StandardMaterial>>) { commands.spawn(PbrBundle { mesh: meshes.add(Mesh::from(shape::Cube { size: 1.0 })), material: materials.add(Color::rgb_u8(124, 144, 255).into()), transform: Transform::from_xyz(0.0, 1., 0.0), ..default() }) .insert(Player); }
- 然后将actions中的相机改为3d
pub fn set_movement_actions( mut actions: ResMut<Actions>, keyboard_input: Res<Input<KeyCode>>, touch_input: Res<Touches>, player: Query<&Transform, With<Player>>, camera: Query<(&Camera, &GlobalTransform), With<Camera3d>>, ) { // ... }
- 然后我们先去掉menu中的相机
fn setup_menu(mut commands: Commands, textures: Res<TextureAssets>) { info!("menu"); // commands.spawn(Camera2dBundle::default()); // ...
- 结果(将
move_player
中的速度调低点)
- 不过这里我们的ui和场景显示到一块了,后面再看看怎么处理
问题
- note: LINK : fatal error LNK1189: 超过 65535 对象的库限制
参考这个解决
文章来源地址https://www.toymoban.com/news/detail-800082.html
文章来源:https://www.toymoban.com/news/detail-800082.html
到了这里,关于【rust/bevy】从game template开始的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!