summaryrefslogtreecommitdiff
path: root/source/game/systems/physics/PhysicsWorldCollisionSystem.cs
blob: ba8da22cd96f51396a84253bd03d3e21349a3fee (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
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;
            }
        }
    }
}