173 lines
5.1 KiB
Rust
173 lines
5.1 KiB
Rust
use avian2d::prelude::*;
|
|
use bevy::{
|
|
input::common_conditions::input_just_pressed,
|
|
prelude::*,
|
|
window::{PrimaryWindow, WindowResized},
|
|
};
|
|
|
|
fn main() {
|
|
App::new()
|
|
.insert_resource(ClearColor(Color::srgb_u8(26, 26, 46)))
|
|
.add_plugins((
|
|
DefaultPlugins.set(WindowPlugin {
|
|
primary_window: Some(Window {
|
|
fit_canvas_to_parent: true,
|
|
prevent_default_event_handling: false,
|
|
canvas: Some("#bevy-canvas".into()),
|
|
..default()
|
|
}),
|
|
..default()
|
|
}),
|
|
PhysicsPlugins::default(),
|
|
))
|
|
.insert_resource(Time::<Physics>::default().with_relative_speed(5.0))
|
|
.add_systems(Startup, setup)
|
|
.add_systems(
|
|
Update,
|
|
(
|
|
update_screen_edges,
|
|
spawn_ball.run_if(input_just_pressed(MouseButton::Left)),
|
|
),
|
|
)
|
|
.run();
|
|
}
|
|
|
|
#[derive(Component, Clone, Copy)]
|
|
enum ScreenEdge {
|
|
Top,
|
|
Bottom,
|
|
Left,
|
|
Right,
|
|
}
|
|
|
|
fn setup(
|
|
mut commands: Commands,
|
|
mut meshes: ResMut<Assets<Mesh>>,
|
|
mut materials: ResMut<Assets<ColorMaterial>>,
|
|
window: Query<&Window, With<PrimaryWindow>>,
|
|
) {
|
|
commands.spawn(Camera2d);
|
|
|
|
if let Ok(window) = window.single() {
|
|
spawn_screen_edges(&mut commands, &mut meshes, &mut materials, window.size());
|
|
}
|
|
}
|
|
|
|
#[derive(Component, Clone, Copy)]
|
|
struct Ball;
|
|
|
|
fn spawn_ball(
|
|
mouse_button: Res<ButtonInput<MouseButton>>,
|
|
window: Single<&Window, With<PrimaryWindow>>,
|
|
camera_query: Single<(&Camera, &GlobalTransform)>,
|
|
time: Res<Time>,
|
|
mut commands: Commands,
|
|
mut meshes: ResMut<Assets<Mesh>>,
|
|
mut materials: ResMut<Assets<ColorMaterial>>,
|
|
) {
|
|
const CIRCLE_RADIUS: f32 = 5.0;
|
|
|
|
let (camera, camera_transform) = *camera_query;
|
|
if mouse_button.just_pressed(MouseButton::Left)
|
|
&& let Some(cursor_position) = window.cursor_position()
|
|
&& let Ok(world_position) = camera.viewport_to_world_2d(camera_transform, cursor_position)
|
|
{
|
|
commands.spawn((
|
|
RigidBody::Dynamic,
|
|
Collider::circle(CIRCLE_RADIUS),
|
|
Restitution::PERFECTLY_ELASTIC.with_combine_rule(CoefficientCombine::Max),
|
|
Mesh2d(meshes.add(Circle::new(CIRCLE_RADIUS))),
|
|
MeshMaterial2d(materials.add(Color::hsl(time.elapsed_secs().sin() * 360.0, 1.0, 0.5))),
|
|
Transform::from_xyz(world_position.x, world_position.y, 0.0),
|
|
Ball,
|
|
));
|
|
}
|
|
}
|
|
|
|
fn spawn_screen_edges(
|
|
commands: &mut Commands,
|
|
meshes: &mut Assets<Mesh>,
|
|
materials: &mut Assets<ColorMaterial>,
|
|
size: Vec2,
|
|
) {
|
|
const EDGE_COLOR: Color = Color::srgb_u8(255, 255, 255);
|
|
|
|
let material = materials.add(EDGE_COLOR);
|
|
|
|
for edge in [
|
|
ScreenEdge::Top,
|
|
ScreenEdge::Bottom,
|
|
ScreenEdge::Left,
|
|
ScreenEdge::Right,
|
|
] {
|
|
let (collider, transform, rect_size) = edge_shape(edge, size);
|
|
commands.spawn((
|
|
RigidBody::Static,
|
|
collider,
|
|
transform,
|
|
edge,
|
|
Mesh2d(meshes.add(Rectangle::from_size(rect_size))),
|
|
MeshMaterial2d(material.clone()),
|
|
));
|
|
}
|
|
}
|
|
|
|
fn edge_shape(edge: ScreenEdge, size: Vec2) -> (Collider, Transform, Vec2) {
|
|
const EDGE_THICKNESS: f32 = 5.0;
|
|
|
|
let half = size / 2.0;
|
|
let thickness = EDGE_THICKNESS;
|
|
|
|
match edge {
|
|
ScreenEdge::Top => {
|
|
let rect = Vec2::new(size.x, thickness);
|
|
(
|
|
Collider::rectangle(rect.x, rect.y),
|
|
Transform::from_xyz(0.0, half.y - thickness / 2.0, 0.0),
|
|
rect,
|
|
)
|
|
}
|
|
ScreenEdge::Bottom => {
|
|
let rect = Vec2::new(size.x, thickness);
|
|
(
|
|
Collider::rectangle(rect.x, rect.y),
|
|
Transform::from_xyz(0.0, -half.y + thickness / 2.0, 0.0),
|
|
rect,
|
|
)
|
|
}
|
|
ScreenEdge::Left => {
|
|
let rect = Vec2::new(thickness, size.y);
|
|
(
|
|
Collider::rectangle(rect.x, rect.y),
|
|
Transform::from_xyz(-half.x + thickness / 2.0, 0.0, 0.0),
|
|
rect,
|
|
)
|
|
}
|
|
ScreenEdge::Right => {
|
|
let rect = Vec2::new(thickness, size.y);
|
|
(
|
|
Collider::rectangle(rect.x, rect.y),
|
|
Transform::from_xyz(half.x - thickness / 2.0, 0.0, 0.0),
|
|
rect,
|
|
)
|
|
}
|
|
}
|
|
}
|
|
|
|
fn update_screen_edges(
|
|
mut resized: PopulatedMessageReader<WindowResized>,
|
|
mut edges: Query<(&ScreenEdge, &mut Collider, &mut Transform, &Mesh2d)>,
|
|
mut meshes: ResMut<Assets<Mesh>>,
|
|
) {
|
|
for event in resized.read() {
|
|
let size = Vec2::new(event.width, event.height);
|
|
for (edge, mut collider, mut transform, mesh2d) in &mut edges {
|
|
let (new_collider, new_transform, rect_size) = edge_shape(*edge, size);
|
|
*collider = new_collider;
|
|
*transform = new_transform;
|
|
if let Some(mut mesh) = meshes.get_mut(&mesh2d.0) {
|
|
*mesh = Rectangle::from_size(rect_size).into();
|
|
}
|
|
}
|
|
}
|
|
}
|