Trivial use of polymorphism?

I am working on a shooter game in which several types of shot motions will be used. It seems like a misuse of polymorphism to create a variety of classes for shot objects when the only difference between them would be a couple of lines of code in the move().

Examples:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
Class basic_shot // shot leaves play when it leaves the screen
{
   ...
    virtual void move()
    {
        x += vx;
        y += vy;
        if( x < 0.0 ) inAir = false;
        if( x > 800.0 ) inAir = false;
        if( y < 0.0 ) inAir = false;
        if( y > 600.0 ) inAir = false;
    }
}

Class ricochet_shot // shot bounces off the top and bottom of the screen
{
   ...
    virtual void move()
    {
        x += vx;
        y += vy;
        if( x < 0.0 ) inAir = false;
        if( x > 800.0 ) inAir = false;
        if( y < 0.0 || y > 600.0 ) vy *= -1.0;
    }
}


These classes have all the same data members, but differ only in the implementation of a single member function. I am tempted to use a single class object then have a pointer to a global function for each shot instance to use for calling the "appropriate" move function. This function pointer data member would be assigned for each shot when it is created.
This approach also would allow me to store more shots in a single vector, instead of having to use a separate vector for storing each type of shot.

What is common / recommended practice in a case like this?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
class bullet{
   movement *behaviour;
};

class movement{
   virtual point next(point) = 0;
}
class straight: public movement;
class bounce: public movement;
class toroid: public movement;
class spiral: public movement;
class compound: public movement{
   container<movement*> list;
}
Somewhat your function pointer approach. But I think this is more flexible, as you can have state.
Look for the strategy pattern.
On a second read ¿is this what your describe as your first approach?

As for classes or functions, I think that the efficiency is the same for both, having to just dereference one pointer. (classes would have the initial overhead of the creation of the objects)
So the issue is how easy is to add a new shot. And there you may have a use for members.


This approach also would allow me to store more shots in a single vector, instead of having to use a separate vector for storing each type of shot.
¿? Store pointers to the base class.
Thank you for the reply ne555.

I have looked into the strategy pattern and it does seem like an intelligent and flexible approach. I will give it a try.
According to what I read, the function pointer approach would be the way to go if I were programming in a language not supporting OOP, such as c.

ne555 wrote:
¿? Store pointers to the base class.

I do maintain a vector of base class pointers for the purpose of moving the shots, drawing them and for hit testing against them. I am maintaining separate vectors for each shot class because I recycle the shot instances. Dealing with the actual object class seems necessary when reassigning data members. This approach is proving to be cumbersome though. I may try going with single use shots, where new and delete are used for each shot fired.

EDIT: Wow. I just realized that I'm already using a strategy pattern based approach for the enemy ships motion. Each ship has a Leg* as a data member ( Leg, as in a portion of a path ). Each Leg type defines a move() which implements a different parametrized motion (straight line, circle, etc...). The Leg class has a Leg* nextLeg member and the move() returns this Leg* when the end of a Leg is reached. Ships travel on closed paths this way quite flexibly and automatically. It works great.
I'm not sure why I didn't think of it in the context of shots!
Last edited on
@ne555: Is there an advantage to this over deriving straight from the bullet class itself:
1
2
3
4
5
6
7
8
9
10
11
12
13
class Bullet
{
public:
virtual void Move(Time) = 0;
private:
Position pos;
//etc...
}

class StraightBullet: public Bullet
{
virtual void Move(Time);
}
?
Sorry, I'm not very good at design patterns.
Me neither, xP.
Suppose that you want other objects to move too.
That the movement can change at runtime
That you want composite movements.

Those would be hard to implement with your model.
http://berniesumption.com/software/inheritance-is-evil-and-must-be-destroyed/
Design Patterns by GoF
Topic archived. No new replies allowed.