Everything compiles

main
Elijah Voigt 1 month ago
parent c3cd7f87b6
commit acbf89a077

@ -2,9 +2,9 @@ use bevy::{color::palettes::css::*, prelude::*};
fn main() { fn main() {
App::new() App::new()
.add_plugins(DefaultPlugins) .add_plugins(DefaultPlugins {})
.insert_resource(ClearColor(WHITE.into())) .insert_resource(ClearColor(WHITE.into()))
.add_event::<CameraMovement>() .add_message::<CameraMovement>()
.add_systems(Startup, setup_2d) .add_systems(Startup, setup_2d)
.add_systems(Update, (move_camera, track_camera_movement, parallax)) .add_systems(Update, (move_camera, track_camera_movement, parallax))
.run(); .run();
@ -82,7 +82,7 @@ fn move_camera(keys: Res<ButtonInput<KeyCode>>, mut camera: Single<&mut Transfor
struct CameraMovement(Vec3); struct CameraMovement(Vec3);
fn track_camera_movement( fn track_camera_movement(
mut events: EventWriter<CameraMovement>, mut events: MessageWriter<CameraMovement>,
camera: Query<&Transform, (With<Camera>, Changed<Transform>)>, camera: Query<&Transform, (With<Camera>, Changed<Transform>)>,
mut last: Local<Vec3>, mut last: Local<Vec3>,
) { ) {

@ -4,7 +4,7 @@ fn main() {
App::new() App::new()
.add_plugins(DefaultPlugins.set(WindowPlugin { .add_plugins(DefaultPlugins.set(WindowPlugin {
primary_window: Some(Window { primary_window: Some(Window {
resolution: (640.0, 480.0).into(), resolution: (640, 480).into(),
..default() ..default()
}), }),
..default() ..default()

@ -3,6 +3,7 @@ use games::*;
fn main() { fn main() {
App::new() App::new()
.add_plugins((BaseGamePlugin { .add_plugins((BaseGamePlugin {
target_resolution: (640, 480).into(),
name: "parallax example".into(), name: "parallax example".into(),
title: "Parallax".into(), title: "Parallax".into(),
game_type: GameType::Two, game_type: GameType::Two,

@ -1,5 +1,3 @@
use avian3d::math::Vector;
// TEMP
use avian2d::prelude::*; use avian2d::prelude::*;
use bevy::{color::palettes::css::*, prelude::*}; use bevy::{color::palettes::css::*, prelude::*};
@ -14,7 +12,7 @@ fn main() {
.add_systems(Update, draw_gizmos) .add_systems(Update, draw_gizmos)
.add_systems( .add_systems(
Update, Update,
event_detection.run_if(on_message::<CollisionStarted>.or(on_message::<CollisionEnded>)), event_detection.run_if(on_message::<CollisionStart>.or(on_message::<CollisionEnd>)),
) )
.add_observer(set_tree_position) .add_observer(set_tree_position)
.run(); .run();
@ -63,7 +61,7 @@ fn setup(
commands.spawn(( commands.spawn((
Player, Player,
RigidBody::Kinematic, RigidBody::Kinematic,
ExternalImpulse::default().with_persistence(true), ConstantForce::default(),
Collider::rectangle(50.0, 50.0), Collider::rectangle(50.0, 50.0),
Mesh2d(meshes.add(Rectangle::new(50.0, 50.0))), Mesh2d(meshes.add(Rectangle::new(50.0, 50.0))),
MeshMaterial2d(materials.add(Color::from(RED))), MeshMaterial2d(materials.add(Color::from(RED))),
@ -87,11 +85,7 @@ fn setup(
)); ));
} }
fn set_tree_position( fn set_tree_position(event: On<Add, TreePos>, tree_pos: Query<&TreePos>, mut commands: Commands) {
event: On<Add, TreePos>,
tree_pos: Query<&TreePos>,
mut commands: Commands,
) {
let TreePos(pos) = tree_pos.get(event.entity).unwrap(); let TreePos(pos) = tree_pos.get(event.entity).unwrap();
let x = if (*pos) > 0 { let x = if (*pos) > 0 {
(200.0 * (*pos) as f32) - 100.0 (200.0 * (*pos) as f32) - 100.0
@ -104,13 +98,13 @@ fn set_tree_position(
fn move_player( fn move_player(
keyboard_input: Res<ButtonInput<KeyCode>>, keyboard_input: Res<ButtonInput<KeyCode>>,
mut player: Single<&mut ExternalImpulse, With<Player>>, mut player: Single<Forces, With<Player>>,
) { ) {
const SPEED: f32 = 5.0; const SPEED: f32 = 5.0;
if keyboard_input.pressed(KeyCode::ArrowLeft) { if keyboard_input.pressed(KeyCode::ArrowLeft) {
player.set_impulse(Vec2::NEG_X * SPEED); player.apply_local_force(Vec2::NEG_X * SPEED);
} else if keyboard_input.pressed(KeyCode::ArrowRight) { } else if keyboard_input.pressed(KeyCode::ArrowRight) {
player.set_impulse(Vec2::X * SPEED); player.apply_local_force(Vec2::X * SPEED);
} }
} }
@ -132,15 +126,26 @@ fn draw_gizmos(mut gizmos: Gizmos, play_area: Single<&GlobalTransform, With<Rend
} }
fn event_detection( fn event_detection(
mut start_events: MessageReader<CollisionStarted>, mut start_events: MessageReader<CollisionStart>,
mut end_events: MessageReader<CollisionEnded>, mut end_events: MessageReader<CollisionEnd>,
player: Single<&Player>,
trees: Query<&TreePos>, trees: Query<&TreePos>,
keyboard_input: Res<ButtonInput<KeyCode>>, keyboard_input: Res<ButtonInput<KeyCode>>,
) { ) {
debug_assert!(!(start_events.is_empty() && end_events.is_empty())); debug_assert!(!(start_events.is_empty() && end_events.is_empty()));
let s = start_events.read().map(|CollisionStarted(a, b)| (a, b)); let s = start_events.read().map(
let e = end_events.read().map(|CollisionEnded(a, b)| (a, b)); |CollisionStart {
collider1,
collider2,
..
}| (collider1, collider2),
);
let e = end_events.read().map(
|CollisionEnd {
collider1,
collider2,
..
}| (collider1, collider2),
);
let mut events = s.chain(e); let mut events = s.chain(e);
let current_tree = events.find_map(|(a, b)| { let current_tree = events.find_map(|(a, b)| {
info!("{a:?}, {b:?}"); info!("{a:?}, {b:?}");

@ -1,222 +0,0 @@
use bevy::{
color::palettes::css::{BLUE, GREEN},
render::mesh::{SphereKind, SphereMeshBuilder},
};
use bevy_rapier3d::rapier::prelude::CollisionEventFlags;
use games::*;
/// Example showing using Rapier3d to do area intersection
///
/// Have you ever wanted to detect if a character is within some bounds?
/// This shows how to do that.
fn main() {
App::new()
.add_plugins(BaseGamePlugin::default())
.init_resource::<InsideArea>()
.add_systems(
Startup,
(
setup_physics_scene,
setup_ui,
position_camera.after(create_camera_3d),
),
)
.add_systems(
Update,
(
control_ball,
process_events,
sync_resource_to_ui::<InsideArea>.run_if(resource_changed::<InsideArea>),
)
.run_if(in_state(LoadingState::Idle)),
)
.run();
}
/// Which area the sphere is in/touching
#[derive(Component, Debug, Clone)]
enum AreaMarker {
Green,
Blue,
}
/// Setup a basic scene with:
/// * Floor
/// * A light for dramatic shadows
/// * A sphere that can move
/// * Two cubes that designate area intersection
fn setup_physics_scene(
mut commands: Commands,
mut meshes: ResMut<Assets<Mesh>>,
mut materials: ResMut<Assets<StandardMaterial>>,
) {
// Create the ground.
// Make this a physical looking object
commands.spawn((
Collider::cuboid(100.0, 0.1, 100.0),
Transform::from_xyz(0.0, -1.0, 0.0),
Pickable::IGNORE,
Mesh3d(meshes.add(Plane3d::new(Vec3::Y, Vec2::splat(50.0)))),
MeshMaterial3d(materials.add(StandardMaterial {
base_color: RED.into(),
..Default::default()
})),
));
commands.spawn((
SpotLight {
color: WHITE.into(),
intensity: 10_000_000.0,
shadows_enabled: true,
..default()
},
Transform::from_xyz(0.0, 10.0, 10.0).looking_at(Vec3::ZERO, Vec3::Y),
));
// Create the bouncing ball.
commands.spawn((
RigidBody::Dynamic,
GravityScale(1.0),
Collider::ball(0.5),
ColliderMassProperties::Mass(2.0),
Restitution::coefficient(0.7),
ExternalImpulse::default(),
Transform::from_xyz(0.0, 4.0, 0.0),
ActiveEvents::all(),
Name::new("Ball"),
Mesh3d(meshes.add(SphereMeshBuilder::new(
0.5,
SphereKind::Uv {
sectors: 10,
stacks: 10,
},
))),
MeshMaterial3d(materials.add(StandardMaterial {
base_color: WHITE.into(),
..Default::default()
})),
));
// Create a box that the ball can pass into/through
commands.spawn((
Sensor,
Collider::cuboid(1.0, 1.0, 1.0),
Transform::from_xyz(0.0, 0.0, 2.0),
Mesh3d(meshes.add(Cuboid::new(2.0, 2.0, 2.0))),
Name::new("Green Area"),
MeshMaterial3d(materials.add(StandardMaterial {
base_color: GREEN.with_alpha(0.5).into(),
alpha_mode: AlphaMode::Blend,
..Default::default()
})),
AreaMarker::Green,
));
// Create a box that the ball can pass into/through
commands.spawn((
Sensor,
Collider::cuboid(1.0, 1.0, 1.0),
Transform::from_xyz(0.0, 0.0, -2.0),
Mesh3d(meshes.add(Cuboid::new(2.0, 2.0, 2.0))),
Name::new("Blue Area"),
MeshMaterial3d(materials.add(StandardMaterial {
base_color: BLUE.with_alpha(0.5).into(),
alpha_mode: AlphaMode::Blend,
..Default::default()
})),
AreaMarker::Blue,
));
}
/// Setup the UI for this example that indicates if the game "sees" the sphere
/// is inside the cube
fn setup_ui(mut commands: Commands) {
commands.spawn((
Node {
align_self: AlignSelf::Start,
justify_self: JustifySelf::Center,
..default()
},
Text("Placeholder".into()),
SyncResource::<InsideArea>::default(),
));
}
/// Position the world camera to get a better view
fn position_camera(mut query: Query<&mut Transform, (With<Camera>, With<Camera3d>)>) {
query.iter_mut().for_each(|mut t| {
*t = Transform::from_xyz(10.0, 10.0, 10.0).looking_at(Vec3::ZERO, Vec3::Y);
})
}
/// Control the ball based on arrow keys
fn control_ball(keys: Res<ButtonInput<KeyCode>>, mut ball: Single<&mut ExternalImpulse>) {
if keys.pressed(KeyCode::ArrowUp) {
ball.torque_impulse = Vec3::new(0.0, 0.0, 0.1);
}
if keys.pressed(KeyCode::ArrowDown) {
ball.torque_impulse = Vec3::new(0.0, 0.0, -0.1);
}
if keys.pressed(KeyCode::ArrowLeft) {
ball.torque_impulse = Vec3::new(0.1, 0.0, 0.0);
}
if keys.pressed(KeyCode::ArrowRight) {
ball.torque_impulse = Vec3::new(-0.1, 0.0, 0.0);
}
}
/// Maps CollisionEvent to a game-specific construct (did X enter/exit an area)
#[derive(Debug)]
enum WithinBounds {
Enter(Entity, Entity),
Exit(Entity, Entity),
}
/// Resource tracking what box the sphere is in
#[derive(Resource, Debug, Default, Clone)]
struct InsideArea(Option<AreaMarker>);
impl Display for InsideArea {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
match self.0 {
Some(AreaMarker::Blue) => write!(f, "Ball IS touching the BLUE box"),
Some(AreaMarker::Green) => write!(f, "Ball IS touching the GREEN box"),
None => write!(f, "Ball is NOT touching ANY box"),
}
}
}
/// Read collision events and procss them into resource updates to be displayed to the user
fn process_events(
mut events: MessageReader<CollisionEvent>,
areas: Query<&AreaMarker>,
mut inside: ResMut<InsideArea>,
) {
events
.read()
.filter_map(|collision_event| match collision_event {
CollisionEvent::Started(a, b, flags) => {
(*flags == CollisionEventFlags::SENSOR).then_some(WithinBounds::Enter(*a, *b))
}
CollisionEvent::Stopped(a, b, flags) => {
(*flags == CollisionEventFlags::SENSOR).then_some(WithinBounds::Exit(*a, *b))
}
})
.for_each(|within_bounds| match within_bounds {
WithinBounds::Enter(a, b) => {
if let Ok(x) = areas.get(a) {
inside.0 = Some(x.clone());
} else if let Ok(x) = areas.get(b) {
inside.0 = Some(x.clone());
}
}
WithinBounds::Exit(a, b) => {
if areas.contains(a) || areas.contains(b) {
inside.0 = None;
}
}
})
}

@ -85,10 +85,12 @@ fn setup_nav_tree(mut commands: Commands) {
)) ))
.with_children(|parent| { .with_children(|parent| {
(0..5).for_each(|_| { (0..5).for_each(|_| {
let title: String = lipsum_title_with_rng(thread_rng()) let title: String = Iterator::intersperse(
lipsum_title_with_rng(thread_rng())
.split_whitespace() .split_whitespace()
.take(2) .take(2),
.intersperse(" ") " ",
)
.collect(); .collect();
parent.spawn(( parent.spawn((
children![Text::new(title),], children![Text::new(title),],
@ -137,7 +139,7 @@ fn control_menu(
hover_map: Res<HoverMap>, hover_map: Res<HoverMap>,
) { ) {
over_events.read().for_each(|over| { over_events.read().for_each(|over| {
let root = children.root_ancestor(over.target); let root = children.root_ancestor(over.entity);
parents.iter_descendants(root).for_each(|child| { parents.iter_descendants(root).for_each(|child| {
if let Ok(mut n) = nav.get_mut(child) { if let Ok(mut n) = nav.get_mut(child) {
@ -157,9 +159,9 @@ fn control_menu(
// For all pointer out events // For all pointer out events
out_events.read().for_each(|out| { out_events.read().for_each(|out| {
// If a relative of out.target is hovered, do nothing // If a relative of out.entity is hovered, do nothing
// Otherwise set to closed // Otherwise set to closed
let root = children.root_ancestor(out.target); let root = children.root_ancestor(out.entity);
let tree_still_hovered = parents let tree_still_hovered = parents
.iter_descendants(root) .iter_descendants(root)
.any(|child| is_hovered.contains(&&child)); .any(|child| is_hovered.contains(&&child));

@ -3,7 +3,7 @@ use games::*;
fn main() { fn main() {
App::new() App::new()
.add_plugins(BaseGamePlugin { .add_plugins(BaseGamePlugin {
target_resolution: (360.0, 640.0).into(), target_resolution: (360, 640).into(),
..default() ..default()
}) })
.add_systems(Startup, init_window_info) .add_systems(Startup, init_window_info)

@ -587,10 +587,7 @@ fn init_ui(mut commands: Commands, server: Res<AssetServer>) {
#[cfg(not(target_arch = "wasm32"))] #[cfg(not(target_arch = "wasm32"))]
{ {
fn quit_game( fn quit_game(_event: On<Pointer<Click>>, mut exit: MessageWriter<AppExit>) {
_event: On<Pointer<Click>>,
mut exit: MessageWriter<AppExit>,
) {
warn!("Quitting game"); warn!("Quitting game");
exit.write(AppExit::Success); exit.write(AppExit::Success);
} }
@ -879,15 +876,11 @@ fn un_pause_game(mut next: ResMut<NextState<PlayerState>>) {
#[derive(Component, Clone, Message, EntityEvent)] #[derive(Component, Clone, Message, EntityEvent)]
struct Flap { struct Flap {
entity: Entity entity: Entity,
} }
// Observer for flapping // Observer for flapping
fn flap( fn flap(event: On<Flap>, mut bird: Query<Forces, With<Bird>>, mut flaps: ResMut<Flaps>) {
event: On<Flap>,
mut bird: Query<Forces, With<Bird>>,
mut flaps: ResMut<Flaps>,
) {
debug!("real flap for {:?}", event.entity); debug!("real flap for {:?}", event.entity);
// Increment flap stat // Increment flap stat
flaps.0 += 1; flaps.0 += 1;
@ -1149,7 +1142,12 @@ fn manage_score(
) { ) {
match state.get() { match state.get() {
PlayerState::Rewind => { PlayerState::Rewind => {
start.read().for_each(|CollisionStart { collider1, collider2, .. }| { start.read().for_each(
|CollisionStart {
collider1,
collider2,
..
}| {
// Set score to collided hitbox // Set score to collided hitbox
if let Ok(Batch(this)) = hitboxes.get(*collider1) { if let Ok(Batch(this)) = hitboxes.get(*collider1) {
debug!("[Rewind] Setting score to {this}"); debug!("[Rewind] Setting score to {this}");
@ -1158,10 +1156,16 @@ fn manage_score(
debug!("[Rewind] Setting score to {this}"); debug!("[Rewind] Setting score to {this}");
score.0 = this.saturating_sub(1); score.0 = this.saturating_sub(1);
} }
}) },
)
} }
_ => { _ => {
end.read().for_each(|CollisionEnd { collider1, collider2, .. }| { end.read().for_each(
|CollisionEnd {
collider1,
collider2,
..
}| {
// Set score to collided hitbox // Set score to collided hitbox
if let Ok(Batch(this)) = hitboxes.get(*collider2) { if let Ok(Batch(this)) = hitboxes.get(*collider2) {
debug!("[Alive] Setting score to {this}"); debug!("[Alive] Setting score to {this}");
@ -1170,7 +1174,8 @@ fn manage_score(
debug!("[Alive] Setting score to {this}"); debug!("[Alive] Setting score to {this}");
score.0 = *this; score.0 = *this;
} }
}) },
)
} }
} }
} }
@ -1192,8 +1197,20 @@ fn move_batches(
state: Res<State<PlayerState>>, state: Res<State<PlayerState>>,
mut commands: Commands, mut commands: Commands,
) { ) {
let s = start.read().map(|CollisionStart { collider1, collider2, .. }| (collider1, collider2)); let s = start.read().map(
let e = end.read().map(|CollisionEnd { collider1, collider2, .. }| (collider1, collider2)); |CollisionStart {
collider1,
collider2,
..
}| (collider1, collider2),
);
let e = end.read().map(
|CollisionEnd {
collider1,
collider2,
..
}| (collider1, collider2),
);
let c = s.chain(e); let c = s.chain(e);
c.for_each(|(a, b)| { c.for_each(|(a, b)| {
debug!("[batches] Collision {a} -> {b}"); debug!("[batches] Collision {a} -> {b}");

@ -1,5 +1,4 @@
#![feature(try_blocks)] #![feature(try_blocks)]
// Bevy basically forces "complex types" with Querys // Bevy basically forces "complex types" with Querys
#![allow(clippy::type_complexity)] #![allow(clippy::type_complexity)]
@ -74,7 +73,7 @@ fn main() {
.run_if(any_component_changed::<Health>.or(any_component_added::<Health>)), .run_if(any_component_changed::<Health>.or(any_component_added::<Health>)),
damage_on_place_shape.run_if(any_component_removed::<Shape>), damage_on_place_shape.run_if(any_component_removed::<Shape>),
damage_on_clear_line.run_if(any_component_removed::<LineBlock>), damage_on_clear_line.run_if(any_component_removed::<LineBlock>),
damage_over_time.run_if(clock_cycle(5.0)) damage_over_time.run_if(clock_cycle(5.0)),
), ),
) )
// UI systems // UI systems
@ -140,16 +139,16 @@ struct GridPosition {
} }
impl GridPosition { impl GridPosition {
fn with_offset(self, other_x: isize, other_y: isize) -> Result<GridPosition, GameError> { fn with_offset(self, other_x: isize, other_y: isize) -> Result<GridPosition, OutOfBoundsError> {
let x = self.x as isize + other_x; let x = self.x as isize + other_x;
let y = self.y as isize + other_y; let y = self.y as isize + other_y;
if x >= X_MAX as isize { if x >= X_MAX as isize {
Err(GameError::OutOfBoundsLeft) Err(OutOfBoundsError::Left)
} else if x < 0 { } else if x < 0 {
Err(GameError::OutOfBoundsRight) Err(OutOfBoundsError::Right)
} else if y < 0 { } else if y < 0 {
Err(GameError::OutOfBoundsDown) Err(OutOfBoundsError::Down)
} else { } else {
Ok(GridPosition { Ok(GridPosition {
x: x as usize, x: x as usize,
@ -166,15 +165,13 @@ impl Display for GridPosition {
} }
#[derive(Error, Debug, PartialEq)] #[derive(Error, Debug, PartialEq)]
enum GameError { enum OutOfBoundsError {
#[error("Coordinates are out of bounds: Left")] #[error("Coordinates are out of bounds: Left")]
OutOfBoundsLeft, Left,
#[error("Coordinates are out of bounds: Right")] #[error("Coordinates are out of bounds: Right")]
OutOfBoundsRight, Right,
#[error("Coordinates are out of bounds: Down")] #[error("Coordinates are out of bounds: Down")]
OutOfBoundsDown, Down,
#[error("Coordiante collision")]
Collision,
} }
impl Default for GridPosition { impl Default for GridPosition {
@ -690,8 +687,8 @@ impl Shape {
fn coordinates( fn coordinates(
&self, &self,
center: &GridPosition, center: &GridPosition,
) -> impl Iterator<Item = Result<GridPosition, GameError>> { ) -> impl Iterator<Item = Result<GridPosition, OutOfBoundsError>> {
let mut v: Vec<Result<GridPosition, GameError>> = Vec::new(); let mut v: Vec<Result<GridPosition, OutOfBoundsError>> = Vec::new();
match self { match self {
Self::M4(inner) => { Self::M4(inner) => {
for (i, y) in (-1..3).rev().enumerate() { for (i, y) in (-1..3).rev().enumerate() {
@ -837,19 +834,34 @@ fn kb_input(
// Up arrow should rotate if in falling mode // Up arrow should rotate if in falling mode
// Only move up if in falling::off mode // Only move up if in falling::off mode
KeyCode::ArrowUp => { KeyCode::ArrowUp => {
commands.entity(e).trigger(|entity| Movement { entity, direction: MovementDirection::Rotate }); commands.entity(e).trigger(|entity| Movement {
entity,
direction: MovementDirection::Rotate,
});
} }
KeyCode::ArrowDown => { KeyCode::ArrowDown => {
commands.entity(e).trigger(|entity| Movement { entity, direction: MovementDirection::Down }); commands.entity(e).trigger(|entity| Movement {
entity,
direction: MovementDirection::Down,
});
} }
KeyCode::ArrowLeft => { KeyCode::ArrowLeft => {
commands.entity(e).trigger(|entity| Movement { entity, direction: MovementDirection::Left }); commands.entity(e).trigger(|entity| Movement {
entity,
direction: MovementDirection::Left,
});
} }
KeyCode::ArrowRight => { KeyCode::ArrowRight => {
commands.entity(e).trigger(|entity| Movement { entity, direction: MovementDirection::Right }); commands.entity(e).trigger(|entity| Movement {
entity,
direction: MovementDirection::Right,
});
} }
KeyCode::Enter => { KeyCode::Enter => {
commands.entity(e).trigger(|entity| Movement { entity, direction: MovementDirection::Skip }); commands.entity(e).trigger(|entity| Movement {
entity,
direction: MovementDirection::Skip,
});
} }
KeyCode::Space => { KeyCode::Space => {
commands.entity(e).trigger(|entity| Swap { entity }); commands.entity(e).trigger(|entity| Swap { entity });
@ -876,7 +888,10 @@ fn kb_input(
fn falling(mut shape: Query<Entity, With<Shape>>, mut commands: Commands) { fn falling(mut shape: Query<Entity, With<Shape>>, mut commands: Commands) {
shape.iter_mut().for_each(|e| { shape.iter_mut().for_each(|e| {
debug!("Making {:?} fall", e); debug!("Making {:?} fall", e);
commands.entity(e).trigger(|entity| Movement { entity, direction: MovementDirection::Down }); commands.entity(e).trigger(|entity| Movement {
entity,
direction: MovementDirection::Down,
});
}); });
} }
@ -994,7 +1009,7 @@ fn adjust_block_lines(
/// Swap the current piece out /// Swap the current piece out
#[derive(EntityEvent, Message, Copy, Clone, PartialEq)] #[derive(EntityEvent, Message, Copy, Clone, PartialEq)]
struct Swap { struct Swap {
entity: Entity entity: Entity,
} }
/// Movement events evented on the piece /// Movement events evented on the piece
@ -1038,7 +1053,10 @@ fn movement(
.collect(), .collect(),
}; };
let new_shape = match event.event().direction { let new_shape = match event.event().direction {
MovementDirection::Down | MovementDirection::Left | MovementDirection::Right | MovementDirection::Skip => *this_shape, MovementDirection::Down
| MovementDirection::Left
| MovementDirection::Right
| MovementDirection::Skip => *this_shape,
MovementDirection::Rotate => this_shape.rotated(), MovementDirection::Rotate => this_shape.rotated(),
}; };
debug!( debug!(
@ -1048,23 +1066,21 @@ fn movement(
); );
for position in new_positions { for position in new_positions {
match position { match position {
Err(GameError::OutOfBoundsLeft) | Err(GameError::OutOfBoundsRight) => (), // Do nothing Err(OutOfBoundsError::Left) | Err(OutOfBoundsError::Right) => (), // Do nothing
Err(GameError::OutOfBoundsDown) => { Err(OutOfBoundsError::Down) => {
commands.entity(event.entity).remove::<Shape>(); commands.entity(event.entity).remove::<Shape>();
} }
Err(GameError::Collision) => panic!("This shouldn't happen!"),
Ok(new_center) => { Ok(new_center) => {
let new_blocks = new_shape.coordinates(&new_center); let new_blocks = new_shape.coordinates(&new_center);
for block_gp in new_blocks { for block_gp in new_blocks {
match block_gp { match block_gp {
Err(GameError::OutOfBoundsLeft) | Err(GameError::OutOfBoundsRight) => { Err(OutOfBoundsError::Left) | Err(OutOfBoundsError::Right) => {
return; return;
} // Do nothing } // Do nothing
Err(GameError::OutOfBoundsDown) => { Err(OutOfBoundsError::Down) => {
commands.entity(event.entity).remove::<Shape>(); commands.entity(event.entity).remove::<Shape>();
return; return;
} }
Err(GameError::Collision) => panic!("This shouldn't happen!"),
Ok(gp) => { Ok(gp) => {
for other_gp in inactive.iter() { for other_gp in inactive.iter() {
// If there would be a collision between blocks // If there would be a collision between blocks
@ -1209,13 +1225,10 @@ fn sync_health(
#[derive(Message, EntityEvent)] #[derive(Message, EntityEvent)]
struct Damage { struct Damage {
entity: Entity, entity: Entity,
quantity: f32 quantity: f32,
} }
fn deal_damage( fn deal_damage(event: On<Damage>, mut healths: Query<&mut Health>) {
event: On<Damage>,
mut healths: Query<&mut Health>
) {
healths.get_mut(event.entity).unwrap().0 -= event.event().quantity healths.get_mut(event.entity).unwrap().0 -= event.event().quantity
} }
@ -1226,7 +1239,10 @@ fn damage_on_place_shape(
) { ) {
events.read().for_each(|_| { events.read().for_each(|_| {
enemies.iter().for_each(|e| { enemies.iter().for_each(|e| {
commands.entity(e).trigger(|entity| Damage { entity, quantity: 1.0 }); commands.entity(e).trigger(|entity| Damage {
entity,
quantity: 1.0,
});
}); });
}); });
} }
@ -1238,14 +1254,17 @@ fn damage_on_clear_line(
) { ) {
events.read().for_each(|_| { events.read().for_each(|_| {
enemies.iter().for_each(|e| { enemies.iter().for_each(|e| {
commands.entity(e).trigger(|entity| Damage { entity, quantity: 1.0 }); commands.entity(e).trigger(|entity| Damage {
entity,
quantity: 1.0,
});
}); });
}); });
} }
fn damage_over_time( fn damage_over_time(protagonist: Single<Entity, With<Protagonist>>, mut commands: Commands) {
protagonist: Single<Entity, With<Protagonist>>, commands.entity(*protagonist).trigger(|entity| Damage {
mut commands: Commands, entity,
) { quantity: 1.0,
commands.entity(*protagonist).trigger(|entity| Damage { entity, quantity: 1.0 }); });
} }

@ -14,7 +14,8 @@ impl Plugin for TreesDebugPlugin {
.run_if(on_message::<Pointer<Over>>.or(on_message::<Pointer<Out>>)), .run_if(on_message::<Pointer<Over>>.or(on_message::<Pointer<Out>>)),
hide_menu.run_if(any_component_changed::<NavState>), hide_menu.run_if(any_component_changed::<NavState>),
clear_monologue.run_if(any_component_changed::<NavState>), clear_monologue.run_if(any_component_changed::<NavState>),
control_menu.run_if(on_message::<Pointer<Over>>.or(on_message::<Pointer<Out>>)), control_menu
.run_if(on_message::<Pointer<Over>>.or(on_message::<Pointer<Out>>)),
delete_tree.run_if(on_message::<Pointer<Click>>), delete_tree.run_if(on_message::<Pointer<Click>>),
drag_tree.run_if(on_message::<Pointer<Drag>>), drag_tree.run_if(on_message::<Pointer<Drag>>),
) )
@ -278,6 +279,7 @@ fn monologue_asset_tooltip(
mut over_events: MessageReader<Pointer<Over>>, mut over_events: MessageReader<Pointer<Over>>,
mut out_events: MessageReader<Pointer<Out>>, mut out_events: MessageReader<Pointer<Out>>,
mut tooltip: ResMut<ToolTip>, mut tooltip: ResMut<ToolTip>,
server: Res<AssetServer>,
trees: Query<(&Tree, Option<&TreeMonologue>)>, trees: Query<(&Tree, Option<&TreeMonologue>)>,
) { ) {
out_events out_events
@ -291,12 +293,10 @@ fn monologue_asset_tooltip(
.read() .read()
.filter_map(|Pointer { entity, .. }| trees.contains(*entity).then_some(*entity)) .filter_map(|Pointer { entity, .. }| trees.contains(*entity).then_some(*entity))
.for_each(|e| match trees.get(e) { .for_each(|e| match trees.get(e) {
Ok((_tree, Some(TreeMonologue(id)))) => { Ok((_tree, Some(TreeMonologue(id)))) => match server.get_path(*id) {
match todo!("Get path for this asset") {
Some(p) => tooltip.insert("Script", format!("{p}")), Some(p) => tooltip.insert("Script", format!("{p}")),
None => tooltip.insert("Script", "A".into()), None => tooltip.insert("Script", "A".into()),
} },
}
Ok((_tree, None)) => { Ok((_tree, None)) => {
tooltip.insert("Script", "N/A".into()); tooltip.insert("Script", "N/A".into());
} }

@ -457,6 +457,7 @@ fn assign_monologue_to_tree(
query: Query<Entity, (With<Tree>, Without<TreeMonologue>)>, query: Query<Entity, (With<Tree>, Without<TreeMonologue>)>,
mut notice: ResMut<Notice>, mut notice: ResMut<Notice>,
mut commands: Commands, mut commands: Commands,
server: Res<AssetServer>,
) { ) {
// Kinda a weird hack because query does not update // Kinda a weird hack because query does not update
// If we do this inline we assign new monologues to the same first tree // If we do this inline we assign new monologues to the same first tree
@ -467,10 +468,10 @@ fn assign_monologue_to_tree(
// Get a valid tree to assign an entity to // Get a valid tree to assign an entity to
if let Some(tree) = t.next() { if let Some(tree) = t.next() {
// Create the TreeMonologue component // Create the TreeMonologue component
let monologue = TreeMonologue(event.0.clone()); let monologue = TreeMonologue(event.0);
// Insert the component to the entity // Insert the component to the entity
commands.entity(tree).insert(monologue); commands.entity(tree).insert(monologue);
} else if let Some(path) = todo!("event.0.path() -> assetId") { } else if let Some(path) = server.get_path(event.0) {
error!("No trees avaliable for {path:?}"); error!("No trees avaliable for {path:?}");
notice.0 = format!("No trees avaliable for {path:?}"); notice.0 = format!("No trees avaliable for {path:?}");
} else { } else {

@ -19,14 +19,13 @@ pub use std::fmt::Display;
// Community libraries // Community libraries
pub use bevy::{ pub use bevy::{
asset::{AssetLoader, AssetMetaCheck, LoadContext, LoadState, LoadedFolder, io::Reader, RenderAssetUsages, uuid_handle}, asset::{
math::{FloatOrd}, AssetLoader, AssetMetaCheck, LoadContext, LoadState, LoadedFolder, RenderAssetUsages,
camera::{*, primitives::*, visibility::*}, io::Reader, uuid_handle,
},
camera::{primitives::*, visibility::*, *},
color::palettes::css::*, color::palettes::css::*,
gizmos::{aabb::AabbGizmoPlugin, light::LightGizmoPlugin}, gizmos::{aabb::AabbGizmoPlugin, light::LightGizmoPlugin},
render::{
render_resource::{Extent3d, TextureDimension, TextureFormat, TextureUsages},
},
input::{ input::{
ButtonState, ButtonState,
common_conditions::{input_just_pressed, input_just_released, input_pressed}, common_conditions::{input_just_pressed, input_just_released, input_pressed},
@ -34,16 +33,18 @@ pub use bevy::{
mouse::MouseMotion, mouse::MouseMotion,
mouse::{MouseScrollUnit, MouseWheel}, mouse::{MouseScrollUnit, MouseWheel},
}, },
math::FloatOrd,
pbr::wireframe::{WireframeConfig, WireframePlugin}, pbr::wireframe::{WireframeConfig, WireframePlugin},
platform::{collections::HashMap, hash::RandomState}, platform::{collections::HashMap, hash::RandomState},
prelude::*, prelude::*,
reflect::TypePath, reflect::TypePath,
render::render_resource::{Extent3d, TextureDimension, TextureFormat, TextureUsages},
sprite_render::*, sprite_render::*,
window::{WindowResized, WindowResolution}, window::{WindowResized, WindowResolution},
}; };
pub use itertools::Itertools;
pub use serde::Deserialize; pub use serde::Deserialize;
pub use thiserror::Error; pub use thiserror::Error;
pub use itertools::Itertools;
// Internal modules // Internal modules
pub use base_game::*; pub use base_game::*;

@ -39,11 +39,7 @@ impl Default for Style {
} }
fn add_ui_button(added: Query<Entity, Added<Button>>, mut commands: Commands) { fn add_ui_button(added: Query<Entity, Added<Button>>, mut commands: Commands) {
fn over( fn over(event: On<Pointer<Over>>, mut query: Query<&mut BorderColor>, style: Res<Style>) {
event: On<Pointer<Over>>,
mut query: Query<&mut BorderColor>,
style: Res<Style>,
) {
if let Ok(mut bc) = query.get_mut(event.entity) { if let Ok(mut bc) = query.get_mut(event.entity) {
debug!("pointer over {:?}", event.entity); debug!("pointer over {:?}", event.entity);
bc.set_all(style.accent); bc.set_all(style.accent);

Loading…
Cancel
Save