예제 #1
0
        /// <summary>
        /// Call if this entity is relevant for the pathfinder
        /// </summary>
        /// <param name="entity"></param>
        /// TODO: These 2 methods currently don't account for a bunch of changes (e.g. airlock unpowered, wrenching, etc.)
        /// TODO: Could probably optimise this slightly more.
        public void AddEntity(IEntity entity, ICollidableComponent collidableComponent)
        {
            // If we're a door
            if (entity.HasComponent <AirlockComponent>() || entity.HasComponent <ServerDoorComponent>())
            {
                // If we need access to traverse this then add to readers, otherwise no point adding it (except for maybe tile costs in future)
                // TODO: Check for powered I think (also need an event for when it's depowered
                // AccessReader calls this whenever opening / closing but it can seem to get called multiple times
                // Which may or may not be intended?
                if (entity.TryGetComponent(out AccessReader accessReader) && !_accessReaders.ContainsKey(entity))
                {
                    _accessReaders.Add(entity, accessReader);
                    ParentChunk.Dirty();
                }
                return;
            }

            DebugTools.Assert((PathfindingSystem.TrackedCollisionLayers & collidableComponent.CollisionLayer) != 0);

            if (!collidableComponent.Anchored)
            {
                _physicsLayers.Add(entity, collidableComponent.CollisionLayer);
            }
            else
            {
                _blockedCollidables.Add(entity, collidableComponent.CollisionLayer);
                GenerateMask();
                ParentChunk.Dirty();
            }
        }
예제 #2
0
 public void CollidedWith(ICollidableComponent component)
 {
     if (component is Asteroid)
     {
         Destroyed = true;
     }
 }
예제 #3
0
 public void CollidedWith(ICollidableComponent component)
 {
     if (component is Asteroid)
     {
         Destroyed = true;
     }
 }
예제 #4
0
        private void ProcessFriction(ICollidableComponent body, float deltaTime)
        {
            if (body.LinearVelocity == Vector2.Zero)
            {
                return;
            }

            // sliding friction coefficient, and current gravity at current location
            var(friction, gravity) = GetFriction(body);

            // friction between the two objects
            var effectiveFriction = friction * body.Friction;

            // current acceleration due to friction
            var fAcceleration = effectiveFriction * gravity;

            // integrate acceleration
            var fVelocity = fAcceleration * deltaTime;

            // Clamp friction because friction can't make you accelerate backwards
            friction = Math.Min(fVelocity, body.LinearVelocity.Length);

            // No multiplication/division by mass here since that would be redundant.
            var frictionVelocityChange = body.LinearVelocity.Normalized * -friction;

            body.LinearVelocity += frictionVelocityChange;
        }
예제 #5
0
        private bool IsAroundCollider(ITransformComponent transform, IMoverComponent mover,
                                      ICollidableComponent collider)
        {
            foreach (var entity in _entityManager.GetEntitiesInRange(transform.Owner, mover.GrabRange, true))
            {
                if (entity == transform.Owner)
                {
                    continue; // Don't try to push off of yourself!
                }

                if (!entity.TryGetComponent <ICollidableComponent>(out var otherCollider))
                {
                    continue;
                }

                // Don't count pulled entities
                if (otherCollider.HasController <PullController>())
                {
                    continue;
                }

                // TODO: Item check.
                var touching = ((collider.CollisionMask & otherCollider.CollisionLayer) != 0x0 ||
                                (otherCollider.CollisionMask & collider.CollisionLayer) != 0x0) && // Ensure collision
                               !entity.HasComponent <IItemComponent>();   // This can't be an item

                if (touching)
                {
                    return(true);
                }
            }

            return(false);
        }
예제 #6
0
        private void UpdatePosition(ICollidableComponent collidable, float frameTime)
        {
            var ent = collidable.Entity;

            if (!collidable.CanMove() || (collidable.LinearVelocity.LengthSquared < Epsilon && MathF.Abs(collidable.AngularVelocity) < Epsilon))
            {
                return;
            }

            if (collidable.LinearVelocity != Vector2.Zero)
            {
                if (ContainerHelpers.IsInContainer(ent))
                {
                    var relayEntityMoveMessage = new RelayMovementEntityMessage(ent);
                    ent.Transform.Parent !.Owner.SendMessage(ent.Transform, relayEntityMoveMessage);
                    // This prevents redundant messages from being sent if solveIterations > 1 and also simulates the entity "colliding" against the locker door when it opens.
                    collidable.LinearVelocity = Vector2.Zero;
                }
            }

            collidable.Owner.Transform.DeferUpdates = true;
            _deferredUpdates.Add(collidable);
            collidable.WorldRotation += collidable.AngularVelocity * frameTime;
            collidable.WorldPosition += collidable.LinearVelocity * frameTime;
        }
        public override void Initialize()
        {
            base.Initialize();

            _collidableComponent = Owner.GetComponent <ICollidableComponent>();
            _doAfterSystem       = EntitySystem.Get <DoAfterSystem>();
        }
예제 #8
0
        public static bool IsRelevant(IEntity entity, ICollidableComponent collidableComponent)
        {
            if (entity.Transform.GridID == GridId.Invalid ||
                (PathfindingSystem.TrackedCollisionLayers & collidableComponent.CollisionLayer) == 0)
            {
                return(false);
            }

            return(true);
        }
예제 #9
0
        public float CalculatePenetration(ICollidableComponent target, ICollidableComponent source)
        {
            var manifold = target.WorldAABB.Intersect(source.WorldAABB);

            if (manifold.IsEmpty())
            {
                return(0.0f);
            }
            return(manifold.Height > manifold.Width ? manifold.Width : manifold.Height);
        }
예제 #10
0
        public Manifold(ICollidableComponent A, ICollidableComponent B, [CanBeNull] SharedPhysicsComponent aPhysics, [CanBeNull] SharedPhysicsComponent bPhysics)
        {
            var physicsManager = IoCManager.Resolve <IPhysicsManager>();

            this.A   = A;
            this.B   = B;
            Normal   = physicsManager.CalculateNormal(A, B);
            APhysics = aPhysics;
            BPhysics = bPhysics;
        }
예제 #11
0
        private (float friction, float gravity) GetFriction(ICollidableComponent body)
        {
            if (!body.OnGround)
            {
                return(0f, 0f);
            }

            var location = body.Owner.Transform;
            var grid     = _mapManager.GetGrid(location.GridPosition.GridID);
            var tile     = grid.GetTileRef(location.GridPosition);
            var tileDef  = _tileDefinitionManager[tile.Tile.TypeId];

            return(tileDef.Friction, grid.HasGravity ? 9.8f : 0f);
        }
예제 #12
0
        public void CollidedWith(ICollidableComponent component)
        {
            if (component is Fireball)
            {
                //GetService<ScoreService>().AddScore();
                //GameServices.GetService<SoundService>().PlayExplosion();
                Destroyed = true;
            }

            else if (component is Asteroid)
            {
            }

            else if (component is Ship)
            {
                Destroyed = true;
            }
        }
예제 #13
0
        private bool Valid(IEntity user, IEntity?utilizing, [MaybeNullWhen(false)] out ICollidableComponent collidable, bool force = false)
        {
            if (!Owner.TryGetComponent(out collidable))
            {
                return(false);
            }

            if (!force)
            {
                if (utilizing == null ||
                    !utilizing.TryGetComponent(out ToolComponent tool) ||
                    !tool.UseTool(user, Owner, ToolQuality.Anchoring))
                {
                    return(false);
                }
            }

            return(true);
        }
예제 #14
0
        public void StartPull(ICollidableComponent puller)
        {
            DebugTools.AssertNotNull(puller);

            if (_puller == puller)
            {
                return;
            }

            _puller = puller;

            if (ControlledComponent == null)
            {
                return;
            }

            ControlledComponent.WakeBody();

            var message = new PullStartedMessage(this, _puller, ControlledComponent);

            _puller.Owner.SendMessage(null, message);
            ControlledComponent.Owner.SendMessage(null, message);
        }
예제 #15
0
        public Vector2 CalculateNormal(ICollidableComponent target, ICollidableComponent source)
        {
            var manifold = target.WorldAABB.Intersect(source.WorldAABB);

            if (manifold.IsEmpty())
            {
                return(Vector2.Zero);
            }
            if (manifold.Height > manifold.Width)
            {
                // X is the axis of seperation
                var leftDist  = source.WorldAABB.Right - target.WorldAABB.Left;
                var rightDist = target.WorldAABB.Right - source.WorldAABB.Left;
                return(new Vector2(leftDist > rightDist ? 1 : -1, 0));
            }
            else
            {
                // Y is the axis of seperation
                var bottomDist = source.WorldAABB.Top - target.WorldAABB.Bottom;
                var topDist    = target.WorldAABB.Top - source.WorldAABB.Bottom;
                return(new Vector2(0, bottomDist > topDist ? 1 : -1));
            }
        }
 public PullStartedMessage(PullController controller, ICollidableComponent puller, ICollidableComponent pulled) :
     base(controller, puller, pulled)
 {
 }
예제 #17
0
        protected void UpdateKinematics(ITransformComponent transform, IMoverComponent mover, ICollidableComponent collidable)
        {
            collidable.EnsureController <MoverController>();

            var weightless = !transform.Owner.HasComponent <MovementIgnoreGravityComponent>() &&
                             _physicsManager.IsWeightless(transform.GridPosition);

            if (weightless)
            {
                // No gravity: is our entity touching anything?
                var touching = IsAroundCollider(transform, mover, collidable);

                if (!touching)
                {
                    return;
                }
            }

            // TODO: movement check.
            var(walkDir, sprintDir) = mover.VelocityDir;
            var combined = walkDir + sprintDir;

            if (combined.LengthSquared < 0.001 || !ActionBlockerSystem.CanMove(mover.Owner) && !weightless)
            {
                if (collidable.TryGetController(out MoverController controller))
                {
                    controller.StopMoving();
                }
            }
            else
            {
                if (weightless)
                {
                    if (collidable.TryGetController(out MoverController controller))
                    {
                        controller.Push(combined, mover.CurrentPushSpeed);
                    }

                    transform.LocalRotation = walkDir.GetDir().ToAngle();
                    return;
                }

                var total = walkDir * mover.CurrentWalkSpeed + sprintDir * mover.CurrentSprintSpeed;

                {
                    if (collidable.TryGetController(out MoverController controller))
                    {
                        controller.Move(total, 1);
                    }
                }

                transform.LocalRotation = total.GetDir().ToAngle();

                HandleFootsteps(mover);
            }
        }
 protected PullMessage(PullController controller, ICollidableComponent puller, ICollidableComponent pulled)
 {
     Controller = controller;
     Puller = puller;
     Pulled = pulled;
 }
예제 #19
0
 private void FindCollisionsFor(ICollidableComponent a, HashSet <(EntityUid, EntityUid)> combinations)
예제 #20
0
        public void CollidedWith(ICollidableComponent component)
        {
            if (component is Fireball)
            {
                //GetService<ScoreService>().AddScore();
                //GameServices.GetService<SoundService>().PlayExplosion();
                Destroyed = true;
            }

            else if (component is Asteroid)
            {
              
            }

            else if (component is Ship)
            {
                Destroyed = true;
            }
        }