Skip to content

Commit

Permalink
fish food and tank
Browse files Browse the repository at this point in the history
  • Loading branch information
cxreiff committed Jul 22, 2024
1 parent 75bed3a commit abe8967
Show file tree
Hide file tree
Showing 10 changed files with 281 additions and 70 deletions.
27 changes: 27 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 3 additions & 3 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,12 @@ license = "MIT OR Apache-2.0 OR CC0-1.0"

[dependencies]
bevy = "0.14.0"
bevy_atmosphere = "0.10.0"
bevy_ratatui = "0.6.0"
bevy_ratatui_render = "0.5.1"
crossterm = "0.27.0"
rand = "0.8.5"
rand_chacha = "0.3.1"
ratatui = "0.27.0"

[features]
Expand All @@ -35,9 +38,6 @@ opt-level = 1
[profile.dev.package."*"]
opt-level = 3

[profile.dev.package.wgpu-types]
debug-assertions = false

[profile.release]
codegen-units = 1
lto = "thin"
Expand Down
Binary file added assets/tank.glb
Binary file not shown.
15 changes: 10 additions & 5 deletions src/draw.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,24 +24,29 @@ fn draw_scene_system(
diagnostics: Res<DiagnosticsStore>,
) -> io::Result<()> {
ratatui.draw(|frame| {
frame.render_widget(ratatui_render.widget("main").unwrap(), frame.size());
if let Some(widget) = ratatui_render.widget("main") {
frame.render_widget(widget, frame.size());
}

#[cfg(feature = "dev")]
if flags.debug {
if let Some(value) = diagnostics
.get(&FrameTimeDiagnosticsPlugin::FPS)
.and_then(|fps| fps.smoothed())
{
let position = Rect::new(0, 0, frame.size().width, 1);
let fps = Text::raw(format!("[fps: {value:.0}]")).alignment(Alignment::Center);
let msg = &flags.msg;
let position = Rect::new(0, 1, frame.size().width, 1);
let fps = Text::raw(format!("[msg: {msg}] [fps: {value:.0}]"))
.alignment(Alignment::Center)
.bg(ratatui::style::Color::Black);

frame.render_widget(fps, position);
}
}

let position = Rect::new(
(frame.size().width / 2) - 15,
frame.size().bottom() - 2,
(frame.size().width / 2).saturating_sub(15),
frame.size().bottom().saturating_sub(2),
30,
1,
);
Expand Down
24 changes: 18 additions & 6 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,13 @@ use bevy::{
app::ScheduleRunnerPlugin, diagnostic::FrameTimeDiagnosticsPlugin, prelude::*,
window::ExitCondition,
};
use bevy_atmosphere::plugin::AtmospherePlugin;
use bevy_ratatui::RatatuiPlugins;
use bevy_ratatui_render::RatatuiRenderPlugin;

mod draw;
mod input;
mod pellets;
mod scene;

pub struct AppPlugin;
Expand All @@ -23,19 +25,29 @@ impl Plugin for AppPlugin {
exit_condition: ExitCondition::DontExit,
close_when_requested: false,
}),
ScheduleRunnerPlugin::run_loop(Duration::from_secs_f64(1. / 60.)),
// DefaultPlugins,
ScheduleRunnerPlugin::run_loop(Duration::from_secs_f64(1. / 90.)),
FrameTimeDiagnosticsPlugin,
RatatuiPlugins::default(),
RatatuiRenderPlugin::new("main", (256, 256)),
RatatuiPlugins {
enable_mouse_capture: true,
..default()
},
RatatuiRenderPlugin::new("main", (512, 512)),
// RatatuiRenderPlugin::new("main", (512, 512)).disable(),
AtmospherePlugin,
))
.insert_resource(ClearColor(Color::WHITE))
.init_resource::<Flags>();
.insert_resource(Msaa::Off)
.insert_resource(Flags {
debug: true,
msg: "N/A".into(),
});

app.add_plugins((draw::plugin, input::plugin, scene::plugin));
app.add_plugins((draw::plugin, input::plugin, pellets::plugin, scene::plugin));
}
}

#[derive(Resource, Default)]
pub struct Flags {
debug: bool,
msg: String,
}
157 changes: 157 additions & 0 deletions src/pellets.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,157 @@
use bevy::prelude::*;
use bevy_ratatui::{event::MouseEvent, terminal::RatatuiContext};
use crossterm::event::{MouseButton, MouseEventKind};
use rand::seq::SliceRandom;
use rand_chacha::{
rand_core::{RngCore, SeedableRng},
ChaCha8Rng,
};
use ratatui::layout::Rect;

use crate::Flags;

pub(super) fn plugin(app: &mut App) {
app.add_systems(Startup, setup_pellets_system)
.add_systems(Update, (create_pellets_system, move_pellets_system))
.init_resource::<PelletThreshold>();
}

#[derive(Component)]
pub struct Pellet;

#[derive(Component, Deref)]
pub struct PelletFalling(Vec3);

#[derive(Resource, Deref, DerefMut)]
pub struct PelletRng(ChaCha8Rng);

#[derive(Resource, Deref)]
pub struct PelletMesh(Handle<Mesh>);

#[derive(Resource, Deref)]
pub struct PelletMaterials(Vec<Handle<StandardMaterial>>);

#[derive(Resource, Default, Deref, DerefMut)]
pub struct PelletThreshold(u32);

fn setup_pellets_system(
mut commands: Commands,
mut meshes: ResMut<Assets<Mesh>>,
mut materials: ResMut<Assets<StandardMaterial>>,
) {
let mesh = meshes.add(Cuboid::from_size(Vec3::new(0.03, 0.03, 0.03)));
commands.insert_resource(PelletMesh(mesh));

let mut seeded_rng = ChaCha8Rng::seed_from_u64(19878367467712);
let pellet_materials = (0..36)
.map(|_| {
let base_color = Color::hsl((seeded_rng.next_u32() % 250 + 90) as f32, 1.0, 0.5);
let emissive = base_color.to_linear() * 10.0;

materials.add(StandardMaterial {
base_color,
emissive,
..default()
})
})
.collect();
commands.insert_resource(PelletMaterials(pellet_materials));
commands.insert_resource(PelletRng(seeded_rng));
}

fn create_pellets_system(
mut commands: Commands,
mut events: EventReader<MouseEvent>,
ratatui: Res<RatatuiContext>,
mut pellet_rng: ResMut<PelletRng>,
pellet_mesh: Res<PelletMesh>,
pellet_materials: Res<PelletMaterials>,
mut pellet_threshold: ResMut<PelletThreshold>,
mut flags: ResMut<Flags>,
camera: Query<&Transform, With<Camera>>,
) {
for event in events.read() {
let crossterm::event::MouseEvent {
kind, column, row, ..
} = event.0;
if let MouseEventKind::Drag(MouseButton::Left) = kind {
if **pellet_threshold == 0 {
let size = ratatui.size().unwrap();
let camera_transform = camera.single();
if let Some(transform) = terminal_coords_to_world_transform(
&mut flags,
column,
row,
size,
camera_transform,
) {
let fall_target = Vec3::new(
transform.translation.x.clamp(-1.94, 1.94),
-1.9,
pellet_rng.next_u32() as f32 / u32::MAX as f32 * 0.6 - 0.5,
);
commands.spawn((
Pellet,
PelletFalling(fall_target),
PbrBundle {
transform,
mesh: pellet_mesh.clone(),
material: pellet_materials.choose(&mut pellet_rng.0).unwrap().clone(),
..default()
},
));
}
**pellet_threshold = 1;
} else {
**pellet_threshold -= 1;
}
}
}
}

fn move_pellets_system(
mut commands: Commands,
mut pellets: Query<(Entity, &mut Transform, &PelletFalling)>,
time: Res<Time>,
) {
for (entity, mut pellet_transform, PelletFalling(fall_target)) in &mut pellets {
pellet_transform.translation = pellet_transform
.translation
.move_towards(*fall_target, time.delta_seconds() / 2.);

pellet_transform.translation.x +=
(time.elapsed_seconds() + (fall_target.x * 16.) % 3.).sin() / 800.;
pellet_transform.translation.x = pellet_transform.translation.x.clamp(-1.94, 1.94);

if pellet_transform.translation.distance(*fall_target) < 0.003 {
commands.entity(entity).remove::<PelletFalling>();
}
}
}

fn terminal_coords_to_world_transform(
flags: &mut ResMut<Flags>,
column: u16,
row: u16,
terminal_size: Rect,
camera: &Transform,
) -> Option<Transform> {
let block_width = terminal_size.width;
let block_height = terminal_size.height * 2;

let render_column = column as f32 - block_width.saturating_sub(block_height) as f32 / 2.;
let render_row = (row as f32 - block_height.saturating_sub(block_width) as f32 / 4.) * 2.;

let x = render_column / block_width.min(block_height) as f32 * 2. - 1.;
let y = render_row / block_height.min(block_width) as f32 * 2. - 1.;

if x.abs() > 0.94 || y > 0.9 {
return None;
}

let mut world_coords = *camera * Vec3::new(x * 2.05, -y * 2. + 0.02, 0.);
world_coords.z = 0.;
flags.msg = format!("{world_coords:?}");

Some(Transform::from_translation(world_coords))
}
56 changes: 0 additions & 56 deletions src/scene.rs

This file was deleted.

Loading

0 comments on commit abe8967

Please sign in to comment.