fyrox-platformer/game/src/player.rs

181 lines
6.0 KiB
Rust

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<Node>,
move_left: bool,
move_right: bool,
jump: bool,
animations: Vec<SpriteSheetAnimation>,
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::<RigidBody>();
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::<RigidBody>();
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::<RigidBody>();
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::<RigidBody>();
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::<Rectangle>())
{
sprite.set_texture(animation_data.texture());
sprite.set_uv_rect(animation_data.current_frame_uv_rect().unwrap_or_default());
}
}
None => {}
}
}
}