Darthmarshie
Darthmarshie

Reputation: 87

Can't initialize child of parent class properly in C# and XNA

I found this website while looking for a solution to my problem, I was wondering if anyone could please help me try and solve my predicament.

I'm using XNA and C# to create something where the user is able to assemble cars from parts they choose at random. The car doesn't have to have 4 wheels and a windshield. It just needs to consist of at least 7 parts that the user chooses. I've created a class called "Car", which will create all 7 instances of the parts that the user has chosen. These parts are of class, "CarPart". I've also created two separate subclasses of "CarPart" called "Wheel" and "Windshield". I intend to expand on these parts later, for example adding "Door" and "Trunk" etc.

So what I do is in my Car class, I declare 7 objects of type "CarPart" and then declare them as new Windshield(). or new Wheel().

But then when I try and access the initialize function of the Windshield or Wheel class, it only allows me to access the initialize function of the parent "CarPart" class.

Am I trying to do this the right way, or should I find another way around the problem?

I've also tried using Virtual and Override to try and overload the functions, but I can't seem to get that to work properly either, it just says, "Cannot find suitable method to overload".

I've included my code for the classes.

Any help at all would be amazing, I've been stuck for days and I can't move on with my project without getting the function of the user being able to assemble cars as they wish without this.

I've found something similar to what I'm trying to do at this link, but I can't seem to get it to work. http://csharp-station.com/Tutorial/CSharp/Lesson09

I'm sure I'm doing something stupid that I can't see because I've been staring at the same problem for too long.

Car class:

namespace TestGame4
{
    class Car
    {
        //Car consists of 7 CarParts chosen by the user//
        //e.g.: 

        CarPart Part1, Part2, Part3, Part4, Part5, Part6, Part7; 

        public void Initialize(CarPart part1, CarPart part2, CarPart part3, CarPart part4, CarPart part5, CarPart part6, CarPart part7)
        {
            Part1 = part1;
            Part2 = part2;
            Part3 = part3;
            Part4 = part4;
            Part5 = part5;
            Part6 = part6;
            Part7 = part7;       

            ***//This is the part that doesn't work how I want it to. I want it to initialize 
            //as a Windshield class, but it's only initializing as a CarPart class//***
            part1.Initialize(

        }
    }
}

CarPart class:

namespace TestGame4
{
    public class CarPart
    {
        public void Initialize(string assetName, Vector2 Position)
        {

        }
    }
}

Windshield class:

namespace TestGame4
{
    public class Windshield : CarPart
    {
        public void Initialize(Vector2 Position)
        {

        }
    }
}

Wheel class:

namespace TestGame4
{
    public class Wheel : CarPart
    {
        public void Initialize(Vector2 Position)
        {

        }
    }
}

My main Game1 class where I initialize the Car class and try to set it up with the Windshield and Wheel classes as parameters:

namespace TestGame4
{
    /// <summary>
    /// This is the main type for your game
    /// </summary>
    public class Game1 : Microsoft.Xna.Framework.Game
    {
        GraphicsDeviceManager graphics;
        SpriteBatch spriteBatch;
        Car myCar;

        public Game1()
        {
            graphics = new GraphicsDeviceManager(this);
            Content.RootDirectory = "Content";
        }

        /// <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

            myCar = new Car();
            myCar.Initialize(new Windshield(), new Wheel(), new Windshield(), new Wheel(), new Windshield(), new Wheel(), new Windshield());           

            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);

            // TODO: Add your drawing code here

            base.Draw(gameTime);
        }
    }
}

I would be immensely grateful for any help I get! Thanks in advance!

Upvotes: 0

Views: 787

Answers (1)

Aneri
Aneri

Reputation: 1352

Your Windshield and Wheel are both descendants of CarPart. For the Car class they are just CarPart (as defined), so Car does not know whether any of them is Wheel or Windshield. Not at compile time, at least.

To resolve the issue you need to add an interface to these classes. Or add an abstract function in CarPart which is easier.

abstract class CarPart
{
   public abstract void Initialize(Vector2 position);
   public void Initialize(string assetName, Vector2 position)
   {
   }
}

After that both subclasses will need to override this function, otherwise they will be abstract too (abstract class can not be used to create objects).

Interfaces are quite simple: an interface is a behaviour you require from a class. For instance

interface IInitializable
{
   void Initialize (Vector2 position);
}
class WindShield: IIinitializable
{
   void Initialize (Vector2 position)
   {
      ...
   }
}

Then you can write in CarPart:

IInitializable [] parts = new IInitializable [7];
parts[0] = new WindShield();
...
parts[6] = new Wheel();

parts[3].Initialize(new Vector2(0, 0));

So all these parts comply to interface IInitializable and you can call the common method Initialize (Vector2). Interfaces are most usable when different unrelated classes implement same behaviour, like IQueryable or IDisposable and so on.

Upvotes: 1

Related Questions