mirror of
https://github.com/cxreiff/ttysvr.git
synced 2025-08-03 09:44:25 +02:00
upgrade: bevy 0.15, bevy_ratatui_camera 0.8
This commit is contained in:
parent
5e2ae54718
commit
c20207815e
8 changed files with 1060 additions and 921 deletions
1428
Cargo.lock
generated
1428
Cargo.lock
generated
File diff suppressed because it is too large
Load diff
|
@ -12,10 +12,10 @@ categories = ["command-line-interface"]
|
|||
keywords = ["bevy", "ratatui", "terminal", "tui", "screensaver"]
|
||||
|
||||
[dependencies]
|
||||
avian2d = "0.1.1"
|
||||
bevy = "0.14.2"
|
||||
bevy_ratatui = "0.6.4"
|
||||
bevy_ratatui_render = "0.6.0"
|
||||
avian2d = { git = "https://github.com/Jondolf/avian.git", branch = "main" }
|
||||
bevy = "0.15.0"
|
||||
bevy_ratatui = "0.7.0"
|
||||
bevy_ratatui_camera = "0.8.2"
|
||||
clap = { version = "4.5.13", features = ["derive"] }
|
||||
rand = "0.8.5"
|
||||
rand_chacha = "0.3.1"
|
||||
|
|
|
@ -5,7 +5,7 @@ use avian2d::{
|
|||
};
|
||||
use bevy::prelude::*;
|
||||
use bevy_ratatui::event::ResizeEvent;
|
||||
use bevy_ratatui_render::RatatuiRenderContext;
|
||||
use bevy_ratatui_camera::RatatuiCamera;
|
||||
use rand::{Rng, SeedableRng};
|
||||
use rand_chacha::ChaCha8Rng;
|
||||
|
||||
|
@ -49,41 +49,36 @@ pub struct BubbleSprite(Handle<Image>);
|
|||
#[derive(Resource, Deref, DerefMut, Default)]
|
||||
pub struct BubbleVisibleRegion(Vec2);
|
||||
|
||||
#[derive(Bundle)]
|
||||
pub struct BubbleBundle {
|
||||
bubble: Bubble,
|
||||
sprite: SpriteBundle,
|
||||
rigidbody: RigidBody,
|
||||
collider: Collider,
|
||||
locked_axes: LockedAxes,
|
||||
friction: Friction,
|
||||
}
|
||||
|
||||
impl BubbleBundle {
|
||||
fn new(rng: &mut BubbleRng, sprite: &BubbleSprite, region: &Rectangle) -> Self {
|
||||
Self {
|
||||
bubble: Bubble {
|
||||
target: region.sample_interior(&mut rng.0),
|
||||
timer: Timer::from_seconds(3., TimerMode::Repeating),
|
||||
},
|
||||
sprite: SpriteBundle {
|
||||
transform: Transform::from_translation(
|
||||
region.sample_interior(&mut rng.0).extend(0.),
|
||||
),
|
||||
texture: (**sprite).clone(),
|
||||
sprite: Sprite {
|
||||
color: Color::hsl(rng.gen_range(0.0..360.0), 1.0, 0.8),
|
||||
custom_size: Some(Vec2::splat(BUBBLE_RADIUS * 2.)),
|
||||
..default()
|
||||
},
|
||||
..default()
|
||||
},
|
||||
rigidbody: RigidBody::Dynamic,
|
||||
collider: Collider::circle(BUBBLE_RADIUS as Scalar),
|
||||
locked_axes: LockedAxes::ROTATION_LOCKED,
|
||||
friction: Friction::new(0.0),
|
||||
}
|
||||
}
|
||||
fn create_bubble(
|
||||
rng: &mut BubbleRng,
|
||||
sprite: &BubbleSprite,
|
||||
region: &Rectangle,
|
||||
) -> (
|
||||
Bubble,
|
||||
Sprite,
|
||||
Transform,
|
||||
RigidBody,
|
||||
Collider,
|
||||
LockedAxes,
|
||||
Friction,
|
||||
) {
|
||||
(
|
||||
Bubble {
|
||||
target: region.sample_interior(&mut rng.0),
|
||||
timer: Timer::from_seconds(3., TimerMode::Repeating),
|
||||
},
|
||||
Sprite {
|
||||
image: (**sprite).clone(),
|
||||
color: Color::hsl(rng.gen_range(0.0..360.0), 1.0, 0.8),
|
||||
custom_size: Some(Vec2::splat(BUBBLE_RADIUS * 2.)),
|
||||
..default()
|
||||
},
|
||||
Transform::from_translation(region.sample_interior(&mut rng.0).extend(0.)),
|
||||
RigidBody::Dynamic,
|
||||
Collider::circle(BUBBLE_RADIUS as Scalar),
|
||||
LockedAxes::ROTATION_LOCKED,
|
||||
Friction::new(0.0),
|
||||
)
|
||||
}
|
||||
|
||||
#[derive(Resource, Deref, DerefMut)]
|
||||
|
@ -95,15 +90,15 @@ impl Default for BubbleTimer {
|
|||
}
|
||||
}
|
||||
|
||||
fn bubbles_setup_system(
|
||||
mut commands: Commands,
|
||||
ratatui_render: Res<RatatuiRenderContext>,
|
||||
asset_server: Res<AssetServer>,
|
||||
) {
|
||||
let mut camera = Camera2dBundle::default();
|
||||
camera.projection.scale = ORTHO_SCALING;
|
||||
camera.camera.target = ratatui_render.target("main").unwrap_or_default();
|
||||
commands.spawn(camera);
|
||||
fn bubbles_setup_system(mut commands: Commands, asset_server: Res<AssetServer>) {
|
||||
commands.spawn((
|
||||
Camera2d,
|
||||
Projection::Orthographic(OrthographicProjection {
|
||||
scale: ORTHO_SCALING,
|
||||
..OrthographicProjection::default_2d()
|
||||
}),
|
||||
RatatuiCamera::autoresize(),
|
||||
));
|
||||
|
||||
let rng = ChaCha8Rng::seed_from_u64(19878367467712);
|
||||
commands.insert_resource(BubbleRng(rng));
|
||||
|
@ -126,7 +121,7 @@ fn bubbles_spawn_system(
|
|||
timer.tick(time.delta());
|
||||
if timer.finished() && *count < **spawn_amount {
|
||||
*count += 1;
|
||||
commands.spawn(BubbleBundle::new(
|
||||
commands.spawn(create_bubble(
|
||||
&mut rng,
|
||||
&sprite,
|
||||
&Rectangle::from_size(**visible_region - BUBBLE_RADIUS * 2.),
|
||||
|
@ -138,10 +133,9 @@ fn handle_resize_system(
|
|||
mut resize_events: EventReader<ResizeEvent>,
|
||||
mut visible_region: ResMut<BubbleVisibleRegion>,
|
||||
mut spawn_amount: ResMut<BubbleAmount>,
|
||||
ratatui_render: Res<RatatuiRenderContext>,
|
||||
) {
|
||||
for _ in resize_events.read() {
|
||||
let (width, height) = ratatui_render.dimensions("main").unwrap();
|
||||
for resize in resize_events.read() {
|
||||
let (width, height) = (resize.width * 2, resize.height * 4);
|
||||
let terminal_dimensions = Vec2::new(width as f32, height as f32);
|
||||
**visible_region = terminal_dimensions * ORTHO_SCALING;
|
||||
**spawn_amount = ((visible_region.x * visible_region.y) / 777.) as u32;
|
||||
|
@ -170,7 +164,7 @@ fn bubble_movement_system(
|
|||
|
||||
bubble.target = bubble
|
||||
.target
|
||||
.move_towards(next_point, time.delta_seconds() * 10.);
|
||||
.move_towards(next_point, time.delta_secs() * 10.);
|
||||
|
||||
**velocity += diff * 0.01;
|
||||
**velocity = velocity.clamp(
|
||||
|
@ -183,7 +177,7 @@ fn bubble_movement_system(
|
|||
|
||||
fn bubble_color_system(time: Res<Time>, mut bubbles: Query<&mut Sprite, With<Bubble>>) {
|
||||
for mut sprite in &mut bubbles {
|
||||
let new_hue = (sprite.color.hue() + time.delta_seconds() * 10.) % 360.;
|
||||
let new_hue = (sprite.color.hue() + time.delta_secs() * 10.) % 360.;
|
||||
sprite.color.set_hue(new_hue);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,233 +0,0 @@
|
|||
use avian2d::{
|
||||
math::{Scalar, Vector},
|
||||
prelude::{Collider, Gravity, RigidBody},
|
||||
PhysicsPlugins,
|
||||
};
|
||||
use bevy::{prelude::*, render::camera::ScalingMode};
|
||||
use bevy_ratatui::event::ResizeEvent;
|
||||
use bevy_ratatui_render::RatatuiRenderContext;
|
||||
use rand::{seq::IteratorRandom, Rng, SeedableRng};
|
||||
use rand_chacha::ChaCha8Rng;
|
||||
|
||||
const ORTHO_SCALING: f32 = 32.;
|
||||
const BUBBLE_RATE: f32 = 1.;
|
||||
const BUBBLE_MAX: u32 = 16;
|
||||
const BUBBLE_RADIUS: f32 = 0.75;
|
||||
|
||||
pub(super) fn plugin(app: &mut App) {
|
||||
app.add_plugins(PhysicsPlugins::default())
|
||||
.insert_resource(Gravity(Vector::ZERO))
|
||||
.init_resource::<BubbleVisibleRegion>()
|
||||
.add_systems(Startup, bubbles_setup_system)
|
||||
.add_systems(Update, (bubbles_spawn_system, handle_resize_system));
|
||||
}
|
||||
|
||||
#[derive(Component)]
|
||||
pub struct Bubble;
|
||||
|
||||
#[derive(Resource, Deref, DerefMut)]
|
||||
pub struct BubbleRng(ChaCha8Rng);
|
||||
|
||||
#[derive(Resource, Deref)]
|
||||
pub struct BubbleMaterials(Vec<Handle<StandardMaterial>>);
|
||||
|
||||
#[derive(Resource, Deref)]
|
||||
pub struct BubbleMesh(Handle<Mesh>);
|
||||
|
||||
#[derive(Resource, Deref, Default)]
|
||||
pub struct BubbleVisibleRegion(Vec2);
|
||||
|
||||
#[derive(Bundle)]
|
||||
pub struct BubbleBundle {
|
||||
bubble: Bubble,
|
||||
pbr: PbrBundle,
|
||||
rigidbody: RigidBody,
|
||||
collider: Collider,
|
||||
}
|
||||
|
||||
impl BubbleBundle {
|
||||
fn new(
|
||||
rng: &mut BubbleRng,
|
||||
materials: &BubbleMaterials,
|
||||
mesh: &BubbleMesh,
|
||||
region: &Rectangle,
|
||||
) -> Self {
|
||||
Self {
|
||||
bubble: Bubble,
|
||||
pbr: PbrBundle {
|
||||
transform: Transform::from_translation(
|
||||
region.sample_interior(&mut rng.0).extend(0.),
|
||||
),
|
||||
material: materials
|
||||
.iter()
|
||||
.choose(&mut rng.0)
|
||||
.expect("bubble materials were not generated.")
|
||||
.clone(),
|
||||
mesh: mesh.0.clone(),
|
||||
..default()
|
||||
},
|
||||
rigidbody: RigidBody::Dynamic,
|
||||
collider: Collider::circle(BUBBLE_RADIUS as Scalar),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Resource, Deref, DerefMut)]
|
||||
pub struct BubbleTimer(Timer);
|
||||
|
||||
impl Default for BubbleTimer {
|
||||
fn default() -> Self {
|
||||
Self(Timer::from_seconds(BUBBLE_RATE, TimerMode::Repeating))
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Component)]
|
||||
pub struct BubbleTopWall;
|
||||
|
||||
#[derive(Component)]
|
||||
pub struct BubbleBottomWall;
|
||||
|
||||
#[derive(Component)]
|
||||
pub struct BubbleLeftWall;
|
||||
|
||||
#[derive(Component)]
|
||||
pub struct BubbleRightWall;
|
||||
|
||||
fn bubbles_setup_system(
|
||||
mut commands: Commands,
|
||||
ratatui_render: Res<RatatuiRenderContext>,
|
||||
mut meshes: ResMut<Assets<Mesh>>,
|
||||
mut materials: ResMut<Assets<StandardMaterial>>,
|
||||
) {
|
||||
commands.spawn(Camera3dBundle {
|
||||
camera: Camera {
|
||||
target: ratatui_render.target("main").unwrap_or_default(),
|
||||
..default()
|
||||
},
|
||||
projection: Projection::Orthographic(OrthographicProjection {
|
||||
scaling_mode: ScalingMode::WindowSize(ORTHO_SCALING),
|
||||
..default()
|
||||
}),
|
||||
transform: Transform::from_xyz(0., 0., 5.).looking_at(Vec3::ZERO, Vec3::Y),
|
||||
..default()
|
||||
});
|
||||
|
||||
commands.spawn(PointLightBundle {
|
||||
transform: Transform::from_xyz(0., 0., -5.),
|
||||
point_light: PointLight {
|
||||
intensity: 10_000.,
|
||||
shadows_enabled: true,
|
||||
..default()
|
||||
},
|
||||
..default()
|
||||
});
|
||||
|
||||
let mut rng = ChaCha8Rng::seed_from_u64(19878367467712);
|
||||
commands.insert_resource(BubbleMaterials(
|
||||
(0..8)
|
||||
.map(|_| {
|
||||
materials.add(StandardMaterial {
|
||||
base_color: Color::hsl(rng.gen_range(0.0..360.0), 1.0, 0.8),
|
||||
specular_transmission: 0.9,
|
||||
diffuse_transmission: 1.0,
|
||||
thickness: 1.8,
|
||||
ior: 1.5,
|
||||
perceptual_roughness: 0.12,
|
||||
..default()
|
||||
})
|
||||
})
|
||||
.collect(),
|
||||
));
|
||||
commands.insert_resource(BubbleRng(rng));
|
||||
commands.insert_resource(BubbleMesh(meshes.add(Sphere::new(BUBBLE_RADIUS))));
|
||||
|
||||
let wall_bundle = (
|
||||
PbrBundle {
|
||||
mesh: meshes.add(Cuboid::from_size(Vec3::new(1., 1., 1.))),
|
||||
material: materials.add(StandardMaterial::default()),
|
||||
..default()
|
||||
},
|
||||
RigidBody::Static,
|
||||
Collider::rectangle(0.95, 0.95),
|
||||
);
|
||||
|
||||
commands.spawn((wall_bundle.clone(), BubbleBottomWall));
|
||||
commands.spawn((wall_bundle.clone(), BubbleTopWall));
|
||||
commands.spawn((wall_bundle.clone(), BubbleLeftWall));
|
||||
commands.spawn((wall_bundle.clone(), BubbleRightWall));
|
||||
}
|
||||
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
fn bubbles_spawn_system(
|
||||
mut commands: Commands,
|
||||
time: Res<Time>,
|
||||
mut rng: ResMut<BubbleRng>,
|
||||
materials: Res<BubbleMaterials>,
|
||||
mesh: Res<BubbleMesh>,
|
||||
visible_region: Res<BubbleVisibleRegion>,
|
||||
mut timer: Local<BubbleTimer>,
|
||||
mut count: Local<u32>,
|
||||
) {
|
||||
timer.tick(time.delta());
|
||||
if timer.finished() && *count < BUBBLE_MAX {
|
||||
*count += 1;
|
||||
commands.spawn(BubbleBundle::new(
|
||||
&mut rng,
|
||||
&materials,
|
||||
&mesh,
|
||||
&Rectangle::from_size(**visible_region - BUBBLE_RADIUS * 2.),
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
type BottomWallQuery = (
|
||||
With<BubbleBottomWall>,
|
||||
Without<BubbleTopWall>,
|
||||
Without<BubbleLeftWall>,
|
||||
Without<BubbleRightWall>,
|
||||
);
|
||||
type TopWallQuery = (
|
||||
With<BubbleTopWall>,
|
||||
Without<BubbleBottomWall>,
|
||||
Without<BubbleLeftWall>,
|
||||
Without<BubbleRightWall>,
|
||||
);
|
||||
type LeftWallQuery = (
|
||||
With<BubbleLeftWall>,
|
||||
Without<BubbleBottomWall>,
|
||||
Without<BubbleTopWall>,
|
||||
Without<BubbleRightWall>,
|
||||
);
|
||||
type RightWallQuery = (
|
||||
With<BubbleRightWall>,
|
||||
Without<BubbleBottomWall>,
|
||||
Without<BubbleTopWall>,
|
||||
Without<BubbleLeftWall>,
|
||||
);
|
||||
fn handle_resize_system(
|
||||
mut resize_events: EventReader<ResizeEvent>,
|
||||
mut visible_region: ResMut<BubbleVisibleRegion>,
|
||||
ratatui_render: Res<RatatuiRenderContext>,
|
||||
mut bottom_wall: Query<&mut Transform, BottomWallQuery>,
|
||||
mut top_wall: Query<&mut Transform, TopWallQuery>,
|
||||
mut left_wall: Query<&mut Transform, LeftWallQuery>,
|
||||
mut right_wall: Query<&mut Transform, RightWallQuery>,
|
||||
) {
|
||||
for _ in resize_events.read() {
|
||||
let (width, height) = ratatui_render.dimensions("main").unwrap();
|
||||
let terminal_dimensions = Vec2::new(width as f32, height as f32);
|
||||
visible_region.0 = terminal_dimensions / ORTHO_SCALING;
|
||||
|
||||
bottom_wall.single_mut().translation = Vec3::new(0.0, -visible_region.y / 2., 0.0);
|
||||
bottom_wall.single_mut().scale = Vec3::new(visible_region.x, 0.5, 1.0);
|
||||
|
||||
top_wall.single_mut().translation = Vec3::new(0.0, visible_region.y / 2., 0.0);
|
||||
top_wall.single_mut().scale = Vec3::new(visible_region.x, 0.5, 1.0);
|
||||
|
||||
left_wall.single_mut().translation = Vec3::new(-visible_region.x / 2., 0.0, 0.0);
|
||||
left_wall.single_mut().scale = Vec3::new(0.5, visible_region.y, 1.0);
|
||||
|
||||
right_wall.single_mut().translation = Vec3::new(visible_region.x / 2., 0.0, 0.0);
|
||||
right_wall.single_mut().scale = Vec3::new(0.5, visible_region.y, 1.0);
|
||||
}
|
||||
}
|
|
@ -4,7 +4,7 @@ use bevy::utils::error;
|
|||
use bevy::{diagnostic::DiagnosticsStore, prelude::*};
|
||||
use bevy_ratatui::event::{KeyEvent, MouseEvent};
|
||||
use bevy_ratatui::terminal::RatatuiContext;
|
||||
use bevy_ratatui_render::RatatuiRenderContext;
|
||||
use bevy_ratatui_camera::RatatuiCameraWidget;
|
||||
|
||||
use crate::Flags;
|
||||
|
||||
|
@ -21,23 +21,13 @@ pub(super) fn plugin(app: &mut App) {
|
|||
|
||||
fn draw_scene_system(
|
||||
mut ratatui: ResMut<RatatuiContext>,
|
||||
ratatui_render: Res<RatatuiRenderContext>,
|
||||
widget: Query<&RatatuiCameraWidget>,
|
||||
_flags: Res<Flags>,
|
||||
_diagnostics: Res<DiagnosticsStore>,
|
||||
) -> io::Result<()> {
|
||||
ratatui.draw(|frame| {
|
||||
if let Some(widget) = ratatui_render.widget("main") {
|
||||
if let Ok(widget) = widget.get_single() {
|
||||
frame.render_widget(widget, frame.area());
|
||||
|
||||
// frame.render_widget(
|
||||
// Paragraph::new(flags.msgs.join("\n")).fg(Color::DarkBlue),
|
||||
// ratatui::layout::Rect {
|
||||
// x: 1,
|
||||
// y: 1,
|
||||
// width: 30,
|
||||
// height: 30,
|
||||
// },
|
||||
// );
|
||||
}
|
||||
})?;
|
||||
|
||||
|
|
|
@ -4,7 +4,7 @@ use bevy::prelude::*;
|
|||
use bevy::winit::WinitPlugin;
|
||||
use bevy::{app::ScheduleRunnerPlugin, log::LogPlugin};
|
||||
use bevy_ratatui::RatatuiPlugins;
|
||||
use bevy_ratatui_render::RatatuiRenderPlugin;
|
||||
use bevy_ratatui_camera::RatatuiCameraPlugin;
|
||||
use logo::LogoPath;
|
||||
pub use logo::{LOGO_PATH_DVD, LOGO_PATH_TTY};
|
||||
use maze::MazePaths;
|
||||
|
@ -30,9 +30,8 @@ impl Plugin for AppPlugin {
|
|||
.disable::<LogPlugin>(),
|
||||
ScheduleRunnerPlugin::run_loop(Duration::from_secs_f64(1. / 60.)),
|
||||
RatatuiPlugins::default(),
|
||||
RatatuiRenderPlugin::new("main", (256, 256)).autoresize(),
|
||||
RatatuiCameraPlugin,
|
||||
))
|
||||
.insert_resource(Msaa::Off)
|
||||
.init_resource::<Flags>();
|
||||
|
||||
app.add_plugins((assets::plugin, common::plugin));
|
||||
|
|
74
src/logo.rs
74
src/logo.rs
|
@ -1,12 +1,13 @@
|
|||
use bevy::prelude::*;
|
||||
use bevy_ratatui::event::ResizeEvent;
|
||||
use bevy_ratatui_render::RatatuiRenderContext;
|
||||
use bevy_ratatui_camera::RatatuiCamera;
|
||||
use rand::SeedableRng;
|
||||
use rand_chacha::ChaCha8Rng;
|
||||
|
||||
pub const LOGO_PATH_DVD: &str = "embedded://ttysvr/../assets/dvd_logo.png";
|
||||
pub const LOGO_PATH_TTY: &str = "embedded://ttysvr/../assets/tty_logo.png";
|
||||
|
||||
const STARTING_DIMENSIONS: (u32, u32) = (256, 256);
|
||||
const ORTHO_SCALING: f32 = 0.5;
|
||||
const LOGO_RADIUS: f32 = 32.;
|
||||
const LOGO_SPEED: f32 = 24.;
|
||||
|
@ -29,61 +30,47 @@ pub struct LogoPath(pub String);
|
|||
#[derive(Resource, Deref, DerefMut, Default)]
|
||||
struct LogoVisibleRegion(Vec2);
|
||||
|
||||
#[derive(Bundle)]
|
||||
struct LogoBundle {
|
||||
logo: Logo,
|
||||
sprite: SpriteBundle,
|
||||
}
|
||||
|
||||
impl LogoBundle {
|
||||
fn new(rng: &mut ChaCha8Rng, texture: Handle<Image>, region: Rectangle) -> Self {
|
||||
Self {
|
||||
logo: Logo {
|
||||
velocity: Vec2::new(LOGO_SPEED, -LOGO_SPEED),
|
||||
},
|
||||
sprite: SpriteBundle {
|
||||
transform: Transform::from_translation(region.sample_interior(rng).extend(0.)),
|
||||
texture,
|
||||
sprite: Sprite {
|
||||
color: Color::hsl(0., 1.0, 0.6),
|
||||
custom_size: Some(Vec2::splat(LOGO_RADIUS * 2.)),
|
||||
..default()
|
||||
},
|
||||
..default()
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn logo_setup_system(
|
||||
mut commands: Commands,
|
||||
ratatui_render: Res<RatatuiRenderContext>,
|
||||
asset_server: Res<AssetServer>,
|
||||
mut visible_region: ResMut<LogoVisibleRegion>,
|
||||
logo_path: Res<LogoPath>,
|
||||
) {
|
||||
let mut camera = Camera2dBundle::default();
|
||||
camera.projection.scale = ORTHO_SCALING;
|
||||
camera.camera.target = ratatui_render.target("main").unwrap_or_default();
|
||||
commands.spawn(camera);
|
||||
commands.spawn((
|
||||
RatatuiCamera::autoresize().with_dimensions(STARTING_DIMENSIONS),
|
||||
Camera2d,
|
||||
OrthographicProjection {
|
||||
scale: ORTHO_SCALING,
|
||||
..OrthographicProjection::default_2d()
|
||||
},
|
||||
));
|
||||
|
||||
**visible_region = get_visible_region(&ratatui_render);
|
||||
let texture = asset_server.load(&**logo_path);
|
||||
**visible_region = get_visible_region(STARTING_DIMENSIONS);
|
||||
let image = asset_server.load(&**logo_path);
|
||||
let mut rng = ChaCha8Rng::seed_from_u64(19878367467712);
|
||||
commands.spawn(LogoBundle::new(
|
||||
&mut rng,
|
||||
texture,
|
||||
Rectangle::from_size(**visible_region * 0.5 - LOGO_RADIUS * 2.),
|
||||
let region = Rectangle::from_size(**visible_region * 0.5 - LOGO_RADIUS * 2.);
|
||||
|
||||
commands.spawn((
|
||||
Logo {
|
||||
velocity: Vec2::new(LOGO_SPEED, -LOGO_SPEED),
|
||||
},
|
||||
Sprite {
|
||||
image,
|
||||
color: Color::hsl(0., 1., 0.6),
|
||||
custom_size: Some(Vec2::splat(LOGO_RADIUS * 2.)),
|
||||
..default()
|
||||
},
|
||||
Transform::from_translation(region.sample_interior(&mut rng).extend(0.)),
|
||||
));
|
||||
}
|
||||
|
||||
fn handle_resize_system(
|
||||
mut resize_events: EventReader<ResizeEvent>,
|
||||
mut visible_region: ResMut<LogoVisibleRegion>,
|
||||
ratatui_render: Res<RatatuiRenderContext>,
|
||||
) {
|
||||
for _ in resize_events.read() {
|
||||
**visible_region = get_visible_region(&ratatui_render);
|
||||
for resize in resize_events.read() {
|
||||
let (width, height) = (resize.width * 2, resize.height * 4);
|
||||
**visible_region = get_visible_region((width as u32, height as u32));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -96,7 +83,7 @@ fn logo_movement_system(
|
|||
let visible_area = Rectangle::from_size(**visible_region - LOGO_RADIUS * 1.95);
|
||||
let visible_half = visible_area.half_size.extend(0.);
|
||||
|
||||
transform.translation += velocity.extend(0.) * time.delta_seconds();
|
||||
transform.translation += velocity.extend(0.) * time.delta_secs();
|
||||
|
||||
if (transform.translation.x < -visible_half.x && velocity.x < 0.)
|
||||
|| (transform.translation.x > visible_half.x && velocity.x > 0.)
|
||||
|
@ -116,8 +103,7 @@ fn logo_movement_system(
|
|||
}
|
||||
}
|
||||
|
||||
fn get_visible_region(ratatui_render: &RatatuiRenderContext) -> Vec2 {
|
||||
let (width, height) = ratatui_render.dimensions("main").unwrap();
|
||||
fn get_visible_region((width, height): (u32, u32)) -> Vec2 {
|
||||
let terminal_dimensions = Vec2::new(width as f32, height as f32);
|
||||
terminal_dimensions * ORTHO_SCALING
|
||||
}
|
||||
|
|
121
src/maze.rs
121
src/maze.rs
|
@ -1,8 +1,7 @@
|
|||
use std::collections::BTreeMap;
|
||||
use std::{collections::BTreeMap, f32::consts::PI};
|
||||
|
||||
use avian2d::math::PI;
|
||||
use bevy::prelude::*;
|
||||
use bevy_ratatui_render::RatatuiRenderContext;
|
||||
use bevy_ratatui_camera::RatatuiCamera;
|
||||
use rand::{seq::SliceRandom, thread_rng};
|
||||
|
||||
pub const MAZE_WALL_PATH_BRICK: &str = "embedded://ttysvr/../assets/maze_wall_brick.png";
|
||||
|
@ -22,8 +21,8 @@ type MazeGraph = BTreeMap<(i32, i32), (bool, bool, bool, bool)>;
|
|||
|
||||
const MAZE_SIZE: i32 = 12;
|
||||
const MAZE_SCALE: f32 = 1.0;
|
||||
const MAZE_WALK_SPEED: f32 = 1.5;
|
||||
const MAZE_TURN_SPEED: f32 = 2.5;
|
||||
const MAZE_WALK_SPEED: f32 = 0.4;
|
||||
const MAZE_TURN_SPEED: f32 = 2.0;
|
||||
const WALL_DIMENSIONS: Vec3 = Vec3::new(1.0, 0.01, 1.0);
|
||||
const DIRECTION_LIST: &[MazeDirection] = &[
|
||||
MazeDirection::North,
|
||||
|
@ -111,7 +110,6 @@ fn maze_generation_system(mut commands: Commands) {
|
|||
|
||||
fn maze_setup_system(
|
||||
mut commands: Commands,
|
||||
ratatui_render: Res<RatatuiRenderContext>,
|
||||
maze: Res<Maze>,
|
||||
asset_server: Res<AssetServer>,
|
||||
mut meshes: ResMut<Assets<Mesh>>,
|
||||
|
@ -150,89 +148,72 @@ fn maze_setup_system(
|
|||
let translation = target_to_vec3((*x, *y));
|
||||
|
||||
if !*north {
|
||||
let transform =
|
||||
Transform::default().with_translation(translation + Vec3::Y * MAZE_SCALE * 0.5);
|
||||
commands.spawn(PbrBundle {
|
||||
transform,
|
||||
mesh: wall_mesh.clone(),
|
||||
material: wall_material.clone(),
|
||||
..default()
|
||||
});
|
||||
commands.spawn((
|
||||
Transform::default().with_translation(translation + Vec3::Y * MAZE_SCALE * 0.5),
|
||||
Mesh3d(wall_mesh.clone()),
|
||||
MeshMaterial3d(wall_material.clone()),
|
||||
));
|
||||
}
|
||||
|
||||
if !*east {
|
||||
let transform = Transform::default()
|
||||
.with_translation(translation + Vec3::X * MAZE_SCALE * 0.5)
|
||||
.with_rotation(Quat::from_rotation_z(PI / 2.));
|
||||
commands.spawn(PbrBundle {
|
||||
transform,
|
||||
mesh: wall_mesh.clone(),
|
||||
material: wall_material.clone(),
|
||||
..default()
|
||||
});
|
||||
commands.spawn((
|
||||
Transform::default()
|
||||
.with_translation(translation + Vec3::X * MAZE_SCALE * 0.5)
|
||||
.with_rotation(Quat::from_rotation_z(PI / 2.)),
|
||||
Mesh3d(wall_mesh.clone()),
|
||||
MeshMaterial3d(wall_material.clone()),
|
||||
));
|
||||
}
|
||||
|
||||
if !*south && *y == 0 {
|
||||
let transform = Transform::default()
|
||||
.with_translation(translation - Vec3::Y * MAZE_SCALE * 0.5)
|
||||
.with_rotation(Quat::from_rotation_z(PI));
|
||||
commands.spawn(PbrBundle {
|
||||
transform,
|
||||
mesh: wall_mesh.clone(),
|
||||
material: wall_material.clone(),
|
||||
..default()
|
||||
});
|
||||
commands.spawn((
|
||||
Transform::default()
|
||||
.with_translation(translation - Vec3::Y * MAZE_SCALE * 0.5)
|
||||
.with_rotation(Quat::from_rotation_z(PI)),
|
||||
Mesh3d(wall_mesh.clone()),
|
||||
MeshMaterial3d(wall_material.clone()),
|
||||
));
|
||||
}
|
||||
|
||||
if !*west && *x == 0 {
|
||||
let transform = Transform::default()
|
||||
.with_translation(translation - Vec3::X * MAZE_SCALE * 0.5)
|
||||
.with_rotation(Quat::from_rotation_z(PI * 3. / 2.));
|
||||
commands.spawn(PbrBundle {
|
||||
transform,
|
||||
mesh: wall_mesh.clone(),
|
||||
material: wall_material.clone(),
|
||||
..default()
|
||||
});
|
||||
commands.spawn((
|
||||
Transform::default()
|
||||
.with_translation(translation - Vec3::X * MAZE_SCALE * 0.5)
|
||||
.with_rotation(Quat::from_rotation_z(PI * 3. / 2.)),
|
||||
Mesh3d(wall_mesh.clone()),
|
||||
MeshMaterial3d(wall_material.clone()),
|
||||
));
|
||||
}
|
||||
|
||||
commands.spawn(PbrBundle {
|
||||
transform: Transform::default()
|
||||
commands.spawn((
|
||||
Transform::default()
|
||||
.with_translation(translation - Vec3::Z * 0.5 * MAZE_SCALE * WALL_DIMENSIONS.z),
|
||||
mesh: floor_ceiling_mesh.clone(),
|
||||
material: floor_material.clone(),
|
||||
..default()
|
||||
});
|
||||
Mesh3d(floor_ceiling_mesh.clone()),
|
||||
MeshMaterial3d(floor_material.clone()),
|
||||
));
|
||||
|
||||
commands.spawn(PbrBundle {
|
||||
transform: Transform::default()
|
||||
commands.spawn((
|
||||
Transform::default()
|
||||
.with_translation(translation + Vec3::Z * 0.5 * MAZE_SCALE * WALL_DIMENSIONS.z),
|
||||
mesh: floor_ceiling_mesh.clone(),
|
||||
material: ceiling_material.clone(),
|
||||
..default()
|
||||
});
|
||||
Mesh3d(floor_ceiling_mesh.clone()),
|
||||
MeshMaterial3d(ceiling_material.clone()),
|
||||
));
|
||||
}
|
||||
|
||||
commands
|
||||
.spawn(Camera3dBundle {
|
||||
camera: Camera {
|
||||
target: ratatui_render.target("main").unwrap_or_default(),
|
||||
..default()
|
||||
},
|
||||
projection: Projection::Perspective(PerspectiveProjection {
|
||||
.spawn((
|
||||
Msaa::Sample8,
|
||||
RatatuiCamera::autoresize().with_autoresize_fn(|(w, h)| (w * 4, h * 4)),
|
||||
Camera3d::default(),
|
||||
Projection::Perspective(PerspectiveProjection {
|
||||
fov: PI / 2.,
|
||||
..default()
|
||||
}),
|
||||
transform: Transform::from_translation(Vec3::new(0., 0., 0.))
|
||||
.looking_at(Vec3::new(0., 1., 0.), Vec3::Z),
|
||||
..default()
|
||||
})
|
||||
Transform::default().looking_at(Vec3::Y, Vec3::Z),
|
||||
))
|
||||
.with_children(|commands| {
|
||||
commands.spawn(PointLightBundle {
|
||||
point_light: PointLight {
|
||||
intensity: 10_000.,
|
||||
..default()
|
||||
},
|
||||
commands.spawn(PointLight {
|
||||
intensity: 10_000.,
|
||||
..default()
|
||||
});
|
||||
});
|
||||
|
@ -242,9 +223,9 @@ fn movement_system(
|
|||
time: Res<Time>,
|
||||
maze: Res<Maze>,
|
||||
mut target: ResMut<MazeTarget>,
|
||||
mut camera: Query<&mut Transform, With<Camera>>,
|
||||
mut camera: Query<&mut Transform, With<Camera3d>>,
|
||||
) {
|
||||
let delta = time.delta_seconds();
|
||||
let delta = time.delta_secs();
|
||||
let mut camera_transform = camera.single_mut();
|
||||
let target_vec = target_to_vec3(**target);
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue