Skip to content

Commit 579537f

Browse files
committed
Improves aquarium performance and appearance
Adjusts the simulation to use a fixed timestep and scales movement based on that timestep. This decouples the simulation speed from the rendering framerate. Increases the default frame duration and provides UI elements to control the render cadence. Reduces fish velocity to complement the fixed timestep, maintaining a visually appealing speed.
1 parent 773fd23 commit 579537f

File tree

2 files changed

+22
-18
lines changed

2 files changed

+22
-18
lines changed

examples/egui_demo.rs

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ struct MyApp {
2020
assets: Vec<asciiquarium_rust::FishArt>,
2121
state: AquariumState,
2222
theme: AsciiquariumTheme,
23+
// Controls repaint cadence (ms). Simulation uses an internal dt; higher values reduce CPU and may not linearly affect perceived speed.
2324
frame_ms: u64,
2425
bg_enabled: bool,
2526
}
@@ -52,7 +53,7 @@ impl MyApp {
5253
assets,
5354
state,
5455
theme,
55-
frame_ms: 33,
56+
frame_ms: 50,
5657
bg_enabled: true,
5758
}
5859
}
@@ -84,6 +85,8 @@ impl eframe::App for MyApp {
8485
ui.separator();
8586

8687
ui.label("Frame (ms):");
88+
ui.label(format!("{} ms", self.frame_ms));
89+
ui.small("Render cadence; simulation uses fixed dt ~33ms");
8790
if ui.button("-").clicked() && self.frame_ms > 5 {
8891
self.frame_ms -= 2;
8992
}
@@ -156,13 +159,13 @@ fn spawn_random_fish(state: &mut AquariumState, asset_count: usize) {
156159
let y = rng.gen_range(0..=max_y) as f32;
157160

158161
// Random velocity with minimum magnitude to avoid stationary fish
159-
let mut vx = rng.gen_range(-0.5_f32..=0.5_f32);
160-
let mut vy = rng.gen_range(-0.25_f32..=0.25_f32);
161-
if vx.abs() < 0.05 {
162-
vx = if vx.is_sign_negative() { -0.08 } else { 0.08 };
162+
let mut vx = rng.gen_range(-0.25_f32..=0.25_f32);
163+
let mut vy = rng.gen_range(-0.12_f32..=0.12_f32);
164+
if vx.abs() < 0.03 {
165+
vx = if vx.is_sign_negative() { -0.04 } else { 0.04 };
163166
}
164-
if vy.abs() < 0.02 {
165-
vy = if vy.is_sign_negative() { -0.03 } else { 0.03 };
167+
if vy.abs() < 0.012 {
168+
vy = if vy.is_sign_negative() { -0.015 } else { 0.015 };
166169
}
167170

168171
state.fishes.push(FishInstance {

src/widgets/asciiquarium.rs

Lines changed: 12 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -319,6 +319,7 @@ fn ensure_environment_initialized(state: &mut AquariumState) {
319319
/// Update the aquarium by one tick with simple wall-bounce physics and environment.
320320
pub fn update_aquarium(state: &mut AquariumState, assets: &[FishArt]) {
321321
let (aw, ah) = (state.size.0 as f32, state.size.1 as f32);
322+
let dt: f32 = 0.033;
322323

323324
// Ensure environment exists.
324325
ensure_environment_initialized(state);
@@ -332,7 +333,7 @@ pub fn update_aquarium(state: &mut AquariumState, assets: &[FishArt]) {
332333
state.env.ships.push(Ship {
333334
x: -(sw as f32),
334335
y: 0,
335-
vx: 1.0,
336+
vx: 6.0,
336337
});
337338
}
338339
if state.env.sharks.is_empty() {
@@ -343,7 +344,7 @@ pub fn update_aquarium(state: &mut AquariumState, assets: &[FishArt]) {
343344
state.env.sharks.push(Shark {
344345
x: -40.0,
345346
y,
346-
vx: 1.2,
347+
vx: 8.0,
347348
});
348349
}
349350
if state.env.whales.is_empty() {
@@ -352,12 +353,12 @@ pub fn update_aquarium(state: &mut AquariumState, assets: &[FishArt]) {
352353
state.env.whales.push(Whale {
353354
x: state.size.0 as f32 + 10.0,
354355
y,
355-
vx: -0.6,
356+
vx: -4.0,
356357
});
357358
}
358359
for fish in &mut state.fishes {
359-
fish.position.0 += fish.velocity.0;
360-
fish.position.1 += fish.velocity.1;
360+
fish.position.0 += fish.velocity.0 * dt;
361+
fish.position.1 += fish.velocity.1 * dt;
361362

362363
let (fw, fh) = assets
363364
.get(fish.fish_art_index)
@@ -398,16 +399,16 @@ pub fn update_aquarium(state: &mut AquariumState, assets: &[FishArt]) {
398399
};
399400
state.bubbles.push(Bubble {
400401
position: (bx, mid_y),
401-
velocity: (0.0, -0.3),
402+
velocity: (0.0, -3.0),
402403
});
403404
}
404405
}
405406

406407
// Update bubbles (rise) and cull above waterline (y < 0).
407408
let mut kept = Vec::with_capacity(state.bubbles.len());
408409
for mut b in state.bubbles.drain(..) {
409-
b.position.0 += b.velocity.0;
410-
b.position.1 += b.velocity.1;
410+
b.position.0 += b.velocity.0 * dt;
411+
b.position.1 += b.velocity.1 * dt;
411412
if b.position.1 >= 0.0 {
412413
kept.push(b);
413414
}
@@ -416,7 +417,7 @@ pub fn update_aquarium(state: &mut AquariumState, assets: &[FishArt]) {
416417

417418
// Move ships.
418419
for ship in &mut state.env.ships {
419-
ship.x += ship.vx;
420+
ship.x += ship.vx * dt;
420421
let (sw, _) = if ship.vx >= 0.0 {
421422
measure_block(SHIP_R)
422423
} else {
@@ -431,7 +432,7 @@ pub fn update_aquarium(state: &mut AquariumState, assets: &[FishArt]) {
431432

432433
// Move sharks.
433434
for shark in &mut state.env.sharks {
434-
shark.x += shark.vx;
435+
shark.x += shark.vx * dt;
435436
let (sw, _) = if shark.vx >= 0.0 {
436437
measure_block(SHARK_R)
437438
} else {
@@ -448,7 +449,7 @@ pub fn update_aquarium(state: &mut AquariumState, assets: &[FishArt]) {
448449

449450
// Move whales.
450451
for whale in &mut state.env.whales {
451-
whale.x += whale.vx;
452+
whale.x += whale.vx * dt;
452453
let (ww, _) = if whale.vx >= 0.0 {
453454
measure_block(WHALE_R)
454455
} else {

0 commit comments

Comments
 (0)