You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

156 lines
4.3 KiB
Rust

use avian3d::math::Vector;
// TEMP
use avian2d::prelude::*;
use bevy::{color::palettes::css::*, prelude::*};
fn main() {
App::new()
.add_plugins(DefaultPlugins)
.add_plugins(PhysicsPlugins::default())
.insert_resource(ClearColor(WHITE.into()))
.add_systems(Startup, setup)
.add_systems(Update, move_player)
.add_systems(Update, follow_player)
.add_systems(Update, draw_gizmos)
.add_systems(
Update,
event_detection.run_if(on_event::<CollisionStarted>.or(on_event::<CollisionEnded>)),
)
.add_observer(set_tree_position)
.run();
}
#[derive(Component)]
struct Player;
#[derive(Component)]
struct RenderGizmo;
#[derive(Component)]
struct PlayArea;
#[derive(Component, Debug)]
struct TreePos(isize);
fn setup(
mut commands: Commands,
mut meshes: ResMut<Assets<Mesh>>,
mut materials: ResMut<Assets<ColorMaterial>>,
) {
commands.spawn(Camera2d);
// Spawn "trees" (which are also sensors)
[
("TREE -3", -3),
("TREE -2", -2),
("TREE -2", -1),
("TREE 1", 1),
("TREE 2", 2),
("TREE 3", 3),
]
.iter()
.for_each(|(label, pos)| {
commands.spawn((
RigidBody::Static,
Collider::rectangle(100.0, 250.0),
Mesh2d(meshes.add(Rectangle::new(100.0, 250.0))),
MeshMaterial2d(materials.add(Color::from(GREEN))),
TreePos(*pos),
children![Text2d::new(*label),],
));
});
commands.spawn((
Player,
RigidBody::Kinematic,
ExternalImpulse::default().with_persistence(true),
Collider::rectangle(50.0, 50.0),
Mesh2d(meshes.add(Rectangle::new(50.0, 50.0))),
MeshMaterial2d(materials.add(Color::from(RED))),
children![
(
Text2d::new("PLAYER"),
Transform::from_scale(Vec3::new(0.5, 0.5, 0.5)),
),
(
Text2d::new("PLAY AREA"),
Transform::from_xyz(0.0, 212.0, 1.0),
TextColor(BLACK.into())
),
(
RenderGizmo,
PlayArea,
Visibility::Visible,
Transform::from_scale(Vec3::new(400.0, 400.0, 0.0)),
),
],
));
}
fn set_tree_position(
trigger: Trigger<OnAdd, TreePos>,
tree_pos: Query<&TreePos>,
mut commands: Commands,
) {
let TreePos(pos) = tree_pos.get(trigger.target()).unwrap();
let x = if (*pos) > 0 {
(200.0 * (*pos) as f32) - 100.0
} else {
(200.0 * (*pos) as f32) + 100.0
};
let t = Transform::from_xyz(x, 0.0, 0.0);
commands.entity(trigger.target()).insert(t);
}
fn move_player(
keyboard_input: Res<ButtonInput<KeyCode>>,
mut player: Single<&mut ExternalImpulse, With<Player>>,
) {
const SPEED: f32 = 5.0;
if keyboard_input.pressed(KeyCode::ArrowLeft) {
player.set_impulse(Vec2::NEG_X * SPEED);
} else if keyboard_input.pressed(KeyCode::ArrowRight) {
player.set_impulse(Vec2::X * SPEED);
}
}
fn follow_player(
player: Query<&Transform, (With<Player>, Changed<Transform>)>,
mut camera: Single<&mut Transform, (With<Camera2d>, Without<Player>)>,
) {
player.iter().for_each(|pt| {
camera.translation = pt.translation;
});
}
fn draw_gizmos(mut gizmos: Gizmos, play_area: Single<&GlobalTransform, With<RenderGizmo>>) {
gizmos.rect_2d(
play_area.translation().truncate(),
play_area.scale().truncate(),
MAGENTA,
)
}
fn event_detection(
mut start_events: EventReader<CollisionStarted>,
mut end_events: EventReader<CollisionEnded>,
player: Single<&Player>,
trees: Query<&TreePos>,
keyboard_input: Res<ButtonInput<KeyCode>>,
) {
debug_assert!(!(start_events.is_empty() && end_events.is_empty()));
let s = start_events.read().map(|CollisionStarted(a, b)| (a, b));
let e = end_events.read().map(|CollisionEnded(a, b)| (a, b));
let mut events = s.chain(e);
let current_tree = events.find_map(|(a, b)| {
info!("{a:?}, {b:?}");
trees.get(*a).or(trees.get(*b)).ok()
});
info!("{:?}", current_tree);
if keyboard_input.pressed(KeyCode::ArrowLeft) {
// moving left
} else if keyboard_input.pressed(KeyCode::ArrowRight) {
// moving right
}
}