I'm working on a SpaceWar-esque project to get comfortable with XNA. I have a Ship DrawableGameComponent and a Bullet DrawableGameComponent. The player's Ship is created at the start of the game, and the Bullets are created for each Ship as part of its constructor.

In my Ship constructor, I have the following code:

for (int i = 0; i < 5; i++)
    activeBullets[i] = new Bullet(game);

The relevant part of my Ship's shoot() function is as follows:

activeBullets[bullet].Visible = true;
activeBullets[bullet].Enabled = true;
activeBullets[bullet].position = this.position;

The first five times I shoot() (that is, once for each bullet object that the ship is allotted), there is lag that I think is due to the bullet sprite being loaded. I've tried setting Visible and Enabled to true in the ship constructor loop where the Bullets are instantiated, but the first-five-shots lag persists. Any shots beyond the first five are completely lag-free.

How do I load the Bullets properly ahead of time so that there is no lag on the first shots?

  • \$\begingroup\$ Load the bullet texture in LoadContent()? \$\endgroup\$ – BlueRaja - Danny Pflughoeft Jul 26 '11 at 4:16
  • \$\begingroup\$ Bullet's texture is loaded in bullet's LoadContent(). Shouldn't this happen when the Bullet() is instantiated, or barring that, Enable'd in the Ship constructor? \$\endgroup\$ – Bill Jul 26 '11 at 4:34
  • \$\begingroup\$ Sorry, should have read your post a bit closer. I'll post a real answer. \$\endgroup\$ – BlueRaja - Danny Pflughoeft Jul 26 '11 at 5:02

DrawableGameComponent's come with a certain amount of overhead - aside from the memory, every time you add a component to the collection it must be resorted (because components have a DrawOrder). You don't want to be constantly adding and removing components.

For this reason, you don't want Bullet to be a DrawableGameComponent. Instead, you should make something like a ProjectileManager, which loads all the projectiles (including their textures), and manages creating/destroying/updating/drawing them. This simultaneously solves your texture-loading problem, as the textures can (and should) be loaded only once, in LoadContent().

If this does not work, then the textures are not your problem, and we'll need more information to help you further.

  • 6
    \$\begingroup\$ +1; DrawableGameComponent is not intended to be used for things like bullets. \$\endgroup\$ – Riki Jul 26 '11 at 5:30
  • \$\begingroup\$ Maybe I'm understanding them incorrectly. I'm not creating and destroying bullets, just enabling/disabling an array of 5 of them. I don't need hundreds on screen at once, and I want to limit the amount of shots my player can fire at a time anyways. Besides, it only happens the first time each bullet is fired. Can I force the add/load to happen at the beginning of the game even though it's a DrawableGameComponent? I thought I was accomplishing this by instantiating/enabling them when the Ship is instantiated. \$\endgroup\$ – Bill Jul 26 '11 at 5:51
  • \$\begingroup\$ @Bill: You could do that, but it comes with the obvious limitation of only allowing five bullets on the screen at once; a much better solution would be to create a ProjectileManager class. In either case, LoadContent() is called after all components have been added to the collection (in Initialize()), before the game starts. Override it and load your content there. Store the texture in a private field. \$\endgroup\$ – BlueRaja - Danny Pflughoeft Jul 26 '11 at 5:56
  • \$\begingroup\$ This is just for a simple demo and I don't see the need to build an underlying framework that could support boatloads of entities at once. I doubt I'll ever have more than a dozen total entities (2 ships, 5 bullets each). I don't want more than 5 bullets per ship available, ever. In my main Game.cs Initialize(), there is the following code: myShip = new Ship(this);. Doesn't this call the Ship constructor, which in turn would call the Bullet constructor 5 times, and load all their textures in turn? \$\endgroup\$ – Bill Jul 26 '11 at 16:14
  • \$\begingroup\$ @Bill: Without the code, I have no idea. Try stepping through the code in a debugger. \$\endgroup\$ – BlueRaja - Danny Pflughoeft Jul 26 '11 at 16:24

It appears that my Update function was being called at least twice before anything was being displayed, and that even though the bullets were part of the collection they were becoming disabled before being drawn and thus textures not loaded (?!?).

By setting the lifetime (which is decremented once per Update, and when lifetime = 0 the bullets are no longer Visible/Enabled) of each Bullet to 3 or greater (this may vary depending on CPU speed?) when I instantiate the Bullets as part of the ship class, the textures are properly loaded at the beginning of the game.

I'm still not sure why manually setting them to Enabled/Visible at creation doesn't force the texture to be loaded.


Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.