Skip to content

Commit

Permalink
Merge pull request #112 from thombruce/feat/enemy-spawning
Browse files Browse the repository at this point in the history
Spawn Enemies
  • Loading branch information
thombruce authored Nov 18, 2023
2 parents 0f4eeb3 + ef02de4 commit fc5fc25
Show file tree
Hide file tree
Showing 6 changed files with 81 additions and 37 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,15 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
### Added

- Add game score that increases when player damages or destroys an enemy
- Spawn timer; enemies will now spawn continuously

### Changed

- Spawn enemies at random distance and direction from player
- Limit total concurrent enemies to 10
- Decrease static orbit scale (planets are now closer)
- Clamp orbit distance (prevents Moon orbiting inside of Earth sprite)
- Indicators spawn on update allowing new entities to be pointed to

## [0.0.25] - 2023-11-17

Expand Down
50 changes: 36 additions & 14 deletions src/ships/enemy.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use bevy::prelude::*;
use bevy_rapier2d::prelude::*;
use rand::Rng;

use crate::core::resources::assets::SpriteAssets;
use crate::systems::events::BulletSpawnEvent;
Expand All @@ -11,6 +12,16 @@ use super::{
ship::{ship_rotation, ship_thrust, Health, Ship},
};

pub struct SpawnTimerPlugin;
impl Plugin for SpawnTimerPlugin {
fn build(&self, app: &mut App) {
app.insert_resource(SpawnTimer(Timer::from_seconds(6.0, TimerMode::Repeating)));
}
}

#[derive(Resource)]
pub struct SpawnTimer(pub Timer);

/// Enemy component
#[derive(Component)]
pub struct Enemy;
Expand Down Expand Up @@ -69,19 +80,30 @@ pub struct Adversaries(pub Vec<DamagedBy>);
// retrieval/use at a later time.

/// The setup function
pub(crate) fn spawn_enemies(mut commands: Commands, sprites: Res<SpriteAssets>) {
// Spawns enemy ships
for (_i, pos) in [
(250.0 as f32, 250.0 as f32),
(-250.0 as f32, -250.0 as f32),
(-25000.0 as f32, 0.0 as f32),
(25000.0 as f32, 0.0 as f32),
(0.0 as f32, 25000.0 as f32),
(0.0 as f32, -25000.0 as f32),
]
.iter()
.enumerate()
{
pub(crate) fn spawn_enemies(
time: Res<Time>,
mut commands: Commands,
sprites: Res<SpriteAssets>,
mut spawn_timer: ResMut<SpawnTimer>,
player_position: Query<&Transform, With<Player>>,
enemies: Query<&Enemy>,
) {
// tick the timer
spawn_timer.0.tick(time.delta());

if spawn_timer.0.finished() && enemies.iter().count() < 10 {
let Ok(from) = player_position.get_single() else {
return;
};

let random_x = rand::thread_rng().gen_range(-25_000.0..25_000.0);
let random_y = rand::thread_rng().gen_range(-25_000.0..25_000.0);

let new_pos = (from.translation.truncate()
+ Vec2::new(random_x, random_y).clamp_length_min(5_000.0))
.extend(100.0);

// Spawns enemy ships
commands.spawn((
Enemy,
Ship {
Expand All @@ -95,7 +117,7 @@ pub(crate) fn spawn_enemies(mut commands: Commands, sprites: Res<SpriteAssets>)
SpriteBundle {
texture: sprites.enemy_ship.clone(),
transform: Transform {
translation: Vec3::new(pos.0, pos.1, 100.0),
translation: new_pos,
scale: Vec3::splat(0.5),
..default()
},
Expand Down
3 changes: 2 additions & 1 deletion src/ships/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,15 @@ pub mod enemy;
pub mod player;
pub mod ship;

use self::player::PlayerPlugin;
use self::{enemy::SpawnTimerPlugin, player::PlayerPlugin};

pub struct ShipsPlugin;
impl Plugin for ShipsPlugin {
fn build(&self, app: &mut App) {
app.add_plugins((
RapierPhysicsPlugin::<NoUserData>::pixels_per_meter(1.0),
PlayerPlugin,
SpawnTimerPlugin,
));
}
}
Expand Down
9 changes: 6 additions & 3 deletions src/ships/ship.rs
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,11 @@ pub(crate) fn ship_death_handling(
};

for event in death_events.read() {
if event.entity == player {
commands.entity(event.entity).despawn();
continue;
}

let Ok(adversaries) = adversaries.get(event.entity) else {
return;
};
Expand All @@ -111,9 +116,7 @@ pub(crate) fn ship_death_handling(

// If the destroyed ship is not the player, award XP to the player equal to
// 10x the damage the player has dealt to the ship.
if event.entity != player {
score.0 += 10 * player_dealt_damage; // TODO: Make proportionate to player-dealt damage relative to MaxHealth
}
score.0 += 10 * player_dealt_damage; // TODO: Make proportionate to player-dealt damage relative to MaxHealth

commands.entity(event.entity).despawn();
}
Expand Down
3 changes: 2 additions & 1 deletion src/systems/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,6 @@ impl Plugin for SystemsPlugin {
pause::setup_pause_systems,
ships::configure_physics_engine,
hud::spawn_hud,
enemy::spawn_enemies,
player::spawn_player,
// Planetary system spawning, chained
(
Expand Down Expand Up @@ -180,8 +179,10 @@ impl Plugin for SystemsPlugin {
effects::animate::animate_sprite,
astronomy::orbit::orbitable_update_system,
astronomy::orbit::orbital_positioning_system,
enemy::spawn_enemies,
ship::bullet_timers_system,
dynamic_orbit::dynamic_orbital_positioning_system,
hud::indicator::spawn_indicator_children.before(hud::indicator::indicators_system),
hud::indicator::indicators_system,
hud::speedometer::hud_speedometer,
hud::health::hud_health,
Expand Down
49 changes: 31 additions & 18 deletions src/ui/hud/indicator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,27 +15,39 @@ pub struct Indicator {
#[derive(Component, Clone, Debug)]
pub struct Bounds {}

pub(crate) fn spawn_indicators(
#[derive(Component, Clone, Debug)]
pub struct IndicatorsContainer;

pub(crate) fn spawn_indicators(mut commands: Commands) {
commands.spawn((
NodeBundle {
style: Style {
position_type: PositionType::Absolute,
width: Val::Percent(100.0),
height: Val::Percent(100.0),
..default()
},
..default()
},
Name::new("Indicators"),
Bounds {},
IndicatorsContainer,
));
}

pub(crate) fn spawn_indicator_children(
mut commands: Commands,
asset_server: Res<AssetServer>,
entities_query: Query<(Entity, &Indicated)>,
parent: Query<Entity, With<IndicatorsContainer>>,
indicators: Query<&Indicator>,
) {
commands
.spawn((
NodeBundle {
style: Style {
position_type: PositionType::Absolute,
width: Val::Percent(100.0),
height: Val::Percent(100.0),
..default()
},
..default()
},
Name::new("Indicators"),
Bounds {},
))
.with_children(|parent| {
for (entity, indicated) in entities_query.iter() {
let parent = parent.get_single().unwrap();

commands.entity(parent).with_children(|parent| {
// TODO: Spawn indicators when in range, despawn when out of range
for (entity, indicated) in entities_query.iter() {
if !indicators.iter().any(|i| i.entity == entity) {
parent.spawn((
ImageBundle {
image: UiImage::new(asset_server.load("images/grey_arrowUpWhite.png")),
Expand All @@ -51,7 +63,8 @@ pub(crate) fn spawn_indicators(
Indicator { entity: entity },
));
}
});
}
});
}

pub(crate) fn indicators_system(
Expand Down

0 comments on commit fc5fc25

Please sign in to comment.