mod debug; use debug::DebugPlugin; use serde::Deserialize; use std::fs::File; use std::io::BufReader; use bevy_inspector_egui::Inspectable; use bevy::{ prelude::*, sprite::{MaterialMesh2dBundle, collide_aabb::collide}, render::camera::ScalingMode, ecs::system::EntityCommands, math::Vec3Swizzles, core::FixedTimestep, }; use bevy::diagnostic::{FrameTimeDiagnosticsPlugin, LogDiagnosticsPlugin}; fn main() { App::new() .add_plugins(DefaultPlugins) .add_startup_system(spawn_camera) .add_startup_system(setup) .add_plugin(LogDiagnosticsPlugin::default()) .add_plugin(FrameTimeDiagnosticsPlugin::default()) .add_stage_after(CoreStage::Update, "physics", SystemStage::parallel() .with_run_criteria(FixedTimestep::steps_per_second(60.0)) .with_system(movement.label("movement")) .with_system(camera_follow.after("movement")) ) .run(); } fn spawn_camera(mut commands: Commands) { let mut camera = OrthographicCameraBundle::new_2d(); camera.orthographic_projection.scaling_mode = ScalingMode::None; camera.transform = Transform::from_xyz(0.0, 0.0, 100.0); commands.spawn_bundle(camera); } fn camera_follow( player_query: Query<(&Transform, With)>, mut camera_query: Query<&mut Transform, (Without, With)>, ) { let (player_transform, _) = player_query.single(); let mut camera_transform = camera_query.single_mut(); camera_transform.translation.x = player_transform.translation.x; camera_transform.translation.y = player_transform.translation.y; } #[derive(Component, Inspectable)] pub struct Player { speed: Vec3, radius: f32 } #[derive(Component, Clone)] pub struct Collider { speed_mul: f32, height: bool, } fn rotate ( ) { } fn wall_collision_check( target_player_pos: Vec3, wall_query: &Query<(&Transform, &Collider), (With, Without)>, ) -> Option { for (wall_transform, collider) in wall_query.iter() { let collision = collide( target_player_pos, Vec2::splat(0.03), wall_transform.translation, wall_transform.scale.xy() ); if collision.is_some() { return Some(collider.clone()); } } None } // https://stackoverflow.com/questions/3838329 fn ccw (a: Vec3, b: Vec3, c: Vec3) -> bool { (c.y - a.y) * (b.x - a.x) > (b.y - a.y) * (c.x - a.x) } fn intersect_segment_segment (a: Vec3, b: Vec3, c: Vec3, d: Vec3) -> bool { ccw(a, c, d) != ccw(b, c, d) && ccw(a, b, c) != ccw(a, b, d) } fn collision_segment_segment ( pos: Vec3, vel: Vec3, lo: Vec3, hi: Vec3, norm: Vec3 ) -> (Vec3, Vec3) { if intersect_segment_segment(pos, pos + vel, lo, hi) { let target = pos + vel - lo; let tan = (hi - lo).normalize(); let tv = target.dot(tan) * tan; return (lo + tv + norm * 0.0001, Vec3::ZERO) } (pos, vel) } // https://stackoverflow.com/questions/1073336 fn intersect_segment_circle (e: Vec3, l: Vec3, c: Vec3, r: f32) -> bool { if (e + l - c).length_squared() < r * r { return true } if (e - c).length_squared() < r * r { return true } let d = l; let f = e - c; let a = d.length_squared(); let b = 2.0 * f.dot(d); let z = f.dot(f) - r * r; let delta = b * b - 4.0 * a * z; if delta > 0.0 { let deltaroot = delta.sqrt(); let t1 = (-b - deltaroot) / (2.0 * a); if t1 >= 0.0 && t1 <= 1.0 { return true } let t2 = (-b + deltaroot) / (2.0 * a); if t2 >= 0.0 && t2 <= 1.0 { return true } } false } fn collision_segment_circle ( pos: Vec3, vel: Vec3, center: Vec3, rad: f32 ) -> (Vec3, Vec3) { if intersect_segment_circle(pos, vel, center, rad) { let out = pos + vel - center; let norm = out.normalize(); let perp = Vec3::new(-out.y, out.x, 0.0).dot(out) * 2.0; return (norm * rad * 1.0005 + center, out * perp) } (pos, vel) } fn movement ( mut player_query: Query<(&mut Player, &mut Transform)>, wall_query: Query<(&Transform, &Collider), (With, Without)>, keyboard: Res>, time: Res