Sudden error in code

Hello all, I’ve been attempting to implement a 2D shooter game on Monogame. I wish to spawn my enemies vertically using the Y axis, but I get an error regarding the ‘public void’ and ‘enemies.count’ part of the code. Would someone be willing to help me out on this because I am not sure what is going wrong. Here is the code:


public void LoadEnemies()
            {
                int randY = random.Next(100, 400);

                if (spawn >= 1)
                {
                    spawn = 0;
                    if (enemies.Count() < 4)
                        enemies.Add(new Enemies(Content.Load<Texture2D>("Enemy1"), new Vector2(1100, randY)
                }
            
            }

If enemies is a List<T>, then Count is a property, not a method, which means it should be accessed without parentheses, like this:

if (enemies.Count < 4)

Also, you seem to be missing a few closing parentheses at the end of the line where you add the enemy. Here’s the method with those errors fixed:

public void LoadEnemies()
{
    int randY = random.Next(100, 400);

    if (spawn >= 1)
    {
        spawn = 0;
        if (enemies.Count < 4)
            enemies.Add(new Enemies(Content.Load<Texture2D>("Enemy1"), new Vector2(1100, randY)));
    }
}

Ah, thank you! that removed that problem. I was wondering now how am I able to fix the error about public void LoadEnemies and the last } in the bottom:

    public void LoadEnemies()
{
    int randY = random.Next(100, 400);

    if (spawn >= 1)
    {
        spawn = 0;
        if (enemies.Count < 4)
            enemies.Add(new Enemies(Content.Load<Texture2D>("Enemy1"), new Vector2(1100, randY)));
    }
}

You probably have a missing or extra brace somewhere in your code. If you post the whole file, I could help you find it.

Should I copy and paste my entire project + classes? or is there another way. Sorry, I’m kind of new here.

No worries. Easiest thing to do is just paste only the class file that contains the LoadEnemies method.

If you’re using Visual Studio, follow these steps:

  1. In the class file containing the LoadEnemies method, highlight the entire file by pressing Ctrl + A on your keyboard.
  2. Press Tab on your keyboard once to indent the entire code four spaces or one tab to the right.
  3. Copy the code using Ctrl + C.
  4. Paste it here in a post.
  5. Go back to Visual Studio and press Ctrl + Z or click Edit > Undo to undo the indentation and get your code back to normal.

The indentation is so that the code appears formatted correctly in a nice scrollable box on the forum, which uses Markdown, which will properly format any code indented by four spaces or one tab.

This is the class for my enemies. Would this suffice?

namespace Game1
{
    class Enemies
    {
        public Texture2D texture;

        public Vector2 position;
        public Vector2 velocity;

        public bool isVisible = true;


        Random random = new Random();
        int randX, randY;

        public Enemies(Texture2D newTexture, Vector2 newPosition)
          {
            texture = newTexture;
            position = newPosition;


            randY = random.Next(-4, 4);
            randX = random.Next(-4, -1);

            velocity = new Vector2(randX, randY);
           }

        public void Update(GraphicsDevice graphics)
        {
            position += velocity;


            if (position.Y <= 0 || position.Y >= graphics.Viewport.Height - texture.Height)
                velocity.Y = -velocity.Y; 

            if (position.X < 0 - texture.Width)
                isVisible = false;
        }

        public void Draw(SpriteBatch spriteBatch)
        {
            spriteBatch.Draw(texture, position, Color.White);
        }
    }
 }

The code file I need is the one that contains the LoadEnemies method, because that’s where the missing or extra brace would be. Is the LoadEnemies method in your Game1 class? If so, that’s the one I’ll need.

Game1 is the only thing I have that is related to that. Here it is:

namespace Game1
{
    /// <summary>
    /// This is the main type for your game.
    /// </summary>
    public class Game1 : Game
    {
        GraphicsDeviceManager graphics;
        SpriteBatch spriteBatch;
        List<Enemies> enemies = new List<Enemies>();
        Random random = new Random();

        // Screen Parameters
        int screenWidth;
        int screenHeight;

        //PLAYER PLANE
        private Texture2D _texture;
        private Vector2 _position;
        
        //BACKGROUNDS
        Scrolling scrolling1;
        Scrolling scrolling2;

        //BULLETS
        List<Bullets> bullets = new List<Bullets>();
        
        

        public Game1()
        {
            graphics = new GraphicsDeviceManager(this);
            Content.RootDirectory = "Content";
        }

        /// <summary>
        /// Allows the game to perform any initialization it needs to before starting to run.
        /// This is where it can query for any required services and load any non-graphic
        /// related content.  Calling base.Initialize will enumerate through any components
        /// and initialize them as well.
        /// </summary>
        protected override void Initialize()
        {
            // TODO: Add your initialization logic here

            base.Initialize();
        }

        /// <summary>
        /// LoadContent will be called once per game and is the place to load
        /// all of your content.
        /// </summary>
        protected override void LoadContent()
        {
            // Create a new SpriteBatch, which can be used to draw textures.
            spriteBatch = new SpriteBatch(GraphicsDevice);

            //SCREEN 
            {
                screenWidth = GraphicsDevice.Viewport.Width;
                screenHeight = GraphicsDevice.Viewport.Height;
            }

            //PLAYER

            {
                _texture = Content.Load<Texture2D>("Sprites/PlayPlane1");
                _position = new Vector2(350, 370);
            }
            
            //BACKGROUNDS
            {
                scrolling1 = new Scrolling(Content.Load<Texture2D>("Backgrounds/sky1"), new Rectangle(0, 0, 800, 900));
                scrolling2 = new Scrolling(Content.Load<Texture2D>("Backgrounds/sky2"), new Rectangle(0, 700, 800, 900));

            }
        }

        /// <summary>
        /// UnloadContent will be called once per game and is the place to unload
        /// game-specific content.
        /// </summary>
        protected override void UnloadContent()
        {
            // TODO: Unload any non ContentManager content here
        }

        /// <summary>
        /// Allows the game to run logic such as updating the world,
        /// checking for collisions, gathering input, and playing audio.
        /// </summary>
        /// <param name="gameTime">Provides a snapshot of timing values.</param>
        /// 

        float spawn = 0;
        private object myRectangle;

        protected override void Update(GameTime gameTime)
        {

            //KEYBOARD COMMANDS FOR PLAYER

            if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed || Keyboard.GetState().IsKeyDown(Keys.Escape))
                Exit();

            if (Keyboard.GetState().IsKeyDown(Keys.Left))
            {
                _position.X -= 3;
            }

            if (Keyboard.GetState().IsKeyDown(Keys.Right))
            {
                _position.X += 3;
            }

            if (Keyboard.GetState().IsKeyDown(Keys.Up))
            {
                _position.Y -= 3;
            }

            if (Keyboard.GetState().IsKeyDown(Keys.Down))
            {
                _position.Y += 3;
            }

           

            //SCROLLING BACKGROUNDS
            if (scrolling1.rectangle.Y + scrolling1.texture.Height <= 10)
                scrolling1.rectangle.Y = scrolling2.rectangle.Y + scrolling2.texture.Height;
            if (scrolling2.rectangle.Y + scrolling2.texture.Height <= 10)
                scrolling2.rectangle.Y = scrolling1.rectangle.Y + scrolling1.texture.Height;

            scrolling1.Update();
            scrolling2.Update();

            base.Update(gameTime);

            //BULLETS
            public void UpdateBullets()
            {
                foreach(Bullets bullet in bullets)
                {
                    bullet.position += bullet.velocity;
                    if (Vector2.Distance(bullet.position, spritePosition) > 500)
                        bullet.isVisible = false;
                }

                for(int i = 0; i < bullets.Count; i++)
                {
                    if (!bullets[i].isVisible)
                    {
                        bullets.RemoveAt(i);
                        i--;
                    }
                }

            }


            public void Shoot()
            {
                Bullets newBullet = new Bullets(Content.Load<Texture2D>("PlayerBullet/PlaneShoot"));
                newBullet = new Vector2((float)Math.Cos(),            }

            //ENEMIES

            public void LoadEnemies()
            {
                int randY = random.Next(100, 400);

                if (spawn >= 1)
                    {
                        spawn = 0;
                        if (enemies.Count < 4)
                            enemies.Add(new Enemies(Content.Load<Texture2D>("Enemy1"), new Vector2(1100, randY)));

                    }

                {


                }
            
            }

        }

        /// <summary>
        /// This is called when the game should draw itself.
        /// </summary>
        /// <param name="gameTime">Provides a snapshot of timing values.</param>
        protected override void Draw(GameTime gameTime)
        {
            GraphicsDevice.Clear(Color.CornflowerBlue);

            // TODO: Add your drawing code here

            spriteBatch.Begin();

            scrolling1.Draw(spriteBatch);
            scrolling2.Draw(spriteBatch);

            spriteBatch.Draw(_texture, _position, Color.White);

            spriteBatch.End();

            base.Draw(gameTime);
        }
    }
}

Thanks, that’s what I needed.

A number of your methods are declared within your Update method. This is valid if you’re using C# 7, which you are if you are using Visual Studio 2017, where methods declared within methods are known as “local functions” or “local methods”, which are only accessible from within the method in which they are declared. However, local functions cannot be declared public, so that is an error. See this documentation for information about local functions.

However, it’s more likely that you weren’t intending to declare them as local methods. To solve the problem, you’ll need to move the functions outside of the Update method so that they are in the same scope as the Update method, and then call them, as opposed to declaring them, from within the Update method.

The Shoot method also has some problems, with an incomplete initialization of a new Vector2, missing the second argument and closing parentheses and a semicolon.

Here’s the Game1 class with the errors I mentioned fixed:

namespace Game1
{
    /// <summary>
    /// This is the main type for your game.
    /// </summary>
    public class Game1 : Game
    {
        GraphicsDeviceManager graphics;
        SpriteBatch spriteBatch;
        List<Enemies> enemies = new List<Enemies>();
        Random random = new Random();

        // Screen Parameters
        int screenWidth;
        int screenHeight;

        //PLAYER PLANE
        private Texture2D _texture;
        private Vector2 _position;

        //BACKGROUNDS
        Scrolling scrolling1;
        Scrolling scrolling2;

        //BULLETS
        List<Bullets> bullets = new List<Bullets>();



        public Game1()
        {
            graphics = new GraphicsDeviceManager(this);
            Content.RootDirectory = "Content";
        }

        /// <summary>
        /// Allows the game to perform any initialization it needs to before starting to run.
        /// This is where it can query for any required services and load any non-graphic
        /// related content.  Calling base.Initialize will enumerate through any components
        /// and initialize them as well.
        /// </summary>
        protected override void Initialize()
        {
            // TODO: Add your initialization logic here

            base.Initialize();
        }

        /// <summary>
        /// LoadContent will be called once per game and is the place to load
        /// all of your content.
        /// </summary>
        protected override void LoadContent()
        {
            // Create a new SpriteBatch, which can be used to draw textures.
            spriteBatch = new SpriteBatch(GraphicsDevice);

            //SCREEN 
            {
                screenWidth = GraphicsDevice.Viewport.Width;
                screenHeight = GraphicsDevice.Viewport.Height;
            }

            //PLAYER

            {
                _texture = Content.Load<Texture2D>("Sprites/PlayPlane1");
                _position = new Vector2(350, 370);
            }

            //BACKGROUNDS
            {
                scrolling1 = new Scrolling(Content.Load<Texture2D>("Backgrounds/sky1"), new Rectangle(0, 0, 800, 900));
                scrolling2 = new Scrolling(Content.Load<Texture2D>("Backgrounds/sky2"), new Rectangle(0, 700, 800, 900));

            }
        }

        /// <summary>
        /// UnloadContent will be called once per game and is the place to unload
        /// game-specific content.
        /// </summary>
        protected override void UnloadContent()
        {
            // TODO: Unload any non ContentManager content here
        }

        float spawn = 0;
        private object myRectangle;

        /// <summary>
        /// Allows the game to run logic such as updating the world,
        /// checking for collisions, gathering input, and playing audio.
        /// </summary>
        /// <param name="gameTime">Provides a snapshot of timing values.</param>
        protected override void Update(GameTime gameTime)
        {

            //KEYBOARD COMMANDS FOR PLAYER

            if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed || Keyboard.GetState().IsKeyDown(Keys.Escape))
                Exit();

            if (Keyboard.GetState().IsKeyDown(Keys.Left))
            {
                _position.X -= 3;
            }

            if (Keyboard.GetState().IsKeyDown(Keys.Right))
            {
                _position.X += 3;
            }

            if (Keyboard.GetState().IsKeyDown(Keys.Up))
            {
                _position.Y -= 3;
            }

            if (Keyboard.GetState().IsKeyDown(Keys.Down))
            {
                _position.Y += 3;
            }



            //SCROLLING BACKGROUNDS
            if (scrolling1.rectangle.Y + scrolling1.texture.Height <= 10)
                scrolling1.rectangle.Y = scrolling2.rectangle.Y + scrolling2.texture.Height;
            if (scrolling2.rectangle.Y + scrolling2.texture.Height <= 10)
                scrolling2.rectangle.Y = scrolling1.rectangle.Y + scrolling1.texture.Height;

            scrolling1.Update();
            scrolling2.Update();

            UpdateBullets();
            Shoot();
            LoadEnemies();

            base.Update(gameTime);
        }

        //BULLETS
        public void UpdateBullets()
        {
            foreach (Bullets bullet in bullets)
            {
                bullet.position += bullet.velocity;
                if (Vector2.Distance(bullet.position, spritePosition) > 500)
                    bullet.isVisible = false;
            }

            for (int i = 0; i < bullets.Count; i++)
            {
                if (!bullets[i].isVisible)
                {
                    bullets.RemoveAt(i);
                    i--;
                }
            }

        }

        public void Shoot()
        {
            Bullets newBullet = new Bullets(Content.Load<Texture2D>("PlayerBullet/PlaneShoot"));
            newBullet = new Vector2(); //This needs to be given a proper value
        }

        //ENEMIES

        public void LoadEnemies()
        {
            int randY = random.Next(100, 400);

            if (spawn >= 1)
            {
                spawn = 0;
                if (enemies.Count < 4)
                    enemies.Add(new Enemies(Content.Load<Texture2D>("Enemy1"), new Vector2(1100, randY)));

            }

            {


            }

        }

        /// <summary>
        /// This is called when the game should draw itself.
        /// </summary>
        /// <param name="gameTime">Provides a snapshot of timing values.</param>
        protected override void Draw(GameTime gameTime)
        {
            GraphicsDevice.Clear(Color.CornflowerBlue);

            // TODO: Add your drawing code here

            spriteBatch.Begin();

            scrolling1.Draw(spriteBatch);
            scrolling2.Draw(spriteBatch);

            spriteBatch.Draw(_texture, _position, Color.White);

            spriteBatch.End();

            base.Draw(gameTime);
        }
    }
}

Thank you so much for the help. Everything seems to be in working order right now. I’ll be sure to check through the link you’ve provided to me as well. I appreciate this quite a lot.

No problem. You can probably safely ignore that link, as local methods are a very recent C# feature, and I have yet to feel the need to use them.

I understand. I just have another error appearing it seems within the Game1 code. It’s this area that says spritePosition, would you happen to know also how to resolve this?

//BULLETS
        public void UpdateBullets()
        {
            foreach (Bullets bullet in bullets)
            {
                bullet.position += bullet.velocity;
                if (Vector2.Distance(bullet.position, spritePosition) > 500)
                    bullet.isVisible = false;
            }

You haven’t declared any field or variable named spritePosition. You’ll need to declare a Vector2 spritePosition variable somewhere and store some meaningful value in it.

Also, you may want to add some code to remove bullets either after they go offscreen or after they’ve been active for a certain amount of time. If they fly offscreen where they’re no longer doing anything, but stay in the list of bullets, then they’re going to end up wasting computer resources by being updated and drawn when they’re no longer relevant.

Would you be willing to post comments on my Game1 post above to show where I can implement the code to remove bullets, and where I should declare the field/variable for spritePosition? My knowledge is a bit limited.

It sounds like you could use a good tutorial to follow. I could certainly write one for a very basic scrolling ‘shmup’, but it would take time and I don’t have any know-how related to enemy movement patterns in these types of games. For removing bullets that are out of play, you would use code something like this:

//BULLETS
public void UpdateBullets()
{
    foreach (Bullets bullet in bullets)
    {
        bullet.position += bullet.velocity;
        if (Vector2.Distance(bullet.position, spritePosition) > 500)
            bullet.isVisible = false;
        //Check if bullet is off-screen
        if (bullet.position.X < 0 || bullet.position.Y < 0 ||
            bullet.position.X > screenWidth || bullet.position.Y > screenHeight)
            bullet.isVisible = false;
    }

    for (int i = 0; i < bullets.Count; i++)
    {
        if (!bullets[i].isVisible)
        {
            bullets.RemoveAt(i);
            i--;
        }
    }
}

But this code may result in the bullets suddenly disappearing right at the edge of the screen, and not once they are past the edge of the screen. One way to solve this problem is by using a buffer:

//Number of pixels bullet position must be past edges of screen to disappear
const int visibilityBuffer = 100;

foreach (Bullets bullet in bullets)
{
    bullet.position += bullet.velocity;
    if (Vector2.Distance(bullet.position, spritePosition) > 500)
        bullet.isVisible = false;
    //Check if bullet is off-screen
    if (bullet.position.X < -visibilityBuffer || 
        bullet.position.Y < -visibilityBuffer ||
        bullet.position.X > screenWidth + visibilityBuffer || 
        bullet.position.Y > screenHeight + visibilityBuffer)
        bullet.isVisible = false;
}

for (int i = 0; i < bullets.Count; i++)
{
    if (!bullets[i].isVisible)
    {
        bullets.RemoveAt(i);
        i--;
    }
}

This way, bullets only disappear once their position is more than 100 pixels past any of the edges of the screen.

How you declare spritePosition depends on what you intended it to store. Is it the location of the player’s ship?

I think it might be better that way. For the spritePosition, it would be for the player’s ship. Would you know how I can get that done, please? I’d also like to know how I can implement the keyboard button ‘spacebar’ to fire the bullet(s).

Only recommendation I would make (as you seem to be making progress) is to avoid using the Content Pipeline during runtime / update. You should be loading ALL content in advance, e.g. avoid the following:

Bullet should probably be it’s own class and load it’s texture on LoadContent for example. Then simply keep drawing “bullet” where you need it.

A good example of this can be found in the PlatformerExample in MonoGame.Samples (the coins) or the NeonShooter example also in MonoGame.Samples.

Might do a subject on good architecture like this on “The Darkside of MonoGame” in the future.