use fyrox::{ animation::spritesheet::SpriteSheetAnimation, core::{ algebra::{Vector2, Vector3}, pool::Handle, reflect::prelude::*, uuid::{uuid, Uuid}, visitor::prelude::*, TypeUuidProvider, }, keyboard::KeyCode, scene::dim2::{rectangle::Rectangle, rigidbody::RigidBody}, scene::node::Node, script::ScriptContext, }; #[derive(Visit, Reflect, Debug, Clone, Default)] pub struct Player { sprite: Handle, move_left: bool, move_right: bool, jump: bool, animations: Vec, current_animation: u32, current_frame: u32, start_y_position: f32, prev_y_velosity: f32, } impl TypeUuidProvider for Player { // Returns unique script id for serialization needs. fn type_uuid() -> Uuid { uuid!("c5671d19-9f1a-4286-8486-add4ebaadaec") } } impl Player { pub fn init(&mut self, context: &mut ScriptContext) { let rigid_body = context.scene.graph[context.handle].cast_mut::(); match rigid_body { Some(rigid_data) => { self.start_y_position = rigid_data.global_position().y; } None => {} } } pub fn loop_over(&mut self, context: &mut ScriptContext) { let rigid_body = context.scene.graph[context.handle].cast_mut::(); match rigid_body { Some(rigid_data) => { self.prev_y_velosity = rigid_data.lin_vel().y; } None => {} } } pub fn key_checker(&mut self, keycode: KeyCode, is_pressed: bool) { match keycode { KeyCode::ArrowLeft => self.move_left = is_pressed, KeyCode::ArrowRight => self.move_right = is_pressed, KeyCode::ArrowUp => self.jump = is_pressed, _ => (), } } fn get_speed(&self) -> f32 { return if self.move_left { 3.0 } else if self.move_right { -3.0 } else { 0.0 }; } pub fn move_do(&mut self, context: &mut ScriptContext) { let rigid_body = context.scene.graph[context.handle].cast_mut::(); match rigid_body { Some(rigid_data) => { let x_speed = self.get_speed(); rigid_data.set_lin_vel(Vector2::new(x_speed, rigid_data.lin_vel().y)); } None => {} } } pub fn is_in_fly(&self, rigid_data: &RigidBody) -> bool { let dif_y = self.prev_y_velosity - rigid_data.lin_vel().y; if dif_y > 0.0 && dif_y > 0.1 { return true; } if dif_y < 0.0 && dif_y < -0.1 { return true; } return false; } pub fn jump_do(&mut self, context: &mut ScriptContext) { let rigid_body = context.scene.graph[context.handle].cast_mut::(); match rigid_body { Some(rigid_data) => { if self.jump && !self.is_in_fly(rigid_data) { self.start_y_position = rigid_data.global_position().y; rigid_data.set_lin_vel(Vector2::new(rigid_data.lin_vel().x, 6.0)); return; } if rigid_data.lin_vel().y == 0.0 && !self.is_in_fly(rigid_data) { self.start_y_position = rigid_data.global_position().y; } // Log::info(format!( // "pos {}, dif_height: {}, lin_vel: {}, jump: {}, is_jumping: {}", // self.prev_y_velosity - rigid_data.lin_vel().y, // self.dif_height(rigid_data), // rigid_data.lin_vel().y, // self.prev_y_velosity - rigid_data.lin_vel().y, // self.is_in_fly(rigid_data), // )); } None => {} } } pub fn change_orientation(&self, context: &mut ScriptContext) { let sprite = context.scene.graph.try_get_mut(self.sprite); match sprite { Some(sprite_data) => { let x_speed = self.get_speed(); if x_speed == 0.0 { return; } // It is always a good practice to check whether the handles are valid, at this point we don't know // for sure what's the value of the `sprite` field. It can be unassigned and the following code won't // execute. A simple `context.scene.graph[self.sprite]` would just panicked in this case. let local_transform: &mut fyrox::scene::transform::Transform = sprite_data.local_transform_mut(); let current_scale = **local_transform.scale(); local_transform.set_scale(Vector3::new( // Just change X scaling to mirror player's sprite. current_scale.x.copysign(-x_speed), current_scale.y, current_scale.z, )); } None => {} } } fn animate_choose(&mut self) { let x_speed = self.get_speed(); if x_speed != 0.0 { self.current_animation = 0; } else { self.current_animation = 1; } } pub fn animation_do(&mut self, context: &mut ScriptContext) { self.animate_choose(); let current_animation = self.animations.get_mut(self.current_animation as usize); match current_animation { Some(animation_data) => { animation_data.update(context.dt); if let Some(sprite) = context .scene .graph .try_get_mut(self.sprite) .and_then(|n| n.cast_mut::()) { sprite.set_texture(animation_data.texture()); sprite.set_uv_rect(animation_data.current_frame_uv_rect().unwrap_or_default()); } } None => {} } } }