Compare commits

..

No commits in common. "0896ccf6913c77251d38054646f0a02af4f3db98" and "10a6bad3365f1b3ae315d3a485ff3607e0681441" have entirely different histories.

4 changed files with 28 additions and 48 deletions

View file

@ -6,13 +6,9 @@ use bevy::prelude::*;
#[require(Collider, Mesh2d, MeshMaterial2d<ColorMaterial>, Restitution = Restitution::new(1.0), RigidBody, TransformInterpolation, Transform)] #[require(Collider, Mesh2d, MeshMaterial2d<ColorMaterial>, Restitution = Restitution::new(1.0), RigidBody, TransformInterpolation, Transform)]
struct GameObject; struct GameObject;
/// Radius of a ball
#[derive(Component, Default)]
pub struct Radius(pub f32);
/// A basic ball with which to interact /// A basic ball with which to interact
#[derive(Component, Default)] #[derive(Component, Default)]
#[require(GameObject, RigidBody = RigidBody::Dynamic, Radius)] #[require(GameObject, RigidBody = RigidBody::Dynamic)]
pub struct Ball; pub struct Ball;
/// The controllable ball /// The controllable ball

View file

@ -1,5 +1,3 @@
use core::f32;
use avian2d::prelude::*; use avian2d::prelude::*;
use bevy::{ use bevy::{
input::mouse::{AccumulatedMouseScroll, MouseScrollUnit}, input::mouse::{AccumulatedMouseScroll, MouseScrollUnit},
@ -7,46 +5,32 @@ use bevy::{
prelude::*, prelude::*,
}; };
use super::objects::{Player, Radius}; use super::objects::Player;
/// Move the player character based on the keyboard input /// Move the player character based on the keyboard input
pub fn move_player( pub fn move_player(
time: Res<Time>, time: Res<Time>,
keyboard_input: Res<ButtonInput<KeyCode>>, keyboard_input: Res<ButtonInput<KeyCode>>,
mut query: Single<(&mut LinearVelocity, &Radius), With<Player>>, mut velocity: Single<&mut LinearVelocity, With<Player>>,
) { ) -> Result {
let (ref mut velocity, radius) = *query; let acceleration = 500.0;
let acceleration_energy = 150000.0; let delta_v = acceleration * time.delta_secs();
// Although it would arguably be more accurate to divide by pi to get the actual mass (or include the density
// somehow), `acceleration_energy` is in arbitrary units so we can just pretend it's proper physics
let delta_v = acceleration_energy * time.delta_secs() / radius.0.powi(2);
let mut direction = Vec2::ZERO;
if keyboard_input.any_pressed([KeyCode::KeyW, KeyCode::ArrowUp]) { if keyboard_input.any_pressed([KeyCode::KeyW, KeyCode::ArrowUp]) {
direction.y += 1.0; velocity.y += delta_v;
} }
if keyboard_input.any_pressed([KeyCode::KeyS, KeyCode::ArrowDown]) { if keyboard_input.any_pressed([KeyCode::KeyS, KeyCode::ArrowDown]) {
direction.y -= 1.0; velocity.y -= delta_v;
} }
if keyboard_input.any_pressed([KeyCode::KeyA, KeyCode::ArrowLeft]) { if keyboard_input.any_pressed([KeyCode::KeyA, KeyCode::ArrowLeft]) {
direction.x -= 1.0; velocity.x -= delta_v;
} }
if keyboard_input.any_pressed([KeyCode::KeyD, KeyCode::ArrowRight]) { if keyboard_input.any_pressed([KeyCode::KeyD, KeyCode::ArrowRight]) {
direction.x += 1.0; velocity.x += delta_v;
} }
// This would be easier if I could compare floats with 0 and still sleep at night Ok(())
let circularize = if direction.x.abs() > 0.0 && direction.y.abs() > 0.0 {
f32::consts::FRAC_1_SQRT_2
} else {
1.0
};
// Kinda annoying I have to manually assign the fields here but I'll leave it in case I remember a better way later
velocity.x += direction.x * delta_v * circularize;
velocity.y += direction.y * delta_v * circularize;
} }
/// Neatly exit game /// Neatly exit game

View file

@ -12,7 +12,7 @@ use bevy_rand::prelude::{GlobalEntropy, WyRand};
use rand::Rng as _; use rand::Rng as _;
use super::{ use super::{
objects::{Ball, Player, Radius, Wall}, objects::{Ball, Player, Wall},
rng::thread_rng, rng::thread_rng,
}; };
@ -24,15 +24,19 @@ const DIMENSION_SIZES: Range<f32> = 500.0..2000.0;
#[derive(Resource)] #[derive(Resource)]
pub struct PlayableArea(f32, f32); pub struct PlayableArea(f32, f32);
/// The size of the player character
#[derive(Resource)]
pub struct PlayerSize(f32);
/// Initialize deterministic values /// Initialize deterministic values
pub fn setup_from_seed(mut commands: Commands, mut rng: GlobalEntropy<WyRand>) { pub fn setup_pseudo_random(mut commands: Commands, mut rng: GlobalEntropy<WyRand>) {
commands.insert_resource(PlayerSize(rng.random_range(BALL_SIZES)));
commands.insert_resource(PlayableArea( commands.insert_resource(PlayableArea(
rng.random_range(DIMENSION_SIZES), rng.random_range(DIMENSION_SIZES),
rng.random_range(DIMENSION_SIZES), rng.random_range(DIMENSION_SIZES),
)); ));
} }
/// I mean, a camera is technically a user interface, I guess
pub fn setup_ui(mut commands: Commands) { pub fn setup_ui(mut commands: Commands) {
commands.spawn((Name::new("Camera"), Camera2d, IsDefaultUiCamera)); commands.spawn((Name::new("Camera"), Camera2d, IsDefaultUiCamera));
} }
@ -42,15 +46,12 @@ pub fn setup_player(
mut commands: Commands, mut commands: Commands,
mut materials: ResMut<Assets<ColorMaterial>>, mut materials: ResMut<Assets<ColorMaterial>>,
mut meshes: ResMut<Assets<Mesh>>, mut meshes: ResMut<Assets<Mesh>>,
radius: Res<PlayerSize>,
) { ) {
let mut random = thread_rng(); let circle = Circle::new(radius.0);
let radius = random.random_range(BALL_SIZES);
let circle = Circle::new(radius);
commands.spawn(( commands.spawn((
Name::new("Player"), Name::new("Player"),
Player, Player,
Radius(radius),
Collider::from(circle), Collider::from(circle),
Mesh2d(meshes.add(circle)), Mesh2d(meshes.add(circle)),
MeshMaterial2d(materials.add(Color::from(LIME_400))), MeshMaterial2d(materials.add(Color::from(LIME_400))),
@ -65,20 +66,19 @@ pub fn setup_balls(
region: Res<PlayableArea>, region: Res<PlayableArea>,
) { ) {
let mut random = thread_rng(); let mut random = thread_rng();
for i in 0..BALL_COUNT { for i in 0..BALL_COUNT {
let radius = random.random_range(BALL_SIZES); let circle = Circle::new(random.random_range(BALL_SIZES));
let circle = Circle::new(radius);
commands.spawn(( commands.spawn((
Name::new(format!("Ball[{i}]")), Name::new(format!("Ball[{i}]")),
Ball, Ball,
Radius(radius),
Collider::from(circle), Collider::from(circle),
Mesh2d(meshes.add(circle)), Mesh2d(meshes.add(circle)),
MeshMaterial2d(materials.add(Color::from(RED_400))), MeshMaterial2d(materials.add(Color::from(RED_400))),
Transform::from_xyz( Transform::from_xyz(
random.random::<f32>() * (region.0 - 2.0 * radius) + radius - region.0 / 2.0, random.random::<f32>() * (region.0 - 2.0 * circle.radius) + circle.radius
random.random::<f32>() * (region.1 - 2.0 * radius) + radius - region.1 / 2.0, - region.0 / 2.0,
random.random::<f32>() * (region.1 - 2.0 * circle.radius) + circle.radius
- region.1 / 2.0,
0.0, 0.0,
), ),
)); ));

View file

@ -7,7 +7,7 @@ mod game;
use game::{ use game::{
runtime::{move_camera, move_player, quit, zoom_camera}, runtime::{move_camera, move_player, quit, zoom_camera},
seed::Seed, seed::Seed,
setup::{setup_balls, setup_from_seed, setup_player, setup_ui, setup_walls}, setup::{setup_balls, setup_player, setup_pseudo_random, setup_ui, setup_walls},
}; };
/// The initial configuration passed to the game's setup functions. /// The initial configuration passed to the game's setup functions.
@ -39,9 +39,9 @@ impl Plugin for AppSettings {
.add_systems( .add_systems(
Startup, Startup,
( (
setup_from_seed, setup_pseudo_random,
setup_ui, setup_ui,
(setup_player, setup_balls, setup_walls).after(setup_from_seed), (setup_player, setup_balls, setup_walls).after(setup_pseudo_random),
), ),
) )
.add_systems( .add_systems(