2
\$\begingroup\$

How can I have events based off animations without relying on them? Take for example reloading in a FPS game. You'd hit a button to reload your weapon, the animation will play, then animation will hit a certain frame, then the weapon will be reloaded. There's a dependency on the animation eventually hitting that key frame before the weapon can reload and the character can go into another state. Without the animation, the weapon would never reload, and without some arbitrary timeout, the character would be stuck in that state forever.

Checking for the existence of an animation is an option. However, this requires us to still know about some sort of animation, and what it's playing. Am I over engineering this? Would it be okay for the logic of some object to have some information about it's animations?

\$\endgroup\$
2
\$\begingroup\$

Introduce a new abstraction: Action

An Action represents something that can be done, and encompassed the time aspect as well as information about the state and state transitions of the action. So a reload action definition might contain information about total duration, relative timestamp of reload complete etc. A spear throw action definition contains information about total duration and timestamp of spear release.

Exactly how you wrap this up in code is up to you and depends on your framework/style. Actions could be simple data objects which you just use to define different actions, and then you make use of the timestamps, durations and other information "manually" in the rest of your code. Or you could improve encapsulation by having your Action module expose events which trigger when the action changes state (OnReloadStarted,OnReloadReady,OnReloadFinished,OnSpearThrown). Or you could have a medium where there are no events, but the Action still manages its states/transitions so that you can poll it: throwSpearAction.isSpearThrown().

If you have multiple reload animations or spear-throw animations with different timings, then you define each alternative as an action, e.g. FastThrowAction and SlowThrowAction. Once again it is up to you exactly how you manage and pick from different alternatives.

The point of all this is that the Action abstraction becomes a natural part of the gameplay model when you focus on the concepts that affect gameplay (action transitions/events) and remove the concepts that don't (animation).

These Action objects can then be used to drive the animation as well. Whenever a FastThrowAction is started, then your renderer/view starts the corresponding FastThrowAnimation.

\$\endgroup\$
0
\$\begingroup\$

All animations are more-or-less based on the idea of "keyframes", whereby you define two or more states/poses/transforms and the length of time between them; when 50% of the animations' total time has passed, the animation is 50% complete. Animations like "reload" have fixed time-costs based on the character, weapon, being suppressed, etc..

Your InputHandler will need to ignore invalid input until the Reloading state expires (not when the animation is finished).

During that time, the animation may also progress, smoothly, from 0% to 100%. When the player presses "R", the current time is recorded. If the computer, then, lags out for X+1 seconds, the entire animation will happen "instantly", when the computer catches back up; the InputHandler would also detect the (instant) expiration of the reload state and clear it.

Basically, the game continues playing with, or without, acceptable animations:

  1. Player presses "R"
  2. Set the player's Reloading flag (disable reload-incompatible inputs)
  3. ReloadTime or ExpiryTime is recorded (100% reload after 3.2 seconds)
  4. Update() and Render() for 3.1999 seconds...
    If using ReloadTime, subtract delta-time from it, every Update().
    (Could be one 3.1999-second update or one-hundred 0.031999-second updates)
  5. During the next Update(),
    ReloadTime will be <=0, or
    ExpiryTime will be a time in the past
  6. If so, clear the player's Reloading flag (enable reload-incompatible inputs).
    The animation is done (not a question).
\$\endgroup\$
2
  • \$\begingroup\$ That will work for something basic like reloading( which doesn't have to be exact ), but consider something more visual like throwing a spear. You'll want the spear to been thrown at some exact time in the animation( where the character actually lets go of it. ) This is not necessarily the end of the animation, because the character might follow through on the throw, and it must be precise to look accurate. Creating the animation to perfectly fit data based on this would be a pain compared to having the animation drive it. \$\endgroup\$
    – Ben
    May 3 '15 at 6:10
  • \$\begingroup\$ @Ben, how do you determine when the player lets go? I'm visualizing those stupid golf games with the "swing meter". In that type of game, you fully describe the swing, then the animation happens, based on the calculated output. The point at which the club hits the ball is known before the animation starts, so stretching the time between key-frames is trivial. When the calculated time has elapsed (key-frame also happens to be hit), the animation is complete, the ball is accelerated, and then a second, follow-through, animation is played, starting with the player's current state. \$\endgroup\$
    – Jon
    May 3 '15 at 6:43

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.