I'm making a top down 2D game and I want to have a lot of different attack types. I'd like to make the attacks very flexible and combine-able the way The Binding of Isaac works. Here's a list of all the collectibles in the game. To find a good example, lets look at the Spoon Bender item.
Spoon Bender gives Isaac the ability to shoot homing tears.
If you look at the "synergies" section, you'll see it can be combined with other collectibles for interesting yet intuitive effects. For example, if it combines with The Inner Eye, it "Will enable Isaac to fire multiple homing shots at once". This makes sense, because The Inner Eye
Gives Isaac a triple shot
What's a good architecture to design things like this? Here's a brute force solution:
if not spoon bender and not the inner eye then ...
if spoon bender and not the inner eye then ...
if not spoon bender and the inner eye then ...
if spoon bender and the inner eye then ...
But that will get out of hand very fast. What's a better way to design a system like this?
Answer
You totally don't need to hand-code combinations. You can instead focus on the properties that each item gives you. For instance, Item A sets Projectile=Fireball,Targetting=Homing
. Item B sets FireMode=ArcShot,Count=3
. The ArcShot
logic is responsible for sending out Count
number of Projectile
items in an arc.
These two items can be combined with any other items that modify these (or other) properties freely. If you add a new type of projectile it'll just automatically work with ArcShot
, and if you add a new firing mode it'll automatically work with Fireball
projectiles. Likewise, Targetting
is a property that sets the controller for the projectiles while FireMode
creates the projectiles, so they can be easily and trivially combined in any combination as makes sense.
You might also set of property dependencies and such. For instance, ArcShot
requires that you have a provider of Projectile
(which might just be the default). You might set priorities so that if you have two active items that both provide Projectile
the code knows which one to use. Or you can provide UI to let the user select which projectile type to use, or simply require the player to unequip high-priority items he doesn't want, or use the most recent item, etc. You can further allow a system of incompatibilities, e.g. such that two items that both just modify Projectile
cannot both be equipped simultaneously.
In general, when possible, prefer any kind of data-driven approach (or declarative) over procedural approaches (the big if-else messes) when it comes to the objects and such in your game. Higher-level generic logic that is configurable by simple data is much preferable over hard-coded lists of special-cased rules.
No comments:
Post a Comment