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.

161 lines
4.4 KiB
Rust

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_message::<CollisionStart>.or(on_message::<CollisionEnd>)),
)
.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,
ConstantForce::default(),
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(event: On<Add, TreePos>, tree_pos: Query<&TreePos>, mut commands: Commands) {
let TreePos(pos) = tree_pos.get(event.entity).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(event.entity).insert(t);
}
fn move_player(
keyboard_input: Res<ButtonInput<KeyCode>>,
mut player: Single<Forces, With<Player>>,
) {
const SPEED: f32 = 5.0;
if keyboard_input.pressed(KeyCode::ArrowLeft) {
player.apply_local_force(Vec2::NEG_X * SPEED);
} else if keyboard_input.pressed(KeyCode::ArrowRight) {
player.apply_local_force(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: MessageReader<CollisionStart>,
mut end_events: MessageReader<CollisionEnd>,
trees: Query<&TreePos>,
keyboard_input: Res<ButtonInput<KeyCode>>,
) {
debug_assert!(!(start_events.is_empty() && end_events.is_empty()));
let s = start_events.read().map(
|CollisionStart {
collider1,
collider2,
..
}| (collider1, collider2),
);
let e = end_events.read().map(
|CollisionEnd {
collider1,
collider2,
..
}| (collider1, collider2),
);
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
}
}