Skip to content

Commit 9f1b615

Browse files
committed
refined snail, added starfish
1 parent 185eb65 commit 9f1b615

16 files changed

+230
-49
lines changed

Cargo.lock

+1-1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "lifecycler"
3-
version = "0.1.8"
3+
version = "0.1.9"
44
edition = "2021"
55
license = "MIT OR Apache-2.0 OR CC0-1.0"
66

assets/fish.glb

-28 Bytes
Binary file not shown.

assets/snail.glb

-12 Bytes
Binary file not shown.

assets/starfish.glb

11.9 KB
Binary file not shown.

src/creatures/behavior.rs

+37-16
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@ use rand_chacha::ChaCha8Rng;
55

66
use crate::pellets::Pellet;
77

8+
const BEHAVIOR_INTERVAL_SECONDS: f32 = 8.;
9+
810
pub(super) fn plugin(app: &mut App) {
911
app.init_resource::<CreatureRng>();
1012
}
@@ -27,7 +29,7 @@ pub struct CreatureBehavior {
2729
impl Default for CreatureBehavior {
2830
fn default() -> Self {
2931
Self {
30-
timer: Timer::from_seconds(5., TimerMode::Repeating),
32+
timer: Timer::from_seconds(BEHAVIOR_INTERVAL_SECONDS, TimerMode::Repeating),
3133
variant: CreatureBehaviorVariant::Debut,
3234
}
3335
}
@@ -64,16 +66,18 @@ pub trait CreatureOperations {
6466
self.clamp();
6567
}
6668

67-
fn decide_behavior(&mut self, time: &Time) {
69+
fn decide_behavior(&mut self, time: &Time, _rng: &mut CreatureRng) {
6870
self.behavior().timer.tick(time.delta());
6971

7072
if self.behavior().timer.just_finished() {
7173
match self.behavior().variant {
7274
CreatureBehaviorVariant::Idle => {
73-
if self.transform().rotation.y == 0. {
74-
self.start_swim_left();
75-
} else {
75+
let current_y = self.transform().rotation.y;
76+
self.face_left();
77+
if self.transform().rotation.y != current_y {
7678
self.start_swim_right();
79+
} else {
80+
self.start_swim_left();
7781
}
7882
}
7983
CreatureBehaviorVariant::SwimRight => self.start_idle(),
@@ -175,22 +179,36 @@ pub trait CreatureOperations {
175179

176180
fn behavior_seek_pellet(
177181
&mut self,
178-
time: &Time,
179-
rng: &mut CreatureRng,
180-
pellet: Result<(Entity, &Transform), QueryEntityError>,
181-
commands: &mut Commands,
182-
);
182+
_time: &Time,
183+
_rng: &mut CreatureRng,
184+
_pellet: Result<(Entity, &Transform), QueryEntityError>,
185+
_commands: &mut Commands,
186+
) {
187+
// optional impl
188+
}
183189

184-
fn face_right(&mut self);
185-
fn face_left(&mut self);
190+
fn face_right(&mut self) {
191+
// optional impl
192+
}
193+
194+
fn face_left(&mut self) {
195+
// optional impl
196+
}
186197

187198
fn clamp(&mut self) {
188199
let (min, max) = Self::valid_area();
189200
self.transform().translation = self.transform().translation.clamp(min, max);
190201
}
191202

192-
fn rank_pellet(&mut self, pellet_transform: &Transform) -> f32;
193-
fn check_pellet(&mut self, rank: f32) -> bool;
203+
fn rank_pellet(&mut self, pellet_transform: &Transform) -> f32 {
204+
self.transform()
205+
.translation
206+
.distance(pellet_transform.translation)
207+
}
208+
209+
fn check_pellet(&mut self, _rank: f32) -> bool {
210+
true
211+
}
194212

195213
fn behavior(&mut self) -> &mut CreatureBehavior;
196214
fn transform(&mut self) -> &mut Transform;
@@ -200,11 +218,14 @@ pub trait CreatureOperations {
200218

201219
fn valid_random_point(rng: &mut CreatureRng) -> Vec3 {
202220
let (min, max) = Self::valid_area();
203-
Cuboid::from_corners(min + Self::valid_point_buffer(), max - Self::valid_point_buffer()).sample_interior(&mut rng.0)
221+
Cuboid::from_corners(
222+
min + Self::valid_point_buffer(),
223+
max - Self::valid_point_buffer(),
224+
)
225+
.sample_interior(&mut rng.0)
204226
}
205227

206228
fn valid_point_buffer() -> Vec3 {
207229
Vec3::splat(0.0)
208230
}
209231
}
210-

src/creatures/fish_behavior.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,6 @@ impl<'a> CreatureOperations for FishOperations<'a> {
129129
}
130130

131131
fn valid_point_buffer() -> Vec3 {
132-
Vec3::new(0.2, 0.3, 0.)
132+
Vec3::new(0.2, 0.3, 0.1)
133133
}
134134
}

src/creatures/fish_systems.rs

+4-2
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ fn setup_fish_system(
5858

5959
let fish_materials = (0..36)
6060
.map(|_| {
61-
let base_color = Color::hsl(((rng.next_u32() % 160 + 200) % 360) as f32, 0.4, 0.3);
61+
let base_color = Color::hsl(((rng.next_u32() % 180 + 165) % 360) as f32, 0.3, 0.4);
6262
let emissive = base_color.to_linear() * 0.3;
6363

6464
materials.add(StandardMaterial {
@@ -138,9 +138,11 @@ fn fish_behavior_system(
138138
fn fish_behavior_change_system(
139139
time: Res<Time>,
140140
mut fishes: Query<(&mut Transform, &mut CreatureBehavior, &mut FishMortality), With<Fish>>,
141+
mut rng: ResMut<CreatureRng>,
141142
) {
142143
for (mut transform, mut behavior, mut mortality) in fishes.iter_mut() {
143-
FishOperations::new(&mut transform, &mut behavior, &mut mortality).decide_behavior(&time);
144+
FishOperations::new(&mut transform, &mut behavior, &mut mortality)
145+
.decide_behavior(&time, &mut rng);
144146
}
145147
}
146148

src/creatures/lifecycle.rs

+5-4
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,11 @@ use bevy::prelude::*;
44
use rand::RngCore;
55

66
use super::{
7-
behavior::CreatureRng, fish_behavior::{
8-
FISH_AGING_INTERVAL_SECONDS, FISH_AVERAGE_LONGEVITY, FISH_BULK_MAX,
9-
FISH_SATIATION_MAX,
10-
}, fish_systems::FishSpawnEvent
7+
behavior::CreatureRng,
8+
fish_behavior::{
9+
FISH_AGING_INTERVAL_SECONDS, FISH_AVERAGE_LONGEVITY, FISH_BULK_MAX, FISH_SATIATION_MAX,
10+
},
11+
fish_systems::FishSpawnEvent,
1112
};
1213

1314
pub(super) fn plugin(app: &mut App) {

src/creatures/mod.rs

+3
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,15 @@ mod fish_systems;
66
mod lifecycle;
77
mod snail_behavior;
88
mod snail_systems;
9+
mod starfish_behavior;
10+
mod starfish_systems;
911

1012
pub(super) fn plugin(app: &mut App) {
1113
app.add_plugins((
1214
behavior::plugin,
1315
fish_systems::plugin,
1416
lifecycle::plugin,
1517
snail_systems::plugin,
18+
starfish_systems::plugin,
1619
));
1720
}

src/creatures/snail_behavior.rs

+7-11
Original file line numberDiff line numberDiff line change
@@ -21,16 +21,16 @@ impl<'a> SnailOperations<'a> {
2121
}
2222

2323
impl<'a> CreatureOperations for SnailOperations<'a> {
24-
fn behavior_debut(&mut self, time: &Time, _rng: &mut CreatureRng) {
25-
self.transform.translation.x += time.delta_seconds() * Self::base_speed();
26-
27-
if self.transform.translation.x > -1. {
24+
fn behavior_debut(&mut self, _time: &Time, _rng: &mut CreatureRng) {
25+
if self.transform.translation.x < 0. {
2826
self.start_swim_right();
27+
} else {
28+
self.start_swim_left();
2929
}
3030
}
3131

3232
fn behavior_idle(&mut self, time: &Time) {
33-
self.transform.translation.y += time.elapsed_seconds().sin() / 1000.;
33+
self.transform.translation.z += time.elapsed_seconds().sin() / 10_000.;
3434
}
3535

3636
fn behavior_seek_pellet(
@@ -69,15 +69,11 @@ impl<'a> CreatureOperations for SnailOperations<'a> {
6969
}
7070

7171
fn face_right(&mut self) {
72-
*self.transform =
73-
self.transform
74-
.with_rotation(Quat::from_euler(EulerRot::XYZ, 0., 3. * PI / 2., 0.));
72+
*self.transform = self.transform.with_rotation(Quat::IDENTITY);
7573
}
7674

7775
fn face_left(&mut self) {
78-
*self.transform =
79-
self.transform
80-
.with_rotation(Quat::from_euler(EulerRot::XYZ, 0., PI / 2., 0.));
76+
*self.transform = self.transform.with_rotation(Quat::from_rotation_y(PI));
8177
}
8278

8379
fn rank_pellet(&mut self, pellet_transform: &Transform) -> f32 {

src/creatures/snail_systems.rs

+14-10
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use std::{f32::consts::PI, time::Duration};
1+
use std::time::Duration;
22

33
use bevy::{prelude::*, time::common_conditions::on_timer};
44

@@ -29,8 +29,8 @@ pub struct Snail;
2929
#[derive(Resource, Deref)]
3030
pub struct SnailScene(Handle<Scene>);
3131

32-
#[derive(Event, Deref)]
33-
pub struct SnailSpawnEvent(pub Vec3);
32+
#[derive(Event)]
33+
pub struct SnailSpawnEvent(pub Vec3, pub f32);
3434

3535
fn setup_snails_system(
3636
mut commands: Commands,
@@ -40,22 +40,25 @@ fn setup_snails_system(
4040
let snail = asset_server.load(GltfAssetLabel::Scene(0).from_asset("embedded://snail.glb"));
4141
commands.insert_resource(SnailScene(snail));
4242

43-
spawn_events.send(SnailSpawnEvent(Vec3::new(-1.4, -1.7, 0.4)));
43+
spawn_events.send(SnailSpawnEvent(Vec3::new(-1.4, -1.7, 0.4), 0.1));
44+
spawn_events.send(SnailSpawnEvent(Vec3::new(1.4, -1.7, -0.1), 0.07));
4445
}
4546

4647
fn spawn_snails_system(
4748
mut commands: Commands,
4849
mut spawn_events: EventReader<SnailSpawnEvent>,
4950
fish_scene: Res<SnailScene>,
5051
) {
51-
for spawn_location in spawn_events.read() {
52-
let transform = Transform::from_translation(**spawn_location)
53-
.with_rotation(Quat::from_euler(EulerRot::XYZ, 0., 3. * PI / 2., 0.))
54-
.with_scale(Vec3::new(0.09, 0.09, 0.09));
52+
for SnailSpawnEvent(location, size) in spawn_events.read() {
53+
let transform = Transform::from_translation(*location).with_scale(Vec3::splat(*size));
54+
let mut behavior = CreatureBehavior::default();
55+
behavior
56+
.timer
57+
.set_duration(behavior.timer.duration() - Duration::from_secs((size * 10.) as u64 % 2));
5558

5659
commands.spawn((
5760
Snail,
58-
CreatureBehavior::default(),
61+
behavior,
5962
SceneBundle {
6063
transform,
6164
scene: fish_scene.clone(),
@@ -85,9 +88,10 @@ fn snails_behavior_system(
8588
fn snails_behavior_change_system(
8689
time: Res<Time>,
8790
mut snails: Query<(&mut Transform, &mut CreatureBehavior), With<Snail>>,
91+
mut rng: ResMut<CreatureRng>,
8892
) {
8993
for (mut transform, mut behavior) in snails.iter_mut() {
90-
SnailOperations::new(&mut transform, &mut behavior).decide_behavior(&time);
94+
SnailOperations::new(&mut transform, &mut behavior).decide_behavior(&time, &mut rng);
9195
}
9296
}
9397

src/creatures/starfish_behavior.rs

+59
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
use bevy::prelude::*;
2+
3+
use super::behavior::{CreatureBehavior, CreatureBehaviorVariant, CreatureOperations, CreatureRng};
4+
5+
pub struct StarfishOperations<'a> {
6+
transform: &'a mut Transform,
7+
behavior: &'a mut CreatureBehavior,
8+
}
9+
10+
impl<'a> StarfishOperations<'a> {
11+
pub(super) fn new(transform: &'a mut Transform, behavior: &'a mut CreatureBehavior) -> Self {
12+
Self {
13+
transform,
14+
behavior,
15+
}
16+
}
17+
}
18+
19+
impl<'a> CreatureOperations for StarfishOperations<'a> {
20+
fn decide_behavior(&mut self, time: &Time, rng: &mut CreatureRng) {
21+
self.behavior().timer.tick(time.delta());
22+
23+
if self.behavior().timer.just_finished() {
24+
match self.behavior().variant {
25+
CreatureBehaviorVariant::Idle => self.start_seek_point(rng),
26+
_ => self.start_idle(),
27+
}
28+
}
29+
}
30+
31+
fn behavior_debut(&mut self, _time: &Time, _rng: &mut CreatureRng) {
32+
self.start_idle()
33+
}
34+
35+
fn behavior_idle(&mut self, time: &Time) {
36+
self.transform()
37+
.rotate_z((time.elapsed_seconds() / 10.).sin() * Self::base_speed() * -0.1);
38+
}
39+
40+
fn base_speed() -> f32 {
41+
0.01
42+
}
43+
44+
fn valid_area() -> (Vec3, Vec3) {
45+
(Vec3::new(-1.4, -1.4, -0.41), Vec3::new(1.4, 1.4, -0.41))
46+
}
47+
48+
fn behavior(&mut self) -> &mut CreatureBehavior {
49+
self.behavior
50+
}
51+
52+
fn transform(&mut self) -> &mut Transform {
53+
self.transform
54+
}
55+
56+
fn valid_point_buffer() -> Vec3 {
57+
Vec3::new(0.1, 0.1, 0.)
58+
}
59+
}

0 commit comments

Comments
 (0)