aboutsummaryrefslogtreecommitdiff
path: root/source/game/systems/physics
diff options
context:
space:
mode:
authorhazel <hazel@hazelthats.me>2026-01-26 22:04:39 +0100
committerhazel <hazel@hazelthats.me>2026-01-26 22:04:39 +0100
commit567c422f8cd42eba2437f9a8c2522716a1649be7 (patch)
tree93c5b296f3b7c14b626d0aadf5cad37764c41c74 /source/game/systems/physics
downloadcelesteia-567c422f8cd42eba2437f9a8c2522716a1649be7.tar.gz
celesteia-567c422f8cd42eba2437f9a8c2522716a1649be7.tar.bz2
celesteia-567c422f8cd42eba2437f9a8c2522716a1649be7.zip
celesteia archive, last updated april 9th 2024
Signed-off-by: hazel <hazel@hazelthats.me>
Diffstat (limited to 'source/game/systems/physics')
-rw-r--r--source/game/systems/physics/PhysicsCollisionDebugSystem.cs61
-rw-r--r--source/game/systems/physics/PhysicsSystem.cs42
-rw-r--r--source/game/systems/physics/PhysicsWorldCollisionSystem.cs83
3 files changed, 186 insertions, 0 deletions
diff --git a/source/game/systems/physics/PhysicsCollisionDebugSystem.cs b/source/game/systems/physics/PhysicsCollisionDebugSystem.cs
new file mode 100644
index 0000000..f605c30
--- /dev/null
+++ b/source/game/systems/physics/PhysicsCollisionDebugSystem.cs
@@ -0,0 +1,61 @@
+using Celesteia.Game.Components.Physics;
+using Celesteia.Game.Planets;
+using Celesteia.Graphics;
+using Microsoft.Xna.Framework;
+using Microsoft.Xna.Framework.Graphics;
+using MonoGame.Extended;
+using MonoGame.Extended.Entities;
+using MonoGame.Extended.Entities.Systems;
+
+namespace Celesteia.Game.Systems.Physics {
+ public class PhysicsCollisionDebugSystem : EntityDrawSystem
+ {
+ private readonly Camera2D _camera;
+ private readonly SpriteBatch _spriteBatch;
+ private readonly ChunkMap _chunkMap;
+
+ private ComponentMapper<Transform2> transformMapper;
+ private ComponentMapper<CollisionBox> collisionBoxMapper;
+
+ public PhysicsCollisionDebugSystem(Camera2D camera, SpriteBatch spriteBatch, ChunkMap chunkMap) : base(Aspect.All(typeof(Transform2), typeof(CollisionBox))) {
+ _camera = camera;
+ _spriteBatch = spriteBatch;
+ _chunkMap = chunkMap;
+ }
+
+ public override void Initialize(IComponentMapperService mapperService)
+ {
+ transformMapper = mapperService.GetMapper<Transform2>();
+ collisionBoxMapper = mapperService.GetMapper<CollisionBox>();
+ }
+
+ public override void Draw(GameTime gameTime)
+ {
+ if (!GameInstance.DebugMode) return;
+
+ _spriteBatch.Begin(SpriteSortMode.Deferred, BlendState.Additive, SamplerState.PointClamp, null, null, null, _camera.GetViewMatrix());
+
+ foreach (int entityId in ActiveEntities) {
+ Rectangle box = collisionBoxMapper.Get(entityId).Rounded;
+
+ int minX = box.X;
+ int maxX = box.X + box.Width;
+
+ int minY = box.Y;
+ int maxY = box.Y + box.Height;
+
+ for (int i = minX; i < maxX; i++)
+ for (int j = minY; j < maxY; j++) {
+ RectangleF? blockBox = _chunkMap.TestBoundingBox(i, j);
+ if (blockBox.HasValue) {
+ _spriteBatch.DrawRectangle(new RectangleF(i, j, blockBox.Value.Width, blockBox.Value.Height), Color.Red, .05f, 0f);
+ } else {
+ _spriteBatch.DrawRectangle(new RectangleF(i, j, 1f, 1f), Color.Green, .05f, 0f);
+ }
+ }
+ }
+
+ _spriteBatch.End();
+ }
+ }
+} \ No newline at end of file
diff --git a/source/game/systems/physics/PhysicsSystem.cs b/source/game/systems/physics/PhysicsSystem.cs
new file mode 100644
index 0000000..3963cc1
--- /dev/null
+++ b/source/game/systems/physics/PhysicsSystem.cs
@@ -0,0 +1,42 @@
+using Celesteia.Game.Components;
+using Celesteia.Game.Components.Physics;
+using Microsoft.Xna.Framework;
+using MonoGame.Extended;
+using MonoGame.Extended.Entities;
+using MonoGame.Extended.Entities.Systems;
+
+namespace Celesteia.Game.Systems.Physics {
+ public class PhysicsSystem : EntityUpdateSystem {
+ public const float GRAVITY_CONSTANT = 9.7f;
+
+ public PhysicsSystem() : base(Aspect.All(typeof(PhysicsEntity), typeof(TargetPosition))) {}
+
+ private ComponentMapper<TargetPosition> targetPositionMapper;
+ private ComponentMapper<PhysicsEntity> physicsEntityMapper;
+
+ public override void Initialize(IComponentMapperService mapperService)
+ {
+ targetPositionMapper = mapperService.GetMapper<TargetPosition>();
+ physicsEntityMapper = mapperService.GetMapper<PhysicsEntity>();
+ }
+
+ public override void Update(GameTime gameTime)
+ {
+ foreach (int entityId in ActiveEntities) {
+ TargetPosition targetPosition = targetPositionMapper.Get(entityId);
+ PhysicsEntity physicsEntity = physicsEntityMapper.Get(entityId);
+
+ // Apply gravity if applicable
+ if (physicsEntity.Gravity) {
+ if (physicsEntity.CollidingDown && physicsEntity.Velocity.Y > 0f) {
+ physicsEntity.SetVelocity(physicsEntity.Velocity.X, 0.1f);
+ }
+
+ physicsEntity.AddVelocity(0f, physicsEntity.Mass * PhysicsSystem.GRAVITY_CONSTANT * gameTime.GetElapsedSeconds());
+ }
+
+ targetPosition.Target += physicsEntity.Velocity * gameTime.GetElapsedSeconds();
+ }
+ }
+ }
+} \ No newline at end of file
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