1
\$\begingroup\$

Currently I loaded all my assets in XNA in the main Game class. What I want to achieve later is that I only load specific assets for specific levels (the game will consist of many levels). Here is how I load my main assets into the main class:

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

            plane = new Player(Content.Load<Texture2D>(@"Player/playerSprite"), 6, 8);
            plane.animation = "down";
            plane.pos = new Vector2(400, 500);
            plane.fps = 15;

            Global.currentPos = plane.pos;

            lvl1 = new Level1(Content.Load<Texture2D>(@"Levels/bgLvl1"), Content.Load<Texture2D>(@"Levels/bgLvl1-other"),
                new Vector2(0, 0), new Vector2(0, -600));

            CommonBullet.LoadContent(Content);
            CommonEnemyBullet.LoadContent(Content);
        }

        protected override void UnloadContent()
        {
        }

        protected override void Update(GameTime gameTime)
        {
            if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed)
                this.Exit();

            plane.Update(gameTime);
            lvl1.Update(gameTime);

            foreach (CommonEnemy ce in cel)
            {
                if (ce.CollidesWith(plane))
                {
                    ce.hasSpawn = false;
                }

                foreach (CommonBullet b in plane.commonBulletList)
                {
                    if (b.CollidesWith(ce))
                    {
                        ce.hasSpawn = false;
                    }
                }

                ce.Update(gameTime);
            }

            LoadCommonEnemy();

            base.Update(gameTime);
        }

        private void LoadCommonEnemy()
        {
            int randY = rand.Next(-600, -10);
            int randX = rand.Next(0, 750);

            if (cel.Count < 3)
            {
                cel.Add(new CommonEnemy(Content.Load<Texture2D>(@"Enemy/Common/commonEnemySprite"), 7, 2, "left", randX, randY));
            }

            for (int i = 0; i < cel.Count; i++)
            {
                if (!cel[i].hasSpawn)
                {
                    cel.RemoveAt(i);
                    i--;
                }
            }
        }

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

            spriteBatch.Begin();

            lvl1.Draw(spriteBatch);
            plane.Draw(spriteBatch);

            foreach (CommonEnemy ce in cel)
            {
                ce.Draw(spriteBatch);
            }

            spriteBatch.End();

            base.Draw(gameTime);
        }

I wish to load my players, enemies, all in Level1 class. However, when I move my player & enemy code into the Level1 class, the gameTime returns null. Here is my Level1 class:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Media;
using Microsoft.Xna.Framework.Input;
using SpaceShooter_Beta.Animation.PlayerCollection;
using SpaceShooter_Beta.Animation.EnemyCollection.Common;

namespace SpaceShooter_Beta.Levels
{
    public class Level1
    {
        public Texture2D bgTexture1, bgTexture2;
        public Vector2 bgPos1, bgPos2;
        public float speed = 5f;
        Player plane;

        public Level1(Texture2D texture1, Texture2D texture2, Vector2 pos1, Vector2 pos2)
        {
            this.bgTexture1 = texture1;
            this.bgTexture2 = texture2;
            this.bgPos1 = pos1;
            this.bgPos2 = pos2;
        }

        public void LoadContent(ContentManager cm)
        {
            plane = new Player(cm.Load<Texture2D>(@"Player/playerSprite"), 6, 8);
            plane.animation = "down";
            plane.pos = new Vector2(400, 500);
            plane.fps = 15;

            Global.currentPos = plane.pos;
        }

        public void Draw(SpriteBatch sb)
        {
            sb.Draw(bgTexture1, bgPos1, Color.White);
            sb.Draw(bgTexture2, bgPos2, Color.White);

            plane.Draw(sb);
        }

        public void Update(GameTime gt)
        {
            bgPos1.Y += speed; bgPos2.Y += speed;

            if (bgPos1.Y >= 600)
            {
                bgPos1.Y = -600;
            }

            if (bgPos2.Y >= 600)
            {
                bgPos2.Y = -600;
            }

            plane.Update(gt);
        }
    }
}

Of course when I did this, I delete all my player's code in the main Game class. All of that works fine (no errors) except that the game cannot start. The debugger says that plane.Update(gt); in Level 1 class has null GameTime, same thing with the Draw method in the Level class.

Please help, I appreciate for the time.

[EDIT] I know that using switch in the main class can be a solution. But I prefer a cleaner solution than that, since using switch still means I need to load all the assets through the main class, the code will be A LOT later on for each levels

\$\endgroup\$
  • \$\begingroup\$ Think of how level1, level2, level3... would be similar then construct a class to cater to that. Create another class whose job it is to possibly load and dispose these levels, and yet another to update and draw these level. \$\endgroup\$ – Dialock Aug 10 '13 at 16:09
1
\$\begingroup\$

Maybe you should look at

http://msdn.microsoft.com/en-us/library/microsoft.xna.framework.gamecomponent.aspx

or

http://msdn.microsoft.com/en-us/library/microsoft.xna.framework.drawablegamecomponent.aspx

Game components are class similar to the Game class, you add a game component to your game with

MyLevel1GameComponent level1 = new MyLevel1GameComponent();
Components.Add(level1);

Game component's loadcontent is automatically called when you do

Components.Add(level1);

and only when you do that. So you can load content only in the moment in the program when you need it. Draw and Update are automatically called each frame after you've executed the previous instruction (only if the property level1.Enabled for Update and level1.Visible for Draw are true).

That means you don't need to put level1.LoadContent(), level1.Update or level1.Draw() anywhere, the Game will take care of this for you.

\$\endgroup\$

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.