Skip to content

Commit

Permalink
Storyteller mechainc
Browse files Browse the repository at this point in the history
  • Loading branch information
rewin123 committed Dec 7, 2023
1 parent fe3423e commit 5ee1532
Show file tree
Hide file tree
Showing 6 changed files with 231 additions and 7 deletions.
25 changes: 25 additions & 0 deletions difficult_prepare/difficult_plot.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import numpy as np
import matplotlib.pyplot as plt

level_time = 4 * 60

l = 20
s_d = 45.0 * 1000.0 / 3600.0
s_s = s_d * 0.5 * 0.2

print("Sheep time:", l / s_s)
print("Dog max travel time:", 2 * np.pi * l / s_d)

hardness = np.linspace(0.05, 1.0, 100)
k_h = 1.5

param_curve = l / s_s - 2 * np.pi * l / s_d - 1 / k_h / hardness

delta_t = 10
c = 10

n = (param_curve + delta_t) / np.sqrt(c)

plt.plot(hardness, n)
plt.grid()
plt.show()
59 changes: 59 additions & 0 deletions src/level_ui.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
use bevy::prelude::*;

use crate::storyteller::LevelTimer;

pub struct LevelUiPlugin;

impl Plugin for LevelUiPlugin {
fn build(&self, app: &mut App) {
app.add_event::<CreateLevelUi>()
.add_systems(Update, create_level_ui_system);
}
}

#[derive(Event)]
pub struct CreateLevelUi;

#[derive(Component)]
pub struct LevelUi;

fn create_level_ui_system(
mut commands: Commands,
asset_server: Res<AssetServer>,
mut ev_create_level_ui: EventReader<CreateLevelUi>,
) {
if ev_create_level_ui.is_empty() {
return;
}

let mut text_style = TextStyle::default();
text_style.font_size = 24.0;

//Spawn top info bar
commands.spawn((NodeBundle {
style: Style {
width: Val::Percent(100.0),
height: Val::Px(50.0),
flex_direction: FlexDirection::Row,
justify_content: JustifyContent::Center,
align_items: AlignItems::Center,

align_self: AlignSelf::Stretch,
..default()
},
..default()
},
LevelUi
)).with_children(|parent| {
parent.spawn((
TextBundle::from_section(
"",
text_style.clone()
),
LevelUi,
LevelTimer
));
});

ev_create_level_ui.clear();
}
4 changes: 4 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ pub mod sheep;
pub mod sprite_material;
pub mod test_level;
pub mod torch;
pub mod storyteller;
pub mod level_ui;

use std::f32::consts::PI;

Expand Down Expand Up @@ -53,6 +55,8 @@ impl Plugin for GamePlugin {
safe_area::SafeAreaPlugin,
sprite_material::SpriteMaterialPlugin,
sheep::SheepPlugin,
storyteller::StorytellerPlugin,
level_ui::LevelUiPlugin,
));

//For long term updates
Expand Down
12 changes: 6 additions & 6 deletions src/sheep.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,12 +21,12 @@ use bevy_spatial::{

const SHEEP_PATH: &str = "test/sheep.png";

const SHEEP_SPEED: f32 = DOG_SPEED * 0.5;
pub const SHEEP_SPEED: f32 = DOG_SPEED * 0.5;
const SHEEP_ACCELERATION: f32 = SHEEP_SPEED * 3.0;

const RANDOM_WALK_RANGE: f32 = 5.0;
const RANDOM_WALK_ACCEPT_RADIUS: f32 = 0.5;
const RANDOM_WALK_SPEED_MULTIPLIER: f32 = 0.2;
pub const RANDOM_WALK_SPEED_MULTIPLIER: f32 = 0.2;

//IDLE FEEDING must be large enough so that player can see sheep and react for escapes
const IDLE_FEEDING_TIME: f32 = 5.0;
Expand All @@ -49,7 +49,9 @@ impl Plugin for SheepPlugin {

//random walk
app.add_event::<InitRandomWalk>()
.add_systems(Update, (init_random_walk, goto_system));
.add_systems(Update, (init_random_walk, ));

app.add_systems(Update, (goto_system,));

//idle feeding
app.add_systems(Update, idle_feeding_system);
Expand Down Expand Up @@ -117,8 +119,6 @@ impl Default for StateChance {
next_state: vec![
(1.0, Decision::Feed), //zero values for unimplemented things
(0.5, Decision::RandomWalk),
(0.5, Decision::MoveToSafeArea),
(0.5, Decision::Escape),
],
};
res.normalize();
Expand Down Expand Up @@ -521,7 +521,7 @@ fn collect_field(
let around_mean_vel = sum / (count as f32);
let dv = around_mean_vel - vel.0;
walk.target_velocity =
vel.0 + 0.5 * dv + 0.9 * distance_force + Vec3::new(0.0, 0.0, sum_dz);
vel.0 + 0.9 * distance_force + Vec3::new(0.0, 0.0, sum_dz);
} else {
walk.target_velocity = vel.0;
}
Expand Down
133 changes: 133 additions & 0 deletions src/storyteller.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
//This global AI is responsible for creating problems for player
//This module will be determine where and how sheep will be try to escape from safe zone

use std::{f32::consts::{PI, E}, time::Duration};

use bevy::prelude::*;
use rand::Rng;

use crate::{sheep::{Sheep, SHEEP_SPEED, RANDOM_WALK_SPEED_MULTIPLIER, GoTo}, test_level::LevelSize, player::DOG_SPEED};

pub struct StorytellerPlugin;

impl Plugin for StorytellerPlugin {
fn build(&self, app: &mut App) {
app
.insert_resource(Storyteller {
level_start_time : 0.0,
level_duration : 4.0 * 60.0,
next_wave : None
})
.add_systems(Update, (
storyteller_system,
level_timer
))
.add_systems(PostStartup, setup_start_time);
}
}

#[derive(Debug, Clone)]
pub struct SheepWave {
pub count : usize,
pub beams : usize,
pub time : f32
}

#[derive(Resource)]
pub struct Storyteller {
pub level_start_time : f32,
pub level_duration : f32,
pub next_wave : Option<SheepWave>
}

fn setup_start_time(
mut teller : ResMut<Storyteller>,
time : Res<Time>
) {
teller.level_start_time = time.elapsed_seconds();
}

fn storyteller_system(
mut commands: Commands,
sheep : Query<(Entity, &Transform), With<Sheep>>,
mut teller : ResMut<Storyteller>,
time : Res<Time>,
level_size : Res<LevelSize>
) {
if teller.next_wave.is_none() {
let level_time = time.elapsed_seconds() - teller.level_start_time;
let unfiorm_time = level_time / teller.level_duration;


let sheep_count = sheep.iter().count() as f32;

let c = sheep_count * unfiorm_time * 0.2 + 1.0;
let dt = 15.0 - 10.0 * unfiorm_time;
let n = 1.0 + 2.0 * unfiorm_time;

teller.next_wave = Some(SheepWave {
count : c as usize,
beams : n as usize,
time : time.elapsed_seconds() + dt
});

info!("Next wave: {:?}", teller.next_wave);
} else {
let wave = teller.next_wave.as_ref().unwrap().clone();
let cur_time = time.elapsed_seconds();
if wave.time <= cur_time {
teller.next_wave = None;

let mut rand = rand::thread_rng();

let split_c = (wave.count / wave.beams).max(1);
for _ in 0..wave.beams {
let random_dir = Vec3::new(rand.gen_range(-1.0..1.0), 0.0, rand.gen_range(-1.0..1.0)).normalize();
//create a sorted list of sheep which far in direction
let mut sorted_sheep = sheep
.iter()
.map(|(e, t)| {
let dir = t.translation;
let proj_dir = dir.dot(random_dir);
(e, dir, proj_dir)
})
.collect::<Vec<_>>();
sorted_sheep.sort_by(|a, b| b.2.partial_cmp(&a.2).unwrap());

//send split_c sheep in that direction
for i in 0..split_c {
if let Some((e, pos, dist)) = sorted_sheep.get(i) {
info!("Sending {:?} with {:?}", e, dist);
commands.entity(*e).insert(
GoTo {
target: *pos + level_size.0 * random_dir,
}
);
}
}
}
}
}


}

#[derive(Component)]
pub struct LevelTimer;

fn level_timer(
mut timers : Query<&mut Text, With<LevelTimer>>,
teller : Res<Storyteller>,
time : Res<Time>
) {
for mut timer in timers.iter_mut() {
let level_time = time.elapsed_seconds() - teller.level_start_time;
if (level_time > 0.0) {
let dur = Duration::from_secs_f32(teller.level_duration - level_time);

timer.sections[0].value = format!("{:02}:{:02}", dur.as_secs() / 60, dur.as_secs() % 60);
} else {
timer.sections[0].value = format!("{:02}:{:02}", 0, 0);
}
}
}
5 changes: 4 additions & 1 deletion src/test_level.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ use std::f32::consts::PI;

use crate::{
get_sprite_rotation, player::SpawnPlayer, safe_area::SafeArea,
sprite_material::create_plane_mesh, torch::SpawnTorch,
sprite_material::create_plane_mesh, torch::SpawnTorch, level_ui::CreateLevelUi,
};

const TREE_PATH: &str = "test/pine.png";
Expand All @@ -33,6 +33,7 @@ pub fn setup(
mut spawn_player_event: EventWriter<SpawnPlayer>,
mut spawn_torch: EventWriter<SpawnTorch>,
level_size: Res<LevelSize>,
mut create_level_ui : EventWriter<CreateLevelUi>,
) {
commands.spawn(Camera3dBundle {
transform: Transform::from_xyz(0.0, 30.0, 30.0).looking_at(Vec3::ZERO, Vec3::Y),
Expand Down Expand Up @@ -140,4 +141,6 @@ pub fn setup(
pos: Vec2::ZERO,
size: Vec2::new(r * 1.5, r * 1.5),
});

create_level_ui.send(CreateLevelUi);
}

0 comments on commit 5ee1532

Please sign in to comment.