1

Add anthilll + ants spawning from it over time

This commit is contained in:
2024-10-06 19:04:01 +02:00
parent a7f1d3e65c
commit 160b4156b5
7 changed files with 134 additions and 34 deletions

BIN
assets/sprites/anthill.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 180 KiB

45
src/components/anthill.rs Normal file
View File

@ -0,0 +1,45 @@
use bevy::prelude::*;
#[derive(Bundle)]
#[allow(clippy::module_name_repetitions)]
pub struct AnthillBundle {
pub capacity: AntCapacity,
pub group_size: GroupSize,
pub spawn_timer: SpawnTimer,
pub sprite: SpriteBundle,
}
#[derive(Component)]
pub struct AntCapacity(pub u32);
#[derive(Component)]
pub struct GroupSize(pub u32);
#[derive(Component)]
pub struct SpawnTimer(pub Timer);
impl AnthillBundle {
pub fn new(
ant_count: u32,
group_size: u32,
period: f32,
position: Vec2,
scale: Vec2,
texture: Handle<Image>,
) -> Self {
Self {
capacity: AntCapacity(ant_count),
group_size: GroupSize(group_size),
spawn_timer: SpawnTimer(Timer::from_seconds(period, TimerMode::Repeating)),
sprite: SpriteBundle {
transform: Transform {
translation: position.extend(1.), // Make sure the anthill occludes the ants
scale: scale.extend(1.),
..default()
},
texture,
..default()
},
}
}
}

View File

@ -1,2 +1,3 @@
pub mod ant; pub mod ant;
pub mod anthill;
pub mod common; pub mod common;

View File

@ -9,6 +9,7 @@ use systems::{
animation_system, position_update_system, randomized_velocity_change_system, animation_system, position_update_system, randomized_velocity_change_system,
randomized_velocity_system, wall_avoidance_system, randomized_velocity_system, wall_avoidance_system,
}, },
anthill::leave_anthill_system,
startup::{hello_ants_system, setup_system}, startup::{hello_ants_system, setup_system},
}; };
@ -16,9 +17,9 @@ use systems::{
const MIN_POSITION: Vec2 = Vec2::splat(-450.); const MIN_POSITION: Vec2 = Vec2::splat(-450.);
const MAX_POSITION: Vec2 = Vec2::splat(450.); const MAX_POSITION: Vec2 = Vec2::splat(450.);
const ANT_COUNT: u32 = 200; const ANT_COUNT: u32 = 20;
const ANT_SPEED: f32 = 0.5; const ANT_SPEED: f32 = 0.5;
const ANT_ANIMATION_SPEED: f32 = 1. / 62.; const ANT_ANIMATION_SPEED: f32 = 1. / 82.;
const ANT_SCALE: f32 = 0.15; const ANT_SCALE: f32 = 0.15;
const VELOCITY_CHANGE_SCALE: f32 = PI / 180. * 1.; // Single degree const VELOCITY_CHANGE_SCALE: f32 = PI / 180. * 1.; // Single degree
@ -53,6 +54,7 @@ fn main() {
app.add_systems( app.add_systems(
FixedUpdate, FixedUpdate,
( (
leave_anthill_system,
randomized_velocity_change_system, randomized_velocity_change_system,
randomized_velocity_system, randomized_velocity_system,
wall_avoidance_system, wall_avoidance_system,

72
src/systems/anthill.rs Normal file
View File

@ -0,0 +1,72 @@
use bevy::prelude::*;
use rand::Rng;
use crate::{
components::{
ant::AntBundle,
anthill::{AntCapacity, GroupSize, SpawnTimer},
common::AnimationIndices,
},
ANT_COUNT, ANT_SCALE,
};
#[allow(clippy::needless_pass_by_value)]
pub fn leave_anthill_system(
mut query: Query<(&mut AntCapacity, &GroupSize, &mut SpawnTimer)>,
mut commands: Commands,
time: Res<Time>,
asset_server: Res<AssetServer>,
mut texture_atlas_layouts: ResMut<Assets<TextureAtlasLayout>>,
) {
for (mut capacity, group_size, mut timer) in &mut query {
timer.0.tick(time.delta());
// Anthill empty :(
if capacity.0 == 0 {
continue;
}
// Each timer period we want to spawn between 1 and group_size ants
if timer.0.just_finished() {
let num_ants: u32 = rand::thread_rng()
.gen_range(1..group_size.0)
.clamp(1, capacity.0);
for _ in 0..num_ants {
spawn_cute_ant(&mut commands, &asset_server, &mut texture_atlas_layouts);
}
capacity.0 -= num_ants;
println!(
"Spawned {} cute ants 😍, {} ants are still at home 🏠",
num_ants, capacity.0
);
}
}
}
fn spawn_cute_ant(
commands: &mut Commands,
asset_server: &Res<AssetServer>,
texture_atlas_layouts: &mut ResMut<Assets<TextureAtlasLayout>>,
) {
// https://github.com/bevyengine/bevy/blob/latest/examples/2d/sprite_sheet.rs
let texture: Handle<Image> = asset_server.load("sprites/ant_walk_anim.png");
let layout = TextureAtlasLayout::from_grid(UVec2::new(202, 248), 8, 8, None, None);
let texture_atlas_layout = texture_atlas_layouts.add(layout);
let animation_indices = AnimationIndices { first: 0, last: 61 };
let texture_atlas = TextureAtlas {
layout: texture_atlas_layout,
index: rand::thread_rng().gen_range(animation_indices.first..=animation_indices.last),
};
commands.spawn(AntBundle::new(
Vec2::ZERO,
texture,
texture_atlas,
animation_indices,
Vec2::splat(ANT_SCALE),
));
}
pub fn enter_anthill_system() {}

View File

@ -1,2 +1,3 @@
pub mod ant; pub mod ant;
pub mod anthill;
pub mod startup; pub mod startup;

View File

@ -1,9 +1,5 @@
use crate::{ use crate::{components::anthill::AnthillBundle, ANT_COUNT};
components::{ant::AntBundle, common::AnimationIndices},
ANT_COUNT, ANT_SCALE, MAX_POSITION,
};
use bevy::prelude::*; use bevy::prelude::*;
use rand::Rng;
/// Signal that the app has started by printing a message to the terminal. /// Signal that the app has started by printing a message to the terminal.
pub fn hello_ants_system() { pub fn hello_ants_system() {
@ -12,35 +8,18 @@ pub fn hello_ants_system() {
/// Prepares the environment before the Update schedule by spawning required entities. /// Prepares the environment before the Update schedule by spawning required entities.
#[allow(clippy::needless_pass_by_value)] #[allow(clippy::needless_pass_by_value)]
pub fn setup_system( pub fn setup_system(mut commands: Commands, asset_server: Res<AssetServer>) {
mut commands: Commands,
asset_server: Res<AssetServer>,
mut texture_atlas_layouts: ResMut<Assets<TextureAtlasLayout>>,
) {
// Using the default camera, world space coordinates correspond 1:1 with screen pixels. // Using the default camera, world space coordinates correspond 1:1 with screen pixels.
// The point (0, 0) is in the center of the screen. // The point (0, 0) is in the center of the screen.
commands.spawn(Camera2dBundle::default()); commands.spawn(Camera2dBundle::default());
// Spawn cute ants // Spawn the anthill that will spawn the ants
// https://github.com/bevyengine/bevy/blob/latest/examples/2d/sprite_sheet.rs commands.spawn(AnthillBundle::new(
// TODO: Some weird cloning here ANT_COUNT,
let texture: Handle<Image> = asset_server.load("sprites/ant_walk_anim.png"); 5,
let layout = TextureAtlasLayout::from_grid(UVec2::new(202, 248), 8, 8, None, None); 1.,
let texture_atlas_layout = texture_atlas_layouts.add(layout);
for _ in 0..ANT_COUNT {
let animation_indices = AnimationIndices { first: 0, last: 61 };
let texture_atlas = TextureAtlas {
layout: texture_atlas_layout.clone(),
index: rand::thread_rng().gen_range(animation_indices.first..=animation_indices.last),
};
commands.spawn(AntBundle::new(
Vec2::ZERO, Vec2::ZERO,
texture.clone(), Vec2::splat(0.2),
texture_atlas, asset_server.load("sprites/anthill.png"),
animation_indices,
Vec2::splat(ANT_SCALE),
)); ));
}
println!("Spawned {ANT_COUNT} cute ants 😍");
} }