How to conditionally load content and draw sprites?

Hello,

I recently got a screen multiplier code to work, so now I’m looking into how to actually draw stuff on screen. But the first issue is that I don’t know how to conditionally draw stuff on screen. Like, all of the sprites in the game are not going to be on screen at once. How do I decide which ones are drawn and which one aren’t? Also, how do I decide what content is loaded at any given time? You probably don’t need to have your gameplay assets loaded when you are sitting in title screen or something like that…
In case it is needed, here is what I have now:

public class Game1 : Game
{
    private GraphicsDeviceManager _graphics;
    private SpriteBatch _spriteBatch;
    private RenderTarget2D _nativeRenderTarget;
    private byte _windowMultiplier;
    private int _screenWidth;
    private int _screenHeight;

    public Game1()
    {
        _graphics = new GraphicsDeviceManager(this);
        Content.RootDirectory = "Content";
        IsMouseVisible = true;
    }

    protected override void Initialize()
    {
        _windowMultiplier = 2;
        _screenWidth = 640;
        _screenHeight = 480;
        Window.Position = new Point(
            (GraphicsAdapter.DefaultAdapter.CurrentDisplayMode.Width / 2) - (_screenWidth),
            (GraphicsAdapter.DefaultAdapter.CurrentDisplayMode.Height / 2) - (_screenHeight)
            );
        _nativeRenderTarget = new RenderTarget2D(GraphicsDevice, _screenWidth, _screenHeight);
        _graphics.IsFullScreen = false;
        _graphics.PreferredBackBufferWidth = _screenWidth * _windowMultiplier;
        _graphics.PreferredBackBufferHeight = _screenHeight * _windowMultiplier;
        _graphics.ApplyChanges();

        base.Initialize();
    }

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

    protected override void Update(GameTime gameTime)
    {
        if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed ||
            Keyboard.GetState().IsKeyDown(Keys.Escape))
            Exit();

        // TODO: Add your update logic here

        base.Update(gameTime);
    }

    protected override void Draw(GameTime gameTime)
    {
        GraphicsDevice.SetRenderTarget(_nativeRenderTarget);
        GraphicsDevice.Clear(Color.CornflowerBlue);
        
        // Apparently I'm supposed to draw stuff here, but how?
        
        GraphicsDevice.SetRenderTarget(null);
        _spriteBatch.Begin(samplerState: SamplerState.PointClamp);
        _spriteBatch.Draw(
            _nativeRenderTarget, 
            new Rectangle(
                0, 
                0, 
                GraphicsDevice.DisplayMode.Width * _windowMultiplier,
                GraphicsDevice.DisplayMode.Height * _windowMultiplier
                ),
            Color.White);
        _spriteBatch.End();
        
        base.Draw(gameTime);
    }
}

Start here: Understanding the Code | MonoGame Documentation

This doesn’t have anything that I didn’t already know. Like I said it’s about drawing multiple things, conditionally drawing things and loading content conditionally based on what is needed…

Treat RenderTarget2D as the “container”. First, render the stuff you want into that container, and then you need to render that container onto screen. For the loading content I’m not sure, cause I ususally load eveything at the start. I do simple 2D games, so I don’t worry about those 10MB more in RAM.

Note that RenderTarget2D is heavy, so you shouldn’t use a lot of them

// Draw into RenderTarget2D
GraphicsDevice.SetRenderTarget(customTarget);
spriteBatch.Begin( );
if (drawCondition) {
    spriteBatch.Draw(...);
    spriteBatch.Draw(...);
}
spriteBatch.End( );

// Draw container onto screen - so you need to set graphic's device render target to null
GraphicsDevice.SetRenderTarget(null);
spriteBatch.Begin( );
spriteBatch.Draw(customTarget2D, Vector2.Zero, Color.White);
spriteBatch.End();

What I do is I have multiple collections of game objects (a class that I define). I have a state property, something like this (overly simplified):

public class GameObject
{
    public enum ObjectStates
    {
       Dead,
       Idle,
       Moving
    }

    public float X;
    public float Y;
    public ObjectStates State;
}

private List<GameObject> GameObjectList = new List<GameObject>();

I then can add objects into that list at any time.

then in the Draw() method I can do:

foreach(var gameObject in GameObjectList)
{
    if (gameObject.State == ObjectStates.Dead)
    {
        continue;
    }

   // Draw the object here...
}

If your game has a “window” into the entire playfield (i.e. not a single game screen) then you can also optimize by checking to see if the game object is visible within that window, if it’s not, don’t draw it.