new character format
This commit is contained in:
BIN
assets/models/characters/angry demonstrator.glb
Normal file
BIN
assets/models/characters/angry demonstrator.glb
Normal file
Binary file not shown.
BIN
assets/models/characters/field medic.glb
Normal file
BIN
assets/models/characters/field medic.glb
Normal file
Binary file not shown.
Binary file not shown.
BIN
assets/models/characters/mig pilot.glb
Normal file
BIN
assets/models/characters/mig pilot.glb
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
81
src/alien.rs
81
src/alien.rs
@@ -1,81 +0,0 @@
|
|||||||
use crate::{GameState, loading_assets::GameAssets};
|
|
||||||
use bevy::prelude::*;
|
|
||||||
use std::time::Duration;
|
|
||||||
|
|
||||||
#[derive(Resource)]
|
|
||||||
pub struct Animations {
|
|
||||||
pub animations: Vec<AnimationNodeIndex>,
|
|
||||||
pub graph: Handle<AnimationGraph>,
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn plugin(app: &mut App) {
|
|
||||||
app.add_systems(OnEnter(GameState::Playing), setup);
|
|
||||||
app.add_systems(
|
|
||||||
Update,
|
|
||||||
(setup_once_loaded, toggle_animation).run_if(in_state(GameState::Playing)),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
fn setup(
|
|
||||||
mut commands: Commands,
|
|
||||||
assets: Res<GameAssets>,
|
|
||||||
mut graphs: ResMut<Assets<AnimationGraph>>,
|
|
||||||
) {
|
|
||||||
// Build the animation graph
|
|
||||||
let (graph, node_indices) = AnimationGraph::from_clips([
|
|
||||||
assets.animations_alien.get("Animation2").cloned().unwrap(),
|
|
||||||
assets.animations_alien.get("Animation1").cloned().unwrap(),
|
|
||||||
assets.animations_alien.get("Animation0").cloned().unwrap(),
|
|
||||||
]);
|
|
||||||
|
|
||||||
// Insert a resource with the current scene information
|
|
||||||
let graph_handle = graphs.add(graph);
|
|
||||||
commands.insert_resource(Animations {
|
|
||||||
animations: node_indices,
|
|
||||||
graph: graph_handle,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
fn setup_once_loaded(
|
|
||||||
mut commands: Commands,
|
|
||||||
animations: Res<Animations>,
|
|
||||||
mut players: Query<(Entity, &mut AnimationPlayer), Added<AnimationPlayer>>,
|
|
||||||
) {
|
|
||||||
for (entity, mut player) in &mut players {
|
|
||||||
let mut transitions = AnimationTransitions::new();
|
|
||||||
|
|
||||||
// Make sure to start the animation via the `AnimationTransitions`
|
|
||||||
// component. The `AnimationTransitions` component wants to manage all
|
|
||||||
// the animations and will get confused if the animations are started
|
|
||||||
// directly via the `AnimationPlayer`.
|
|
||||||
transitions
|
|
||||||
.play(&mut player, animations.animations[1], Duration::ZERO)
|
|
||||||
.repeat();
|
|
||||||
|
|
||||||
commands
|
|
||||||
.entity(entity)
|
|
||||||
.insert(AnimationGraphHandle(animations.graph.clone()))
|
|
||||||
.insert(transitions);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn toggle_animation(
|
|
||||||
animations: Res<Animations>,
|
|
||||||
mut transitions: Query<(&mut AnimationTransitions, &mut AnimationPlayer)>,
|
|
||||||
keys: Res<ButtonInput<KeyCode>>,
|
|
||||||
mut animation_index: Local<u32>,
|
|
||||||
) {
|
|
||||||
if keys.just_pressed(KeyCode::KeyT) {
|
|
||||||
for (mut transition, mut player) in &mut transitions {
|
|
||||||
transition
|
|
||||||
.play(
|
|
||||||
&mut player,
|
|
||||||
animations.animations[*animation_index as usize],
|
|
||||||
Duration::from_secs(1),
|
|
||||||
)
|
|
||||||
.repeat();
|
|
||||||
}
|
|
||||||
|
|
||||||
*animation_index ^= 1; // Toggle between 0 and 1
|
|
||||||
}
|
|
||||||
}
|
|
||||||
102
src/character.rs
Normal file
102
src/character.rs
Normal file
@@ -0,0 +1,102 @@
|
|||||||
|
use crate::{GameState, heads_database::HeadsDatabase, loading_assets::GameAssets};
|
||||||
|
use bevy::{prelude::*, utils::HashMap};
|
||||||
|
use std::time::Duration;
|
||||||
|
|
||||||
|
#[derive(Component, Debug)]
|
||||||
|
pub struct AnimatedCharacter(pub usize);
|
||||||
|
|
||||||
|
#[derive(Component, Debug, Reflect)]
|
||||||
|
#[reflect(Component)]
|
||||||
|
pub struct CharacterAnimations {
|
||||||
|
pub idle: AnimationNodeIndex,
|
||||||
|
pub run: AnimationNodeIndex,
|
||||||
|
pub jump: AnimationNodeIndex,
|
||||||
|
pub graph: Handle<AnimationGraph>,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn plugin(app: &mut App) {
|
||||||
|
app.add_systems(
|
||||||
|
Update,
|
||||||
|
(spawn, setup_once_loaded).run_if(in_state(GameState::Playing)),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn spawn(
|
||||||
|
mut commands: Commands,
|
||||||
|
mut query: Query<(Entity, &AnimatedCharacter), Added<AnimatedCharacter>>,
|
||||||
|
gltf_assets: Res<Assets<Gltf>>,
|
||||||
|
assets: Res<GameAssets>,
|
||||||
|
heads_db: Res<HeadsDatabase>,
|
||||||
|
) {
|
||||||
|
for (entity, character) in &mut query {
|
||||||
|
let key = heads_db.head_key(character.0);
|
||||||
|
|
||||||
|
let handle = assets
|
||||||
|
.characters
|
||||||
|
.get(format!("{key}.glb").as_str())
|
||||||
|
.unwrap_or_else(|| {
|
||||||
|
//TODO: remove once we use the new format for all
|
||||||
|
info!("Character not found, using default [{}]", key);
|
||||||
|
&assets.characters["angry demonstrator.glb"]
|
||||||
|
});
|
||||||
|
let asset = gltf_assets.get(handle).unwrap();
|
||||||
|
|
||||||
|
commands.entity(entity).insert((
|
||||||
|
Transform::from_translation(Vec3::new(0., -1.45, 0.)).with_scale(Vec3::splat(1.2)),
|
||||||
|
SceneRoot(asset.scenes[0].clone()),
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn setup_once_loaded(
|
||||||
|
mut commands: Commands,
|
||||||
|
mut query: Query<(Entity, &mut AnimationPlayer), Added<AnimationPlayer>>,
|
||||||
|
parent_query: Query<&Parent>,
|
||||||
|
animated_character: Query<&AnimatedCharacter>,
|
||||||
|
assets: Res<GameAssets>,
|
||||||
|
gltf_assets: Res<Assets<Gltf>>,
|
||||||
|
mut graphs: ResMut<Assets<AnimationGraph>>,
|
||||||
|
) {
|
||||||
|
for (entity, mut player) in &mut query {
|
||||||
|
let Some(_animated_character) = parent_query
|
||||||
|
.iter_ancestors(entity)
|
||||||
|
.find_map(|ancestor| animated_character.get(ancestor).ok())
|
||||||
|
else {
|
||||||
|
continue;
|
||||||
|
};
|
||||||
|
|
||||||
|
let (_, handle) = assets.characters.iter().next().unwrap();
|
||||||
|
let asset = gltf_assets.get(handle).unwrap();
|
||||||
|
|
||||||
|
let animations = asset
|
||||||
|
.named_animations
|
||||||
|
.iter()
|
||||||
|
.map(|(name, animation)| (name.to_string(), animation.clone()))
|
||||||
|
.collect::<HashMap<_, _>>();
|
||||||
|
|
||||||
|
let (graph, node_indices) = AnimationGraph::from_clips([
|
||||||
|
animations["idle"].clone(),
|
||||||
|
animations["run"].clone(),
|
||||||
|
animations["jump"].clone(),
|
||||||
|
]);
|
||||||
|
|
||||||
|
// // Insert a resource with the current scene information
|
||||||
|
let graph_handle = graphs.add(graph);
|
||||||
|
let animations = CharacterAnimations {
|
||||||
|
idle: node_indices[0],
|
||||||
|
run: node_indices[1],
|
||||||
|
jump: node_indices[2],
|
||||||
|
graph: graph_handle.clone(),
|
||||||
|
};
|
||||||
|
|
||||||
|
let mut transitions = AnimationTransitions::new();
|
||||||
|
transitions
|
||||||
|
.play(&mut player, animations.idle, Duration::ZERO)
|
||||||
|
.repeat();
|
||||||
|
commands
|
||||||
|
.entity(entity)
|
||||||
|
.insert(AnimationGraphHandle(animations.graph.clone()))
|
||||||
|
.insert(transitions)
|
||||||
|
.insert(animations);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -38,7 +38,6 @@ pub struct AudioAssets {
|
|||||||
pub throw_explosion: Handle<AudioSource>,
|
pub throw_explosion: Handle<AudioSource>,
|
||||||
#[asset(path = "sfx/abilities/jet.ogg")]
|
#[asset(path = "sfx/abilities/jet.ogg")]
|
||||||
pub jet: Handle<AudioSource>,
|
pub jet: Handle<AudioSource>,
|
||||||
|
|
||||||
#[asset(path = "sfx/ui/backpack_open.ogg")]
|
#[asset(path = "sfx/ui/backpack_open.ogg")]
|
||||||
pub backpack_open: Handle<AudioSource>,
|
pub backpack_open: Handle<AudioSource>,
|
||||||
#[asset(path = "sfx/ui/backpack_close.ogg")]
|
#[asset(path = "sfx/ui/backpack_close.ogg")]
|
||||||
@@ -91,21 +90,11 @@ pub struct GameAssets {
|
|||||||
#[asset(path = "models/cash.glb#Scene0")]
|
#[asset(path = "models/cash.glb#Scene0")]
|
||||||
pub mesh_cash: Handle<Scene>,
|
pub mesh_cash: Handle<Scene>,
|
||||||
|
|
||||||
#[asset(path = "models/alien_naked.glb#Scene0")]
|
|
||||||
pub mesh_alien: Handle<Scene>,
|
|
||||||
|
|
||||||
#[asset(
|
|
||||||
paths(
|
|
||||||
"models/alien_naked.glb#Animation0",
|
|
||||||
"models/alien_naked.glb#Animation1",
|
|
||||||
"models/alien_naked.glb#Animation2",
|
|
||||||
),
|
|
||||||
collection(mapped, typed)
|
|
||||||
)]
|
|
||||||
pub animations_alien: HashMap<AssetLabel, Handle<AnimationClip>>,
|
|
||||||
|
|
||||||
#[asset(path = "models/projectiles", collection(mapped, typed))]
|
#[asset(path = "models/projectiles", collection(mapped, typed))]
|
||||||
pub projectiles: HashMap<AssetFileName, Handle<Gltf>>,
|
pub projectiles: HashMap<AssetFileName, Handle<Gltf>>,
|
||||||
|
|
||||||
|
#[asset(path = "models/characters", collection(mapped, typed))]
|
||||||
|
pub characters: HashMap<AssetFileName, Handle<Gltf>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct LoadingPlugin;
|
pub struct LoadingPlugin;
|
||||||
|
|||||||
@@ -1,11 +1,11 @@
|
|||||||
mod abilities;
|
mod abilities;
|
||||||
mod ai;
|
mod ai;
|
||||||
mod aim;
|
mod aim;
|
||||||
mod alien;
|
|
||||||
mod backpack;
|
mod backpack;
|
||||||
mod camera;
|
mod camera;
|
||||||
mod cash;
|
mod cash;
|
||||||
mod cash_heal;
|
mod cash_heal;
|
||||||
|
mod character;
|
||||||
mod control;
|
mod control;
|
||||||
mod cutscene;
|
mod cutscene;
|
||||||
mod debug;
|
mod debug;
|
||||||
@@ -126,7 +126,7 @@ fn main() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
app.add_plugins(ai::plugin);
|
app.add_plugins(ai::plugin);
|
||||||
app.add_plugins(alien::plugin);
|
app.add_plugins(character::plugin);
|
||||||
app.add_plugins(cash::plugin);
|
app.add_plugins(cash::plugin);
|
||||||
app.add_plugins(player::plugin);
|
app.add_plugins(player::plugin);
|
||||||
app.add_plugins(gates::plugin);
|
app.add_plugins(gates::plugin);
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
use crate::{
|
use crate::{
|
||||||
GameState,
|
GameState,
|
||||||
ai::Ai,
|
ai::Ai,
|
||||||
|
character::AnimatedCharacter,
|
||||||
head::ActiveHead,
|
head::ActiveHead,
|
||||||
head_drop::HeadDrops,
|
head_drop::HeadDrops,
|
||||||
heads::{ActiveHeads, HEAD_COUNT, HeadState},
|
heads::{ActiveHeads, HEAD_COUNT, HeadState},
|
||||||
@@ -44,6 +45,7 @@ fn init(mut commands: Commands, query: Query<(Entity, &EnemySpawn)>, heads_db: R
|
|||||||
]),
|
]),
|
||||||
Ai,
|
Ai,
|
||||||
))
|
))
|
||||||
|
.with_child((Name::from("body-rig"), AnimatedCharacter(id)))
|
||||||
.observe(on_kill);
|
.observe(on_kill);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,15 +1,15 @@
|
|||||||
use crate::{
|
use crate::{
|
||||||
GameState,
|
GameState,
|
||||||
alien::Animations,
|
|
||||||
camera::{CameraArmRotation, CameraTarget},
|
camera::{CameraArmRotation, CameraTarget},
|
||||||
cash::{Cash, CashCollectEvent},
|
cash::{Cash, CashCollectEvent},
|
||||||
|
character::{AnimatedCharacter, CharacterAnimations},
|
||||||
control::controller_common::{CharacterControllerBundle, PlayerMovement},
|
control::controller_common::{CharacterControllerBundle, PlayerMovement},
|
||||||
global_observer,
|
global_observer,
|
||||||
head::ActiveHead,
|
head::ActiveHead,
|
||||||
heads::{ActiveHeads, HeadChanged, HeadState},
|
heads::{ActiveHeads, HeadChanged, HeadState},
|
||||||
heads_database::{HeadControls, HeadsDatabase},
|
heads_database::{HeadControls, HeadsDatabase},
|
||||||
hitpoints::Hitpoints,
|
hitpoints::Hitpoints,
|
||||||
loading_assets::{AudioAssets, GameAssets},
|
loading_assets::AudioAssets,
|
||||||
physics_layers::GameLayer,
|
physics_layers::GameLayer,
|
||||||
sounds::PlaySound,
|
sounds::PlaySound,
|
||||||
tb_entities::SpawnPoint,
|
tb_entities::SpawnPoint,
|
||||||
@@ -29,9 +29,6 @@ pub struct Player;
|
|||||||
#[derive(Component, Default)]
|
#[derive(Component, Default)]
|
||||||
struct PlayerAnimations;
|
struct PlayerAnimations;
|
||||||
|
|
||||||
#[derive(Component, Default)]
|
|
||||||
struct PlayerHeadMesh;
|
|
||||||
|
|
||||||
#[derive(Component, Default)]
|
#[derive(Component, Default)]
|
||||||
pub struct PlayerBodyMesh;
|
pub struct PlayerBodyMesh;
|
||||||
|
|
||||||
@@ -56,7 +53,6 @@ fn spawn(
|
|||||||
mut commands: Commands,
|
mut commands: Commands,
|
||||||
asset_server: Res<AssetServer>,
|
asset_server: Res<AssetServer>,
|
||||||
query: Query<&Transform, With<SpawnPoint>>,
|
query: Query<&Transform, With<SpawnPoint>>,
|
||||||
assets: Res<GameAssets>,
|
|
||||||
heads_db: Res<HeadsDatabase>,
|
heads_db: Res<HeadsDatabase>,
|
||||||
) {
|
) {
|
||||||
let Some(spawn) = query.iter().next() else {
|
let Some(spawn) = query.iter().next() else {
|
||||||
@@ -65,9 +61,6 @@ fn spawn(
|
|||||||
|
|
||||||
let transform = Transform::from_translation(spawn.translation + Vec3::new(0., 3., 0.));
|
let transform = Transform::from_translation(spawn.translation + Vec3::new(0., 3., 0.));
|
||||||
|
|
||||||
let mesh = asset_server
|
|
||||||
.load(GltfAssetLabel::Scene(0).from_asset("models/heads/angry demonstrator.glb"));
|
|
||||||
|
|
||||||
let gravity = Vector::NEG_Y * 40.0;
|
let gravity = Vector::NEG_Y * 40.0;
|
||||||
let collider = Collider::capsule(0.9, 1.2);
|
let collider = Collider::capsule(0.9, 1.2);
|
||||||
|
|
||||||
@@ -94,21 +87,13 @@ fn spawn(
|
|||||||
.with_children(|parent| {
|
.with_children(|parent| {
|
||||||
parent
|
parent
|
||||||
.spawn((
|
.spawn((
|
||||||
Name::from("body rig"),
|
Name::new("player-rig"),
|
||||||
|
Transform::default(),
|
||||||
|
Visibility::default(),
|
||||||
PlayerBodyMesh,
|
PlayerBodyMesh,
|
||||||
CameraArmRotation,
|
CameraArmRotation,
|
||||||
Transform::from_translation(Vec3::new(0., -1.45, 0.))
|
|
||||||
.with_rotation(Quat::from_rotation_y(std::f32::consts::PI))
|
|
||||||
.with_scale(Vec3::splat(1.4)),
|
|
||||||
SceneRoot(assets.mesh_alien.clone()),
|
|
||||||
))
|
))
|
||||||
.with_child((
|
.with_child(AnimatedCharacter(0));
|
||||||
Name::from("head"),
|
|
||||||
PlayerHeadMesh,
|
|
||||||
Transform::from_translation(Vec3::new(0., 1.6, 0.))
|
|
||||||
.with_scale(Vec3::splat(0.7)),
|
|
||||||
SceneRoot(mesh),
|
|
||||||
));
|
|
||||||
});
|
});
|
||||||
|
|
||||||
commands.spawn((
|
commands.spawn((
|
||||||
@@ -176,29 +161,33 @@ fn setup_animations_marker_for_player(
|
|||||||
for ancestor in parent_query.iter_ancestors(entity) {
|
for ancestor in parent_query.iter_ancestors(entity) {
|
||||||
if player.contains(ancestor) {
|
if player.contains(ancestor) {
|
||||||
commands.entity(entity).insert(PlayerAnimations);
|
commands.entity(entity).insert(PlayerAnimations);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn toggle_animation(
|
fn toggle_animation(
|
||||||
animations: Res<Animations>,
|
|
||||||
mut transitions: Query<
|
mut transitions: Query<
|
||||||
(&mut AnimationTransitions, &mut AnimationPlayer),
|
(
|
||||||
|
&mut AnimationTransitions,
|
||||||
|
&mut AnimationPlayer,
|
||||||
|
&CharacterAnimations,
|
||||||
|
),
|
||||||
With<PlayerAnimations>,
|
With<PlayerAnimations>,
|
||||||
>,
|
>,
|
||||||
movement: Res<PlayerMovement>,
|
movement: Res<PlayerMovement>,
|
||||||
) {
|
) {
|
||||||
if movement.is_changed() {
|
if movement.is_changed() {
|
||||||
let index = if movement.any_direction { 0 } else { 1 };
|
for (mut transition, mut player, animations) in &mut transitions {
|
||||||
|
let index = if movement.any_direction {
|
||||||
|
animations.run
|
||||||
|
} else {
|
||||||
|
animations.idle
|
||||||
|
};
|
||||||
|
|
||||||
for (mut transition, mut player) in &mut transitions {
|
|
||||||
transition
|
transition
|
||||||
.play(
|
.play(&mut player, index, Duration::from_millis(100))
|
||||||
&mut player,
|
|
||||||
animations.animations[index],
|
|
||||||
Duration::from_millis(100),
|
|
||||||
)
|
|
||||||
.repeat();
|
.repeat();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -207,13 +196,12 @@ fn toggle_animation(
|
|||||||
fn on_update_head(
|
fn on_update_head(
|
||||||
trigger: Trigger<HeadChanged>,
|
trigger: Trigger<HeadChanged>,
|
||||||
mut commands: Commands,
|
mut commands: Commands,
|
||||||
asset_server: Res<AssetServer>,
|
body_mesh: Query<Entity, With<PlayerBodyMesh>>,
|
||||||
head: Query<Entity, With<PlayerHeadMesh>>,
|
|
||||||
mut player_head: Query<&mut ActiveHead, With<Player>>,
|
mut player_head: Query<&mut ActiveHead, With<Player>>,
|
||||||
head_db: Res<HeadsDatabase>,
|
head_db: Res<HeadsDatabase>,
|
||||||
audio_assets: Res<AudioAssets>,
|
audio_assets: Res<AudioAssets>,
|
||||||
) {
|
) {
|
||||||
let Ok(head) = head.get_single() else {
|
let Ok(body_mesh) = body_mesh.get_single() else {
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -227,21 +215,15 @@ fn on_update_head(
|
|||||||
|
|
||||||
commands.trigger(PlaySound::Head(head_str.to_string()));
|
commands.trigger(PlaySound::Head(head_str.to_string()));
|
||||||
|
|
||||||
//TODO: load from dynamic asset collection? or keep lazy?
|
commands.entity(body_mesh).despawn_descendants();
|
||||||
let mesh = asset_server
|
|
||||||
.load(GltfAssetLabel::Scene(0).from_asset(format!("models/heads/{}.glb", head_str)));
|
|
||||||
|
|
||||||
commands.entity(head).despawn_descendants();
|
commands
|
||||||
commands.entity(head).insert(SceneRoot(mesh));
|
.entity(body_mesh)
|
||||||
|
.with_child(AnimatedCharacter(trigger.0));
|
||||||
|
|
||||||
//TODO: make part of full character mesh later
|
//TODO: make part of full character mesh later
|
||||||
if head_db.head_stats(trigger.0).controls == HeadControls::Plane {
|
if head_db.head_stats(trigger.0).controls == HeadControls::Plane {
|
||||||
let mesh = asset_server.load(GltfAssetLabel::Scene(0).from_asset("models/mig.glb"));
|
commands.entity(body_mesh).with_child((
|
||||||
|
|
||||||
commands
|
|
||||||
.entity(head)
|
|
||||||
.with_child((Transform::from_xyz(0., -1., 0.), SceneRoot(mesh)))
|
|
||||||
.with_child((
|
|
||||||
Name::new("sfx"),
|
Name::new("sfx"),
|
||||||
AudioPlayer::new(audio_assets.jet.clone()),
|
AudioPlayer::new(audio_assets.jet.clone()),
|
||||||
PlaybackSettings {
|
PlaybackSettings {
|
||||||
|
|||||||
@@ -117,11 +117,8 @@ pub struct EnemySpawn {
|
|||||||
|
|
||||||
impl EnemySpawn {
|
impl EnemySpawn {
|
||||||
fn on_add(mut world: DeferredWorld, entity: Entity, _id: ComponentId) {
|
fn on_add(mut world: DeferredWorld, entity: Entity, _id: ComponentId) {
|
||||||
let Some(asset_server) = world.get_resource::<AssetServer>() else {
|
//TODO: figure out why this crashes if removed
|
||||||
return;
|
let Some(_assets) = world.get_resource::<GameAssets>() else {
|
||||||
};
|
|
||||||
|
|
||||||
let Some(assets) = world.get_resource::<GameAssets>() else {
|
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -135,17 +132,9 @@ impl EnemySpawn {
|
|||||||
let mut this_transform = *this_transform;
|
let mut this_transform = *this_transform;
|
||||||
this_transform.translation += Vec3::new(0., 1., 0.);
|
this_transform.translation += Vec3::new(0., 1., 0.);
|
||||||
|
|
||||||
let mesh = assets.mesh_alien.clone();
|
|
||||||
|
|
||||||
let head_mesh = asset_server
|
|
||||||
.load(GltfAssetLabel::Scene(0).from_asset(format!("models/heads/{}.glb", this.head)));
|
|
||||||
|
|
||||||
let head = this.head.clone();
|
let head = this.head.clone();
|
||||||
|
|
||||||
world
|
world.commands().entity(entity).insert((
|
||||||
.commands()
|
|
||||||
.entity(entity)
|
|
||||||
.insert((
|
|
||||||
this_transform,
|
this_transform,
|
||||||
Name::from(format!("enemy [{}]", head)),
|
Name::from(format!("enemy [{}]", head)),
|
||||||
Visibility::default(),
|
Visibility::default(),
|
||||||
@@ -153,20 +142,7 @@ impl EnemySpawn {
|
|||||||
Collider::capsule(0.4, 2.),
|
Collider::capsule(0.4, 2.),
|
||||||
CollisionLayers::new(LayerMask(GameLayer::Npc.to_bits()), LayerMask::ALL),
|
CollisionLayers::new(LayerMask(GameLayer::Npc.to_bits()), LayerMask::ALL),
|
||||||
LockedAxes::new().lock_rotation_z().lock_rotation_x(),
|
LockedAxes::new().lock_rotation_z().lock_rotation_x(),
|
||||||
))
|
|
||||||
.with_children(|parent| {
|
|
||||||
parent
|
|
||||||
.spawn((
|
|
||||||
Transform::from_translation(Vec3::new(0., 1., 0.)),
|
|
||||||
SceneRoot(head_mesh),
|
|
||||||
))
|
|
||||||
.with_child((
|
|
||||||
Visibility::default(),
|
|
||||||
Transform::from_translation(Vec3::new(0., -2.4, 0.))
|
|
||||||
.with_scale(Vec3::splat(1.5)),
|
|
||||||
SceneRoot(mesh),
|
|
||||||
));
|
));
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user