use fyrox::{ core::{ algebra::{UnitQuaternion, UnitVector3, Vector3}, pool::Handle, reflect::prelude::*, visitor::prelude::*, variable::InheritableVariable, type_traits::prelude::* }, event::{DeviceEvent, ElementState, MouseButton, WindowEvent, Event}, script::{ScriptContext, ScriptDeinitContext, ScriptTrait}, graph::SceneGraph, keyboard::{KeyCode, PhysicalKey}, scene::{node::Node, rigidbody::RigidBody}, }; #[derive(Visit, Reflect, Default, Debug, Clone, TypeUuidProvider, ComponentProvider)] #[type_uuid(id = "d14f7a07-1ea0-4d20-ad74-017b2497c88e")] #[visit(optional)] pub struct Player { #[reflect(hidden)] move_forward: bool, #[reflect(hidden)] move_backward: bool, #[reflect(hidden)] move_left: bool, #[reflect(hidden)] move_right: bool, #[reflect(hidden)] yaw: f32, #[reflect(hidden)] pitch: f32, camera: Handle, } impl ScriptTrait for Player { fn on_init(&mut self, context: &mut ScriptContext) { // Put initialization logic here. } fn on_start(&mut self, context: &mut ScriptContext) { // There should be a logic that depends on other scripts in scene. // It is called right after **all** scripts were initialized. } fn on_deinit(&mut self, context: &mut ScriptDeinitContext) { // Put de-initialization logic here. } fn on_os_event(&mut self, event: &Event<()>, context: &mut ScriptContext) { match event { Event::DeviceEvent { event: DeviceEvent::MouseMotion { delta: (dx, dy), .. }, .. } => { let mouse_speed = 0.35; self.pitch = (self.pitch + *dy as f32 * mouse_speed).clamp(-89.9, 89.9); self.yaw -= *dx as f32 * mouse_speed; }, Event::WindowEvent { event: WindowEvent::KeyboardInput { event, .. }, .. } => { if let PhysicalKey::Code(code) = event.physical_key { let is_pressed = event.state == ElementState::Pressed; match code { KeyCode::KeyW => { self.move_forward = is_pressed; }, KeyCode::KeyS => { self.move_backward = is_pressed; }, KeyCode::KeyA => { self.move_left = is_pressed; }, KeyCode::KeyD => { self.move_right = is_pressed; }, _ => (), } } }, _ => (), } } fn on_update(&mut self, context: &mut ScriptContext) { let mut look_vector = Vector3::default(); let mut side_vector = Vector3::default(); if let Some(camera) = context.scene.graph.try_get_mut(self.camera) { look_vector = camera.look_vector(); side_vector = camera.side_vector(); let yaw = UnitQuaternion::from_axis_angle( &Vector3::y_axis(), self.yaw.to_radians() ); let transform = camera.local_transform_mut(); transform.set_rotation( UnitQuaternion::from_axis_angle( &UnitVector3::new_normalize(yaw * Vector3::x()), self.pitch.to_radians(), ) * yaw, ); } if let Some(rigid_body) = context.scene.graph.try_get_mut_of_type::(context.handle) { let mut velocity = Vector3::new(0.0, 0.0, 0.0); if self.move_forward { velocity += look_vector; } if self.move_backward { velocity -= look_vector; } if self.move_left { velocity += side_vector; } if self.move_right { velocity -= side_vector; } let y_vel = rigid_body.lin_vel().y; if let Some(normalized_velocity) = velocity.try_normalize(f32::EPSILON) { let movement_speed = 240.0 * context.dt; rigid_body.set_lin_vel(Vector3::new( normalized_velocity.x * movement_speed, y_vel, normalized_velocity.z * movement_speed, )); } else { rigid_body.set_lin_vel(Vector3::new(0.0, y_vel, 0.0)); } } } }