1
\$\begingroup\$

I'm trying out Monogame because my course has a simple game programming class in it which is just going over basics. The final project will be using Monogame so I've been getting ahead and making my game.

Anyway, each player (Tank) has a list of Shells (bullets) and a list of Tracks (tank tracks). I load their content in the player's LoadContent method. LoadContent is called when the game is ran.

Let's say I wanted to add a new player sometime later in the game for whatever odd reason. I would do something along the lines of:

 entityManager.Add(new Player("Player Name", resourceManager.GetTexture("BlueTank")) 
 { 
      set initial position and keybinds here,
 };

This successfully creates a new player and loads its texture but what about its bullets textures, sound effects, track textures etc... Since LoadContent only gets called once at the start the code below will not run.

Example of the player's LoadContent method:

 // Match the players bullets with the players colour
 switch (Texture.Tag)
 {
      case "BlueTank":
           shellTexture = resourceManager.GetTexture("BlueShell");
           break;
      case "DarkTank":
           shellTexture = resourceManager.GetTexture("DarkShell");
           break;
 }

 // After this I use the resourceManager to set private Texture2D's and sound effects for the bullets, tracks and player.

 // e.g.
 trackTexture = resourceManager.GetTexture("Track");

When I finally shoot a bullet I set the bullets texture and sound effect properties to the private ones in the player.

When a player dies I currently just set their IsActive bool to false and the entity manager will remove them completely so I'm stuck on how to load content again.

I feel like I'm overthinking this but I can't seem to find a clean and simple way to get this done. Also I'm bad at explaining things hopefully this isn't too much of a mess.

Edit: Would it be a bad idea to pass the resource manager in the players constructor and just create a method for loading that is called in the players constructor? That way when a player is created the content is loaded for that player. It's only a small game for a basic school project. I could potentially do all the content setting outside of the player itself and in the GameplayState by looping through unloaded entities or something.

\$\endgroup\$

2 Answers 2

1
\$\begingroup\$

The way how I see and use Loadcontent is likely different than yours. But I prefer to use loadcontent to load all the content at once, on different variables each. If it's a small game, then performance doesn't matter much.

When you're loading content, then that content is ready to be used. but the draw method decides when the content should be visible on the screen.

So instead of using LoadContent to change textures, I use a different method to set these variables to their right object.

For example:

public Texture blueShellTexture = new Texture();
public Texture darkShellTexture = new Texture();
public Texture shellTexture = new Texture();   //the texture that chooses the right texture

Loadcontent () {
    blueShellTexture = resourceManager.GetTexture("BlueShell");
    darkShellTexture = resourceManager.GetTexture("DarkShell");
}

Then I can use a different method (or property) to set the texture:

public void setShelltexture () {
    switch (Texture.Tag)
    {
        case "BlueTank":
           shellTexture = blueShellTexture;
           break;
        case "DarkTank":
           shellTexture = darkShellTexture;
           break;
    }
}

As for your isActive bool, you can use a method that changes all values to their base values, and call that method when you restart the game, so the tank will 'reset' itself. For example:

public reset(){
    isActive = true;
    lives = 3;
    //add move default values here...
}

I hope this helps you out.

\$\endgroup\$
1
  • \$\begingroup\$ Currently I'm creating the ResourceManager (based off a tutorial I found) with a list of "Resources" that contain an image key, type and path. I just SetContent on state load/change so I don't need to worry about actually loading those just setting them. So in the GameplayState should I be storing each of the shell textures then just set them in the player using the example method you provided? I would have to change it slightly since the player wouldn't know that those textures exist without passing them to the setShellTexture method \$\endgroup\$ Oct 11, 2018 at 13:20
0
\$\begingroup\$

When the size of the assets in your game is manageable, then you should consider to just load every single asset at game start and keep all of it in memory while the game is running. That really saves you a lot of headache which would otherwise be caused if you try to load assets while the game is running.

But there are also some good reasons why you would not want to do this:

  • You want to keep your initial loading time as short as possible.
  • You have more assets than you can fit into RAM.
  • You don't know about all assets at game start, for example because your game loads user-generated assets from the Internet.

When I read between the lines of the question, then I do not get the impression that any of these reasons apply here. But if they do, then you might want to use a resourceManager which keeps track of which assets are already loaded. When the asset is already loaded, it just returns the copy from memory. When the asset is not yet loaded, then there are multiple possible solution, ranging from simple but crude to complex but elegant:

  • Block until the asset is loaded. This is easy to do, but might result in some notable stuttering whenever a new object with unloaded assets appears in the game.
  • Return a placeholder asset (like an empty image) which then gets replaced with the actual asset as soon as it is loaded.
  • Never return an asset. Have the caller pass a callback-function. As soon as the asset is ready, the callback-function is called with the asset as an argument.
\$\endgroup\$

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .