1
\$\begingroup\$

I'm working on a game a bit like "Super Smash Bros.", using C++ and SFML. I can't figure out a good way to program attacks.

First, I coded individual functions for each attack. The problem with this was that I needed three functions for each attack; one for dealing knock-back to other players, one for setting variables for the actual punch and one for checking for unique types of collision. This ends up being almost the same code for all the other attacks, and was also very messy for programming combos.

I then tried creating a class called Attack, and inherited classes like Punch and Kick. The problem with this was that I wasn't sure how to implement all of the methods in the Player class.

How do I program attacks and combos in a fighting game?

\$\endgroup\$
5
\$\begingroup\$

This advice is more general, rather than being specific to fighting games, but typically player behaviour in games with any reasonable level of complexity will be coded as a finite state machine, where the different actions that the player can perform (normal locomotion, climbing over objects, melee attacks), are encoded as mutually exclusive "states" that encapsulate that action.

https://en.wikipedia.org/wiki/Finite-state_machine

(Edit: This article has a more game-specific explanation of how finite state machines are often used in player code http://gameprogrammingpatterns.com/state.html)

These states drive player animation and movement, and triggering the consequences of those actions (inflicting damage on enemies when you reach a certain point in the animation, triggering visual effects, etc). The player can be in one state, and only ever one state at a time, and each state can only transition to certain other states.

This kind of approach generally makes more sense than implementing as functions, because typically your player is going to be in one of these states for longer than a single frame, and this is a natural way to handle that more long-lived state. For example, if the player performs a heavy attack, you might want to keep them locked into that animation/state until a certain point has been reached, for balancing purposes but also to give the action a real sense of weight and consequence.

It also makes things easier to reason about, if you ever decide to implement networked multiplayer, because then it becomes much easier to think about what information you need to replicate to other players.

One thing I would caution against though, is making heavy use of class inheritance when writing this code. It becomes a massive pain if at some point in the future you want to share functionality between states that aren't otherwise related. Then you end up pushing functionality into some base class where it doesn't belong and messing up the code.. or having to duplicate bug fixes in several different player state classes that end up being almost complete copy-pastes of one another with a few things changed.

For a melee attack state for example, your different attacks might be conceptually similar enough to one another, that it makes sense to have one melee attack state, and just drive the different attack types based on the "start parameters" that the state was given when it started.

Consequences like inflicting damage, can usually be written into some kind of common utils function that's called from various places, and called internally from within your state.

If you're careful not to put too much player-input specific logic in your state machine code, it also comes in handy if you find you want to implement AI that can play your game at some point in the future, as they can reuse a lot of the same player state machine code to drive their animations/actions. (It's just that the actions being requested are coming from the AI now, instead of directly from an input device)

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.