-1
\$\begingroup\$

looking for a quick code example (im a visual guy) and this is getting a little confusing/frustrating.

Because im a very "modular" kind of guy, I like to split my code up into logical files as often as possible, and all examples in the XNA tutorials led me into a small funk as all I ever did seemingly happened in the main .cs file save for my typical classes but all rendering takes in (example) Game1.cs so far.

I then heard about GameComponents and see they have the exact same structure as "Game1.cs", So I immediately set out to migrate my player code (it's not much) over to it, and it compiles correctly, but I honestly have NO idea how to implement the new component into my game.

So I made a new GameComponentCollection but when I try to add my new GameComponent class (extends DrawableGameComponent btw as you will see) with components.Add it simply tells me that I cannot.

Im not sure where to go from here to be honest, MSDN is useless with this topic (theres no documentation nor examples) and thread after thread has lead to very elaborate and very strange places that I would rather not get into. This seems like it should be a very simple concept, please correct me if im wrong here:

  1. You create a new GameComponentCollection manager
  2. You add your GameComponents and DrawableGameComponents to the manager
  3. You do something with the manager (I'm not sure at this point, iterate through and call their updates?)

Need some help, heres my source code to this

Game1.cs

using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;
using System.Diagnostics;

namespace TestGame1
{
    /// <summary>
    /// This is the main type for your game
    /// </summary>
    public class Game1 : Microsoft.Xna.Framework.Game
    {
        GameComponentCollection components;
        DrawableGameComponent player;
        GraphicsDeviceManager graphics;
        SpriteBatch spriteBatch;


        public Game1()
        {
            graphics = new GraphicsDeviceManager(this);
            Content.RootDirectory = "Content";
            player = new GC_Player( this );
            components.Add(player); // DOESN'T WORK. NullReferenceException


        }

        /// <summary>
        /// Allows the game to perform any initialization it needs to before starting to run.
        /// This is where it can query for any required services and load any non-graphic
        /// related content.  Calling base.Initialize will enumerate through any components
        /// and initialize them as well.
        /// </summary>
        protected override void Initialize()
        {
            // TODO: Add your initialization logic here

            base.Initialize();

        }

        /// <summary>
        /// LoadContent will be called once per game and is the place to load
        /// all of your content.
        /// </summary>
        protected override void LoadContent()
        {

            // Create a new SpriteBatch, which can be used to draw textures.
            spriteBatch = new SpriteBatch(GraphicsDevice);

            // TODO: use this.Content to load your game content here
        }

        /// <summary>
        /// UnloadContent will be called once per game and is the place to unload
        /// all content.
        /// </summary>
        protected override void UnloadContent()
        {
            // TODO: Unload any non ContentManager content here
        }

        /// <summary>
        /// Allows the game to run logic such as updating the world,
        /// checking for collisions, gathering input, and playing audio.
        /// </summary>
        /// <param name="gameTime">Provides a snapshot of timing values.</param>
        protected override void Update(GameTime gameTime)
        {
            // Allows the game to exit
            if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed)
                this.Exit();

            // TODO: Add your update logic here


            base.Update(gameTime);
        }



        /// <summary>
        /// This is called when the game should draw itself.
        /// </summary>
        /// <param name="gameTime">Provides a snapshot of timing values.</param>
        protected override void Draw(GameTime gameTime)
        {
            GraphicsDevice.Clear(Color.CornflowerBlue);
            spriteBatch.Begin();


            spriteBatch.End();
            // TODO: Add your drawing code here

            base.Draw(gameTime);
        }
    }
}

GC_Player.cs

using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;


namespace TestGame1
{
    /// <summary>
    /// This is a game component that implements IUpdateable.
    /// </summary>
    public class GC_Player : Microsoft.Xna.Framework.DrawableGameComponent
    {

        King theKing;
        SpriteBatch spriteBatch;

        public GC_Player(Game game)
            : base(game)
        {
            // TODO: Construct any child components here
            // Make THE KING.
            theKing = new King();
        }

        /// <summary>
        /// Allows the game component to perform any initialization it needs to before starting
        /// to run.  This is where it can query for any required services and load content.
        /// </summary>
        public override void Initialize()
        {
            // TODO: Add your initialization code here

            base.Initialize();
        }

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

            theKing.Sprite = Game.Content.Load<Texture2D>("King");
        }


        /// <summary>
        /// Allows the game component to update itself.
        /// </summary>
        /// <param name="gameTime">Provides a snapshot of timing values.</param>
        public override void Update(GameTime gameTime)
        {
            // TODO: Add your update code here

            UpdateSprite(gameTime);

            base.Update(gameTime);
        }


        void UpdateSprite(GameTime gameTime)
        {
            //spritePosition += spriteSpeed * (float)gameTime.ElapsedGameTime.TotalSeconds;
            //theKing.Position = theKing.Position += theKing.Speed * (float)gameTime.ElapsedGameTime.TotalSeconds;


            //int MaxX = Game.graphics.GraphicsDevice.Viewport.Width - theKing.SpriteWidth;
            int MinX = 0;
            //int MaxY = Game.graphics.GraphicsDevice.Viewport.Height - theKing.SpriteHeight;
            int MinY = 0;


            if (Keyboard.GetState().IsKeyDown(Keys.Down))
            {
                theKing.SpeedVertical += theKing.AccelerationVertical;
            }
            if (Keyboard.GetState().IsKeyDown(Keys.Up))
            {
                theKing.SpeedVertical -= theKing.AccelerationVertical;
            }
            if (Keyboard.GetState().IsKeyDown(Keys.Right))
            {
                theKing.SpeedHorizontal += theKing.AccelerationHorizontal;
            }

            if (Keyboard.GetState().IsKeyDown(Keys.Left))
            {
                theKing.SpeedHorizontal -= theKing.AccelerationHorizontal;
            }
            if (Keyboard.GetState().IsKeyUp(Keys.Down) && Keyboard.GetState().IsKeyUp(Keys.Up))
            {
                if (theKing.SpeedVertical > 0)
                {
                    theKing.SpeedVertical -= theKing.AccelerationVertical;
                }
                else if (theKing.SpeedVertical < 0)
                {
                    theKing.SpeedVertical += theKing.AccelerationVertical;
                }
            }
            if (Keyboard.GetState().IsKeyUp(Keys.Left) && Keyboard.GetState().IsKeyUp(Keys.Right))
            {
                if (theKing.SpeedHorizontal > 0)
                {
                    theKing.SpeedHorizontal -= theKing.AccelerationHorizontal;
                }
                else if (theKing.SpeedHorizontal < 0)
                {
                    theKing.SpeedHorizontal += theKing.AccelerationHorizontal;
                }
            }



        }

        public override void Draw(GameTime gameTime)
        {
            base.Draw(gameTime);
            spriteBatch.Begin();
            if (theKing.FlipSprite)
            {
                spriteBatch.Draw(theKing.Sprite, theKing.CalculatePosition, null, Color.White, 0, Vector2.Zero, 1, SpriteEffects.FlipHorizontally, 0);
            }
            else
            {
                spriteBatch.Draw(theKing.Sprite, theKing.Position, Color.White);
            }
            spriteBatch.End();
        }
    }
}

King.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Diagnostics;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;

namespace TestGame1
{
    class King
    {

        private String spriteRef;
        private Texture2D sprite;
        private Vector2 position;
        private Vector2 speed;
        private Vector2 maxSpeed;
        private Boolean flipSprite;
        private Vector2 accel;

        public String SpriteReference
        {
            get { return spriteRef; }
            set { spriteRef = value; }
        }
        public Texture2D Sprite
        {
            get { return sprite; }
            set { sprite = value; }
        }
        public int SpriteWidth
        {
            get { return sprite.Width; }
        }
        public int SpriteHeight
        {
            get { return sprite.Height; }
        }

        public Vector2 Position
        {
            get { return position; }
            set { position = value; }
        }
        public float PositonHorizontal
        {
            get { return position.X; }
            set { position.X = value; }
        }
        public float PositionVertical
        {
            get { return position.Y; }
            set { position.Y = value; }
        }

        public Vector2 CalculatePosition
        {
            get
            {
                //Trace.WriteLine("Hor: " + SpeedHorizontal);
                //Trace.WriteLine("Ver: " + SpeedVertical);
                if (SpeedHorizontal != 0 || SpeedVertical != 0)
                {
                    if (SpeedHorizontal != 0)
                    {
                        if (SpeedHorizontal > 0 || SpeedHorizontal < 0)
                        {
                            position.X += SpeedHorizontal / 2;
                        }
                    }
                    if (SpeedVertical != 0)
                    {
                        if (SpeedVertical > 0 || SpeedVertical < 0)
                        {
                            position.Y += SpeedVertical / 2;
                        }
                    }
                }
                return Position;
            }
        }

        public Vector2 Speed
        {
            get { return speed; }
            set { speed = value; }
        }
        public float SpeedHorizontal
        {
            get { return speed.X; }
            set { speed.X = value; }
        }
        public float SpeedVertical
        {
            get { return speed.Y; }
            set { speed.Y = value; }
        }
        public Vector2 MaxSpeed
        {
            get { return maxSpeed; }
            set { maxSpeed = value; }
        }
        public float MaxSpeedHorizontal
        {
            get { return maxSpeed.X; }
            set { maxSpeed.X = value; }
        }
        public float MaxSpeedVertical
        {
            get { return maxSpeed.Y; }
            set { maxSpeed.Y = value; }
        }

        public Vector2 Acceleration
        {
            get { return accel; }
            set { accel = value; }
        }
        public float AccelerationHorizontal
        {
            get { return accel.X; }
            set { accel.X = value; }
        }
        public float AccelerationVertical
        {
            get { return accel.Y; }
            set { accel.Y = value; }
        }


        public Boolean FlipSprite
        {
            get { return flipSprite; }
            set { flipSprite = value; }
        }




        public King()
        {
            SpriteReference = "King";
            Position = new Vector2(10.0f, 100.0f);
            Speed = new Vector2(0.0f, 0.0f);
            Acceleration = new Vector2(0.01f, 0.02f);
            FlipSprite = true;
        }

        public void FlipSpriteHorizontal() 
        {
            if (FlipSprite)
                FlipSprite = false;
            else 
                FlipSprite = true;
        }

    }
}
\$\endgroup\$
2
  • \$\begingroup\$ If you could remove all the source code that's not required for the question that would help a lot. It's sort of daunting at the moment. Remember, help us help you :) \$\endgroup\$
    – House
    Jul 19, 2012 at 3:41
  • \$\begingroup\$ hah every single time I've done that I've had to answer a mountain of questions of "what code am I hiding that could be crucial to solving the problem", so better to overendulge than withhold. At the same time this is very basic and rudamentry, just a single sprite to the screen that can be moved with keyboard input, but its THIS specific sprite that I'm trying to get delegated again. Not familiar enough with XNA to know what to avoid posting yet lol \$\endgroup\$ Jul 19, 2012 at 7:43

2 Answers 2

5
\$\begingroup\$

Base Game class already has GameComponentCollection in it and it handles calling updates and draws, so don't create new one and just use theirs.

http://msdn.microsoft.com/en-us/library/microsoft.xna.framework.game.components

By the way: I think the GameComponent is meant for more complex things then just game entities, for stuff like SceneGraphComponent (that would handle drawing of every SceneNode class) or NetworkingComponent (that would send and recieve queued packets)

\$\endgroup\$
1
  • \$\begingroup\$ You were absolutely correct, there is a Components already setup, I just .Add my instantiated player and Boom there he was all functional and everything. As far as I read about the subject, its entire idea is just a different way of handling game objects and scene management in a more "modular" sense. This method makes the most sense to me and I'm glad that I can see it working out the way it is in my head now. I appreciate it sir, thanks for informing me that this already exists (and in hindsight, makes sense that it does lol) \$\endgroup\$ Jul 19, 2012 at 7:49
0
\$\begingroup\$

By looking at your code, you need to initialize components first.

components = new GameComponentCollection();
\$\endgroup\$
1
  • \$\begingroup\$ You WERE indeed correct, initializing the components collection did in fact make the code compile again, and the sprite didnt show up (as expected). But before I got into creating my own initializers, updaters etc, Kikaimaru's answer got the sprite up and functional by taking away code and changing one line. Again technically you were absolutely correct, but the chosen answer just has to go to Kikaimaru for the solid answer to my lifes greatest challenge at this moment haha Thanks for your help man! \$\endgroup\$ Jul 19, 2012 at 7:52

You must log in to answer this question.

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