コード例 #1
0
        /// <summary>
        /// Berechnet die Geschwindigkeit einer <see cref="Entity"/> nach der Kollision mit der Welt. (Original Lassi)
        /// </summary>
        /// <param name="gameTime">Simulation time</param>
        /// <param name="position">Position der <see cref="Entity"/></param>
        /// <param name="cache"><see cref="ILocalChunkCache"/> as workspace</param>
        /// <param name="radius">Radius der <see cref="Entity"/></param>
        /// <param name="height">Höhe der <see cref="Entity"/></param>
        /// <param name="deltaPosition">Positionsänderung zwischen zwei Simulationsdurchläufen</param>
        /// <param name="velocity">Berechnete Geschwindigkeit</param>
        /// <exception cref="ArgumentNullException">Cache</exception>
        /// <returns>Geschwindigkeit der <see cref="Entity"/> nach der Killisionsprüfung</returns>
        public Vector3 WorldCollision(GameTime gameTime, Coordinate position, ILocalChunkCache cache, float radius, float height,
                                      Vector3 deltaPosition, Vector3 velocity)
        {
            if (cache == null)
            {
                throw new ArgumentNullException(nameof(cache));
            }

            Vector3 move = deltaPosition;

            //Blocks finden die eine Kollision verursachen könnten
            int minx = (int)Math.Floor(Math.Min(
                                           position.BlockPosition.X - radius,
                                           position.BlockPosition.X - radius + deltaPosition.X));
            int maxx = (int)Math.Ceiling(Math.Max(
                                             position.BlockPosition.X + radius,
                                             position.BlockPosition.X + radius + deltaPosition.X));
            int miny = (int)Math.Floor(Math.Min(
                                           position.BlockPosition.Y - radius,
                                           position.BlockPosition.Y - radius + deltaPosition.Y));
            int maxy = (int)Math.Ceiling(Math.Max(
                                             position.BlockPosition.Y + radius,
                                             position.BlockPosition.Y + radius + deltaPosition.Y));
            int minz = (int)Math.Floor(Math.Min(
                                           position.BlockPosition.Z,
                                           position.BlockPosition.Z + deltaPosition.Z));
            int maxz = (int)Math.Ceiling(Math.Max(
                                             position.BlockPosition.Z + height,
                                             position.BlockPosition.Z + height + deltaPosition.Z));

            //Beteiligte Flächen des Spielers
            var playerplanes = CollisionPlane.GetEntityCollisionPlanes(radius, height, velocity, position);

            for (int z = minz; z <= maxz; z++)
            {
                for (int y = miny; y <= maxy; y++)
                {
                    for (int x = minx; x <= maxx; x++)
                    {
                        move = velocity * (float)gameTime.ElapsedGameTime.TotalSeconds;

                        Index3 pos      = new Index3(x, y, z);
                        Index3 blockPos = pos + position.GlobalBlockIndex;
                        ushort block    = cache.GetBlock(blockPos);

                        if (block == 0)
                        {
                            continue;
                        }

                        var blockplanes = CollisionPlane.GetBlockCollisionPlanes(pos, velocity);

                        foreach (var playerPlane in playerplanes)
                        {
                            foreach (var blockPlane in blockplanes)
                            {
                                if (!CollisionPlane.Intersect(blockPlane, playerPlane))
                                {
                                    continue;
                                }

                                var distance = CollisionPlane.GetDistance(blockPlane, playerPlane);
                                if (!CollisionPlane.CheckDistance(distance, move))
                                {
                                    continue;
                                }

                                var subvelocity = (distance / (float)gameTime.ElapsedGameTime.TotalSeconds);
                                var diff        = velocity - subvelocity;

                                float vx;
                                float vy;
                                float vz;

                                if (blockPlane.normal.X != 0 && (velocity.X > 0 && diff.X >= 0 && subvelocity.X >= 0 ||
                                                                 velocity.X < 0 && diff.X <= 0 && subvelocity.X <= 0))
                                {
                                    vx = subvelocity.X;
                                }
                                else
                                {
                                    vx = velocity.X;
                                }

                                if (blockPlane.normal.Y != 0 && (velocity.Y > 0 && diff.Y >= 0 && subvelocity.Y >= 0 ||
                                                                 velocity.Y < 0 && diff.Y <= 0 && subvelocity.Y <= 0))
                                {
                                    vy = subvelocity.Y;
                                }
                                else
                                {
                                    vy = velocity.Y;
                                }

                                if (blockPlane.normal.Z != 0 && (velocity.Z > 0 && diff.Z >= 0 && subvelocity.Z >= 0 ||
                                                                 velocity.Z < 0 && diff.Z <= 0 && subvelocity.Z <= 0))
                                {
                                    vz = subvelocity.Z;
                                }
                                else
                                {
                                    vz = velocity.Z;
                                }

                                velocity = new Vector3(vx, vy, vz);
                                if (vx == 0 && vy == 0 && vz == 0)
                                {
                                    return(velocity);
                                }
                            }
                        }
                    }
                }
            }
            return(velocity);
        }
コード例 #2
0
ファイル: MoveComponent.cs プロジェクト: marsat02/octoawesome
        private void CheckBoxCollision(GameTime gameTime, Entity entity, MoveableComponent movecomp, PositionComponent poscomp)
        {
            if (!entity.Components.ContainsComponent <BodyComponent>())
            {
                return;
            }

            BodyComponent bc = entity.Components.GetComponent <BodyComponent>();


            Coordinate position = poscomp.Position;

            Vector3 move = movecomp.PositionMove;

            //Blocks finden die eine Kollision verursachen könnten
            int minx = (int)Math.Floor(Math.Min(
                                           position.BlockPosition.X - bc.Radius,
                                           position.BlockPosition.X - bc.Radius + movecomp.PositionMove.X));
            int maxx = (int)Math.Ceiling(Math.Max(
                                             position.BlockPosition.X + bc.Radius,
                                             position.BlockPosition.X + bc.Radius + movecomp.PositionMove.X));
            int miny = (int)Math.Floor(Math.Min(
                                           position.BlockPosition.Y - bc.Radius,
                                           position.BlockPosition.Y - bc.Radius + movecomp.PositionMove.Y));
            int maxy = (int)Math.Ceiling(Math.Max(
                                             position.BlockPosition.Y + bc.Radius,
                                             position.BlockPosition.Y + bc.Radius + movecomp.PositionMove.Y));
            int minz = (int)Math.Floor(Math.Min(
                                           position.BlockPosition.Z,
                                           position.BlockPosition.Z + movecomp.PositionMove.Z));
            int maxz = (int)Math.Ceiling(Math.Max(
                                             position.BlockPosition.Z + bc.Height,
                                             position.BlockPosition.Z + bc.Height + movecomp.PositionMove.Z));

            //Beteiligte Flächen des Spielers
            var playerplanes = CollisionPlane.GetEntityCollisionPlanes(bc.Radius, bc.Height, movecomp.Velocity, poscomp.Position);

            bool abort = false;

            var cache = entity.Components.GetComponent <LocalChunkCacheComponent>().LocalChunkCache;

            for (int z = minz; z <= maxz && !abort; z++)
            {
                for (int y = miny; y <= maxy && !abort; y++)
                {
                    for (int x = minx; x <= maxx && !abort; x++)
                    {
                        move = movecomp.Velocity * (float)gameTime.ElapsedGameTime.TotalSeconds;

                        Index3 pos      = new Index3(x, y, z);
                        Index3 blockPos = pos + position.GlobalBlockIndex;
                        ushort block    = cache.GetBlock(blockPos);
                        if (block == 0)
                        {
                            continue;
                        }



                        var blockplane = CollisionPlane.GetBlockCollisionPlanes(pos, movecomp.Velocity).ToList();

                        var planes = from pp in playerplanes
                                     from bp in blockplane
                                     where CollisionPlane.Intersect(bp, pp)
                                     let distance = CollisionPlane.GetDistance(bp, pp)
                                                    where CollisionPlane.CheckDistance(distance, move)
                                                    select new { BlockPlane = bp, PlayerPlane = pp, Distance = distance };

                        foreach (var plane in planes)
                        {
                            var subvelocity = (plane.Distance / (float)gameTime.ElapsedGameTime.TotalSeconds);
                            var diff        = movecomp.Velocity - subvelocity;

                            float vx;
                            float vy;
                            float vz;

                            if (plane.BlockPlane.normal.X != 0 && (movecomp.Velocity.X > 0 && diff.X >= 0 && subvelocity.X >= 0 || movecomp.Velocity.X < 0 && diff.X <= 0 && subvelocity.X <= 0))
                            {
                                vx = subvelocity.X;
                            }
                            else
                            {
                                vx = movecomp.Velocity.X;
                            }

                            if (plane.BlockPlane.normal.Y != 0 && (movecomp.Velocity.Y > 0 && diff.Y >= 0 && subvelocity.Y >= 0 || movecomp.Velocity.Y < 0 && diff.Y <= 0 && subvelocity.Y <= 0))
                            {
                                vy = subvelocity.Y;
                            }
                            else
                            {
                                vy = movecomp.Velocity.Y;
                            }

                            if (plane.BlockPlane.normal.Z != 0 && (movecomp.Velocity.Z > 0 && diff.Z >= 0 && subvelocity.Z >= 0 || movecomp.Velocity.Z < 0 && diff.Z <= 0 && subvelocity.Z <= 0))
                            {
                                vz = subvelocity.Z;
                            }
                            else
                            {
                                vz = movecomp.Velocity.Z;
                            }

                            movecomp.Velocity = new Vector3(vx, vy, vz);

                            if (vx == 0 && vy == 0 && vz == 0)
                            {
                                abort = true;
                                break;
                            }
                        }
                    }
                }
            }

            // TODO: Was ist für den Fall Gravitation = 0 oder im Scheitelpunkt des Sprungs?
            //movecomp.OnGround = Player.Velocity.Z == 0f;

            movecomp.PositionMove = movecomp.Velocity * (float)gameTime.ElapsedGameTime.TotalSeconds;
        }