コード例 #1
0
ファイル: Collider.cs プロジェクト: bramkelder/MonoGear
        /// <summary>
        /// Method that checks if there is a collision with any collider
        /// </summary>
        /// <returns>True if a collision is detected</returns>
        public virtual bool CollidesAny()
        {
            // Check if we could be colliding
            var colliders = BoxOverlapAny(this);

            if (colliders.Count() != 0)
            {
                // Run through all colliders that might collide and check if we do
                foreach (var col in colliders)
                {
                    if (Collides(col))
                    {
                        return(true);
                    }
                }
            }

            // Tilemap collision
            var circle = this as CircleCollider;

            if (circle != null)
            {
                return(CircleTilemapOverlap(circle, MonoGearGame.GetCurrentLevel()));
            }
            else
            {
                return(BoxTilemapOverlap(this, MonoGearGame.GetCurrentLevel()));
            }
        }
コード例 #2
0
ファイル: Collider.cs プロジェクト: bramkelder/MonoGear
        /// <summary>
        /// Method that checks if there is a collision with any collider
        /// </summary>
        /// <param name="other">Returns the other collider</param>
        /// <param name="hitTilemap">Returns if the collision is with the tilemap</param>
        /// <returns>True if a collision is detected</returns>
        public virtual bool CollidesAny(out Collider other, out bool hitTilemap)
        {
            // Check if we could be colliding
            var colliders = BoxOverlapAny(this);

            if (colliders.Count() != 0)
            {
                // Run through all colliders that might collide and check if we do
                foreach (var col in colliders)
                {
                    if (Collides(col))
                    {
                        other      = col;
                        hitTilemap = false;
                        return(true);
                    }
                }
            }
            other = null;

            // Tilemap collision
            var circle = this as CircleCollider;

            if (circle != null)
            {
                hitTilemap = CircleTilemapOverlap(circle, MonoGearGame.GetCurrentLevel());
            }
            else
            {
                hitTilemap = BoxTilemapOverlap(this, MonoGearGame.GetCurrentLevel());
            }

            return(hitTilemap);
        }
コード例 #3
0
ファイル: Pathfinding.cs プロジェクト: bramkelder/MonoGear
        /// <summary>
        /// Adds a node to the list if it's walkable.
        /// </summary>
        /// <param name="x">Tile x</param>
        /// <param name="y">Tile y</param>
        /// <param name="map">map of tiles</param>
        /// <param name="list">list to add to</param>
        static void GetNodeIfWalkable(int x, int y, Tile[] map, List <Node> list)
        {
            var level = MonoGearGame.GetCurrentLevel();

            if (x < level.Width && x >= 0 && (y) < level.Height && y >= 0 && (map[x + y * level.Width]?.Walkable) == true)
            {
                list.Add(nodes[x + y * level.Width]);
            }
        }
コード例 #4
0
ファイル: Pathfinding.cs プロジェクト: bramkelder/MonoGear
        /// <summary>
        /// Updates the internal tilemap and nodes based on the active level
        /// </summary>
        private void UpdateInternalMap()
        {
            var level = MonoGearGame.GetCurrentLevel();

            if (level != null)
            {
                map = level.Tiles;

                nodes = new Node[map.Length];

                // New nodes
                for (int y = 0; y < level.Height; y++)
                {
                    for (int x = 0; x < level.Width; x++)
                    {
                        nodes[x + y * level.Width]            = new Node();
                        nodes[x + y * level.Width].Location.X = x;
                        nodes[x + y * level.Width].Location.Y = y;
                    }
                }
            }
        }
コード例 #5
0
ファイル: Pathfinding.cs プロジェクト: bramkelder/MonoGear
        /// <summary>
        /// Does actual A* pathfinding.
        /// </summary>
        /// <param name="from">Start point</param>
        /// <param name="to">End point</param>
        /// <returns>List of Vector2 or null if no path can be found</returns>
        private static List <Vector2> FindPathImpl(Vector2 from, Vector2 to)
        {
            // Set up start and end nodes
            Node current = null;
            var  level   = MonoGearGame.GetCurrentLevel();
            var  start   = nodes[(int)(from.X / level.TileWidth) + (int)(from.Y / level.TileHeight) * level.Width];
            var  target  = nodes[(int)(to.X / level.TileWidth) + (int)(to.Y / level.TileHeight) * level.Width];

            // Check for unreachable targets
            if (!unreachableTargets.Contains(target.Location))
            {
                foreach (var node in nodes)
                {
                    node.F      = 0;
                    node.G      = 0;
                    node.H      = 0;
                    node.closed = false;
                    node.Parent = null;
                }

                var openList = new HashSet <Node>();
                int g        = 0;

                // start by adding the original position to the open list
                openList.Add(start);

                bool pathFound = false;

                while (openList.Count > 0)
                {
                    // get the tile with the lowest F score
                    var lowest = openList.Min(l => l.F);
                    current = openList.First(l => l.F == lowest);

                    // add the current square to the closed list
                    current.closed = true;

                    // remove it from the open list
                    openList.Remove(current);

                    // if we added the destination to the closed list, we've found a path
                    if (target.closed)
                    {
                        pathFound = true;
                        break;
                    }

                    var adjacentTiles = GetWalkableAdjacentTiles(current.Location, map);
                    g++;

                    foreach (var adjacentTile in adjacentTiles)
                    {
                        // if this adjacent square is already in the closed list, ignore it
                        if (adjacentTile.closed)
                        {
                            continue;
                        }

                        // if it's not in the open list...
                        if (!openList.Contains(adjacentTile))
                        {
                            // compute its score, set the parent
                            adjacentTile.G      = g;
                            adjacentTile.H      = ComputeHScore(adjacentTile.Location, target.Location);
                            adjacentTile.F      = adjacentTile.G + adjacentTile.H;
                            adjacentTile.Parent = current;

                            // and add it to the open list
                            openList.Add(adjacentTile);
                        }
                        else
                        {
                            // test if using the current G score makes the adjacent square's F score
                            // lower, if yes update the parent because it means it's a better path
                            if (g + adjacentTile.H < adjacentTile.F)
                            {
                                adjacentTile.G      = g;
                                adjacentTile.F      = adjacentTile.G + adjacentTile.H;
                                adjacentTile.Parent = current;
                            }
                        }
                    }
                }

                if (pathFound)
                {
                    List <Vector2> path = new List <Vector2>();

                    // Build path by backtracing
                    while (current != null)
                    {
                        path.Add(new Vector2(current.Location.X, current.Location.Y) * level.TileHeight + Vector2.One * level.TileHeight / 2);
                        current = current.Parent;
                    }

                    // Reverse it for the correct order
                    path.Reverse();

                    return(path);
                }
                else
                {
                    // Assume point is not reachable for anyone since the playable area should always be one zone
                    unreachableTargets.Add(target.Location);
                }
            }

            // Couldn't find anything
            return(null);
        }
コード例 #6
0
        /// <summary>
        /// Called once per frame
        /// </summary>
        /// <param name="input">input</param>
        /// <param name="gameTime">gametime</param>
        public override void Update(Input input, GameTime gameTime)
        {
            // Animation done by parent class
            base.Update(input, gameTime);

            // Movement delta
            var dx = 0.0f;
            var dy = 0.0f;

            // Use analog sticks or keyboard for movement depending on if we have a gamepad connected
            if (input.PadConnected())
            {
                var sticks = input.GetGamepadState().ThumbSticks;

                dx += sticks.Left.X * Speed;
                dy += sticks.Left.Y * Speed;
            }
            else
            {
                if (input.IsButtonDown(Input.Button.Left))
                {
                    dx -= Speed;
                }
                if (input.IsButtonDown(Input.Button.Right))
                {
                    dx += Speed;
                }
                if (input.IsButtonDown(Input.Button.Up))
                {
                    dy -= Speed;
                }
                if (input.IsButtonDown(Input.Button.Down))
                {
                    dy += Speed;
                }
            }

            // Sneak mode
            if (input.IsButtonDown(Input.Button.Sneak))
            {
                SneakMode = true;
                Speed     = 50;
            }
            else
            {
                SneakMode = false;
                Speed     = 100;
            }

            // Clamp movement speed
            var delta = new Vector2(dx, dy);

            if (delta.LengthSquared() > Speed * Speed)
            {
                delta.Normalize();
                delta *= Speed;
            }

            // Get correct tile sound
            var tilevalue = MonoGearGame.GetCurrentLevel().GetTile(Position)?.Sound;
            SoundEffectInstance tilesound;

            switch (tilevalue)
            {
            case Tile.TileSound.Grass:
                tilesound = walkingSoundGrass;
                break;

            case Tile.TileSound.Water:
                tilesound = walkingSoundWater;
                break;

            case Tile.TileSound.Concrete:
                tilesound = walkingSoundStone;
                break;

            default:
                tilesound = walkingSoundStone;
                break;
            }

            if (tilesound != null && tilesound != walkingSound)
            {
                // stop old sound
                walkingSound.Stop();
                walkingSound = tilesound;
            }

            if (delta.LengthSquared() > 0)
            {
                // Moving
                Rotation         = MathExtensions.VectorToAngle(delta);
                AnimationRunning = true;
                walkingSound.Play();
            }
            else
            {
                // Standing still
                SneakMode             = true;
                AnimationRunning      = false;
                AnimationCurrentFrame = 1;
                walkingSound.Stop();
            }

            // Sneaking is silent
            if (SneakMode)
            {
                walkingSound.Stop();
            }

            // Reduce delay per frame
            if (ThrowingDelay > 0)
            {
                ThrowingDelay -= 1;
            }


            // Throw rock
            if (input.IsButtonPressed(Input.Button.Throw))
            {
                if (ThrowingDelay <= 0)
                {
                    // Spawn rock and play sound
                    var rock = new Rock(MonoGearGame.FindEntitiesOfType <Player>()[0].Collider);
                    rock.Position = Position;
                    rock.Rotation = Rotation;
                    MonoGearGame.SpawnLevelEntity(rock);
                    ThrowingDelay = 45;
                    var sound = MonoGearGame.GetResource <SoundEffect>("Audio/AudioFX/StoneTrow_sound").CreateInstance();
                    sound.Volume = 1 * SettingsPage.Volume * SettingsPage.EffectVolume;
                    sound.Play();
                }
            }

            // Shoot sleep dart
            if (input.IsButtonPressed(Input.Button.Shoot))
            {
                if (DartCount > 0)
                {
                    // Spawn dart and play sound
                    var sleepDart = new SleepDart(MonoGearGame.FindEntitiesOfType <Player>()[0].Collider);
                    sleepDart.Position = Position;
                    sleepDart.Rotation = Rotation;
                    MonoGearGame.SpawnLevelEntity(sleepDart);
                    DartCount--;
                    var sound = MonoGearGame.GetResource <SoundEffect>("Audio/AudioFX/Blowgun").CreateInstance();
                    sound.Volume = 1 * SettingsPage.Volume * SettingsPage.EffectVolume;
                    sound.Play();
                }
            }


            // Check collisions
            if (input.IsKeyDown(Keys.N))
            {
                // Noclip mode for debugging
                Position += delta * (float)gameTime.ElapsedGameTime.TotalSeconds * 10;
            }
            else
            {
                // Check collisions per axis
                var prevPos = Position;
                var deltaX  = new Vector2(delta.X, 0);
                var deltaY  = new Vector2(0, delta.Y);

                Position += deltaX * (float)gameTime.ElapsedGameTime.TotalSeconds;
                if (Collider.CollidesAny())
                {
                    // Reset if we hit anything
                    Position = prevPos;
                }
                prevPos   = Position;
                Position += deltaY * (float)gameTime.ElapsedGameTime.TotalSeconds;
                if (Collider.CollidesAny())
                {
                    // Reset if we hit anything
                    Position = prevPos;
                }
            }

            // Camera tracks player
            Camera.main.Position = new Vector2(Position.X, Position.Y);
        }