Example #1
0
        private static void HandleCollision(
            Ecs.Registry registry,
            Queue <Entity> toRemove,
            Entity entity,
            Comps.Solid solidComp,
            Comps.Position positionComp,
            Comps.Shapes.Rectangle rectangleComp,
            PhysicalVector2 tilePosition,
            Rectangle tileRectangle
            )
        {
            if (solidComp.ephemeral)
            {
                toRemove.Enqueue(entity);
            }
            else
            {
                PhysicalVector2 correction = GetMinCorrection(
                    rectangleComp.data, positionComp.data,
                    tileRectangle, tilePosition
                    );

                positionComp.data += correction;
            }
        }
Example #2
0
        public static void Run(Ecs.Registry registry)
        {
            // To avoid performance costs from doing list intersections, only
            // query for entities with `Solid` components.
            //
            // However, we can assume that all entities with a `Solid` component
            // also have these components:
            // - `Position`
            // - `Shape.Rectangle`
            List <Entity> entities1 = registry.GetEntitiesList(typeof(Comps.Solid));

            // Use a `HashSet` to make removing entities O(1)
            var entities2 = new HashSet <Entity>(entities1);

            // Queue entities to remove so we aren't removing entities while
            // iterating over them
            Queue <Entity> toRemove = new Queue <Entity>();

            foreach (Ecs.Entity entity1 in entities1)
            {
                var entity1Pos = registry.GetComponentUnsafe <Comps.Position>(entity1);

                foreach (Ecs.Entity entity2 in entities2)
                {
                    var entity2Pos = registry.GetComponentUnsafe <Comps.Position>(entity2);

                    if (!IsCollisionPossible(entity1Pos.data, entity2Pos.data) ||
                        entity1.Equals(entity2)
                        )
                    {
                        continue;
                    }

                    var entity1Rect = registry.GetComponentUnsafe <Comps.Shapes.Rectangle>(entity1);
                    var entity2Rect = registry.GetComponentUnsafe <Comps.Shapes.Rectangle>(entity2);

                    if (!entity1.Equals(entity2) &&
                        CheckCollision(
                            entity1Rect.data, entity1Pos.data,
                            entity2Rect.data, entity2Pos.data
                            )
                        )
                    {
                        var entity1Solid = registry.GetComponentUnsafe <Comps.Solid>(entity1);
                        var entity2Solid = registry.GetComponentUnsafe <Comps.Solid>(entity2);
                        HandleCollision(
                            registry, toRemove,
                            entity1, entity1Solid, entity1Pos, entity1Rect,
                            entity2, entity2Solid, entity2Pos, entity2Rect
                            );
                    }
                }

                entities2.Remove(entity1);
            }

            ProcessRemoves(toRemove, registry);
        }
Example #3
0
        public static void Run(
            Ecs.Registry registry,
            IMap map
            )
        {
            // To avoid performance costs from doing list intersections, only
            // query for entities with `Solid` components.
            //
            // However, we can assume that all entities with a `Solid` component
            // also have these components:
            // - `Position`
            // - `Shape.Rectangle`
            List <Entity> entities = registry.GetEntitiesList(typeof(Comps.Solid));

            // Queue entities to remove so we aren't removing entities while
            // iterating over them
            Queue <Entity> toRemove = new Queue <Entity>();

            foreach (Ecs.Entity entity in entities)
            {
                var entityRect    = registry.GetComponentUnsafe <Comps.Shapes.Rectangle>(entity);
                var entityPos     = registry.GetComponentUnsafe <Comps.Position>(entity);
                var entityPosRect = new PosRectangle(entityPos.data, entityRect.data);

                // Check every tile that the rectangle is touching.
                foreach (int index in OverlappingTiles(map, entityPosRect))
                {
                    var gameTile = (GameTile)map.GameLayer.tiles[index];
                    switch (gameTile.kind)
                    {
                    case GameTile.Kind.Solid:
                        var tilePos  = GetTilePosition(map, index);
                        var tileRect = new Rectangle(
                            map.TileWidth,
                            map.TileHeight
                            );

                        if (CheckCollision(
                                entityRect.data, entityPos.data,
                                tileRect, tilePos
                                ))
                        {
                            var entitySolid = registry.GetComponentUnsafe <Comps.Solid>(entity);
                            HandleCollision(
                                registry, toRemove,
                                entity, entitySolid, entityPos, entityRect,
                                tilePos, tileRect
                                );
                        }

                        break;
                    }
                }
            }

            ProcessRemoves(toRemove, registry);
        }
Example #4
0
        public static void Run(Ecs.Registry registry)
        {
            // To avoid performance costs from doing list intersections, only
            // query for entities with `Projectile` and `Door` components.
            //
            // However, we can assume that these entities also have these
            // components:
            // - `Position`
            // - `Shape.Rectangle`
            List <Entity> projectileEntities = registry.GetEntitiesList(typeof(Comps.Projectile));
            List <Entity> doorEntities       = registry.GetEntitiesList(typeof(Comps.Door));

            // Queue entities to remove so we aren't removing entities while
            // iterating over them
            Queue <Entity> toRemove = new Queue <Entity>();

            foreach (Ecs.Entity projectileEntity in projectileEntities)
            {
                var projectilePosition = registry.GetComponentUnsafe <Comps.Position>(projectileEntity);

                foreach (Ecs.Entity doorEntity in doorEntities)
                {
                    var doorPosition = registry.GetComponentUnsafe <Comps.Position>(doorEntity);

                    if (!IsCollisionPossible(projectilePosition.data, doorPosition.data) ||
                        projectileEntity.Equals(doorEntity)
                        )
                    {
                        continue;
                    }

                    var projectileRectangle = registry.GetComponentUnsafe <Comps.Shapes.Rectangle>(projectileEntity);
                    var projectile          = registry.GetComponentUnsafe <Comps.Projectile>(projectileEntity);

                    var doorRectangle = registry.GetComponentUnsafe <Comps.Shapes.Rectangle>(doorEntity);
                    var door          = registry.GetComponentUnsafe <Comps.Door>(doorEntity);

                    if (CanUnlock(projectile.kind, door.kind) &&
                        CheckCollision(
                            doorRectangle.data, doorPosition.data,
                            projectileRectangle.data, projectilePosition.data
                            )
                        )
                    {
                        toRemove.Enqueue(doorEntity);
                        Console.WriteLine(
                            "The {0} door has been opened",
                            door.kind
                            );
                    }
                }
            }

            ProcessRemoves(toRemove, registry);
        }
Example #5
0
 public static void ProcessRemoves(
     Queue <Entity> toRemove,
     Ecs.Registry registry
     )
 {
     while (toRemove.Count > 0)
     {
         Entity entity = toRemove.Dequeue();
         registry.Remove(entity);
     }
 }
Example #6
0
        private static void HandleCollision(
            Ecs.Registry registry,
            Queue <Entity> toRemove,
            Entity entity1,
            Comps.Solid entity1Solid,
            Comps.Position entity1Pos,
            Comps.Shapes.Rectangle entity1Rect,
            Entity entity2,
            Comps.Solid entity2Solid,
            Comps.Position entity2Pos,
            Comps.Shapes.Rectangle entity2Rect
            )
        {
            if (entity1Solid.ephemeral)
            {
                toRemove.Enqueue(entity1);
                return;
            }

            if (entity2Solid.ephemeral)
            {
                toRemove.Enqueue(entity2);
                return;
            }

            Vector2 correction = GetMinCorrection(
                entity1Rect.data, entity1Pos.data,
                entity2Rect.data, entity2Pos.data
                );

            // Ignore the case where both are unmovable
            if (entity1Solid.unmovable)
            {
                entity2Pos.data -= correction;
            }
            else if (entity2Solid.unmovable)
            {
                entity1Pos.data += correction;
            }
            else
            {
                entity1Pos.data += correction / 2f;
                entity2Pos.data -= correction / 2f;
            }
        }
Example #7
0
        public static void Run(Ecs.Registry registry)
        {
            // To avoid performance costs from doing list intersections, only
            // query for entities with `Damaging` and `Inventory` components.
            //
            // However, we can assume that these entities also have these
            // components:
            // - `Position`
            // - `Shape.Rectangle`
            List <Entity> hitEntities  = registry.GetEntitiesList(typeof(Comps.Damaging));
            List <Entity> hurtEntities = registry.GetEntitiesList(typeof(Comps.Inventory));

            foreach (Ecs.Entity hitEntity in hitEntities)
            {
                var hitPosition = registry.GetComponentUnsafe <Comps.Position>(hitEntity);

                foreach (Ecs.Entity hurtEntity in hurtEntities)
                {
                    var hurtPosition = registry.GetComponentUnsafe <Comps.Position>(hurtEntity);

                    if (!IsCollisionPossible(hitPosition.data, hurtPosition.data) ||
                        hitEntity.Equals(hurtEntity)
                        )
                    {
                        continue;
                    }

                    var hitRectangle = registry.GetComponentUnsafe <Comps.Shapes.Rectangle>(hitEntity);
                    var hitDamage    = registry.GetComponentUnsafe <Comps.Damaging>(hitEntity);

                    var hurtRectangle = registry.GetComponentUnsafe <Comps.Shapes.Rectangle>(hurtEntity);

                    // Only check for collision if the entity isn't being hit by
                    // its own attack (unless it has self damage on).
                    bool canDamage = (hurtEntity.id != hitDamage.attackerId || hitDamage.selfDamage);
                    if (canDamage &&
                        CheckCollision(
                            hurtRectangle.data, hurtPosition.data,
                            hitRectangle.data, hitPosition.data
                            )
                        )
                    {
                        var hurtInventory = registry.GetComponentUnsafe <Comps.Inventory>(hurtEntity);

                        bool isInvulnerable = true; // TODO
                        if (isInvulnerable)
                        {
                            // Deal damage
                            hurtInventory.data[Comps.Item.Kind.Heart].Count--;

                            // TODO: give invulnerability ticks

                            registry.AssignComponent(
                                hurtEntity,
                                new Comps.Damaged {
                                damage    = hitDamage.damage,
                                damagerId = hitEntity.id
                            }
                                );

                            Console.WriteLine(
                                "Entity {0} now at {1} HP (damaged by Entity {2})",
                                hurtEntity.id,
                                hurtInventory.data[Comps.Item.Kind.Heart].Count,
                                hitDamage.attackerId
                                );
                        }
                    }
                }
            }
        }