Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Designing Game Objects

Tags:

c#

oop

xna

I recently started working on a small game for my own amusement, using Microsoft XNA and C#. My question is in regards to designing a game object and the objects that inherit it. I'm going to define a game object as something that can be rendered on screen. So for this, I decided to make a base class which all other objects that will need to be rendered will inherit, called GameObject. The code below is the class I made:

class GameObject
{
    private Model model = null;
    private float scale = 1f;
    private Vector3 position = Vector3.Zero;
    private Vector3 rotation = Vector3.Zero;
    private Vector3 velocity = Vector3.Zero;
    private bool alive = false;
    protected ContentManager content;

    #region Constructors
    public GameObject(ContentManager content, string modelResource)
    {
        this.content = content;
        model = content.Load<Model>(modelResource);
    }
    public GameObject(ContentManager content, string modelResource, bool alive)
        : this(content, modelResource)
    {
        this.alive = alive;
    }
    public GameObject(ContentManager content, string modelResource, bool alive, float scale)
        : this(content, modelResource, alive)
    {
        this.scale = scale;
    }
    public GameObject(ContentManager content, string modelResource, bool alive, float scale, Vector3 position)
        : this(content, modelResource, alive, scale)
    {
        this.position = position;
    }
    public GameObject(ContentManager content, string modelResource, bool alive, float scale, Vector3 position, Vector3 rotation)
        : this(content, modelResource, alive, scale, position)
    {
        this.rotation = rotation;
    }
    public GameObject(ContentManager content, string modelResource, bool alive, float scale, Vector3 position, Vector3 rotation, Vector3 velocity)
        : this(content, modelResource, alive, scale, position, rotation)
    {
        this.velocity = velocity;
    }
    #endregion
}

I've left out extra methods that do things such as rotate, move, and draw the object. Now if I wanted to create another object, like a ship, I'd create a Ship class, which would inherit GameObject. Sample code below:

class Ship : GameObject
{
    private int num_missiles = 20; // the number of missiles this ship can have alive at any given time
    private Missile[] missiles;
    private float max_missile_distance = 3000f; // max distance a missile can be from the ship before it dies

    #region Constructors
    public Ship(ContentManager content, string modelResource)
        : base(content, modelResource)
    {
        InitShip();
    }
    public Ship(ContentManager content, string modelResource , bool alive)
        : base(content, modelResource, alive)
    {
        InitShip();
    }
    public Ship(ContentManager content, string modelResource, bool alive, float scale)
        : base(content, modelResource, alive, scale)
    {
        InitShip();
    }
    public Ship(ContentManager content, string modelResource, bool alive, float scale, Vector3 position)
        : base(content, modelResource, alive, scale, position)
    {
        InitShip();
    }
    public Ship(ContentManager content, string modelResource, bool alive, float scale, Vector3 position, Vector3 rotation)
        : base(content, modelResource, alive, scale, position, rotation)
    {
        InitShip();
    }
    public Ship(ContentManager content, string modelResource, bool alive, float scale, Vector3 position, Vector3 rotation, Vector3 velocity)
        : base(content, modelResource, alive, scale, position, rotation, velocity)
    {
        InitShip();
    }
    #endregion
}

Again, I've left out any extra Ship-specific methods, like firing a missile. Do you think that this sort of design is good or should it be improved somehow or changed completely? It seems like the constructors for child classes is messy, but maybe that's the only way to do it. I've never done anything like this and am wondering if I'm way off track.


Thanks to everyone that left an answer. They were all very helpful. There seems to be a general consensus that changing it around to use an MVC pattern would be best. I'm going to look further into exactly how to do that. I'll also be removing most of the constructors and will have just one constructor, because all of the arguments after modelResource aren't necessary to create the object, and they can all be changed later through method calls.

like image 883
Kobol Avatar asked Oct 07 '08 19:10

Kobol


People also ask

What are game objects in game design?

A game object generally represents a particular object or element in your game that can emit a sound, including characters, weapons, ambient objects, such as torches, and so on. In some cases, however, you may want to assign game objects to different parts of an in-game element.

What are game objects?

GameObjects are the fundamental objects in Unity that represent characters, props and scenery. They do not accomplish much in themselves but they act as containers for Components, which implement the real functionality. For example, a Light object is created by attaching a Light component to a GameObject.

What are objects in games called?

In pencil and paper games and computer and video games, an item is an object within the game world that can be collected by a player or, occasionally, a non-player character. These items are sometimes called pick-ups. Items are most often beneficial to the player character.


3 Answers

Personally I find the sheer number of constructors you have a little offputting, but that's your choice, nothing fundamentally wrong with it :)

With regards to the general strategy of deriving game objects from a common base, that's a pretty common way to do things. Standard, even. I've tended to start using something far more akin to MVC, with incredibly lightweight "model" game objects that contain only data.

Other common approaches I've seen in XNA include / things you may want to consider:

  • Implementation of an IRenderable interface rather than doing any render code in the base or derived classes. For instance, you may want game objects that are never rendered - waypoints or somesuch.
  • You could make your base class abstract, you're not likely to want to ever instantiate a GameObject.

Again though, minor points. Your design is fine.

like image 190
NM. Avatar answered Oct 12 '22 23:10

NM.


Not only is the number of constructors a potential issue (especially having to re-define them for each derived class) - but the number of parameters to the constructor can become an issue. Even if you make the optional parameters nullable, it becomes difficult to read and maintain the code later.

If I write:

new Ship(content, "resource", true, null, null, null, null);

What does the second NULL do?

It makes code more readable (but more verbose) to use a structure to hold your parameters if the parameter list goes beyond four or five parameters:

GameObjectParams params(content, "resource");
params.IsAlive = true;
new Ship(params);

There are a lot of ways this can be done.

like image 32
Jeff B Avatar answered Oct 12 '22 22:10

Jeff B


Since you are asking a design-related question, I will try to give some hints on that, rather than on the lots of code you posted, because others have already started on that.

Games lend themselves very much to the Model-View-Controller pattern. You are explicitly talking about the display part, but think about it: you have vectors in there, etc., and that usually is part of what you are modelling. Think of the game world and the objects in there as the models. They have a position, they might have velocity and direction. That's the model part of MVC.

I noticed your wish to have the ship fire. You will probably want the mechanic to make the ship fire in a controller class, something that takes keyboard input, for example. And this controller class will send messages to the model-part. A sound and easy think you will probably want is to have some fireAction()-method on the model. On your base-model, that might be an overridable (virtual, abstract) method. On the ship it might add a "bullet" to the game world.

Seeing how I wrote about behaviour of your model so much already, here's another thing that has helped me plenty: use the strategy pattern to make behaviour of classes exchangeable. The strategy pattern is also great if you think AI and want behaviour to change somewhen in the future. You might not know it now, but in a month you might want ballistic missiles as the default missiles and you can easily change that later if you had used the strategy pattenr.

So eventually you might want to really make something like a display class. It will have primitives like you named: rotate, translate, and so on. And you want to derive from it to add more functionality or change functionality. But think about it, once you have more than a ship, a special kind of ship, another special kind of ship, you'll run into derivation hell and you will replicate a lot of code. Again, use the strategy pattern. And remember to keep it simple. What does a Displayble class need to have?

  • Means to know its position relative to the screen. It can, thanks to the model of its in-world object and something like the gameworld's model!
  • It must know of a bitmap to display for its model and its dimensions.
  • It must know if anything should prevent it from drawing, if that is not handled by the drawing engine (i.e. another object occluding it).
like image 26
mstrobl Avatar answered Oct 12 '22 22:10

mstrobl