From 98132d8f8ead8faf3ed5da1e69ea9b2df15d50be Mon Sep 17 00:00:00 2001
From: Louis Capitanchik <contact@louiscap.co>
Date: Sun, 2 Jul 2023 23:37:25 +0100
Subject: [PATCH] Add basic collision checks, recycle background sprites

---
 src/entities/collision.rs | 40 +++++++++++++++++++++++++++++++++++++++
 src/entities/mod.rs       |  2 ++
 src/entities/spawning.rs  |  5 +++--
 src/system/mod.rs         | 12 +++++++++---
 src/system/parallax.rs    | 17 ++++++++++++++---
 5 files changed, 68 insertions(+), 8 deletions(-)
 create mode 100644 src/entities/collision.rs

diff --git a/src/entities/collision.rs b/src/entities/collision.rs
new file mode 100644
index 0000000..08a43e7
--- /dev/null
+++ b/src/entities/collision.rs
@@ -0,0 +1,40 @@
+use crate::deref_as;
+use bevy::prelude::{Color, Component, Rect, Vec2};
+
+#[derive(Clone, Copy, Debug, Component)]
+pub struct BoxSize(Vec2);
+deref_as!(BoxSize => Vec2);
+impl From<Vec2> for BoxSize {
+	fn from(value: Vec2) -> Self {
+		BoxSize(value)
+	}
+}
+
+pub fn check_box_collisions(first: Rect, second: Rect) -> bool {
+	first.min.x < second.max.x
+		&& first.max.x > second.min.x
+		&& first.min.y < second.max.y
+		&& first.max.y > second.min.y
+}
+
+#[derive(Clone, Copy, Debug, Component)]
+pub enum CollisionGroup {
+	Player,
+	Pickup,
+	FriendlyProjectile,
+	HostileProjectile,
+	Enemy,
+}
+
+impl CollisionGroup {
+	pub fn color(&self) -> Color {
+		use CollisionGroup::*;
+		match self {
+			Player => Color::rgb_u8(0, 116, 217),
+			Pickup => Color::rgb_u8(177, 13, 201),
+			FriendlyProjectile => Color::rgb_u8(46, 204, 64),
+			HostileProjectile => Color::rgb_u8(255, 65, 54),
+			Enemy => Color::rgb_u8(133, 20, 75),
+		}
+	}
+}
diff --git a/src/entities/mod.rs b/src/entities/mod.rs
index e587cb6..e6d1739 100644
--- a/src/entities/mod.rs
+++ b/src/entities/mod.rs
@@ -1,3 +1,4 @@
+mod collision;
 mod motion;
 mod player;
 mod spawning;
@@ -19,6 +20,7 @@ mod _plugin {
 }
 
 pub use _plugin::EntityPlugin;
+pub use collision::{check_box_collisions, BoxSize, CollisionGroup};
 pub use motion::Velocity;
 pub use player::Player;
 pub use spawning::EntitySpawner;
diff --git a/src/entities/spawning.rs b/src/entities/spawning.rs
index 0c8c7a5..92174c6 100644
--- a/src/entities/spawning.rs
+++ b/src/entities/spawning.rs
@@ -1,6 +1,6 @@
 use crate::entities::motion::Velocity;
-use crate::entities::Player;
-use crate::system::Background;
+use crate::entities::{BoxSize, Player};
+use crate::system::{Background, BACKGROUND_HEIGHT, BACKGROUND_WIDTH};
 use bevy::ecs::system::SystemParam;
 use bevy::prelude::{AssetServer, Commands, Entity, Res, SpriteBundle, Transform, Vec2};
 
@@ -40,6 +40,7 @@ impl<'w, 's> EntitySpawner<'w, 's> {
 				},
 				Velocity::from(Vec2::new(-75.0, 0.0)),
 				Background,
+				BoxSize::from(Vec2::new(BACKGROUND_WIDTH, BACKGROUND_HEIGHT)),
 			))
 			.id()
 	}
diff --git a/src/system/mod.rs b/src/system/mod.rs
index b405660..d70e631 100644
--- a/src/system/mod.rs
+++ b/src/system/mod.rs
@@ -4,19 +4,25 @@ mod window;
 
 mod _plugin {
 	use bevy::app::App;
-	use bevy::prelude::Plugin;
+	use bevy::prelude::{IntoSystemConfig, Plugin};
+	use bevy::time::common_conditions::on_fixed_timer;
+	use std::time::Duration;
 
 	pub struct SystemPlugin;
 	impl Plugin for SystemPlugin {
 		fn build(&self, app: &mut App) {
 			app.add_startup_system(super::camera::spawn_2d_camera)
-				.add_startup_system(super::parallax::spawn_backgrounds);
+				.add_startup_system(super::parallax::spawn_backgrounds)
+				.add_system(
+					super::parallax::cycle_background_positions
+						.run_if(on_fixed_timer(Duration::from_millis(100))),
+				);
 		}
 	}
 }
 
 pub use camera::default_projection;
-pub use parallax::Background;
+pub use parallax::{Background, BACKGROUND_HEIGHT, BACKGROUND_WIDTH};
 pub use window::{window_bounds, VIEWPORT_HEIGHT, VIEWPORT_WIDTH};
 
 pub use _plugin::SystemPlugin;
diff --git a/src/system/parallax.rs b/src/system/parallax.rs
index b064555..9b33a4e 100644
--- a/src/system/parallax.rs
+++ b/src/system/parallax.rs
@@ -1,12 +1,13 @@
-use crate::entities::EntitySpawner;
+use crate::entities::{BoxSize, EntitySpawner};
 use crate::system::window_bounds;
-use bevy::prelude::{Component, Vec2};
+use bevy::prelude::{Component, Query, Transform, Vec2, With};
 
 #[derive(Component)]
 pub struct Background;
 
 // TODO: No Magic Numbers!
-const BACKGROUND_WIDTH: f32 = 2110.0;
+pub const BACKGROUND_WIDTH: f32 = 2110.0;
+pub const BACKGROUND_HEIGHT: f32 = 300.0;
 
 pub fn spawn_backgrounds(mut spawner: EntitySpawner) {
 	let bounds = window_bounds();
@@ -17,3 +18,13 @@ pub fn spawn_backgrounds(mut spawner: EntitySpawner) {
 		bounds.height() / 2.0,
 	));
 }
+
+pub fn cycle_background_positions(
+	mut background_query: Query<(&mut Transform, &BoxSize), With<Background>>,
+) {
+	for (mut transform, size) in &mut background_query {
+		if transform.translation.x <= -(size.x / 2.0) {
+			transform.translation.x = size.x + (size.x / 2.0);
+		}
+	}
+}
-- 
GitLab