2

I have found a pretty strange thing while coding an Asteroid Destroyer minigame using MonoGame with Visual Studio 2017. In the LoadContent() method I load the textures for my spaceship in a list of Sprites which is created on the spot. Then this list is fed into the Spaceship constructor so that the spaceship gets its textures. The code is as follows:

protected override void LoadContent()
        {
            spriteBatch = new SpriteBatch(GraphicsDevice);

            List<Sprite> spaceship1Sprites = new List<Sprite>
            {
                new Sprite(Content, "Spaceship1On"),
                new Sprite(Content, "Spaceship1Off"),
                new Sprite(Content, "Bullet1")
            };

            spaceship1 = new Spaceship(spaceship1Sprites, new Vector2(graphics.GraphicsDevice.DisplayMode.Width / 2, graphics.GraphicsDevice.DisplayMode.Height / 2))
            {
                Controls = new Input(Keys.W, Keys.D, Keys.A, Keys.Space)
            };
        }

The strange thing is that, if after running the program once, I delete the lines in which the Sprite list is defined,

            //List<Sprite> spaceship1Sprites = new List<Sprite>
            //{
            //    new Sprite(Content, "Spaceship1On"),
            //    new Sprite(Content, "Spaceship1Off"),
            //    new Sprite(Content, "Bullet1")
            //};

the program will still run, even though the list is not defined anywhere else in the program and the Spaceship constructor should be getting an unexistent list as its first parameter. How can this still work?

This is not something that is preventing me from making my program work, but I would still like to know what is the cause so that I know a little bit more about how C# works.

Edit: Adding the rest of the code in the Game1 class. The Spaceship class does not contain the list spaceship1Sprites, it has three fields for the three sprites, which are loaded in the constructor.

using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using System;
using System.Collections.Generic;
using System.IO;

namespace Asteroid_Destroyer
{
    public class Game1 : Game
    {
        public static GraphicsDeviceManager graphics;
        SpriteBatch spriteBatch;

        KeyboardState currentKeyboardState, previousKeyboardState;
        bool paused = false;

        Spaceship spaceship1;

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

        protected override void Initialize()
        {
            //Change screen resolution
            graphics.PreferredBackBufferWidth = graphics.GraphicsDevice.DisplayMode.Width;
            graphics.PreferredBackBufferHeight = graphics.GraphicsDevice.DisplayMode.Height;
            graphics.IsFullScreen = true;
            graphics.HardwareModeSwitch = false; //fullscreen borderless
            graphics.ApplyChanges();

            base.Initialize();
        }

        protected override void LoadContent()
        {
            spriteBatch = new SpriteBatch(GraphicsDevice);

            List<Sprite> spaceship1Sprites = new List<Sprite>
            {
                new Sprite(Content, "Spaceship1On"),
                new Sprite(Content, "Spaceship1Off"),
                new Sprite(Content, "Bullet1")
            };

            spaceship1 = new Spaceship(spaceship1Sprites, new Vector2(graphics.GraphicsDevice.DisplayMode.Width / 2, graphics.GraphicsDevice.DisplayMode.Height / 2))
            {
                Controls = new Input(Keys.W, Keys.D, Keys.A, Keys.Space)
            };
        }

        protected override void UnloadContent()
        {
            // TODO: Unload any non ContentManager content here
        }

        protected override void Update(GameTime gameTime)
        {
            currentKeyboardState = Keyboard.GetState();

            if (currentKeyboardState.IsKeyDown(Keys.Escape))
                Exit();

            if(currentKeyboardState.IsKeyDown(Keys.P) && previousKeyboardState.IsKeyUp(Keys.P))
                paused = paused ? false : true;

            if (!paused)
                spaceship1.Update();

            base.Update(gameTime);
            previousKeyboardState = currentKeyboardState;
        }

        protected override void Draw(GameTime gameTime)
        {
            GraphicsDevice.Clear(Color.Black);

            spriteBatch.Begin();
            spaceship1.Draw(spriteBatch);
            spriteBatch.End();

            base.Draw(gameTime);
        }
    }
}

Edit 2: Solved! As expected, it wasn't something about the code but about what Visual Studio was running. Somehow my Visual Studio configuration let the previous working version run if there is an error in the current build... But I have already found the setting to change this, so mystery solved!

Nordellak
  • 41
  • 6
  • 1
    Given that the code woudn't compile if you indeed comment out the stated lines, then a) `spaceship1Sprites` is defined in a wider scope, or b) your example is not what you really did, or is incomplete. Please extend the code you posted. – Jens Aug 12 '18 at 14:05
  • @Jens I have added the complete code. I can also add the contents of the `Spaceship` class if needed, but it doesn't have any trace of the list `spaceship1Sprites` appart from it being a parameter in the constructor. – Nordellak Aug 12 '18 at 20:16
  • I have discovered that in Visual Studio I can "Run" the code (F5) or "Compile the solution" (Ctrl+Shift+B). When compiling it doesn't work, as expected, but pressing "Run" works, as if it didn't compile it beforehand and it used some old version of the program. If this is the case, then I don't understand why most changes are applied when I "Run" the program, but some aren't applied (such as the elimination of the sprite list). – Nordellak Aug 12 '18 at 20:55
  • I have found what was causing this! I have writtent he explanation in the second edit. – Nordellak Aug 12 '18 at 21:10
  • 1
    Good on ya. You can also write an answer to your own question and mark it as solved. – Jens Aug 12 '18 at 21:22

1 Answers1

1

Apparently there is an option in the settings which enables Visual Studio to run a previous working build of the project if there is an error, which was enabled by default in my installation (unless I had inadvertedly enabled the option by mistake).

I found the solution thanks to this answer in another question while trying to investigate the issue:

Try changing this value:

  • Tools
    • Options
      • Projects and Solutions
        • Build and Run
          • On Run, when build or deployment errors occur: Do not Launch
Nordellak
  • 41
  • 6
  • 1
    When you first install Visual Studio it will prompt for this setting the first time you have a build error. If you accidentally click the checkbox when this dialog pops up it won't pop up again. I've done it a few times myself. Super annoying. – craftworkgames Aug 15 '18 at 06:47
  • I wasn't aware of that! I will take it into account for the next time I have to reinstall Visual Studio. – Nordellak Aug 16 '18 at 08:42