move the enemies to different places
This commit is contained in:
parent
e061a1405a
commit
f0142c3ed2
|
|
@ -0,0 +1,479 @@
|
|||
use crate::Player;
|
||||
use fyrox::graph::SceneGraph;
|
||||
use fyrox::{
|
||||
core::{
|
||||
algebra::{Point2, Vector2, Vector3},
|
||||
impl_component_provider,
|
||||
pool::Handle,
|
||||
reflect::prelude::*,
|
||||
uuid_provider,
|
||||
visitor::prelude::*,
|
||||
},
|
||||
scene::{
|
||||
animation::spritesheet::SpriteSheetAnimation,
|
||||
collider::{BitMask, InteractionGroups},
|
||||
dim2::{
|
||||
physics::{Intersection, RayCastOptions},
|
||||
rectangle::Rectangle,
|
||||
rigidbody::RigidBody,
|
||||
},
|
||||
graph::Graph,
|
||||
node::Node,
|
||||
},
|
||||
script::{ScriptContext, ScriptTrait},
|
||||
};
|
||||
|
||||
impl_component_provider!(Archer,);
|
||||
uuid_provider!(Archer = "a5671d19-9f1a-4286-8486-add4ebaadaec");
|
||||
|
||||
#[derive(Debug, Clone, Default, Copy)]
|
||||
enum Animations {
|
||||
#[default]
|
||||
Idle = 0,
|
||||
Run = 1,
|
||||
Fight = 2,
|
||||
Dead = 3,
|
||||
Block = 4,
|
||||
}
|
||||
|
||||
const DISTANCE_TO_FIGHT: f32 = 0.5;
|
||||
const DISTANCE_TO_VIEW: f32 = 5.0;
|
||||
const END_MAP_LEFT: f32 = -30.0;
|
||||
const END_MAP_RIGHT: f32 = 30.0;
|
||||
const SPEED: f32 = 3.1;
|
||||
|
||||
#[derive(Visit, Reflect, Debug, Clone, Default)]
|
||||
pub struct Archer {
|
||||
// pub sprite: Handle<Node>,
|
||||
move_left: bool,
|
||||
move_right: bool,
|
||||
jump: bool,
|
||||
pub animations: Vec<SpriteSheetAnimation>,
|
||||
fight: bool,
|
||||
win: bool,
|
||||
dead: bool,
|
||||
block: bool,
|
||||
|
||||
#[reflect(hidden)]
|
||||
#[visit(skip)]
|
||||
current_animation: Animations,
|
||||
|
||||
handle: Handle<Node>,
|
||||
player_handle: Handle<Node>,
|
||||
player_collider: Handle<Node>,
|
||||
|
||||
attack_damage: f32,
|
||||
attack_timer: f32,
|
||||
attack_speed: f32,
|
||||
pub x: f32,
|
||||
pub y: f32,
|
||||
}
|
||||
impl Archer {
|
||||
fn init(&mut self) {
|
||||
self.attack_damage = 100.0;
|
||||
self.attack_speed = 0.1;
|
||||
}
|
||||
|
||||
fn round(&self, a: f32) -> i32 {
|
||||
return a.round() as i32;
|
||||
}
|
||||
|
||||
pub fn take_damage(&mut self, _damage: &f32) {
|
||||
if self.dead {
|
||||
return;
|
||||
}
|
||||
self.block = true;
|
||||
}
|
||||
|
||||
fn intersections_box(&self, graph: &mut Graph) -> bool {
|
||||
if self.dead {
|
||||
return false;
|
||||
}
|
||||
let self_node = match graph.try_get_mut(self.handle) {
|
||||
Some(node) => node,
|
||||
None => return false,
|
||||
};
|
||||
let self_position = self_node.global_position();
|
||||
|
||||
// Cast a ray from *this* node in the direction of the player node
|
||||
let mut buffer = Vec::<Intersection>::new();
|
||||
|
||||
graph.physics2d.cast_ray(
|
||||
RayCastOptions {
|
||||
ray_origin: Point2::new(self_position.x, self_position.y),
|
||||
ray_direction: Vector2::new(0.0, 1.0),
|
||||
max_len: 0.5,
|
||||
groups: InteractionGroups::default(),
|
||||
// Sort the results by distance
|
||||
sort_results: true,
|
||||
},
|
||||
// Store the collisions in the vector
|
||||
&mut buffer,
|
||||
);
|
||||
if buffer.len() == 0 {
|
||||
return false;
|
||||
}
|
||||
for i in 0..buffer.len() {
|
||||
if self.player_handle == buffer[i].collider {
|
||||
continue;
|
||||
}
|
||||
if buffer[i].toi == 0.0 {
|
||||
continue;
|
||||
}
|
||||
if self.round(buffer[i].position[0]) != self.round(self_position.x) {
|
||||
continue;
|
||||
}
|
||||
if self.round(buffer[i].position[1]) == self.round(self_position.y) {
|
||||
continue;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
fn intersections_player(&self, graph: &mut Graph, max_len: f32) -> Option<Vec<Intersection>> {
|
||||
if self.dead {
|
||||
return None;
|
||||
}
|
||||
// Get *this* node instance
|
||||
let self_node = match graph.try_get_mut(self.handle) {
|
||||
Some(node) => node,
|
||||
None => return None,
|
||||
};
|
||||
let self_position = self_node.global_position();
|
||||
|
||||
// Get the player node
|
||||
let player_node = match graph.try_get_mut(self.player_handle) {
|
||||
Some(node) => node,
|
||||
None => return None,
|
||||
};
|
||||
|
||||
// Get the current position of *this* node and the player node
|
||||
let player_position = player_node.global_position();
|
||||
|
||||
// Calculate the direction vector from *this* node to the player node
|
||||
let direction = player_position - self_position;
|
||||
|
||||
// Cast a ray from *this* node in the direction of the player node
|
||||
let mut buffer = Vec::<Intersection>::new();
|
||||
|
||||
graph.physics2d.cast_ray(
|
||||
RayCastOptions {
|
||||
ray_origin: Point2::new(self_position.x, self_position.y),
|
||||
ray_direction: Vector2::new(direction.x, direction.y),
|
||||
max_len: max_len,
|
||||
groups: InteractionGroups::new(
|
||||
// Only collide with the player
|
||||
BitMask(0b1000_0000_0000_0000_0000_0000_0000_0000),
|
||||
BitMask(0b0111_1111_1111_1111_1111_1111_1111_1111),
|
||||
),
|
||||
// groups: InteractionGroups::default(),
|
||||
// Sort the results by distance
|
||||
sort_results: true,
|
||||
},
|
||||
// Store the collisions in the vector
|
||||
&mut buffer,
|
||||
);
|
||||
if buffer.len() == 0 {
|
||||
return None;
|
||||
}
|
||||
return Some(buffer);
|
||||
}
|
||||
|
||||
fn attack_player(&mut self, ctx: &mut ScriptContext) {
|
||||
if self.win {
|
||||
return;
|
||||
}
|
||||
if !self.fight {
|
||||
return;
|
||||
}
|
||||
let player_script = ctx
|
||||
.scene
|
||||
.graph
|
||||
.try_get_script_of_mut::<Player>(self.player_handle)
|
||||
.unwrap();
|
||||
if player_script.get_health() <= 0.0 {
|
||||
self.fight = false;
|
||||
self.block = false;
|
||||
self.win = true;
|
||||
return;
|
||||
}
|
||||
self.block = false;
|
||||
player_script.take_damage(&self.attack_damage);
|
||||
}
|
||||
|
||||
fn get_player_position(&self, context: &mut ScriptContext) -> Vector3<f32> {
|
||||
let player_binding = context.scene.graph.try_get_mut(self.player_handle).unwrap();
|
||||
let player_rigid_body = player_binding.cast::<RigidBody>();
|
||||
let player_rigid_data = match player_rigid_body {
|
||||
Some(rigid_body) => rigid_body,
|
||||
None => panic!("wrong player position"),
|
||||
};
|
||||
|
||||
return Vector3::new(
|
||||
player_rigid_data.local_transform().position().x,
|
||||
player_rigid_data.local_transform().position().y,
|
||||
player_rigid_data.local_transform().position().z,
|
||||
);
|
||||
}
|
||||
|
||||
fn distance_to_player(&self, context: &mut ScriptContext) -> f32 {
|
||||
let player_position = self.get_player_position(context);
|
||||
|
||||
let enemy_binding = context.scene.graph.try_get_mut(context.handle).unwrap();
|
||||
let enemy_rigid_body = enemy_binding.cast::<RigidBody>();
|
||||
let enemy_rigid_data = match enemy_rigid_body {
|
||||
Some(rigid_data) => rigid_data,
|
||||
None => return 0.0,
|
||||
};
|
||||
|
||||
// TODO: if player is places abroad maps - stop activity
|
||||
// if player_position.x <= END_MAP_LEFT || player_position.x >= END_MAP_RIGHT {
|
||||
// return 100.0;
|
||||
// }
|
||||
|
||||
let enemy_position = enemy_rigid_data.local_transform().position();
|
||||
if player_position.y > enemy_position.y {
|
||||
return DISTANCE_TO_VIEW * 2.0;
|
||||
}
|
||||
return player_position.x - enemy_position.x;
|
||||
}
|
||||
|
||||
fn get_speed(&self, context: &mut ScriptContext) -> f32 {
|
||||
if self.dead {
|
||||
return 0.0;
|
||||
}
|
||||
if self.win {
|
||||
return 0.0;
|
||||
}
|
||||
let collaider = self.intersections_player(&mut context.scene.graph, DISTANCE_TO_VIEW);
|
||||
let mut see_player: bool = false;
|
||||
if let Some(collaider_data) = collaider {
|
||||
for i in 0..collaider_data.len() {
|
||||
if collaider_data[i].toi == 0.0 {
|
||||
continue;
|
||||
}
|
||||
if collaider_data[i].collider == self.player_collider {
|
||||
see_player = true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
if !see_player {
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
let player_position = self.get_player_position(context);
|
||||
let enemy_rigid_body = context.scene.graph[context.handle]
|
||||
.cast_mut::<RigidBody>()
|
||||
.unwrap();
|
||||
if enemy_rigid_body.global_position().x <= END_MAP_LEFT {
|
||||
return 0.0;
|
||||
}
|
||||
if enemy_rigid_body.global_position().x >= END_MAP_RIGHT {
|
||||
return 0.0;
|
||||
}
|
||||
let mut dif_x = player_position.x - enemy_rigid_body.global_position().x;
|
||||
if enemy_rigid_body.global_position().x > player_position.x {
|
||||
dif_x = player_position.x - enemy_rigid_body.global_position().x;
|
||||
}
|
||||
if dif_x < 0.0 {
|
||||
dif_x *= -1.0;
|
||||
}
|
||||
if player_position.y > enemy_rigid_body.global_position().y && dif_x < 1.0 {
|
||||
if player_position.x > enemy_rigid_body.global_position().x {
|
||||
return SPEED * -1.0;
|
||||
}
|
||||
if player_position.x < enemy_rigid_body.global_position().x {
|
||||
return SPEED;
|
||||
}
|
||||
}
|
||||
if enemy_rigid_body.global_position().x < END_MAP_LEFT + 3.0 {
|
||||
return SPEED / 2.0;
|
||||
}
|
||||
if enemy_rigid_body.global_position().x > END_MAP_RIGHT - 3.0 {
|
||||
return SPEED / 2.0;
|
||||
}
|
||||
|
||||
let distance = self.distance_to_player(context);
|
||||
if distance > DISTANCE_TO_VIEW {
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
if distance > DISTANCE_TO_FIGHT {
|
||||
return SPEED;
|
||||
}
|
||||
if distance < DISTANCE_TO_FIGHT * -1.0 {
|
||||
return SPEED * -1.0;
|
||||
}
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
fn change_orientation(&self, context: &mut ScriptContext) {
|
||||
let x_speed = self.get_speed(context);
|
||||
if x_speed == 0.0 {
|
||||
return;
|
||||
}
|
||||
let sprite = context.scene.graph.try_get_mut(context.handle);
|
||||
match sprite {
|
||||
Some(sprite_data) => {
|
||||
// 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 move_do(&mut self, context: &mut ScriptContext) {
|
||||
let x_speed = self.get_speed(context);
|
||||
if x_speed > 0.0 {
|
||||
self.block = false;
|
||||
}
|
||||
let enemy_rigid_body = context.scene.graph[context.handle].cast_mut::<RigidBody>();
|
||||
if let Some(enemy_rigid_data) = enemy_rigid_body {
|
||||
enemy_rigid_data.set_lin_vel(Vector2::new(x_speed, -1.0));
|
||||
}
|
||||
}
|
||||
|
||||
fn animate_choose(&mut self, context: &mut ScriptContext) {
|
||||
self.current_animation = Animations::Idle;
|
||||
if self.win {
|
||||
return;
|
||||
}
|
||||
if self.block {
|
||||
self.current_animation = Animations::Block;
|
||||
return;
|
||||
}
|
||||
if self.dead {
|
||||
self.current_animation = Animations::Dead;
|
||||
return;
|
||||
}
|
||||
if self.get_speed(context) != 0.0 {
|
||||
self.current_animation = Animations::Run;
|
||||
return;
|
||||
}
|
||||
if self.fight {
|
||||
self.current_animation = Animations::Fight;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
fn set_fight(&mut self, context: &mut ScriptContext) {
|
||||
if self.win {
|
||||
return;
|
||||
}
|
||||
if self.dead {
|
||||
return;
|
||||
}
|
||||
if self.block {
|
||||
return;
|
||||
}
|
||||
let distance = self.distance_to_player(context);
|
||||
self.fight = distance < DISTANCE_TO_FIGHT && distance > -1.0 * DISTANCE_TO_FIGHT;
|
||||
if !self.fight {
|
||||
self.attack_timer = 0.0;
|
||||
return;
|
||||
}
|
||||
self.attack_timer += context.dt;
|
||||
if self.attack_timer >= self.attack_speed {
|
||||
self.attack_player(context);
|
||||
self.attack_timer = 0.0;
|
||||
return;
|
||||
}
|
||||
self.fight = false;
|
||||
}
|
||||
|
||||
pub fn animation_do(&mut self, context: &mut ScriptContext) {
|
||||
self.animate_choose(context);
|
||||
let cur_anim = self.current_animation as usize;
|
||||
let current_animation = self.animations.get_mut(cur_anim);
|
||||
match current_animation {
|
||||
Some(animation_data) => {
|
||||
{
|
||||
let graph_ctx = context.scene.graph.begin_multi_borrow();
|
||||
let enemy_rigid_data = match graph_ctx.try_get(context.handle) {
|
||||
Ok(rigid_body) => rigid_body,
|
||||
Err(_) => return,
|
||||
};
|
||||
for child in enemy_rigid_data.children().iter() {
|
||||
if let Ok(mut enemy) = graph_ctx.try_get_mut(*child) {
|
||||
if !enemy.is_rectangle() {
|
||||
continue;
|
||||
}
|
||||
let sprite: &mut Rectangle = enemy.cast_mut::<Rectangle>().unwrap();
|
||||
animation_data.update(context.dt);
|
||||
sprite
|
||||
.material()
|
||||
.data_ref()
|
||||
.set_texture(&"diffuseTexture".into(), animation_data.texture())
|
||||
.unwrap();
|
||||
sprite.set_uv_rect(
|
||||
animation_data.current_frame_uv_rect().unwrap_or_default(),
|
||||
);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
animation_data.update(context.dt);
|
||||
if let Some(sprite) = context
|
||||
.scene
|
||||
.graph
|
||||
.try_get_mut(context.handle)
|
||||
.and_then(|n| n.cast_mut::<Rectangle>())
|
||||
{
|
||||
sprite
|
||||
.material()
|
||||
.data_ref()
|
||||
.set_texture(&"diffuseTexture".into(), animation_data.texture())
|
||||
.unwrap();
|
||||
sprite.set_uv_rect(animation_data.current_frame_uv_rect().unwrap_or_default());
|
||||
}
|
||||
}
|
||||
None => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
impl ScriptTrait for Archer {
|
||||
fn on_init(&mut self, context: &mut ScriptContext) {
|
||||
self.init();
|
||||
// Store reference to *this* instance of the enemy node
|
||||
self.handle = context.handle;
|
||||
|
||||
// Find the Player node
|
||||
match context.scene.graph.find_by_name_from_root("Player") {
|
||||
// (Handle<Node>, Node)
|
||||
Some(handle) => {
|
||||
// If found, store the handle
|
||||
self.player_handle = handle.0;
|
||||
|
||||
// Find and store the Player's collider node handle
|
||||
for child in handle.1.children().iter() {
|
||||
self.player_collider = *child;
|
||||
break;
|
||||
}
|
||||
}
|
||||
None => {}
|
||||
}
|
||||
}
|
||||
|
||||
fn on_update(&mut self, context: &mut ScriptContext) {
|
||||
if self.intersections_box(&mut context.scene.graph) {
|
||||
self.dead = true
|
||||
}
|
||||
self.set_fight(context);
|
||||
self.change_orientation(context);
|
||||
self.animation_do(context);
|
||||
self.move_do(context);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,2 @@
|
|||
pub mod enemy;
|
||||
pub mod spawn;
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
use crate::Enemy;
|
||||
use crate::Archer;
|
||||
use fyrox::{
|
||||
asset::manager::ResourceManager,
|
||||
core::{
|
||||
|
|
@ -25,20 +25,20 @@ use fyrox::{
|
|||
rigidbody::RigidBodyType,
|
||||
transform::TransformBuilder,
|
||||
},
|
||||
script::{Script, ScriptContext, ScriptTrait},
|
||||
script::{ScriptContext, ScriptTrait},
|
||||
};
|
||||
|
||||
impl_component_provider!(EnemySpawn,);
|
||||
uuid_provider!(EnemySpawn = "b5671d19-9f1a-4286-8486-add4ebaadaec");
|
||||
impl_component_provider!(ArcherSpawn,);
|
||||
uuid_provider!(ArcherSpawn = "b5671d19-9f1a-4286-8486-add4ebaadaec");
|
||||
#[derive(Visit, Reflect, Debug, Clone, Default)]
|
||||
pub struct EnemySpawn {
|
||||
pub struct ArcherSpawn {
|
||||
x: f32,
|
||||
y: f32,
|
||||
enemy: Enemy,
|
||||
enemy: Archer,
|
||||
}
|
||||
impl EnemySpawn {
|
||||
impl ArcherSpawn {
|
||||
pub fn new() -> Self {
|
||||
return EnemySpawn::default();
|
||||
return ArcherSpawn::default();
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -144,7 +144,7 @@ impl EnemySpawn {
|
|||
|
||||
pub fn spawn_enemy(&self, graph: &mut Graph, resource_manager: &ResourceManager, x: f32) {
|
||||
// TODO: add with_build
|
||||
let mut enemy = Enemy::default();
|
||||
let mut enemy = Archer::default();
|
||||
enemy.x = x;
|
||||
enemy.y = -3.0;
|
||||
let x = enemy.x;
|
||||
|
|
@ -207,7 +207,7 @@ impl EnemySpawn {
|
|||
.build(graph);
|
||||
}
|
||||
}
|
||||
impl ScriptTrait for EnemySpawn {
|
||||
impl ScriptTrait for ArcherSpawn {
|
||||
fn on_init(&mut self, context: &mut ScriptContext) {
|
||||
let resource_manager: &ResourceManager = &context.resource_manager;
|
||||
self.spawn_enemy(&mut context.scene.graph, resource_manager, 0.0);
|
||||
|
|
@ -0,0 +1,2 @@
|
|||
pub mod swordsman;
|
||||
pub mod archer;
|
||||
|
|
@ -0,0 +1,2 @@
|
|||
pub mod enemy;
|
||||
pub mod spawn;
|
||||
|
|
@ -0,0 +1,216 @@
|
|||
use crate::Swordman;
|
||||
use fyrox::{
|
||||
asset::manager::ResourceManager,
|
||||
core::{
|
||||
algebra::{Vector2, Vector3},
|
||||
impl_component_provider,
|
||||
math::Rect,
|
||||
reflect::prelude::*,
|
||||
sstorage::ImmutableString,
|
||||
uuid_provider,
|
||||
visitor::prelude::*,
|
||||
},
|
||||
generic_animation::spritesheet::{ImageParameters, SpriteSheetAnimation},
|
||||
material::{shader::SamplerFallback, Material, MaterialResource, PropertyValue},
|
||||
resource::texture::Texture,
|
||||
scene::{
|
||||
base::BaseBuilder,
|
||||
collider::InteractionGroups,
|
||||
dim2::{
|
||||
collider::{CapsuleShape, ColliderBuilder, ColliderShape},
|
||||
rectangle::RectangleBuilder,
|
||||
rigidbody::RigidBodyBuilder,
|
||||
},
|
||||
graph::Graph,
|
||||
rigidbody::RigidBodyType,
|
||||
transform::TransformBuilder,
|
||||
},
|
||||
script::{ScriptContext, ScriptTrait},
|
||||
};
|
||||
|
||||
impl_component_provider!(SwordmanSpawn,);
|
||||
uuid_provider!(SwordmanSpawn = "b5671d19-9f1a-4286-8486-add4ebaadaec");
|
||||
#[derive(Visit, Reflect, Debug, Clone, Default)]
|
||||
pub struct SwordmanSpawn {
|
||||
x: f32,
|
||||
y: f32,
|
||||
enemy: Swordman,
|
||||
}
|
||||
impl SwordmanSpawn {
|
||||
pub fn new() -> Self {
|
||||
return SwordmanSpawn::default();
|
||||
}
|
||||
|
||||
|
||||
fn block_anmation(&self, resource_manager: &ResourceManager) -> SpriteSheetAnimation<fyrox::asset::Resource<Texture>> {
|
||||
let idle = resource_manager.request::<Texture>(
|
||||
"assets/data/characters/skeleton/Skeleton_Warrior/Protect.png".to_owned(),
|
||||
);
|
||||
let mut idle_animation = SpriteSheetAnimation::new_from_image_parameters(ImageParameters {
|
||||
width: 128,
|
||||
height: 128,
|
||||
frame_width: 128,
|
||||
frame_height: 128,
|
||||
first_frame: 0,
|
||||
last_frame: 1,
|
||||
column_major: false,
|
||||
});
|
||||
idle_animation.set_texture(Some(idle));
|
||||
idle_animation.set_looping(false);
|
||||
idle_animation.set_speed(20.);
|
||||
idle_animation.play();
|
||||
return idle_animation;
|
||||
}
|
||||
|
||||
fn attack_anmation(&self, resource_manager: &ResourceManager) -> SpriteSheetAnimation<fyrox::asset::Resource<Texture>> {
|
||||
let idle = resource_manager.request::<Texture>(
|
||||
"assets/data/characters/skeleton/Skeleton_Warrior/Attack_3.png".to_owned(),
|
||||
);
|
||||
let mut idle_animation = SpriteSheetAnimation::new_from_image_parameters(ImageParameters {
|
||||
width: 512,
|
||||
height: 128,
|
||||
frame_width: 128,
|
||||
frame_height: 128,
|
||||
first_frame: 0,
|
||||
last_frame: 6,
|
||||
column_major: false,
|
||||
});
|
||||
idle_animation.set_texture(Some(idle));
|
||||
idle_animation.set_looping(true);
|
||||
idle_animation.set_speed(20.);
|
||||
idle_animation.play();
|
||||
return idle_animation;
|
||||
}
|
||||
|
||||
fn run_anmation(&self, resource_manager: &ResourceManager) -> SpriteSheetAnimation<fyrox::asset::Resource<Texture>> {
|
||||
let idle = resource_manager.request::<Texture>(
|
||||
"assets/data/characters/skeleton/Skeleton_Warrior/Run.png".to_owned(),
|
||||
);
|
||||
let mut idle_animation = SpriteSheetAnimation::new_from_image_parameters(ImageParameters {
|
||||
width: 1024,
|
||||
height: 128,
|
||||
frame_width: 128,
|
||||
frame_height: 128,
|
||||
first_frame: 0,
|
||||
last_frame: 8,
|
||||
column_major: false,
|
||||
});
|
||||
idle_animation.set_texture(Some(idle));
|
||||
idle_animation.set_looping(true);
|
||||
idle_animation.set_speed(10.);
|
||||
idle_animation.play();
|
||||
return idle_animation;
|
||||
}
|
||||
|
||||
fn die_anmation(&self, resource_manager: &ResourceManager) -> SpriteSheetAnimation<fyrox::asset::Resource<Texture>> {
|
||||
let idle = resource_manager.request::<Texture>(
|
||||
"assets/data/characters/skeleton/Skeleton_Warrior/Dead.png".to_owned(),
|
||||
);
|
||||
let mut idle_animation = SpriteSheetAnimation::new_from_image_parameters(ImageParameters {
|
||||
width: 512,
|
||||
height: 128,
|
||||
frame_width: 128,
|
||||
frame_height: 128,
|
||||
first_frame: 0,
|
||||
last_frame: 4,
|
||||
column_major: false,
|
||||
});
|
||||
idle_animation.set_texture(Some(idle));
|
||||
idle_animation.set_looping(false);
|
||||
idle_animation.set_speed(10.);
|
||||
idle_animation.play();
|
||||
return idle_animation;
|
||||
}
|
||||
|
||||
fn idle_anmation(&self, resource_manager: &ResourceManager) -> SpriteSheetAnimation<fyrox::asset::Resource<Texture>> {
|
||||
let idle = resource_manager.request::<Texture>(
|
||||
"assets/data/characters/skeleton/Skeleton_Warrior/Idle.png".to_owned(),
|
||||
);
|
||||
let mut idle_animation = SpriteSheetAnimation::new_from_image_parameters(ImageParameters {
|
||||
width: 896,
|
||||
height: 128,
|
||||
frame_width: 128,
|
||||
frame_height: 128,
|
||||
first_frame: 0,
|
||||
last_frame: 7,
|
||||
column_major: false,
|
||||
});
|
||||
idle_animation.set_texture(Some(idle));
|
||||
idle_animation.set_looping(true);
|
||||
idle_animation.set_speed(10.);
|
||||
idle_animation.play();
|
||||
return idle_animation;
|
||||
}
|
||||
|
||||
pub fn spawn_enemy(&self, graph: &mut Graph, resource_manager: &ResourceManager, x: f32) {
|
||||
// TODO: add with_build
|
||||
let mut enemy = Swordman::default();
|
||||
enemy.x = x;
|
||||
enemy.y = -3.0;
|
||||
let x = enemy.x;
|
||||
let y = enemy.y;
|
||||
let mut material = Material::standard_2d();
|
||||
enemy.animations = vec![
|
||||
self.idle_anmation(resource_manager),
|
||||
self.run_anmation(resource_manager),
|
||||
self.attack_anmation(resource_manager),
|
||||
self.die_anmation(resource_manager),
|
||||
self.block_anmation(resource_manager),
|
||||
];
|
||||
material
|
||||
.set_property(
|
||||
&ImmutableString::new("diffuseTexture"),
|
||||
PropertyValue::Sampler {
|
||||
value: None,
|
||||
fallback: SamplerFallback::Normal,
|
||||
},
|
||||
)
|
||||
.unwrap();
|
||||
let shape = ColliderShape::Capsule(CapsuleShape {
|
||||
begin: Vector2::new(0.0, -0.80),
|
||||
end: Vector2::new(0.0, -0.35),
|
||||
radius: 0.2,
|
||||
});
|
||||
let rb_transform = TransformBuilder::new()
|
||||
.with_local_position(Vector3::new(x, y, 0.0))
|
||||
.with_local_scale(Vector3::new(2.0, 2.0, 1.0))
|
||||
.build();
|
||||
|
||||
RigidBodyBuilder::new(
|
||||
BaseBuilder::new()
|
||||
.with_children(&[
|
||||
// Collider to prevent player from moving past boundary
|
||||
RectangleBuilder::new(BaseBuilder::new())
|
||||
.with_material(MaterialResource::new_ok(Default::default(), material))
|
||||
// Sprite is located in top left corner of sprite sheet
|
||||
.with_uv_rect(Rect::new(0.0, 0.3, 0.13, 0.8))
|
||||
.build(graph),
|
||||
ColliderBuilder::new(BaseBuilder::new())
|
||||
.with_shape(shape)
|
||||
.with_collision_groups(InteractionGroups::default())
|
||||
.with_solver_groups(InteractionGroups::default())
|
||||
.build(graph),
|
||||
])
|
||||
// Optional, set name of tile
|
||||
.with_name(format!("Sceleton ({x}, {y})",))
|
||||
// Set position of tile
|
||||
.with_local_transform(rb_transform)
|
||||
.with_script(enemy),
|
||||
)
|
||||
.with_mass(20.0)
|
||||
// Turn off gravity for tile
|
||||
.with_gravity_scale(1.)
|
||||
.with_lin_damping(0.0)
|
||||
// Set tile to be static and not rotate
|
||||
.with_rotation_locked(true)
|
||||
.with_body_type(RigidBodyType::Dynamic)
|
||||
.build(graph);
|
||||
}
|
||||
}
|
||||
impl ScriptTrait for SwordmanSpawn {
|
||||
fn on_init(&mut self, context: &mut ScriptContext) {
|
||||
let resource_manager: &ResourceManager = &context.resource_manager;
|
||||
self.spawn_enemy(&mut context.scene.graph, resource_manager, 0.0);
|
||||
// self.enemy.on_init(context);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,4 +1,5 @@
|
|||
//! Game project.
|
||||
use fyrox::graph::SceneGraph;
|
||||
use fyrox::{
|
||||
asset::manager::ResourceManager,
|
||||
core::{log::Log, pool::Handle},
|
||||
|
|
@ -11,18 +12,16 @@ use fyrox::{
|
|||
UiNode, UserInterface,
|
||||
},
|
||||
plugin::{Plugin, PluginConstructor, PluginContext, PluginRegistrationContext},
|
||||
scene::{graph::Graph, Scene,},
|
||||
scene::{graph::Graph, Scene},
|
||||
};
|
||||
use fyrox::graph::SceneGraph;
|
||||
use std::path::Path;
|
||||
mod enemy;
|
||||
mod enemy_spawn;
|
||||
mod enemies;
|
||||
mod map;
|
||||
mod msg;
|
||||
mod player;
|
||||
|
||||
use enemy::Enemy;
|
||||
use enemy_spawn::EnemySpawn;
|
||||
use enemies::swordsman::{enemy::Swordman, spawn::SwordmanSpawn};
|
||||
use enemies::archer::{enemy::Archer, spawn::ArcherSpawn};
|
||||
use map::build_map;
|
||||
use msg::Message;
|
||||
use player::Player;
|
||||
|
|
@ -33,7 +32,7 @@ impl PluginConstructor for GameConstructor {
|
|||
fn register(&self, context: PluginRegistrationContext) {
|
||||
// Register your scripts here.
|
||||
let script_constructors = &context.serialization_context.script_constructors;
|
||||
script_constructors.add::<Enemy>("Enemy");
|
||||
script_constructors.add::<Swordman>("Enemy");
|
||||
script_constructors.add::<Player>("Player");
|
||||
}
|
||||
|
||||
|
|
@ -47,6 +46,7 @@ pub struct Game {
|
|||
|
||||
new_game: Handle<UiNode>,
|
||||
exit: Handle<UiNode>,
|
||||
level: u32,
|
||||
}
|
||||
|
||||
impl Game {
|
||||
|
|
@ -56,7 +56,10 @@ impl Game {
|
|||
|result, game: &mut Game, ctx| match result {
|
||||
Ok(menu) => {
|
||||
*ctx.user_interface = menu;
|
||||
(game.new_game, _) = ctx.user_interface.find_by_name_from_root("NewGame").unwrap();
|
||||
(game.new_game, _) = ctx
|
||||
.user_interface
|
||||
.find_by_name_from_root("NewGame")
|
||||
.unwrap();
|
||||
(game.exit, _) = ctx.user_interface.find_by_name_from_root("Exit").unwrap();
|
||||
}
|
||||
Err(e) => Log::err(format!("Unable to load main menu! Reason: {:?}", e)),
|
||||
|
|
@ -68,6 +71,7 @@ impl Game {
|
|||
scene: Handle::NONE,
|
||||
new_game: Handle::NONE,
|
||||
exit: Handle::NONE,
|
||||
level: 1,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -113,8 +117,7 @@ impl Plugin for Game {
|
|||
MessageDirection::ToWidget,
|
||||
false,
|
||||
));
|
||||
ctx.async_scene_loader
|
||||
.request("data/scene.rgs");
|
||||
ctx.async_scene_loader.request("data/scene.rgs");
|
||||
} else if message.destination() == self.exit {
|
||||
if let Some(window_target) = ctx.window_target {
|
||||
window_target.exit();
|
||||
|
|
@ -148,6 +151,11 @@ impl Plugin for Game {
|
|||
let graph: &mut Graph = &mut context.scenes[self.scene].graph;
|
||||
let resource_manager: &ResourceManager = &context.resource_manager;
|
||||
build_map(graph, resource_manager);
|
||||
EnemySpawn::new().spawn_enemy(graph, resource_manager, -5.0);
|
||||
if self.level == 1 {
|
||||
SwordmanSpawn::new().spawn_enemy(graph, resource_manager, -5.0);
|
||||
}
|
||||
if self.level == 2 {
|
||||
ArcherSpawn::new().spawn_enemy(graph, resource_manager, -5.0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
use std::collections::VecDeque;
|
||||
|
||||
use crate::msg::Message;
|
||||
use crate::Enemy;
|
||||
use crate::Swordman;
|
||||
use fyrox::graph::BaseSceneGraph;
|
||||
use fyrox::{
|
||||
core::{
|
||||
|
|
@ -52,6 +52,7 @@ pub struct Player {
|
|||
start_fight_last: f32,
|
||||
prev_y_velosity: f32,
|
||||
damage: f32,
|
||||
damage: f32,
|
||||
|
||||
pub window_height: u32, // TODO: need change place
|
||||
pub window_width: u32,
|
||||
|
|
@ -366,9 +367,10 @@ impl Player {
|
|||
let enemy_script = context
|
||||
.scene
|
||||
.graph
|
||||
.try_get_script_of_mut::<Enemy>(d)
|
||||
.unwrap();
|
||||
enemy_script.take_damage(&self.damage);
|
||||
.try_get_script_of_mut::<Swordman>(d);
|
||||
if let Some(enemy) = enemy_script {
|
||||
enemy.take_damage(&self.damage);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue