コード例 #1
0
        private void GenerateTileGeometry()
        {
            // We only care about layers that are solid. Cache which are.
            Tile[][,] SolidTiles = Scene.Layers.Where(c => c.IsSolid).Select(c => c.Tiles).ToArray();
            // We'll check if tiles are checked already, as it could get a bit complicated to keep track.
            // To check if a tile is checked, we'll simply store if it's X and Y coordinate was checked.
            // Using a bool array of hundreds of thousands of elements seems a bit wasteful however.
            BitArray CheckedTiles = new BitArray((int)(Scene.TilesInMap.Y * Scene.TilesInMap.X), false);

            for (int y = 0; y < Scene.TilesInMap.Y; y++)
            {
                for (int x = 0; x < Scene.TilesInMap.X; x++)
                {
                    if (!Exists(SolidTiles, CheckedTiles, x, y))
                    {
                        continue;
                    }
                    int  BitIndex       = y * (int)Scene.TilesInMap.X + x;
                    bool AlreadyChecked = CheckedTiles.Get(BitIndex);
                    if (AlreadyChecked)
                    {
                        continue;
                    }
                    //CheckedTiles.Set(BitIndex, true);
                    // When we have a tile we need to check, find the largest rectangle that encompasses it.
                    Rectangle TileBoundaries  = GetLargestSolidTileRectangle(SolidTiles, CheckedTiles, x, y);
                    Rectangle WorldBoundaries = new Rectangle(TileBoundaries.X * (int)Scene.TileSize.X, TileBoundaries.Y * (int)Scene.TileSize.Y,
                                                              TileBoundaries.Width * (int)Scene.TileSize.X, TileBoundaries.Height * (int)Scene.TileSize.Y);
                    TiledPlatformerGeometryObject Obj = new TiledPlatformerGeometryObject(WorldBoundaries);
                    AddGeometry(Obj);
                }
            }
        }
コード例 #2
0
        /// <summary>
        /// Indicates whether the given Entity can reach the second object, starting from the first, in one jump.
        /// </summary>
        public bool CanEntityReachObject(Entity Entity, TiledPlatformerGeometryObject First, TiledPlatformerGeometryObject Second)
        {
            var PhysicsComponent  = Entity.GetComponent <PhysicsComponent>();
            var PhysicsSystem     = Scene.GetSystem <PhysicsSystem>();
            var MovementComponent = Entity.GetComponent <MovementComponent>();

            if (PhysicsComponent == null || PhysicsSystem == null || MovementComponent == null)
            {
                throw new InvalidOperationException("Unable to calculate a path for an Entity that has no physics component, movement component, or if a physics system is not set.");
            }
            double   Gravity          = PhysicsSystem.Gravity * PhysicsComponent.GravityCoefficient;
            double   Drag             = PhysicsSystem.HorizontalDrag * PhysicsComponent.HorizontalDragCoefficient;
            double   JumpAccel        = MovementComponent.JumpSpeed;
            TimeSpan TimeForTopHeight = TimeSpan.FromSeconds(JumpAccel / Gravity);
            double   JumpHeight       = JumpAccel / TimeForTopHeight.TotalSeconds / 2;

            if (First.Location.Top + JumpHeight < Second.Location.Top)
            {
                return(false);
            }
            // Another alternative to all this below stuff is to determine the time for the next tile and evaluate it using the Curve class.
            // Then check if there's a geometry object there.
            double HeightDifference = Second.Location.Top - First.Location.Top;
            // Next, we need to determine the amount of time it would take to hit the ground.
            // This is done in the same way as above, added on to time for top.
            // This is technically wrong, because it assumes equal height and not ground.
            // But we'll keep it for now. The alternative is much, much, less pleasant curve calculations.
            TimeSpan TimeToSecondHeight = TimeSpan.FromSeconds((JumpHeight - HeightDifference) / Gravity) + TimeForTopHeight;

            /*// Calculate how long it'll take us to reach our max walking speed to determine X distance.
             * TimeSpan TimeToMaxWalkingSpeed = TimeSpan.FromSeconds((MovementComponent.MaxWalkingSpeed - PhysicsComponent.VelocityX) / (MovementComponent.WalkAcceleration - Drag));*/
            // Turns out we don't need that; instead we'll assume constant speed because we're going to get a running start when jumping off the platform.
            // Probably.
            // Thus, our max horizontal distance travelled just our total velocity * time.
            double HorizDistance = TimeToSecondHeight.TotalSeconds * MovementComponent.MaxWalkingSpeed;

            if (Second.Location.Left > First.Location.Right - (Scene.TileSize.X / 2) + HorizDistance)
            {
                return(false);
            }

            // So we now know that there is a theoretical possibility that we can reach that object.
            // The next step is to use a curve and determine if we're going to collide with anything.
            // One approach would be to determine the amount of time until reaching the next tile vertically and check if object at X location there.
            // This is a pretty painfully expensive approach however.
            // But what do we do if we are?
            // Perhaps if we jumped a few steps early we wouldn't be colliding with anything.
            // Perhaps we could slightly stop while in the air to prevent it.
            // Perhaps we'd hit a barrier that we wouldn't if we were going slower.
            // Much unpleasantness.
            // For now... close enough, we'll pretend we can reach.
            return(true);
        }
コード例 #3
0
 private void GenerateTileGeometry()
 {
     // We only care about layers that are solid. Cache which are.
     Tile[][,] SolidTiles = Scene.Layers.Where(c => c.IsSolid).Select(c => c.Tiles).ToArray();
     // We'll check if tiles are checked already, as it could get a bit complicated to keep track.
     // To check if a tile is checked, we'll simply store if it's X and Y coordinate was checked.
     // Using a bool array of hundreds of thousands of elements seems a bit wasteful however.
     BitArray CheckedTiles = new BitArray((int)(Scene.TilesInMap.Y * Scene.TilesInMap.X), false);
     for(int y = 0; y < Scene.TilesInMap.Y; y++) {
         for(int x = 0; x < Scene.TilesInMap.X; x++) {
             if(!Exists(SolidTiles, CheckedTiles, x, y))
                 continue;
             int BitIndex = y * (int)Scene.TilesInMap.X + x;
             bool AlreadyChecked = CheckedTiles.Get(BitIndex);
             if(AlreadyChecked)
                 continue;
             //CheckedTiles.Set(BitIndex, true);
             // When we have a tile we need to check, find the largest rectangle that encompasses it.
             Rectangle TileBoundaries = GetLargestSolidTileRectangle(SolidTiles, CheckedTiles, x, y);
             Rectangle WorldBoundaries = new Rectangle(TileBoundaries.X * (int)Scene.TileSize.X, TileBoundaries.Y * (int)Scene.TileSize.Y,
                 TileBoundaries.Width * (int)Scene.TileSize.X, TileBoundaries.Height * (int)Scene.TileSize.Y);
             TiledPlatformerGeometryObject Obj = new TiledPlatformerGeometryObject(WorldBoundaries);
             AddGeometry(Obj);
         }
     }
 }
コード例 #4
0
        /// <summary>
        /// Indicates whether the given Entity can reach the second object, starting from the first, in one jump.
        /// </summary>
        public bool CanEntityReachObject(Entity Entity, TiledPlatformerGeometryObject First, TiledPlatformerGeometryObject Second)
        {
            var PhysicsComponent = Entity.GetComponent<PhysicsComponent>();
            var PhysicsSystem = Scene.GetSystem<PhysicsSystem>();
            var MovementComponent = Entity.GetComponent<MovementComponent>();
            if(PhysicsComponent == null || PhysicsSystem == null || MovementComponent == null)
                throw new InvalidOperationException("Unable to calculate a path for an Entity that has no physics component, movement component, or if a physics system is not set.");
            double Gravity = PhysicsSystem.Gravity * PhysicsComponent.GravityCoefficient;
            double Drag = PhysicsSystem.HorizontalDrag * PhysicsComponent.HorizontalDragCoefficient;
            double JumpAccel = MovementComponent.JumpSpeed;
            TimeSpan TimeForTopHeight = TimeSpan.FromSeconds(JumpAccel / Gravity);
            double JumpHeight = JumpAccel / TimeForTopHeight.TotalSeconds / 2;
            if(First.Location.Top + JumpHeight < Second.Location.Top)
                return false;
            // Another alternative to all this below stuff is to determine the time for the next tile and evaluate it using the Curve class.
            // Then check if there's a geometry object there.
            double HeightDifference = Second.Location.Top - First.Location.Top;
            // Next, we need to determine the amount of time it would take to hit the ground.
            // This is done in the same way as above, added on to time for top.
            // This is technically wrong, because it assumes equal height and not ground.
            // But we'll keep it for now. The alternative is much, much, less pleasant curve calculations.
            TimeSpan TimeToSecondHeight = TimeSpan.FromSeconds((JumpHeight - HeightDifference) / Gravity) + TimeForTopHeight;
            /*// Calculate how long it'll take us to reach our max walking speed to determine X distance.
            TimeSpan TimeToMaxWalkingSpeed = TimeSpan.FromSeconds((MovementComponent.MaxWalkingSpeed - PhysicsComponent.VelocityX) / (MovementComponent.WalkAcceleration - Drag));*/
            // Turns out we don't need that; instead we'll assume constant speed because we're going to get a running start when jumping off the platform.
            // Probably.
            // Thus, our max horizontal distance travelled just our total velocity * time.
            double HorizDistance = TimeToSecondHeight.TotalSeconds * MovementComponent.MaxWalkingSpeed;
            if(Second.Location.Left > First.Location.Right - (Scene.TileSize.X / 2) + HorizDistance)
                return false;

            // So we now know that there is a theoretical possibility that we can reach that object.
            // The next step is to use a curve and determine if we're going to collide with anything.
            // One approach would be to determine the amount of time until reaching the next tile vertically and check if object at X location there.
            // This is a pretty painfully expensive approach however.
            // But what do we do if we are?
            // Perhaps if we jumped a few steps early we wouldn't be colliding with anything.
            // Perhaps we could slightly stop while in the air to prevent it.
            // Perhaps we'd hit a barrier that we wouldn't if we were going slower.
            // Much unpleasantness.
            // For now... close enough, we'll pretend we can reach.
            return true;
        }