You seem to be confused with some OO aspects here. When you have a class such as:
class Meteor
{
}
You are describing a template for every meteor you are going to create. This will describe what a SINGLE meteor should contain. So, following that, what attributes should EACH meteor have?
class Meteor
{
Texture2D texture;
Rectangle bounds;
int fallSpeed;
double damage;
// x, y, WIDTH, HEIGHT are not needed here. That information can be obtained through the 'bounds' rectangle we have declared.
// List of meteor is not needed. Why would each meteor contain a list of meteors?
}
So, that describes what each meteor would need. We need a reference to a texture2D in order to draw each, we need a bounds to describe the rectangle that the meteor lies within, for collision and position. We have a damage for each( bigger meteors might have bigger damage. ). That's it. x, y, width, and height would be a waste of memory here, because we know those things from the bounds rectangle.
So, what does each meteor do? It can be drawn, it can be updated, and it can be constructed:
class Meteor
{
Texture2D texture;
Rectangle bounds;
int fallSpeed;
double damage;
public Meteor( Rectangle meteorBounds, int meteorFallSpeed, double meteorDamage,
Texture2D meteorTexture )
{
// We want to pass the bounds in as a parameter. This means, any one constructing
// a meteor will be able to tell us how big they want it to be.
bounds = meteorBounds;
// Same again, we want different meteors to have different fall speeds, so let
// that be descided by the owner of the object.
fallSpeed = meteorFallSpeed;
// Once again, decide the damage based on values that are passed in to us.
damage = meteorDamage;
// Pass in a reference. We do NOT want each meteor to allocate their own texture.
// We would run out of vram pretty quickly. When the level is loaded, or the game
// is started we load the texture. Then we pass it around to each meteor. This
// way, each meteor knows where the texture is, it doesn't have it's own copy.
texture = meteorTexture;
}
public void Update()
{
// Move the meteor down by the fall speed given to us in the constructor.
bounds.y += ( int )fallSpeed;
// No check for 'm' here. Why would a meteor create another meteor when 'm' is
// pressed?
}
public void Draw( SpriteBatch spriteBatch )
{
// Just draw the texture we have at the rectangle x and y.
spriteBatch.Draw( texture, new Vector2( bounds.x, bounds.y ), Color.White );
}
}
There we go. Our meteor should be fully functional. It can be constructed( with any height, speed, damage, and texture ), it can be updated( moves downwards at it's falling speed ), and it can be drawn at it's current location.
So, how do we get a bunch of them on screen now? Well, let's go back to the Game1 class. Here we want to do a few things; load our meteor texture, make our random object, make a list of meteors, make it so we can add one when the 'm' key is pressed:
public class Game1 : Microsoft.Xna.Framework.Game
{
GraphicsDeviceManager graphics;
SpriteBatch spriteBatch;
GraphicsDevice device;
// Here we want our random class, so we can generate random positions for our meteors
// just like the original code did.
Random random = new Random();
// Here we make the texture that will be loaded from a file somewhere. This will be
// the only one that is loaded. All others will just be a reference to this one.
Texture2D meteorTexture;
// This is our list of meteors in our game.
List<Meteor> meteors = new List<Meteor>();
private void CreateMeteor()
{
int size = random.Next( 0, 60 );
int fallSpeed = random.Next( 0, 10 );
// We add a new meteor to the list. We give it a random size, randome fallSpeed,
// and a damage based off the fall speed. The meteor texture we have already
// loaded is passed in.
meteors.Add( new Meteor( new Rectangle( Random.next( 0, 600 ), 0, size, size ),
fallSpeed, fallSpeed * 2, meteorTexture ) );
}
public Game1()
{
graphics = new GraphicsDeviceManager(this);
Content.RootDirectory = "Content";
}
protected override void Initialize()
{
base.Initialize();
}
protected override void LoadContent()
{
spriteBatch = new SpriteBatch(GraphicsDevice);
device = graphics.GraphicsDevice;
// Load our meteor texture. This is the only place in the game this should be
// done.
meteorTexture = Content.Load<Texture2D>("Sprites/meteor");
}
protected override void UnloadContent()
{
}
protected override void Update(GameTime gameTime)
{
if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed)
this.Exit();
if (Keyboard.GetState().IsKeyDown(Keys.M))
{
// If 'm' is down, we create a new meteor. Note that once this is working
// this is going to make a lot of meteors. That's another issue, though.
createMeteor();
}
// Here's something that was missing in the original code. It's not enough to
// update one meteor, we must update each of them.
foreach( Meteor meteor in meteors )
{
meteor.Update();
}
base.Update(gameTime);
}
protected override void Draw(GameTime gameTime)
{
device.Clear(Color.CornflowerBlue);
// Only call begin and end once. You never want to call this for every object you
// have.
spriteBatch.Begin();
// Once again we want to draw EACH meteor.
foreach( Meteor meteor in meteors )
{
// Draw every single meteor, and pass in spriteBatch.
meteor.Draw( spriteBatch );
}
spriteBatch.End();
base.Draw(gameTime);
}
}
Here in our Game1 class, we maintain a list of meteors. Every frame we update them ALL by looping through them. We do the same with drawing. When we construct, we pass in information that should vary between meteors.