summaryrefslogtreecommitdiff
path: root/source/game/systems/physics/PhysicsWorldCollisionSystem.cs
diff options
context:
space:
mode:
Diffstat (limited to 'source/game/systems/physics/PhysicsWorldCollisionSystem.cs')
-rw-r--r--source/game/systems/physics/PhysicsWorldCollisionSystem.cs83
1 files changed, 83 insertions, 0 deletions
diff --git a/source/game/systems/physics/PhysicsWorldCollisionSystem.cs b/source/game/systems/physics/PhysicsWorldCollisionSystem.cs
new file mode 100644
index 0000000..ba8da22
--- /dev/null
+++ b/source/game/systems/physics/PhysicsWorldCollisionSystem.cs
@@ -0,0 +1,83 @@
+using System;
+using Celesteia.Game.Components;
+using Celesteia.Game.Components.Physics;
+using Celesteia.Game.Planets;
+using Microsoft.Xna.Framework;
+using MonoGame.Extended;
+using MonoGame.Extended.Entities;
+using MonoGame.Extended.Entities.Systems;
+
+namespace Celesteia.Game.Systems.Physics {
+ public class PhysicsWorldCollisionSystem : EntityUpdateSystem {
+ private ChunkMap _chunkMap;
+
+ public PhysicsWorldCollisionSystem(ChunkMap chunkMap) : base(Aspect.All(typeof(TargetPosition), typeof(PhysicsEntity), typeof(CollisionBox))) {
+ _chunkMap = chunkMap;
+ }
+
+ private ComponentMapper<Transform2> transformMapper;
+ private ComponentMapper<TargetPosition> targetPositionMapper;
+ private ComponentMapper<PhysicsEntity> physicsEntityMapper;
+ private ComponentMapper<CollisionBox> collisionBoxMapper;
+
+ public override void Initialize(IComponentMapperService mapperService)
+ {
+ transformMapper = mapperService.GetMapper<Transform2>();
+ targetPositionMapper = mapperService.GetMapper<TargetPosition>();
+ physicsEntityMapper = mapperService.GetMapper<PhysicsEntity>();
+ collisionBoxMapper = mapperService.GetMapper<CollisionBox>();
+ }
+
+ public override void Update(GameTime gameTime)
+ {
+ foreach (int entityId in ActiveEntities) {
+ Transform2 transform = transformMapper.Get(entityId);
+ TargetPosition targetPosition = targetPositionMapper.Get(entityId);
+ PhysicsEntity physicsEntity = physicsEntityMapper.Get(entityId);
+ CollisionBox collisionBox = collisionBoxMapper.Get(entityId);
+
+ collisionBox.Update(targetPosition.Target);
+
+ int minX = (int)MathF.Floor(collisionBox.Bounds.Center.X - (collisionBox.Bounds.Width / 2f));
+ int maxX = (int)MathF.Ceiling(collisionBox.Bounds.Center.X + (collisionBox.Bounds.Width / 2f));
+
+ int minY = (int)MathF.Floor(collisionBox.Bounds.Center.Y - (collisionBox.Bounds.Height / 2f));
+ int maxY = (int)MathF.Ceiling(collisionBox.Bounds.Center.Y + (collisionBox.Bounds.Height / 2f));
+
+ bool collLeft = false;
+ bool collRight = false;
+ bool collUp = false;
+ bool collDown = false;
+
+ for (int i = minX; i < maxX; i++)
+ for (int j = minY; j < maxY; j++) {
+ RectangleF? blockBox = _chunkMap.TestBoundingBox(i, j);
+ if (blockBox.HasValue) {
+ RectangleF inter = RectangleF.Intersection(collisionBox.Bounds, blockBox.Value);
+
+ if (inter.IsEmpty) continue;
+
+ if (inter.Width < inter.Height) {
+ collLeft = blockBox.Value.Center.X < collisionBox.Bounds.Center.X;
+ collRight = blockBox.Value.Center.X > collisionBox.Bounds.Center.X;
+
+ targetPosition.Target += new Vector2(blockBox.Value.Center.X < collisionBox.Bounds.Center.X ? inter.Width : -inter.Width, 0f);
+ } else {
+ collUp = blockBox.Value.Center.Y < collisionBox.Bounds.Center.Y;
+ collDown = blockBox.Value.Center.Y > collisionBox.Bounds.Center.Y;
+
+ targetPosition.Target += new Vector2(0f, blockBox.Value.Center.Y < collisionBox.Bounds.Center.Y ? inter.Height : -inter.Height);
+ }
+
+ collisionBox.Update(targetPosition.Target);
+ }
+ }
+
+ physicsEntity.CollidingDown = collDown;
+ physicsEntity.CollidingUp = collUp;
+ physicsEntity.CollidingLeft = collLeft;
+ physicsEntity.CollidingRight = collRight;
+ }
+ }
+ }
+} \ No newline at end of file