Practical use of Polymorphism for a shooter?

Started by
12 comments, last by dzeligman 15 years, 9 months ago
Ok, I understand how polymorphism works, but as far as when to actually use it in a game is concerned I'm still a bit foggy. So, here's my question: Let's say we have a 2D top-down shooter. Your character has a primary and a secondary weapon slot. Any kind of pistol can go in the primary slot and any kind of bigger weapon in the secondary. The various different kinds of pistols/secondaries are all very different and fire differently etc. So... would it be a good idea to do this: Make a base Weapon class, and then for example a Pistol class, Rifle class and Shotgun class that inherits from Weapon. Weapon will be pure virtual with functions such as reload(), fire() etc. The player class will have this: Weapon* primWeap Weapon* secWeap And thus, if the player has the secondary weapon selected and presses fire, we call secWeap->fire(). Is that a practical, efficient use of polymorphism? Seems like it'd be a fairly handy way of doing things.
Advertisement
You're correct. That is the way polymorphism is meant to be used. And as like any other project you'd do, a game, be it a shooter or an RTS is just a piece of software engineering.

But you got it right. Of course, you could implement parts of the weapon in the main class. A weapon recycle would be the same for all weapons, as it's just time based. And if a weapon is empty, you could call the virtual reload() function.

Toolmaker

If you've ever done any Half-Life I/II modding, then you might have noticed that Valve's SDKs contain a fairly elaborate class hierarchy, with most unique items having their own class type. On the other hand, I've worked on projects where there was only a single base object class, and through the use of attachable, data-driven "components" we were able to create all the unique behaviors and properties we needed. I used to be a fan of the deep class hierarchies during my modding years, but lately I've come around. This type of system makes it very easy to prototype new objects without requiring new code all the time, and it makes your objects more flexible and dynamic at run-time. This was for an RTS, so YMMV depending on the type of game you're making and what features you need.
K cool, thanks.

And ZOMG Zipster, I know you from the Petroglyph boards :O
Quote:Original post by Toolmaker
But you got it right. Of course, you could implement parts of the weapon in the main class. A weapon recycle would be the same for all weapons, as it's just time based. And if a weapon is empty, you could call the virtual reload() function.

I can imagine all sorts of different ways for a weapon recycle to function, not just time based. It might be dependent on your current score or multiplier, or it might need a weapon pickup to activate again, or it could be based on your position on the screen. Moving that functionality into the calling class would be a mistake IMHO.

If you're worried about duplication of common code, I like to have an IWeapon which is a pure-virtual interface and no functionality, and a WeaponBase which inherits from IWeapon and provides the common functionality needed to get a typical weapon implemented quickly and easily. IWeapon would provide the interface to allow you to handle reloading on a per weapon basis, and WeaponBase would provide a default implementation that just waits a set amount of time (which can be set in the sub class). That way you can have MachineGun and Pistol both inheriting from WeaponBase and needing only the minimum amount of code required for the different bullet patterns, and CrazyLaser inheriting directly from IWeapon and providing custom reload and firing behaviour.
primWeapon isn't just any old Weapon, it's a Pistol. Why not make it one?
Quote:Original post by Ezbez
primWeapon isn't just any old Weapon, it's a Pistol. Why not make it one?


Because you might be able to swap your primary weapon for non-pistols? My primary weapon is always the sledgehammer.
Quote:Original post by DaedalusOwnsYou
Quote:Original post by Ezbez
primWeapon isn't just any old Weapon, it's a Pistol. Why not make it one?


Because you might be able to swap your primary weapon for non-pistols? My primary weapon is always the sledgehammer.


Dear god, not the crowbar? [wow]
You may want to have two more bases from Weapon, SmallWeapon and BigWeapon. You can do
BigWeapon* primary;SmallWeapon* secondary;


It will keep weapons in their correct slots, which may or may not be beneficial. Heck, maybe you want to allow a rifle as a secondary. And it will take a little tweaking to allow for medium weapons in either slot (SMG's, for example. Is that a primary or secondary).
Your example is a good example of how to explain it but a poor example of use in practice. Weapon behavior is fairly uniform, and the differences are easily abstracted by data you shouldn't need a whole new class just to change rate of fire or damage. The use of polymorphism is driven by the need for a similar interface but different code. A good example would in shots fired you use the same code for a cross bow as a gun just different ammo which would be a good place to use polymorphism.

As an example Halo has multiple vehicles. To model all of halo's vehicles you need a base class vehicle to provide the interface, since all vehicles accept the same messages(all the vehicles use the same control scheme.) From there you would have two sub classes one for land based vehicles and one for air based vehicles. Each type of vehicle can be created through data manipulation on one of the subclasses not a proliferation of classes.

Now the Halo example could easily be done as a component system where you only have the vehicle class with a component for how physics effects the vehicle but then you would still need polymorphism to unify object types between the different physics models. And that is the hart of the matter only use inheritance and polymorphism when you need objects that behave fundamentally different(no easy data driven solution)to have the same type otherwise use data and/or composition. The data driven solution you are trying to avoid is basically if A do method A if B do method B sort of stuff.

This topic is closed to new replies.

Advertisement