Jump to content

  • Log In with Google      Sign In   
  • Create Account


Class inheritance?


Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.

  • You cannot reply to this topic
12 replies to this topic

#1 Jaap85   Members   -  Reputation: 241

Like
0Likes
Like

Posted 29 December 2013 - 09:57 AM

Hello everybody,

 

It's been a while since i have visited this forum, good to see it is still so active.

 

I have recently picked up game programming again and i am currently working in C# (XNA). I try to create a simple flying shooter game (Raptor clone).

 

Right now i am implementing the enemies and i would like to know what the best programming standard is for implementing the different types of enemies. I have already created a class "Enemy" which holds all the functions and variables needed for the enemies (such as the movement function, etc.)

 

I will create different subtypes of enemies, which differ in (for example): image, speed, firing rate, hitpoints, and so on.

 

What is the best way to implement is? I was first thinking of creating a separate class for each enemy type, which inherits from the enemy class, but that might be cumbersome.

 

Another option could be to just use the enemy class and assign every enemy a type when it is constructed, then work with lots of switch statements in the class based on the enemy type.

 

Is this the best way? Or is there a better way to do this? I feel a better way should be possible, but i cant really figure out how yet.

 

Thank you in advance for your replies. 



Sponsor:

#2 SiCrane   Moderators   -  Reputation: 9559

Like
1Likes
Like

Posted 29 December 2013 - 10:27 AM

Another option is to load the enemy data from a data file. Then the constructor only needs to know the name of the file (or index into an archive, etc.).



#3 Jaap85   Members   -  Reputation: 241

Like
0Likes
Like

Posted 29 December 2013 - 10:43 AM

Thank you, i will look into that. I thought that such a method should exist but have never worked with if before. What is a good file format to use for such a file? XML? Any examples would be very much appreciated.



#4 phil_t   Crossbones+   -  Reputation: 3258

Like
0Likes
Like

Posted 29 December 2013 - 04:14 PM


I will create different subtypes of enemies, which differ in (for example): image, speed, firing rate, hitpoints, and so on.

 

All the examples you cite above can be accomplished with just a single enemy class. There's no custom functionality at all, so no need to create new classes that inherit from enemy (and even if there were, composition would probably be a better solution than inheritance).

 

Just create new instances of the Enemy class with the required information (image, speed, etc...) supplied in the constructor. You could load that data from a file (as SiCrane suggests), but that's functionality that could be added later - it doesn't enable anything new, it just makes it easier to add enemy types or modify enemies without making code changes.



#5 rpiller   Members   -  Reputation: 666

Like
2Likes
Like

Posted 30 December 2013 - 07:57 AM


Another option could be to just use the enemy class and assign every enemy a type when it is constructed, then work with lots of switch statements in the class based on the enemy type.

 

 

People seem to be overlooking this statement. Why do you need the switches? Is it because each enemy will behave differently? If so, then this will be where either inheritance or composition will take place. Inheritance is easy to think about in this example and since you are using C# can be just as dynamic if you make a plug-in system for each enemy and dynamically create enemies by class name. If you go the composition route you could store an AI interface class object inside Enemy and then have different AI objects that implement that interface. Each different AI class would be the functionality that you want. To use Left 4 Dead as an example you would have iAI interface with function like Update(). Then you would make classes that implement this interface like: ZombieAI, HunterAI, BoomerAI, SmokerAI, Tank, etc.

 

If you find yourself doing a bunch of switches then there is most likely a better way. Switch statements aren't very dynamic. You don't want to have to remember to update switch statements when you think of a new enemy type.

interface iAI
{
    void Update();
}
 
class ZombieAI : iAI
{
    void Update()
    {
        // zombies behave differently than other enemies so they get their own class
    }
}

class TankAI : iAI
{
    void Update()
    {
        // tanks behave differently than other enemies so they get their own class
    }
}
 
class Enemy
{
    private iAI ai;
    private Image img;
 
    // inject the ai into the enemy class so that it can be more than 1 type
    public Enemey(iAI a, Image i) { ai = a; img = i; }
 
    public Update() { ai.Update(); }
};
 
// read from a text file or db to get the type of enemy you want to make. I would then dynamically create an instance based on string name using reflection
List<Enemy> enemies = new List<Enemy>();
 
// this enemy now acts like a zombie
enemies.Add(new Enemy(new ZombieAI(), new Image(filename));
 
// this enemy now acts like a zombie
enemies.Add(new Enemy(new TankAI(), new Image(filename));

Here is a decent example that compares the 2 approaches: http://www.javaworld.com/article/2076814/core-java/inheritance-versus-composition--which-one-should-you-choose-.html


Edited by rpiller, 30 December 2013 - 08:03 AM.


#6 haegarr   Crossbones+   -  Reputation: 4172

Like
0Likes
Like

Posted 30 December 2013 - 09:49 AM


What is a good file format to use for such a file? XML?

XML is stil bloated, still costly to parse, and still has a couple of features that doesn't help in this use case. The major opinion is to create a customized binary file format fitted to your needs *if* you speak of the load file format; it is something other if you speak of file formats for the development phase where interchangeability plays a role.



#7 Tutorial Doctor   Members   -  Reputation: 1569

Like
0Likes
Like

Posted 30 December 2013 - 11:10 AM

Yeah, it seems you wouldn't need another class. You could just put the type in the constructor so that each enemy has a type. I don't know how it is done in C# but I lua I would implement it like so:

badGuy = Enemy(type)

They call me the Tutorial Doctor.


#8 Jaap85   Members   -  Reputation: 241

Like
0Likes
Like

Posted 04 January 2014 - 10:55 AM

All right, thank you very much for responding everybody :-)

 

If i try to summarize your findings, i come to the following conclusions:

  • If the behaviour of all the different enemies is  the same, the best way to code everything is one of the following:
    1. Pass the type to the constructor, then use a switch statement in the constructor to set the different values
    2. Pass the different values directly to the constructor

When considering these methods i prefer the first one, since it will allow me to create new enemies easier. An even more advanced approach would be to dynamically generate the enemies by loading them from an external data file. 

 

  • If the behaviour of the enemies is different, composition is the best option. This is something new to me (i am not yet very experienced) but something i will definitely look into.

 

I hope the above is correct. Thank you very much for all your replies.



#9 phil_t   Crossbones+   -  Reputation: 3258

Like
0Likes
Like

Posted 04 January 2014 - 12:25 PM


If the behaviour of all the different enemies is  the same, the best way to code everything is one of the following:
 1) Pass the type to the constructor, then use a switch statement in the constructor to set the different values
 2) Pass the different values directly to the constructor
When considering these methods i prefer the first one, since it will allow me to create new enemies easier. An even more advanced approach would be to dynamically generate the enemies by loading them from an external data file. 

 

Except with the first one, you need to go change the Enemy class every time you create a new enemy type.



#10 Tutorial Doctor   Members   -  Reputation: 1569

Like
0Likes
Like

Posted 04 January 2014 - 12:55 PM

I don't understand why he would have to change the enemy class every time he creates a new enemy. If the class is designed correctly, everything could be adjusted outside of the class. 

 

This is pseudocode for how it could be done (python)

class Enemy():
def _init_(self) pass
self.hitpoints = hit_points;
self.image_speed = image_speed;

badGuy = Enemy()
badGuy2 = Enemy()

print (badGuy.hit_points)
print (badGuy2.hit_points)





If you wanted to specify a type, you could make the type a boolean value and make that an argument of the object. 

badGuy = Enemy(sniper)


In the class you would have:

sniper = false

And you would have a switch or conditional statement in the class like:

if (sniper == true)
{}
else if (bomber == true)
{}
else if (tank == true)

etc

class Enemy()

The boolean type would be in the constructor of the class, and it is designated upfront. All you do is check the type in the class, and perform whatever actions you want to do if a certain type is chosen. 

 

You'd create all of your enemy functions inside the class, so that once a type is selected, then those functions are triggered. 


Edited by Tutorial Doctor, 04 January 2014 - 12:56 PM.

They call me the Tutorial Doctor.


#11 rpiller   Members   -  Reputation: 666

Like
0Likes
Like

Posted 04 January 2014 - 01:20 PM


I don't understand why he would have to change the enemy class every time he creates a new enemy.

 

He means, every time you create a new enemy type, not a new enemy instance. It's a little messy to have a giant if/switch statement in a class like that. There are cleaner ways.



#12 Tutorial Doctor   Members   -  Reputation: 1569

Like
0Likes
Like

Posted 04 January 2014 - 02:47 PM

Yeah, there could be a switch statement for elements in an array (which would be the types, and which would also be boolean values) or however else. I gotcha though. Yeah, adding a new type would have to be done in the class. 


They call me the Tutorial Doctor.


#13 ChaosEngine   Crossbones+   -  Reputation: 2290

Like
0Likes
Like

Posted 05 January 2014 - 03:30 PM

 


What is a good file format to use for such a file? XML?

XML is stil bloated, still costly to parse, and still has a couple of features that doesn't help in this use case. The major opinion is to create a customized binary file format fitted to your needs *if* you speak of the load file format; it is something other if you speak of file formats for the development phase where interchangeability plays a role.

 

There are two problems with binary source formats from a development perspective.

  1. They are difficult for developers to edit with confidence
  2. Source control can't give you a useful diff history.

 

OTOH, you're right about xml being bloated at runtime. One option would be to write the source data in xml/json/whatever and then write a simple tool to parse the xml into your custom binary format as a build step. This should be relatively trivial to do and then you get the best of both worlds; human readable source that is easily put into version control and fast, compact files to distribute.


if you think programming is like sex, you probably haven't done much of either.-------------- - capn_midnight




Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.



PARTNERS