Skip to content

Commit

Permalink
Add enemies, sorta
Browse files Browse the repository at this point in the history
  • Loading branch information
DotWith committed Aug 24, 2024
1 parent 8b8ac36 commit 5ecbe42
Show file tree
Hide file tree
Showing 19 changed files with 704 additions and 487 deletions.
1 change: 0 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,3 @@ bevy-panic-handler = "3.0.0"
avian3d = "0.1.2"
leafwing-input-manager = "0.15.0"
bevy_mod_billboard = "0.7.0"
bevy-inspector-egui = "0.25.2"
12 changes: 12 additions & 0 deletions src/game/enemy/components.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
use bevy::prelude::*;

#[derive(Component)]
pub struct Enemy {
pub speed: f32,
}

impl Default for Enemy {
fn default() -> Self {
Self { speed: 0.01 }
}
}
24 changes: 24 additions & 0 deletions src/game/enemy/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
use crate::AppState;
use bevy::{animation::animate_targets, prelude::*};
use systems::*;

pub mod components;
pub mod resources;
mod systems;

pub struct EnemyPlugin;

impl Plugin for EnemyPlugin {
fn build(&self, app: &mut App) {
app.add_systems(
Update,
enemies_once_loaded
.before(animate_targets)
.run_if(in_state(AppState::Game)),
)
.add_systems(
Update,
(enemies_update, enemies_animation).run_if(in_state(AppState::Game)),
);
}
}
8 changes: 8 additions & 0 deletions src/game/enemy/resources.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
use bevy::prelude::*;

#[derive(Resource)]
pub struct Animations {
pub animations: Vec<AnimationNodeIndex>,
#[allow(dead_code)]
pub graph: Handle<AnimationGraph>,
}
73 changes: 73 additions & 0 deletions src/game/enemy/systems.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
use super::{components::Enemy, resources::Animations};
use crate::game::player::components::Player;
use avian3d::prelude::*;
use bevy::prelude::*;
use std::time::Duration;

pub fn enemies_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[0], Duration::ZERO)
.repeat();

commands
.entity(entity)
.insert(animations.graph.clone())
.insert(transitions);
}
}

pub fn enemies_update(
mut e_query: Query<(&mut Transform, &mut LinearVelocity, &Visibility, &Enemy), Without<Player>>,
p_query: Query<&Transform, (With<Player>, Without<Enemy>)>,
) {
if let Ok(p_transform) = p_query.get_single() {
for (mut e_transform, mut linear_velocity, visibility, enemy) in &mut e_query {
if *visibility != Visibility::Hidden {
e_transform.look_at(p_transform.translation, Vec3::Y);
let direction = p_transform.translation - e_transform.translation;
if direction.length() > 1.5 {
let movement_direction = direction.normalize();
linear_velocity.0 += movement_direction * enemy.speed;
}
// BlurTimer = 200;
}
}
}
}

pub fn enemies_animation(
mut animation_players: Query<
(
&mut AnimationPlayer,
&mut AnimationTransitions,
&LinearVelocity,
),
With<Enemy>,
>,
animations: Res<Animations>,
) {
for (mut player, mut transitions, linear_velocity) in &mut animation_players {
let current_animation = if linear_velocity.length() > 0.0 {
animations.animations[1]
} else {
animations.animations[0]
};

if !player.is_playing_animation(current_animation) {
transitions
.play(&mut player, current_animation, Duration::ZERO)
.repeat();
}
}
}
4 changes: 4 additions & 0 deletions src/game/glimpse/components.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
use bevy::prelude::*;

#[derive(Component)]
pub struct Glimpse;
14 changes: 14 additions & 0 deletions src/game/glimpse/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
use crate::AppState;
use bevy::prelude::*;
use systems::update_glimpses;

pub mod components;
mod systems;

pub struct GlimpsePlugin;

impl Plugin for GlimpsePlugin {
fn build(&self, app: &mut App) {
app.add_systems(Update, update_glimpses.run_if(in_state(AppState::Game)));
}
}
31 changes: 31 additions & 0 deletions src/game/glimpse/systems.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
use super::components::Glimpse;
use crate::{game::player::components::Player, resources::AudioAssets};
use bevy::prelude::*;

#[allow(clippy::type_complexity)]
pub fn update_glimpses(
mut commands: Commands,
audio_assets: Res<AudioAssets>,
g_query: Query<(&Transform, Entity), (With<Glimpse>, Without<Player>)>,
p_query: Query<(&Player, &Transform), Without<Glimpse>>,
) {
for (player, p_transform) in &p_query {
for (g_transform, g_entity) in &g_query {
if player.floor_index - 1 == ((-g_transform.translation.y - 0.5) / 2.0) as usize
&& p_transform.translation.distance(Vec3::new(
g_transform.translation.x,
g_transform.translation.y,
g_transform.translation.z,
)) < 2.3
{
// TODO: Make a 3d audio
commands.spawn(AudioBundle {
source: audio_assets.no_sfx.clone(),
settings: PlaybackSettings::DESPAWN,
});

commands.entity(g_entity).despawn();
}
}
}
}
3 changes: 0 additions & 3 deletions src/game/components.rs → src/game/map/components.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,5 @@
use bevy::prelude::*;

#[derive(Component)]
pub struct Glimpse;

#[derive(Component)]
pub struct FloorLabelUi;

Expand Down
20 changes: 20 additions & 0 deletions src/game/map/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
use crate::AppState;
use bevy::prelude::*;
use resources::ObjectPool;
use systems::*;

pub mod components;
pub mod resources;
pub mod systems;

pub const FLOOR_AMOUNT: usize = 210;

pub struct MapPlugin;

impl Plugin for MapPlugin {
fn build(&self, app: &mut App) {
app.insert_resource(ObjectPool::default())
.add_systems(OnEnter(AppState::Game), spawn_map)
.add_systems(Update, update_floors.run_if(in_state(AppState::Game)));
}
}
119 changes: 82 additions & 37 deletions src/game/map_gen.rs → src/game/map/resources.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,80 @@
use bevy::prelude::*;
use super::FLOOR_AMOUNT;
use crate::resources::MapAssets;
use avian3d::prelude::*;
use bevy::{prelude::*, utils::HashMap};
use bevy_rand::prelude::*;
use rand::Rng;
use rand::prelude::*;

#[derive(Resource, Default)]
pub struct ObjectPool {
available_rooms: HashMap<RoomType, Vec<Entity>>,
pub active_rooms: HashMap<usize, Entity>,
}

impl ObjectPool {
pub fn get_or_spawn(
&mut self,
room_index: usize,
room: &Room,
commands: &mut Commands,
map_assets: &Res<MapAssets>,
transform: Transform,
) -> Entity {
// Check if the room is already active
if let Some(&entity) = self.active_rooms.get(&room_index) {
// Update the transform if the room is already active
commands.entity(entity).insert(transform);
return entity;
}

// Get the available rooms list, or create an empty list if none exists
let available_rooms = self.available_rooms.entry(room.kind).or_default();

let entity = if let Some(entity) = available_rooms.pop() {
commands.entity(entity).insert(transform);
entity
} else {
// Spawn a new entity if none are available
let scene = match room.kind {
RoomType::Map => map_assets.map.clone(),
RoomType::Map0 => map_assets.map0.clone(),
RoomType::Map1 => map_assets.map1.clone(),
RoomType::Map2 => map_assets.map2.clone(),
RoomType::Map3 => map_assets.map3.clone(),
RoomType::Map4 => map_assets.map4.clone(),
RoomType::Map5 => map_assets.map5.clone(),
RoomType::Map6 => map_assets.map6.clone(),
RoomType::Maze => map_assets.map7.clone(),
};

let new_entity = commands
.spawn((
SceneBundle {
scene,
transform,
..default()
},
ColliderConstructorHierarchy::new(Some(ColliderConstructor::TrimeshFromMesh)),
RigidBody::Static,
))
.id();
new_entity
};

// Mark this room as active
self.active_rooms.insert(room_index, entity);
entity
}

pub fn release(&mut self, room_index: usize, room_type: RoomType) {
if let Some(entity) = self.active_rooms.remove(&room_index) {
self.available_rooms
.entry(room_type)
.or_default()
.push(entity);
}
}
}

#[derive(PartialEq, Eq, Default, Clone, Copy, Debug)]
pub enum FloorAction {
Expand Down Expand Up @@ -57,15 +131,17 @@ pub struct Map {
pub rooms: Vec<Room>,
}

impl Map {
pub fn new(floor_amount: usize) -> Self {
impl Default for Map {
fn default() -> Self {
Self {
floor_amount,
floors: vec![Floor::default(); floor_amount],
floor_amount: FLOOR_AMOUNT,
floors: vec![Floor::default(); FLOOR_AMOUNT],
rooms: Default::default(),
}
}
}

impl Map {
pub fn generate(&mut self, rng: &mut ResMut<GlobalEntropy<WyRand>>) {
self.assign_floor_action(1, FloorAction::Proceed, 1.0);

Expand Down Expand Up @@ -245,34 +321,3 @@ impl Map {
[above_room, current_room, bottom_room]
}
}

pub fn floor_transform(i: usize) -> Transform {
let mut transform = Transform::default();

if (i as f32 / 2.0).floor() == (i as f32 / 2.0).ceil() {
// parillinen
transform.translation = Vec3::new(0.0, -(i as f32) * 2.0, 0.0);
} else {
// pariton
transform.rotate_y(f32::to_radians(180.0));
transform.translation = Vec3::new(8.0, -(i as f32) * 2.0, 7.0);
}

transform
}

pub fn room_label_transform(i: usize) -> Transform {
let mut transform = Transform {
rotation: Quat::from_rotation_x(f32::to_radians(-90.0)),
..default()
};

if (i as f32 / 2.0).floor() == (i as f32 / 2.0).ceil() {
transform.translation = Vec3::new(-0.24, -(i as f32) * 2.0 - 0.6, 0.5);
transform.rotate_y(f32::to_radians(180.0));
} else {
transform.translation = Vec3::new(7.4 + 0.6 + 0.24, -(i as f32) * 2.0 - 0.6, 6.0 + 0.5);
}

transform
}
Loading

0 comments on commit 5ecbe42

Please sign in to comment.